diff --git a/.gitmodules b/.gitmodules index 7cc3ee6f..20ce0a42 100644 --- a/.gitmodules +++ b/.gitmodules @@ -21,3 +21,6 @@ [submodule "libdiskpp/contrib/matplotplusplus"] path = libdiskpp/contrib/matplotplusplus url = https://github.com/alandefreitas/matplotplusplus/ +[submodule "libdiskpp/contrib/spectra"] + path = libdiskpp/contrib/spectra + url = https://github.com/yixuan/spectra.git diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..171628ac --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,86 @@ +{ + "files.associations": { + ".inc": ".f90", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "format": "cpp", + "text_encoding": "cpp", + "csignal": "cpp", + "strstream": "cpp", + "bitset": "cpp", + "cfenv": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "condition_variable": "cpp", + "forward_list": "cpp", + "regex": "cpp", + "source_location": "cpp", + "hash_map": "cpp", + "future": "cpp", + "mutex": "cpp", + "shared_mutex": "cpp", + "stdfloat": "cpp", + "typeindex": "cpp", + "valarray": "cpp" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 5563ca25..b7cd6344 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,7 @@ endif() #add_subdirectory(contrib/eigen) find_package(Eigen3 REQUIRED) set(LINK_LIBS ${LINK_LIBS} Eigen3::Eigen) +include_directories(libdiskpp/contrib/spectra/include) ###################################################################### ## ~jburkardt code @@ -279,3 +280,5 @@ set(CPACK_DEBIAN_PACKAGE_SECTION "science") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6,libgcc1,libstdc++6") include(CPack) + + diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index e3871658..3783f0d2 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -113,3 +113,13 @@ if (BUILD_APP_VEM_2D) add_subdirectory(vem2d) endif() + +option(BUILD_APP_UNFITTED_HHO "Build unfitted_HHO application" ON) +if (BUILD_APP_UNFITTED_HHO) + add_subdirectory(unfitted_HHO) +endif() + +option(BUILD_APP_WAVE_PROPAGATION "Build wave_propagation application" ON) +if (BUILD_APP_WAVE_PROPAGATION) + add_subdirectory(wave_propagation) +endif() diff --git a/apps/unfitted_HHO/CMakeLists.txt b/apps/unfitted_HHO/CMakeLists.txt new file mode 100644 index 00000000..46a19e9f --- /dev/null +++ b/apps/unfitted_HHO/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LINK_LIBS diskpp) + +add_executable(unfitted_HHO src/unfitted_HHO.cpp) +target_link_libraries(unfitted_HHO ${LINK_LIBS}) +install(TARGETS unfitted_HHO RUNTIME DESTINATION bin) diff --git a/apps/unfitted_HHO/src/unfitted_HHO.cpp b/apps/unfitted_HHO/src/unfitted_HHO.cpp new file mode 100644 index 00000000..cd60b681 --- /dev/null +++ b/apps/unfitted_HHO/src/unfitted_HHO.cpp @@ -0,0 +1,9 @@ +#include +#include +#include "diskpp/loaders/loader.hpp" +#include "diskpp/mesh/cut_mesh.hpp" + +int main(int argc, char **argv) { + + +} diff --git a/apps/wave_propagation/CMakeLists.txt b/apps/wave_propagation/CMakeLists.txt new file mode 100644 index 00000000..11a89fc4 --- /dev/null +++ b/apps/wave_propagation/CMakeLists.txt @@ -0,0 +1,6 @@ +set(LINK_LIBS diskpp) + +add_executable(wave_propagation src/wave_propagation.cpp) +target_link_libraries(wave_propagation ${LINK_LIBS}) + +install(TARGETS wave_propagation RUNTIME DESTINATION bin) diff --git a/apps/wave_propagation/src/CMakeLists.txt b/apps/wave_propagation/src/CMakeLists.txt new file mode 100644 index 00000000..24fdd91b --- /dev/null +++ b/apps/wave_propagation/src/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(common) diff --git a/apps/wave_propagation/src/common/CMakeLists.txt b/apps/wave_propagation/src/common/CMakeLists.txt new file mode 100644 index 00000000..ed499c7d --- /dev/null +++ b/apps/wave_propagation/src/common/CMakeLists.txt @@ -0,0 +1,35 @@ + +set(fitted_waves_sources ${fitted_waves_sources} + #${CMAKE_CURRENT_SOURCE_DIR}/fitted_geometry_builders.cpp +PARENT_SCOPE) + +set(fitted_waves_headers ${fitted_waves_headers} + ${CMAKE_CURRENT_SOURCE_DIR}/display_settings.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/preprocessor.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/postprocessor.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/acoustic_material_data.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/elastic_material_data.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/scal_analytic_functions.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/vec_analytic_functions.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/scal_vec_analytic_functions.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/fitted_geometry_builders.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/assembly_index.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/acoustic_one_field_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/acoustic_two_fields_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/elastodynamic_one_field_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/elastodynamic_two_fields_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/elastodynamic_three_fields_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/elastoacoustic_two_fields_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/elastoacoustic_four_fields_assembler.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/fitted_geometry_builders.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/linear_solver.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/dirk_hho_scheme.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/erk_hho_scheme.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ssprk_hho_scheme.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/dirk_butcher_tableau.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/erk_butcher_tableau.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/ssprk_shu_osher_tableau.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/lsrk_butcher_tableau.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/sourceterm.hpp +PARENT_SCOPE) + diff --git a/apps/wave_propagation/src/common/acoustic_material_data.hpp b/apps/wave_propagation/src/common/acoustic_material_data.hpp new file mode 100644 index 00000000..9b54ee8b --- /dev/null +++ b/apps/wave_propagation/src/common/acoustic_material_data.hpp @@ -0,0 +1,91 @@ +// +// acoustic_material_data.hpp +// acoustics +// +// Created by Omar Durán on 4/14/20. +// + +#pragma once +#ifndef acoustic_material_data_hpp +#define acoustic_material_data_hpp + +#include + +template +class acoustic_material_data { + + /// Fluid density + T m_rho; + + /// Compressional P-wave velocity + T m_vp; + +public: + + /// Default constructor + acoustic_material_data(T rho, T vp){ + m_rho = rho; + m_vp = vp; + } + + /// Copy constructor + acoustic_material_data(const acoustic_material_data & other){ + m_rho = other.m_rho; + m_vp = other.m_vp; + } + + /// Assignement constructor + const acoustic_material_data & operator=(const acoustic_material_data & other){ + + // check for self-assignment + if(&other == this){ + return *this; + } + + m_rho = other.m_rho; + m_vp = other.m_vp; + return *this; + + } + + /// Desconstructor + virtual ~acoustic_material_data(){ + + } + + /// Print class attributes + virtual void Print(std::ostream &out = std::cout) const{ + out << "\n density = " << m_rho; + out << "\n p-wave velocity = " << m_vp; + } + + /// Print class attributes + friend std::ostream & operator<<( std::ostream& out, const acoustic_material_data & material ){ + material.Print(out); + return out; + } + + void Set_rho(T rho) + { + m_rho = rho; + } + + T rho() + { + return m_rho; + } + + + void Set_vp(T vp) + { + m_vp = vp; + } + + T vp() + { + return m_vp; + } + +}; + +#endif /* acoustic_material_data_hpp */ diff --git a/apps/wave_propagation/src/common/acoustic_one_field_assembler.hpp b/apps/wave_propagation/src/common/acoustic_one_field_assembler.hpp new file mode 100644 index 00000000..621f62d7 --- /dev/null +++ b/apps/wave_propagation/src/common/acoustic_one_field_assembler.hpp @@ -0,0 +1,643 @@ +// +// acoustic_one_field_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/14/20. +// + +#pragma once +#ifndef acoustic_one_field_assembler_hpp +#define acoustic_one_field_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/acoustic_material_data.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class acoustic_one_field_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_mass_triplets; + std::vector< acoustic_material_data > m_material; + std::vector< size_t > m_elements_with_bc_eges; + + std::vector< std::pair > m_f_l_indexes; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + +public: + + SparseMatrix LHS; + Matrix RHS; + SparseMatrix MASS; + + acoustic_one_field_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + + classify_cells(msh); + expand_triplet(msh); + } + + void scatter_data(const std::pair & dest_indexes, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + size_t first_ind = dest_indexes.first; + size_t last_ind = dest_indexes.second; + size_t l = 0; + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ){ + m_triplets[first_ind+l] = Triplet(asm_map[i], asm_map[j], lhs(i,j)); + l++; + } + } + } + + size_t cell_nnz = (last_ind - first_ind); + assert( (l-1) == cell_nnz ); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_bc_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + + } + } + + } + + void scatter_rhs_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows()); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_mass_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + + } + + void assemble(const Mesh& msh, std::function rhs_fun){ + + LHS.setZero(); + RHS.setZero(); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix laplacian_operator_loc = this->laplacian_operator(cell_ind, msh, cell); + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + this->scatter_data(m_f_l_indexes[cell_ind], msh, cell, laplacian_operator_loc, f_loc); + } + ); + #else + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + + scatter_data(m_f_l_indexes[cell_ind], msh, cell, laplacian_operator_loc, f_loc); + } + #endif + + finalize(); + } + + void apply_bc(const Mesh& msh, T scale = T(1.0)){ + + #ifdef HAVE_INTEL_TBB + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&scale] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + laplacian_operator_loc *= scale; + scatter_bc_data(msh, cell, laplacian_operator_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto& cell_ind : m_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + laplacian_operator_loc *= scale; + scatter_bc_data(msh, cell, laplacian_operator_loc); + } + #endif + + } + + void assemble_rhs(const Mesh& msh, std::function rhs_fun){ + + RHS.setZero(); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + } + ); + #else + auto contribute = [this,&msh,&rhs_fun] (const typename Mesh::cell_type& cell){ + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + }; + + for (auto& cell : msh){ + contribute(cell); + } + #endif + } + + void assemble_mass(const Mesh& msh){ + + MASS.setZero(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + Matrix mass_matrix = mass_operator(cell_ind,msh,cell); + scatter_mass_data(msh, cell, mass_matrix); + cell_ind++; + } + finalize_mass(); + } + + Matrix laplacian_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + + auto reconstruction_operator = make_scalar_hho_laplacian(msh, cell, m_hho_di); + Matrix R_operator = reconstruction_operator.second; + + + Matrix S_operator; + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_scalar_hho_stabilization(msh, cell, reconstruction_operator.first, m_hho_di); + S_operator = stabilization_operator; + }else{ + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di); + S_operator = stabilization_operator; + } + acoustic_material_data & material = m_material[cell_ind]; + return (1.0/material.rho())*(R_operator + S_operator); + } + + Matrix mass_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + + acoustic_material_data & material = m_material[cell_ind]; + auto scal_basis = disk::make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix = disk::make_mass_matrix(msh, cell, scal_basis); + mass_matrix *= (1.0/(material.rho()*material.vp()*material.vp())); + return mass_matrix; + } + + void classify_cells(const Mesh& msh){ + + m_elements_with_bc_eges.clear(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + cell_ind++; + } + } + + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function scal_fun){ + + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + size_t n_dof = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + x_glob = Matrix::Zero(n_dof); + for (auto& cell : msh) + { + Matrix x_proj_dof = project_function(msh, cell, m_hho_di.cell_degree(), scal_fun); + scatter_cell_dof_data(msh, cell, x_glob, x_proj_dof); + } + } + + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function scal_fun){ + + for (auto& cell : msh) + { + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), scal_fun); + scatter_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + void expand_triplet(const Mesh& msh){ + + size_t n_cells = msh.cells_size(); + m_f_l_indexes.reserve(n_cells); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + size_t first_ind = 0; + size_t last_ind = 0; + for (auto& cell : msh) + { + auto fcs = faces(msh, cell); + last_ind = 0; + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + last_ind += n_fbs; + } + last_ind = first_ind + n_cbs*n_cbs + 2.0*n_cbs*last_ind + last_ind*last_ind; + m_f_l_indexes.push_back(std::make_pair(first_ind,last_ind-1)); + first_ind = last_ind; + } + + // expanding global triplets + m_triplets.resize(last_ind); + } + + void clear(void) + { + m_elements_with_bc_eges.clear(); + m_f_l_indexes.clear(); + m_triplets.clear(); + m_mass_triplets.clear(); + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + void finalize_mass(void) + { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + Matrix x_local(n_cbs + num_faces * n_fbs ); + x_local.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = disk::make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, fc, fb, m_hho_di.face_degree()); + auto velocity = m_bnd.dirichlet_boundary_func(face_id); + Matrix rhs = make_rhs(msh, fc, fb, velocity, m_hho_di.face_degree()); + x_local.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_local.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_local; + } + + void + scatter_cell_dof_data( const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix x_proj_dof) const + { + auto cell_ofs = disk::offset(msh, cell); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1) = x_proj_dof; + } + + void + scatter_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix x_proj_dof) const + { + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(),Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + size_t n_cells = msh.cells_size(); + auto face_offset = disk::offset(msh, face); + auto glob_offset = n_cbs * n_cells + m_compress_indexes.at(face_offset)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + void load_material_data(const Mesh& msh){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + T rho = 1.0; + T vp = 1.0; + acoustic_material_data material(rho,vp); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, acoustic_material_data & material){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, std::function(const typename Mesh::point_type& )> acoustic_mat_fun){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + std::vector mat_data = acoustic_mat_fun(bar); + T rho = mat_data[0]; + T vp = mat_data[1]; + acoustic_material_data material(rho,vp); + m_material.push_back(material); + } + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } + + boundary_type & get_bc_conditions(){ + return m_bnd; + } + + std::vector< acoustic_material_data > & get_material_data(){ + return m_material; + } + + size_t get_n_face_dof(){ + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + size_t n_face_dof = (m_n_edges - m_n_essential_edges) * n_fbs; + return n_face_dof; + } + + size_t get_n_cell_basis(){ + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(),Mesh::dimension); + return n_cbs; + } + + size_t get_n_face_basis(){ + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + return n_fbs; + } + + std::vector< std::pair > & get_f_l_indexes(){ + return m_f_l_indexes; + } + + std::vector< Triplet > & get_triplets(){ + return m_triplets; + } + + size_t get_cell_basis_data(){ + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(),Mesh::dimension); + return n_cbs; + } + +}; + +#endif /* acoustic_one_field_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/acoustic_two_fields_assembler.hpp b/apps/wave_propagation/src/common/acoustic_two_fields_assembler.hpp new file mode 100644 index 00000000..07eff3b5 --- /dev/null +++ b/apps/wave_propagation/src/common/acoustic_two_fields_assembler.hpp @@ -0,0 +1,734 @@ +// +// acoustic_two_fields_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/21/20. +// + +#pragma once +#ifndef acoustic_two_fields_assembler_hpp +#define acoustic_two_fields_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/acoustic_material_data.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class acoustic_two_fields_assembler +{ + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_mass_triplets; + std::vector< acoustic_material_data > m_material; + std::vector< size_t > m_elements_with_bc_eges; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + bool m_scaled_stabilization_Q; + +public: + + SparseMatrix LHS; + Matrix RHS; + SparseMatrix MASS; + + acoustic_two_fields_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true), m_scaled_stabilization_Q(false) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + + classify_cells(msh); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + auto fcs = faces(msh, cl); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(size_t(asm_map[i])) += rhs(i); + } + + } + + void scatter_bc_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + auto fcs = faces(msh, cl); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + + } + } + + } + + void scatter_rhs_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows()); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_mass_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + + } + + void assemble(const Mesh& msh, std::function rhs_fun){ + + LHS.setZero(); + RHS.setZero(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + Matrix f_loc = mixed_rhs(msh, cell, rhs_fun); + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_data(msh, cell, mixed_operator_loc, f_loc); + cell_ind++; + } + finalize(); + } + + Matrix mixed_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + acoustic_material_data & material = m_material[cell_ind]; + auto reconstruction_operator = mixed_scalar_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_scalar_hho_stabilization(msh, cell, reconstruction_operator.first, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + }else{ + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + + T rho = material.rho(); + T vp = material.vp(); + return R_operator + ((1.0)/(vp*rho))*S_operator; + } + + void apply_bc(const Mesh& msh){ + + #ifdef HAVE_INTEL_TBB + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, mixed_operator_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto& cell_ind : m_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, mixed_operator_loc); + } + #endif + + } + + void assemble_rhs(const Mesh& msh, std::function & rhs_fun, size_t di = 0){ + + RHS.setZero(); + + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun,&di] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix f_loc = this->mixed_rhs(msh, cell, rhs_fun,di); + this->scatter_rhs_data(msh, cell, f_loc); + } + ); + #else + auto contribute = [this,&msh,&rhs_fun,&di] (const typename Mesh::cell_type& cell){ + Matrix f_loc = this->mixed_rhs(msh, cell, rhs_fun,di); + this->scatter_rhs_data(msh, cell, f_loc); + }; + + for (auto& cell : msh){ + contribute(cell); + } + #endif + } + + void assemble_mass(const Mesh& msh, bool add_scalar_mass_Q = true){ + + MASS.setZero(); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = mass_operator(cell_ind, msh, cell, add_scalar_mass_Q); + scatter_mass_data(msh, cell, mass_matrix); + } + finalize_mass(); + } + + Matrix mass_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, bool add_scalar_mass_Q = true){ + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + + acoustic_material_data & material = m_material[cell_ind]; + Matrix mass_matrix = Matrix::Zero(n_cbs, n_cbs); + + auto recdeg = m_hho_di.reconstruction_degree(); + auto rec_basis = make_scalar_monomial_basis(msh, cell, recdeg); + auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + + Matrix mass_matrix_q_full = make_stiffness_matrix(msh, cell, rec_basis); + Matrix mass_matrix_q = Matrix::Zero(rbs-1, rbs-1); + mass_matrix_q = mass_matrix_q_full.block(1, 1, rbs-1, rbs-1); + mass_matrix_q *= material.rho(); + mass_matrix.block(0, 0, n_vec_cbs, n_vec_cbs) = mass_matrix_q; + + if (add_scalar_mass_Q) { + auto scal_basis = disk::make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix_v = disk::make_mass_matrix(msh, cell, scal_basis); + mass_matrix_v *= (1.0/(material.rho()*material.vp()*material.vp())); + mass_matrix.block(n_vec_cbs, n_vec_cbs, n_scal_cbs, n_scal_cbs) = mass_matrix_v; + } + + return mass_matrix; + } + + void classify_cells(const Mesh& msh){ + + size_t cell_ind = 0; + for (auto& cell : msh) + { + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + cell_ind++; + } + } + + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function scal_fun, std::function(const typename Mesh::point_type& )> vec_fun){ + size_t n_dof = MASS.rows(); + x_glob = Matrix::Zero(n_dof); + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + for (auto& cell : msh) + { + + Matrix x_proj_vec_dof = project_vec_function(msh, cell, vec_fun); + Matrix x_proj_sca_dof = project_function(msh, cell, m_hho_di.cell_degree(), scal_fun); + + Matrix x_proj_dof = Matrix::Zero(n_cbs); + x_proj_dof.block(0, 0, n_vec_cbs, 1) = x_proj_vec_dof; + x_proj_dof.block(n_vec_cbs, 0, n_scal_cbs, 1) = x_proj_sca_dof; + scatter_cell_dof_data(msh, cell, x_glob, x_proj_dof); + } + } + + Matrix project_vec_function(const Mesh& msh, const typename Mesh::cell_type& cell, + std::function(const typename Mesh::point_type& )> vec_fun){ + + auto recdeg = m_hho_di.reconstruction_degree(); + auto rec_basis = make_scalar_monomial_basis(msh, cell, recdeg); + auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + Matrix mass_matrix_q_full = make_stiffness_matrix(msh, cell, rec_basis); + Matrix mass_matrix_q = Matrix::Zero(rbs-1, rbs-1); + mass_matrix_q = mass_matrix_q_full.block(1, 1, rbs-1, rbs-1); + + Matrix rhs = Matrix::Zero(rbs-1); + Matrix f_vec = Matrix::Zero(1, 2); + const auto qps = integrate(msh, cell, 2*recdeg); + for (auto& qp : qps) + { + auto dphi = rec_basis.eval_gradients(qp.point()); + std::vector flux = vec_fun(qp.point()); + f_vec(0,0) = flux[0]; + f_vec(0,1) = flux[1]; + for (size_t i = 0; i < rbs-1; i++){ + Matrix phi_i = dphi.block(i+1, 0, 1, 2).transpose(); + rhs(i,0) = rhs(i,0) + (qp.weight() * f_vec*phi_i)(0,0); + } + } + Matrix x_dof = mass_matrix_q.llt().solve(rhs); + return x_dof; + } + + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function scal_fun){ + + for (auto& cell : msh) + { + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), scal_fun); + scatter_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + void finalize_mass(void) + { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = disk::make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, fc, fb, m_hho_di.face_degree()); + auto velocity = m_bnd.dirichlet_boundary_func(face_id); + Matrix rhs = make_rhs(msh, fc, fb, velocity, m_hho_di.face_degree()); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + void scatter_cell_dof_data( const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix &x_proj_dof) const + { + auto cell_ofs = disk::offset(msh, cell); + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1) = x_proj_dof; + } + + void scatter_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix &x_proj_dof) const + { + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + size_t n_cells = msh.cells_size(); + auto face_offset = disk::offset(msh, face); + auto glob_offset = n_cbs * n_cells + m_compress_indexes.at(face_offset)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + std::pair< Matrix, + Matrix > + mixed_scalar_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) + { + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + typedef Matrix vector_type; + + const size_t DIM = Mesh::dimension; + + const auto recdeg = m_hho_di.reconstruction_degree(); + const auto celdeg = m_hho_di.cell_degree(); + const auto facdeg = m_hho_di.face_degree(); + + auto cb = make_scalar_monomial_basis(msh, cell, recdeg); + + const auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + const auto cbs = disk::scalar_basis_size(celdeg, Mesh::dimension); + const auto fbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + const auto num_faces = howmany_faces(msh, cell); + + const matrix_type stiff = make_stiffness_matrix(msh, cell, cb); + matrix_type gr_lhs = matrix_type::Zero(rbs-1, rbs-1); + matrix_type gr_rhs = matrix_type::Zero(rbs-1, cbs + num_faces*fbs); + + gr_lhs = stiff.block(1, 1, rbs-1, rbs-1); + gr_rhs.block(0, 0, rbs-1, cbs) = stiff.block(1, 0, rbs-1, cbs); + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + auto fb = make_scalar_monomial_basis(msh, fc, facdeg); + + auto qps_f = integrate(msh, fc, recdeg - 1 + std::max(facdeg,celdeg)); + for (auto& qp : qps_f) + { + vector_type c_phi_tmp = cb.eval_functions(qp.point()); + vector_type c_phi = c_phi_tmp.head(cbs); + Matrix c_dphi_tmp = cb.eval_gradients(qp.point()); + Matrix c_dphi = c_dphi_tmp.block(1, 0, rbs-1, DIM); + vector_type f_phi = fb.eval_functions(qp.point()); + gr_rhs.block(0, cbs+i*fbs, rbs-1, fbs) += qp.weight() * (c_dphi * n) * f_phi.transpose(); + gr_rhs.block(0, 0, rbs-1, cbs) -= qp.weight() * (c_dphi * n) * c_phi.transpose(); + } + } + + auto vec_cell_size = gr_lhs.cols(); + auto nrows = gr_rhs.cols()+vec_cell_size; + auto ncols = gr_rhs.cols()+vec_cell_size; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(nrows,ncols); + data_mixed.block(0, vec_cell_size, vec_cell_size, ncols-vec_cell_size) = -gr_rhs; + data_mixed.block(vec_cell_size, 0, nrows-vec_cell_size, vec_cell_size) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + Matrix + mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function & rhs_fun, size_t di = 0) + { + const auto recdeg = m_hho_di.reconstruction_degree(); + const auto celdeg = m_hho_di.cell_degree(); + const auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension) - 1; + const auto cbs = disk::scalar_basis_size(celdeg, Mesh::dimension) + rbs; + auto cell_basis = make_scalar_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + + for (auto& qp : qps) + { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(rbs,0,cell_basis.size(),1) = ret_loc; + return ret; + } + + void load_material_data(const Mesh& msh){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + T rho = 1.0; + T vp = 1.0; + acoustic_material_data material(rho,vp); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, acoustic_material_data material){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, std::function(const typename Mesh::point_type& )> acoustic_mat_fun){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + std::vector mat_data = acoustic_mat_fun(bar); + T rho = mat_data[0]; + T vp = mat_data[1]; + acoustic_material_data material(rho,vp); + m_material.push_back(material); + } + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } + + void set_scaled_stabilization(){ + m_scaled_stabilization_Q = true; + } + + boundary_type & get_bc_conditions(){ + return m_bnd; + } + + std::vector< acoustic_material_data > & get_material_data(){ + return m_material; + } + + size_t get_n_face_dof(){ + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + size_t n_face_dof = (m_n_edges - m_n_essential_edges) * n_fbs; + return n_face_dof; + } + + size_t get_n_faces(){ + return m_n_edges - m_n_essential_edges; + } + + size_t get_face_basis_data(){ + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + return n_fbs; + } + + size_t get_cell_basis_data(){ + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + return n_cbs; + } + +}; + +#endif /* acoustic_two_fields_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/assembly_index.hpp b/apps/wave_propagation/src/common/assembly_index.hpp new file mode 100644 index 00000000..4da8c62d --- /dev/null +++ b/apps/wave_propagation/src/common/assembly_index.hpp @@ -0,0 +1,49 @@ +// +// assembly_index.hpp +// acoustics +// +// Created by Omar Durán on 5/6/20. +// + +#pragma once +#ifndef assembly_index_hpp +#define assembly_index_hpp + +#include + +class assembly_index +{ + size_t idx; + bool assem; + +public: + assembly_index(size_t i, bool as) + : idx(i), assem(as) + {} + + operator size_t() const + { + if (!assem) + throw std::logic_error("Invalid assembly_index"); + + return idx; + } + + bool assemble() const + { + return assem; + } + + size_t vidx() const + { + return idx; + } + + friend std::ostream& operator<<(std::ostream& os, const assembly_index& as) + { + os << "(" << as.idx << "," << as.assem << ")"; + return os; + } +}; + +#endif /* assembly_index_hpp */ diff --git a/apps/wave_propagation/src/common/assembly_index_bis.hpp b/apps/wave_propagation/src/common/assembly_index_bis.hpp new file mode 100644 index 00000000..6accf7c9 --- /dev/null +++ b/apps/wave_propagation/src/common/assembly_index_bis.hpp @@ -0,0 +1,44 @@ +// +// assembly_index.hpp +// acoustics +// +// Created by Omar Durán on 5/6/20. +// + +#pragma once +#ifndef assembly_index_hpp +#define assembly_index_hpp + +#include + +class assembly_index +{ + size_t idx; + bool assem; + +public: + assembly_index(size_t i, bool as) + : idx(i), assem(as) + {} + + operator size_t() const + { + if (!assem) + throw std::logic_error("Invalid assembly_index"); + + return idx; + } + + bool assemble() const + { + return assem; + } + + friend std::ostream& operator<<(std::ostream& os, const assembly_index& as) + { + os << "(" << as.idx << "," << as.assem << ")"; + return os; + } +}; + +#endif /* assembly_index_hpp */ diff --git a/apps/wave_propagation/src/common/deprecated/one_field_assembler.hpp b/apps/wave_propagation/src/common/deprecated/one_field_assembler.hpp new file mode 100644 index 00000000..7d041992 --- /dev/null +++ b/apps/wave_propagation/src/common/deprecated/one_field_assembler.hpp @@ -0,0 +1,260 @@ +// +// one_field_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/10/20. +// + +#pragma once +#ifndef one_field_assembler_hpp +#define one_field_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" + +template +class one_field_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + + class assembly_index + { + size_t idx; + bool assem; + + public: + assembly_index(size_t i, bool as) + : idx(i), assem(as) + {} + + operator size_t() const + { + if (!assem) + throw std::logic_error("Invalid assembly_index"); + + return idx; + } + + bool assemble() const + { + return assem; + } + + friend std::ostream& operator<<(std::ostream& os, const assembly_index& as) + { + os << "(" << as.idx << "," << as.assem << ")"; + return os; + } + }; + +public: + + SparseMatrix LHS; + Matrix RHS; + + one_field_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + else + RHS(asm_map[i]) -= lhs(i,j) * dirichlet_data(j); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(asm_map[i]) += rhs(i); + } + + } // + + void assemble(const Mesh& msh, std::function rhs_fun){ + + for (auto& cell : msh) + { + auto reconstruction_operator = make_scalar_hho_laplacian(msh, cell, m_hho_di); + Matrix R_operator = reconstruction_operator.second; + + + Matrix S_operator; + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_scalar_hho_stabilization(msh, cell, reconstruction_operator.first, m_hho_di); + S_operator = stabilization_operator; + }else{ + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di); + S_operator = stabilization_operator; + } + + Matrix laplacian_operator_loc = R_operator + S_operator; + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + + scatter_data(msh, cell, laplacian_operator_loc, f_loc); + } + finalize(); + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = disk::make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, fc, fb, m_hho_di.face_degree()); + auto velocity = m_bnd.dirichlet_boundary_func(face_id); + Matrix rhs = make_rhs(msh, fc, fb, velocity, m_hho_di.face_degree()); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } +}; + +#endif /* one_field_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/deprecated/one_field_vectorial_assembler.hpp b/apps/wave_propagation/src/common/deprecated/one_field_vectorial_assembler.hpp new file mode 100644 index 00000000..8aa34f73 --- /dev/null +++ b/apps/wave_propagation/src/common/deprecated/one_field_vectorial_assembler.hpp @@ -0,0 +1,263 @@ +// +// one_field_vectorial_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/11/20. +// + +#pragma once +#ifndef one_field_vectorial_assembler_hpp +#define one_field_vectorial_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" + +template +class one_field_vectorial_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + + class assembly_index + { + size_t idx; + bool assem; + + public: + assembly_index(size_t i, bool as) + : idx(i), assem(as) + {} + + operator size_t() const + { + if (!assem) + throw std::logic_error("Invalid assembly_index"); + + return idx; + } + + bool assemble() const + { + return assem; + } + + friend std::ostream& operator<<(std::ostream& os, const assembly_index& as) + { + os << "(" << as.idx << "," << as.assem << ")"; + return os; + } + }; + +public: + + SparseMatrix LHS; + Matrix RHS; + + one_field_vectorial_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + else + RHS(asm_map[i]) -= lhs(i,j) * dirichlet_data(j); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(asm_map[i]) += rhs(i); + } + + } // + + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun){ + + for (auto& cell : msh) + { + auto reconstruction_operator = make_matrix_symmetric_gradrec(msh, cell, m_hho_di); + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto divergence_operator = make_hho_divergence_reconstruction(msh, cell, m_hho_di); + + Matrix R_operator = reconstruction_operator.second; + + + Matrix S_operator; + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di); + S_operator = stabilization_operator; + }else{ + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di); + S_operator = stabilization_operator; + } + + Matrix vectorial_laplacian_operator_loc = 2.0*(R_operator + S_operator)+divergence_operator.second; + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + + scatter_data(msh, cell, vectorial_laplacian_operator_loc, f_loc); + } + finalize(); + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } +}; + +#endif /* one_field_vectorial_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/deprecated/three_fields_vectorial_assembler.hpp b/apps/wave_propagation/src/common/deprecated/three_fields_vectorial_assembler.hpp new file mode 100644 index 00000000..e8476aed --- /dev/null +++ b/apps/wave_propagation/src/common/deprecated/three_fields_vectorial_assembler.hpp @@ -0,0 +1,451 @@ +// +// three_fields_vectorial_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/12/20. +// + +#pragma once +#ifndef three_fields_vectorial_assembler_hpp +#define three_fields_vectorial_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" + +template +class three_fields_vectorial_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + + class assembly_index + { + size_t idx; + bool assem; + + public: + assembly_index(size_t i, bool as) + : idx(i), assem(as) + {} + + operator size_t() const + { + if (!assem) + throw std::logic_error("Invalid assembly_index"); + + return idx; + } + + bool assemble() const + { + return assem; + } + + friend std::ostream& operator<<(std::ostream& os, const assembly_index& as) + { + os << "(" << as.idx << "," << as.assem << ")"; + return os; + } + }; + +public: + + SparseMatrix LHS; + Matrix RHS; + + three_fields_vectorial_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + else + RHS(asm_map[i]) -= lhs(i,j) * dirichlet_data(j); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(asm_map[i]) += rhs(i); + } + + } + + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun){ + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + for (auto& cell : msh) + { + auto reconstruction_operator = strain_tensor_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + + // Weak hydrostatic component + auto divergence_operator = div_vector_reconstruction(msh, cell); + Matrix D_operator = divergence_operator.second; + + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + if(m_hho_stabilization_Q) + { + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + }else{ + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + + // For the sake of clarity ... + T lambda, mu; + lambda = 1.0; + mu = 1.0; + + R_operator.block(0, 0, n_ten_cbs, n_ten_cbs) *= (1.0/(2.0*mu)); + D_operator.block(0, 0, n_sca_cbs, n_sca_cbs) *= (1.0/(lambda)); + + Matrix mixed_elastic_hho_operator = R_operator + D_operator + 2.0*mu*S_operator; + Matrix f_loc = mixed_rhs(msh, cell, rhs_fun); + + scatter_data(msh, cell, mixed_elastic_hho_operator, f_loc); + } + finalize(); + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + Matrix x_el(n_vec_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_vec_cbs, 1) = x_glob.block(cell_ofs * n_cbs + n_ten_cbs + n_sca_cbs, 0, n_vec_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_vec_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_vec_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + std::pair< Matrix, + Matrix > + strain_tensor_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) + { + + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + + const size_t N = Mesh::dimension; + + auto graddeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, graddeg); + auto vec_b = make_vector_monomial_basis(msh, cell, celdeg); + + auto ten_bs = disk::sym_matrix_basis_size(graddeg, Mesh::dimension, Mesh::dimension); + auto sca_bs = disk::scalar_basis_size(facdeg, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + auto fbs = disk::vector_basis_size(facdeg, Mesh::dimension - 1, Mesh::dimension); + + auto num_faces = howmany_faces(msh, cell); + + matrix_type gr_lhs = matrix_type::Zero(ten_bs, ten_bs); + matrix_type gr_rhs = matrix_type::Zero(ten_bs, vec_bs + num_faces * fbs); + + const auto qps = integrate(msh, cell, 2 * graddeg); + + size_t dec = 0; + if (N == 3) + dec = 6; + else if (N == 2) + dec = 3; + else + std::logic_error("Expected 3 >= dim > 1"); + + for (auto& qp : qps) + { + const auto gphi = ten_b.eval_functions(qp.point()); + + for (size_t j = 0; j < ten_bs; j++) + { + + auto qp_gphi_j = disk::priv::inner_product(qp.weight(), gphi[j]); + for (size_t i = j; i < ten_bs; i += dec){ + gr_lhs(i, j) += disk::priv::inner_product(gphi[i], qp_gphi_j); + } + } + } + + // upper part + for (size_t j = 0; j < ten_bs; j++) + for (size_t i = 0; i < j; i++) + gr_lhs(i, j) = gr_lhs(j, i); + + // compute rhs + if (celdeg > 0) + { + const auto qpc = integrate(msh, cell, graddeg + celdeg - 1); + for (auto& qp : qpc) + { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto dphi = vec_b.eval_sgradients(qp.point()); + const auto qp_dphi = disk::priv::inner_product(qp.weight(), dphi); + + gr_rhs.block(0, 0, ten_bs, vec_bs) += disk::priv::outer_product(gphi, qp_dphi); + + } // end qp + } + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + const auto fb = make_vector_monomial_basis(msh, fc, facdeg); + + const auto qps_f = integrate(msh, fc, graddeg + std::max(celdeg, facdeg)); + for (auto& qp : qps_f) + { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto cphi = vec_b.eval_functions(qp.point()); + const auto fphi = fb.eval_functions(qp.point()); + + const auto qp_gphi_n = disk::priv::inner_product(gphi, disk::priv::inner_product(qp.weight(), n)); + gr_rhs.block(0, vec_bs + i * fbs, ten_bs, fbs) += disk::priv::outer_product(qp_gphi_n, fphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) -= disk::priv::outer_product(qp_gphi_n, cphi); + } + } + + auto n_rows = gr_rhs.cols() + ten_bs + sca_bs; + auto n_cols = gr_rhs.cols() + ten_bs + sca_bs; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(n_rows,n_cols); + data_mixed.block(0, 0, ten_bs, ten_bs) = gr_lhs; + data_mixed.block(0, (ten_bs + sca_bs), ten_bs, n_cols-(ten_bs + sca_bs)) = -gr_rhs; + data_mixed.block((ten_bs + sca_bs), 0, n_rows-(ten_bs + sca_bs), ten_bs) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + std::pair< Matrix, + Matrix > + div_vector_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) + { + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + + auto graddeg = m_hho_di.grad_degree(); + auto facedeg = m_hho_di.face_degree(); + auto ten_bs = disk::sym_matrix_basis_size(graddeg, Mesh::dimension, Mesh::dimension); + auto sca_bs = disk::scalar_basis_size(facedeg, Mesh::dimension); + + auto cbas_s = make_scalar_monomial_basis(msh, cell, m_hho_di.face_degree()); + auto dr_lhs = make_mass_matrix(msh, cell, cbas_s); + auto dr_rhs = make_hho_divergence_reconstruction_rhs(msh, cell, m_hho_di); + + assert( dr_lhs.rows() == sca_bs && dr_lhs.cols() == sca_bs ); + + // Shrinking data + auto n_rows = dr_rhs.cols() + ten_bs + sca_bs; + auto n_cols = dr_rhs.cols() + ten_bs + sca_bs; + matrix_type data_mixed = matrix_type::Zero(n_rows,n_cols); + data_mixed.block(ten_bs, ten_bs, sca_bs, sca_bs) = dr_lhs; + data_mixed.block(ten_bs, (ten_bs + sca_bs), sca_bs, n_cols-(ten_bs + sca_bs)) = -dr_rhs; + data_mixed.block((ten_bs + sca_bs), ten_bs, n_rows-(ten_bs + sca_bs), sca_bs) = dr_rhs.transpose(); + + matrix_type oper = dr_lhs.ldlt().solve(dr_rhs); + return std::make_pair(oper, data_mixed); + } + + Matrix + mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function(const typename Mesh::point_type& )> rhs_fun, size_t di = 0) + { + auto recdeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_bs = disk::sym_matrix_basis_size(recdeg, Mesh::dimension, Mesh::dimension); + auto sca_bs = disk::scalar_basis_size(facdeg, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + size_t n_cbs = ten_bs + sca_bs + vec_bs; + auto cell_basis = make_vector_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(n_cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + + for (auto& qp : qps) + { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(ten_bs + sca_bs,0,vec_bs,1) = ret_loc; + return ret; + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } +}; + +#endif /* three_fields_vectorial_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/deprecated/two_fields_assembler.hpp b/apps/wave_propagation/src/common/deprecated/two_fields_assembler.hpp new file mode 100644 index 00000000..2e16c089 --- /dev/null +++ b/apps/wave_propagation/src/common/deprecated/two_fields_assembler.hpp @@ -0,0 +1,355 @@ +// +// two_fields_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/10/20. +// + +#ifndef two_fields_assembler_hpp +#define two_fields_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" + +template +class two_fields_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + + class assembly_index + { + size_t idx; + bool assem; + + public: + assembly_index(size_t i, bool as) + : idx(i), assem(as) + {} + + operator size_t() const + { + if (!assem) + throw std::logic_error("Invalid assembly_index"); + + return idx; + } + + bool assemble() const + { + return assem; + } + + friend std::ostream& operator<<(std::ostream& os, const assembly_index& as) + { + os << "(" << as.idx << "," << as.assem << ")"; + return os; + } + }; + +public: + + SparseMatrix LHS; + Matrix RHS; + + two_fields_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + else + RHS(asm_map[i]) -= lhs(i,j) * dirichlet_data(j); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(asm_map[i]) += rhs(i); + } + + } + + void assemble(const Mesh& msh, std::function rhs_fun){ + + for (auto& cell : msh) + { + auto reconstruction_operator = mixed_scalar_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_scalar_hho_stabilization(msh, cell, reconstruction_operator.first, m_hho_di); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + }else{ + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + + Matrix mixed_operator_loc = R_operator + S_operator; + Matrix f_loc = mixed_rhs(msh, cell, rhs_fun); + + scatter_data(msh, cell, mixed_operator_loc, f_loc); + } + finalize(); + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = disk::make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, fc, fb, m_hho_di.face_degree()); + auto velocity = m_bnd.dirichlet_boundary_func(face_id); + Matrix rhs = make_rhs(msh, fc, fb, velocity, m_hho_di.face_degree()); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + std::pair< Matrix, + Matrix > + mixed_scalar_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) + { + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + typedef Matrix vector_type; + + const size_t DIM = Mesh::dimension; + + const auto recdeg = m_hho_di.reconstruction_degree(); + const auto celdeg = m_hho_di.cell_degree(); + const auto facdeg = m_hho_di.face_degree(); + + auto cb = make_scalar_monomial_basis(msh, cell, recdeg); + + const auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + const auto cbs = disk::scalar_basis_size(celdeg, Mesh::dimension); + const auto fbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + const auto num_faces = howmany_faces(msh, cell); + + const matrix_type stiff = make_stiffness_matrix(msh, cell, cb); + matrix_type gr_lhs = matrix_type::Zero(rbs-1, rbs-1); + matrix_type gr_rhs = matrix_type::Zero(rbs-1, cbs + num_faces*fbs); + + gr_lhs = stiff.block(1, 1, rbs-1, rbs-1); + gr_rhs.block(0, 0, rbs-1, cbs) = stiff.block(1, 0, rbs-1, cbs); + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + auto fb = make_scalar_monomial_basis(msh, fc, facdeg); + + auto qps_f = integrate(msh, fc, recdeg - 1 + std::max(facdeg,celdeg)); + for (auto& qp : qps_f) + { + vector_type c_phi_tmp = cb.eval_functions(qp.point()); + vector_type c_phi = c_phi_tmp.head(cbs); + Matrix c_dphi_tmp = cb.eval_gradients(qp.point()); + Matrix c_dphi = c_dphi_tmp.block(1, 0, rbs-1, DIM); + vector_type f_phi = fb.eval_functions(qp.point()); + gr_rhs.block(0, cbs+i*fbs, rbs-1, fbs) += qp.weight() * (c_dphi * n) * f_phi.transpose(); + gr_rhs.block(0, 0, rbs-1, cbs) -= qp.weight() * (c_dphi * n) * c_phi.transpose(); + } + } + + auto vec_cell_size = gr_lhs.cols(); + auto nrows = gr_rhs.cols()+vec_cell_size; + auto ncols = gr_rhs.cols()+vec_cell_size; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(nrows,ncols); + data_mixed.block(0, 0, vec_cell_size, vec_cell_size) = gr_lhs; + data_mixed.block(0, vec_cell_size, vec_cell_size, ncols-vec_cell_size) = -gr_rhs; + data_mixed.block(vec_cell_size, 0, nrows-vec_cell_size, vec_cell_size) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + Matrix + mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function rhs_fun, size_t di = 0) + { + const auto recdeg = m_hho_di.reconstruction_degree(); + const auto celdeg = m_hho_di.cell_degree(); + const auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension) - 1; + const auto cbs = disk::scalar_basis_size(celdeg, Mesh::dimension) + rbs; + auto cell_basis = make_scalar_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + + for (auto& qp : qps) + { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(rbs,0,cell_basis.size(),1) = ret_loc; + return ret; + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } +}; + +#endif /* two_fields_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/dirk_butcher_tableau.hpp b/apps/wave_propagation/src/common/dirk_butcher_tableau.hpp new file mode 100644 index 00000000..fae49b61 --- /dev/null +++ b/apps/wave_propagation/src/common/dirk_butcher_tableau.hpp @@ -0,0 +1,204 @@ +// +// dirk_butcher_tableau.hpp +// acoustics +// +// Created by Omar Durán on 4/21/20. +// + +#pragma once +#ifndef dirk_butcher_tableau_hpp +#define dirk_butcher_tableau_hpp + +#include + +class dirk_butcher_tableau +{ + public: + + static void dirk_tables(int s, Matrix &a, Matrix &b, Matrix &c){ + + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, 1); + c = Matrix::Zero(s, 1); + + switch (s) { // Implicit midpoint DIRK(1, 2) or SDIRK(1, 2) + case 1: + { + a(0,0) = 0.5; + b(0,0) = 1.0; + c(0,0) = 0.5; + } + break; + case 2: + { + // https://www.jstor.org/stable/pdf/43692558.pdf?refreqid=excelsior%3A6b91257ea1427dcb8b00a78353c96ef4 + // Construction Of High-order symplectic Runge-Kutta Methods + // SDIRK(2, 2) + a(0,0) = 0.25; + a(1,0) = 0.5; + a(1,1) = 0.25; + + b(0,0) = 0.5; + b(1,0) = 0.5; + + c(0,0) = 1.0/4.0; + c(1,0) = 3.0/4.0; + + } + break; + case 3: + { +// // DIRK(3, 4) + a(0,0) = 0.956262348020; + a(1,0) = -0.676995728936; + a(1,1) = 1.092920059741; + a(2,0) = 4.171447220367; + a(2,1) = -5.550750999686; + a(2,2) = 1.189651889660; + + b(0,0) = 0.228230955547; + b(1,0) = 0.706961029433; + b(2,0) = 0.064808015020; + + c(0,0) = 0.956262348020; + c(1,0) = 0.415924330804; + c(2,0) = -0.189651889660; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + + static void odirk_tables(int s, Matrix &a, Matrix &b, Matrix &c){ + + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, 1); + c = Matrix::Zero(s, 1); + + // Optimized diagonally implicit Runge-Kutta schemes for time-dependent wave propagation problems + switch (s) { + case 1: + { + a(0,0) = 0.5; + b(0,0) = 1.0; + c(0,0) = 0.5; + } + break; + case 2: + { + a(0,0) = 0.780078125000; + a(1,0) = -0.595072059507; + a(1,1) = 0.797536029754; + + b(0,0) = 0.515112081837; + b(1,0) = 0.484887918163; + + c(0,0) = 0.780078125; + c(1,0) = 0.202463970246; + + + + } + break; + case 3: + { + + a(0,0) = 0.956262348020; + a(1,0) = -0.676995728936; + a(1,1) = 1.092920059741; + a(2,0) = 4.171447220367; + a(2,1) = -5.550750999686; + a(2,2) = 1.189651889660; + + b(0,0) = 0.228230955547; + b(1,0) = 0.706961029433; + b(2,0) = 0.064808015020; + + c(0,0) = 0.956262348020; + c(1,0) = 0.415924330804; + c(2,0) = -0.189651889660; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + + static void sdirk_tables(int s, Matrix &a, Matrix &b, Matrix &c){ + + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, 1); + c = Matrix::Zero(s, 1); + + // A−stable SDIRK method + switch (s) { // Implicit midpoint (1, 2) + case 1: + { + a(0,0) = 0.5; + b(0,0) = 1.0; + c(0,0) = 0.5; + } + break; + case 2: + { + // The only 2-stages A-stable SDIRK scheme of order 3 has been given by Crouzeix + // Crouzeix/LDD-A2(2, 3) + double gamma = 1.0/std::sqrt(3.0); + a(0,0) = 0.5 + 0.5*gamma; + a(1,0) = -1.0*gamma; + a(1,1) = 0.5 + 0.5*gamma; + + b(0,0) = 0.5; + b(1,0) = 0.5; + + c(0,0) = 0.5 + 0.5*gamma; + c(1,0) = 0.5 - 0.5*gamma; + + } + break; + case 3: + { + + // Crouzeix & Raviart (3, 4) + double gamma = (1.0/std::sqrt(3.0))*std::cos(M_PI/18.0)+0.5; + double delta = 1.0/(6.0*(2.0*gamma-1.0)*(2.0*gamma-1.0)); + a(0,0) = gamma; + a(1,0) = (1.0/2.0)-gamma; + a(1,1) = gamma; + a(2,0) = 2.0*gamma; + a(2,1) = 1.0-4.0*gamma; + a(2,2) = gamma; + + b(0,0) = delta; + b(1,0) = 1.0-2.0*delta; + b(2,0) = delta; + + c(0,0) = gamma; + c(1,0) = 1.0/2.0; + c(2,0) = 1.0-gamma; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + +}; + +#endif /* dirk_butcher_tableau_hpp */ diff --git a/apps/wave_propagation/src/common/dirk_hho_scheme.hpp b/apps/wave_propagation/src/common/dirk_hho_scheme.hpp new file mode 100644 index 00000000..584ba62e --- /dev/null +++ b/apps/wave_propagation/src/common/dirk_hho_scheme.hpp @@ -0,0 +1,132 @@ +// +// dirk_hho_scheme.hpp +// acoustics +// +// Created by Omar Durán on 4/21/20. +// + +#ifndef dirk_hho_scheme_hpp +#define dirk_hho_scheme_hpp + +#include +#include +#include +#include "../common/linear_solver.hpp" + +template +class dirk_hho_scheme { + + private: + + T m_scale; + SparseMatrix m_Mg; + SparseMatrix m_Kg; + Matrix m_Fg; + linear_solver m_analysis; + std::vector> m_cell_basis_data; + size_t m_n_f_dof; + bool m_global_sc_Q; + bool m_iteraive_solver_Q; + + public: + + dirk_hho_scheme(SparseMatrix & Kg, Matrix & Fg, SparseMatrix & Mg){ + + m_Mg = Mg; + m_Kg = Kg; + m_Fg = Fg; + m_scale = 0.0; + m_global_sc_Q = false; + m_iteraive_solver_Q = false; + } + + dirk_hho_scheme(SparseMatrix & Kg, Matrix & Fg, SparseMatrix & Mg, T scale){ + m_Mg = Mg; + m_Kg = Kg; + m_Fg = Fg; + m_scale = scale; + m_global_sc_Q = false; + m_iteraive_solver_Q = false; + } + + void set_static_condensation_data(std::pair cell_basis_data, size_t n_f_dof){ + std::vector> vec_cell_basis_data(1); + vec_cell_basis_data[0] = cell_basis_data; + m_cell_basis_data = vec_cell_basis_data; + m_n_f_dof = n_f_dof; + m_global_sc_Q = true; + } + + void set_static_condensation_data(std::vector> cell_basis_data, size_t n_f_dof){ + m_cell_basis_data = cell_basis_data; + m_n_f_dof = n_f_dof; + m_global_sc_Q = true; + } + + void condense_equations() { + SparseMatrix K = m_Mg + m_scale * m_Kg; + m_analysis.set_Kg(K,m_n_f_dof); + m_analysis.condense_equations(m_cell_basis_data); + } + + void ComposeMatrix() { + if(m_global_sc_Q) + condense_equations(); + else{ + SparseMatrix K = m_Mg + m_scale * m_Kg; + m_analysis.set_Kg(K); + } + } + + void setIterativeSolver() { + m_iteraive_solver_Q = true; + m_analysis.set_iterative_solver(false, 1.0e-1); + } + + void DecomposeMatrix() { + m_analysis.factorize(); + } + + linear_solver & DirkAnalysis() { + return m_analysis; + } + + SparseMatrix & Mg(){ + return m_Mg; + } + + SparseMatrix & Kg(){ + return m_Kg; + } + + Matrix & Fg(){ + return m_Fg; + } + + void SetScale(T & scale){ + m_scale = scale; + } + + void SetFg(Matrix & Fg) { + m_Fg = Fg; + } + + void irk_weight(Matrix & y, Matrix & k, T dt, T a, bool is_sdirk_Q){ + + m_Fg -= Kg()*y; + if (is_sdirk_Q) + k = DirkAnalysis().solve(m_Fg); + else { + T scale = a * dt; + SetScale(scale); + ComposeMatrix(); + if (m_iteraive_solver_Q) + DirkAnalysis().set_iterative_solver(); + DecomposeMatrix(); + k = DirkAnalysis().solve(m_Fg); + } + } + +}; + +#endif /* dirk_hho_scheme_hpp */ diff --git a/apps/wave_propagation/src/common/display_settings.hpp b/apps/wave_propagation/src/common/display_settings.hpp new file mode 100644 index 00000000..b7098676 --- /dev/null +++ b/apps/wave_propagation/src/common/display_settings.hpp @@ -0,0 +1,28 @@ +// +// display_settings.cpp +// acoustics +// +// Created by Omar Durán on 4/8/20. +// + +#include + +std::ostream& bold(std::ostream& os) { os << "\x1b[1m"; return os; } +std::ostream& nobold(std::ostream& os) { os << "\x1b[21m"; return os; } + +std::ostream& underline(std::ostream& os) { os << "\x1b[4m"; return os; } +std::ostream& nounderline(std::ostream& os) { os << "\x1b[24m"; return os; } + +std::ostream& blink(std::ostream& os) { os << "\x1b[5m"; return os; } +std::ostream& noblink(std::ostream& os) { os << "\x1b[25m"; return os; } + +std::ostream& reset(std::ostream& os) { os << "\x1b[0m"; return os; } +std::ostream& erase_line(std::ostream& os) { os << "\x1b[0K"; return os; } + +std::ostream& red(std::ostream& os) { os << "\x1b[31m"; return os; } +std::ostream& green(std::ostream& os) { os << "\x1b[32m"; return os; } +std::ostream& yellow(std::ostream& os) { os << "\x1b[33m"; return os; } +std::ostream& blue(std::ostream& os) { os << "\x1b[34m"; return os; } +std::ostream& magenta(std::ostream& os) { os << "\x1b[35m"; return os; } +std::ostream& cyan(std::ostream& os) { os << "\x1b[36m"; return os; } +std::ostream& nocolor(std::ostream& os) { os << "\x1b[39m"; return os; } diff --git a/apps/wave_propagation/src/common/elastic_material_data.hpp b/apps/wave_propagation/src/common/elastic_material_data.hpp new file mode 100644 index 00000000..8d97a26b --- /dev/null +++ b/apps/wave_propagation/src/common/elastic_material_data.hpp @@ -0,0 +1,107 @@ +// +// elastic_material_data.hpp +// acoustics +// +// Created by Omar Durán on 4/14/20. +// + +#ifndef elastic_material_data_hpp +#define elastic_material_data_hpp + +#include + +template +class elastic_material_data { + + /// Fluid density + T m_rho; + + /// Compressional P-wave velocity + T m_vp; + + /// Shear S-wave velocity + T m_vs; + +public: + + /// Default constructor + elastic_material_data(T rho, T vp, T vs){ + m_rho = rho; + m_vp = vp; + m_vs = vs; + } + + /// Copy constructor + elastic_material_data(const elastic_material_data & other){ + m_rho = other.m_rho; + m_vp = other.m_vp; + m_vs = other.m_vs; + } + + /// Assignement constructor + const elastic_material_data & operator=(const elastic_material_data & other){ + + // check for self-assignment + if(&other == this){ + return *this; + } + + m_rho = other.m_rho; + m_vp = other.m_vp; + m_vs = other.m_vs; + return *this; + + } + + /// Desconstructor + virtual ~elastic_material_data(){ + + } + + /// Print class attributes + virtual void Print(std::ostream &out = std::cout) const{ + out << "\n density = " << m_rho; + out << "\n p-wave velocity = " << m_vp; + out << "\n s-wave velocity = " << m_vs; + } + + /// Print class attributes + friend std::ostream & operator<<( std::ostream& out, const elastic_material_data & material ){ + material.Print(out); + return out; + } + + void Set_rho(T rho) + { + m_rho = rho; + } + + T rho() + { + return m_rho; + } + + + void Set_vp(T vp) + { + m_vp = vp; + } + + T vp() + { + return m_vp; + } + + void Set_vs(T vs) + { + m_vs = vs; + } + + T vs() + { + return m_vs; + } + +}; + +#endif /* elastic_material_data_hpp */ diff --git a/apps/wave_propagation/src/common/elastoacoustic_four_fields_assembler.hpp b/apps/wave_propagation/src/common/elastoacoustic_four_fields_assembler.hpp new file mode 100644 index 00000000..e397c8fd --- /dev/null +++ b/apps/wave_propagation/src/common/elastoacoustic_four_fields_assembler.hpp @@ -0,0 +1,1683 @@ +// +// elastoacoustic_four_fields_assembler.hpp +// acoustics +// +// Created by Omar Durán on 9/7/20. +// Contributor: Romain Mottier + + +#pragma once +#ifndef elastoacoustic_four_fields_assembler_hpp +#define elastoacoustic_four_fields_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/acoustic_material_data.hpp" +#include "../common/elastic_material_data.hpp" +#include + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class elastoacoustic_four_fields_assembler { + + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_e_compress_indexes; + std::vector m_e_expand_indexes; + + std::vector m_a_compress_indexes; + std::vector m_a_expand_indexes; + + disk::hho_degree_info m_hho_di; + e_boundary_type m_e_bnd; + a_boundary_type m_a_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_triplets_stab; + std::vector< Triplet > m_c_triplets; + std::vector< Triplet > m_mass_triplets; + std::map> m_e_material; + std::map> m_a_material; + std::map m_e_cell_index; + std::map m_a_cell_index; + std::vector< size_t > m_e_elements_with_bc_eges; + std::vector< size_t > m_a_elements_with_bc_eges; + std::map> m_interface_cell_indexes; + + size_t m_n_elastic_cells; + size_t m_n_acoustic_cells; + + size_t n_e_edges; + size_t n_a_edges; + + size_t m_n_edges; + size_t m_n_essential_edges; + size_t m_n_elastic_cell_dof; + size_t m_n_acoustic_cell_dof; + size_t m_n_elastic_face_dof; + size_t m_n_acoustic_face_dof; + bool m_hho_stabilization_Q; + bool m_scaled_stabilization_Q; + +public: + + SparseMatrix LHS; + SparseMatrix LHS_STAB; + Matrix RHS; + SparseMatrix MASS; + SparseMatrix P; + SparseMatrix IminusP; + SparseMatrix COUPLING; + + + // Identification of Dirichlet faces; Construction of compressed face index maps; Computation of dofs counts; + // Initialization of global matrices and RHS; Setup of cell classification and local-to-global mapping structures. + elastoacoustic_four_fields_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const e_boundary_type& e_bnd, const a_boundary_type& a_bnd, std::map> & e_material, std::map> & a_material) : m_hho_di(hho_di), m_e_bnd(e_bnd), m_a_bnd(a_bnd), m_e_material(e_material), m_a_material(a_material), m_hho_stabilization_Q(true), m_scaled_stabilization_Q(false) { + + auto storage = msh.backend_storage(); + auto is_e_dirichlet = [&](const typename Mesh::face& fc) -> bool { + auto fc_id = msh.lookup(fc); + return e_bnd.is_dirichlet_face(fc_id); + }; + + auto is_a_dirichlet = [&](const typename Mesh::face& fc) -> bool { + auto fc_id = msh.lookup(fc); + return a_bnd.is_dirichlet_face(fc_id); + }; + + size_t n_e_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_e_dirichlet); + size_t n_a_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_a_dirichlet); + + std::set e_egdes; + for (auto &chunk : m_e_material) { + size_t cell_i = chunk.first; + auto& cell = storage->surfaces[cell_i]; + auto cell_faces = faces(msh,cell); + for (auto &face : cell_faces) { + if (!is_e_dirichlet(face)) { + auto fc_id = msh.lookup(face); + e_egdes.insert(fc_id); + } + } + } + n_e_edges = e_egdes.size(); + std::set a_egdes; + for (auto &chunk : m_a_material) { + size_t cell_i = chunk.first; + auto& cell = storage->surfaces[cell_i]; + auto cell_faces = faces(msh,cell); + for (auto &face : cell_faces) { + if (!is_a_dirichlet(face)) { + auto fc_id = msh.lookup(face); + a_egdes.insert(fc_id); + } + } + } + n_a_edges = a_egdes.size(); + + m_n_edges = msh.faces_size(); + m_n_essential_edges = n_e_essential_edges + n_a_essential_edges; + + m_e_compress_indexes.resize( m_n_edges ); + m_e_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + m_a_compress_indexes.resize( m_n_edges ); + m_a_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t e_compressed_offset = 0; + for (auto face_id : e_egdes) { + m_e_compress_indexes.at(face_id) = e_compressed_offset; + m_e_expand_indexes.at(e_compressed_offset) = face_id; + e_compressed_offset++; + } + size_t a_compressed_offset = 0; + for (auto face_id : a_egdes) { + m_a_compress_indexes.at(face_id) = a_compressed_offset; + m_a_expand_indexes.at(a_compressed_offset) = face_id; + a_compressed_offset++; + } + + size_t n_cbs = get_e_cell_basis_data(); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t n_s_cbs = get_a_cell_basis_data(); + size_t n_s_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + m_n_elastic_cell_dof = (n_cbs * m_e_material.size()); + m_n_acoustic_cell_dof = (n_s_cbs * m_a_material.size()); + + m_n_elastic_face_dof = (n_fbs * n_e_edges); + m_n_acoustic_face_dof = (n_s_fbs * n_a_edges); + size_t system_size = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_n_acoustic_face_dof; + + LHS = SparseMatrix( system_size, system_size ); + LHS_STAB = SparseMatrix( system_size, system_size ); //OPTIONAL + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + COUPLING = SparseMatrix( system_size, system_size ); + P = SparseMatrix( system_size, system_size ); + IminusP = SparseMatrix( m_n_elastic_cell_dof + m_n_acoustic_cell_dof, m_n_elastic_cell_dof + m_n_acoustic_cell_dof ); + + classify_cells(msh); + build_cells_maps(); + } + + // Elastic cell– and face–dofs mapping; construction of assembly indices with Dirichlet filtering; Computation of global offsets for elastic unknowns; + // Insertion of local matrix entries into global triplets; Insertion of local RHS contributions into the global vector. + void scatter_e_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& lhs, const Matrix& rhs) { + + auto fcs = faces(msh, cl); + size_t n_cbs = get_e_cell_basis_data(); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + } + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + bool dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < n_fbs; i++) { + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + } + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + for (size_t i = 0; i < lhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + for (size_t j = 0; j < lhs.cols(); j++) { + if ( asm_map[j].assemble() ) { + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + } + + for (size_t i = 0; i < rhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + RHS(asm_map[i].vidx()) += rhs(i); + } + } + + // Acoustic cell– and face–dofs mapping; Construction of assembly indices with Dirichlet filtering; Computation of global offsets for acoustic unknowns; + // Insertion of local matrix entries into global triplets; Insertion of local RHS contributions into the global vector. + void scatter_a_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& lhs, const Matrix& rhs) { + + auto fcs = faces(msh, cl); + size_t n_cbs = get_a_cell_basis_data(); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + } + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + bool dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < n_fbs; i++) { + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + } + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + for (size_t i = 0; i < lhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + for (size_t j = 0; j < lhs.cols(); j++) { + if (asm_map[j].assemble()) { + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + } + + for (size_t i = 0; i < rhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + RHS(asm_map[i].vidx()) += rhs(i); + } + + } + + // Elastic cell–DoF mapping; Construction of assembly indices; Computation of global offsets for elastic cell unknowns; + // Insertion of local mass-matrix entries into global mass triplets. + void scatter_e_mass_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& mass_matrix) { + + size_t n_cbs = get_e_cell_basis_data(); + std::vector asm_map; + asm_map.reserve(n_cbs); + auto cell_LHS_offset = e_cell_ind * n_cbs; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back(assembly_index(cell_LHS_offset+i, true)); + } + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + for (size_t i = 0; i < mass_matrix.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + for (size_t j = 0; j < mass_matrix.cols(); j++) { + if (asm_map[j].assemble()) { + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + } + } + + // Acoustic cell–DoF mapping; Construction of assembly indices; Computation of global offsets for acoustic cell unknowns; + // Insertion of local mass-matrix entries into global mass triplets. + void scatter_a_mass_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& mass_matrix) { + + size_t n_cbs = get_a_cell_basis_data(); + std::vector asm_map; + asm_map.reserve(n_cbs); + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back(assembly_index(cell_LHS_offset+i, true)); + } + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + for (size_t i = 0; i < mass_matrix.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + for (size_t j = 0; j < mass_matrix.cols(); j++) { + if (asm_map[j].assemble()) { + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + } + } + + // Assembly of global mass matrix; local elastic and acoustic cell mass matrix computation; + // Scattering of elastic and acoustic mass contributions into global triplets; Finalization of mass assembly. + void assemble_mass(const Mesh& msh, bool add_vector_mass_Q = true) { + + auto storage = msh.backend_storage(); + MASS.setZero(); + + // elastic block + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + elastic_material_data material = e_chunk.second; + Matrix mass_matrix = e_mass_operator(material, msh, cell, add_vector_mass_Q); + scatter_e_mass_data(e_cell_ind,msh, cell, mass_matrix); + } + + // acoustic block + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + acoustic_material_data material = a_chunk.second; + Matrix mass_matrix = a_mass_operator(material, msh, cell); + scatter_a_mass_data(a_cell_ind, msh, cell, mass_matrix); + } + + finalize_mass(); + } + + // Elastic cell–DoF mapping; Construction of assembly indices; Computation of global offsets for elastic cell unknowns; + // Insertion of local RHS contributions into the global vector. + void scatter_e_rhs_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& rhs) { + + size_t n_cbs = get_e_cell_basis_data(); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + } + + assert( asm_map.size() == rhs.rows() ); + for (size_t i = 0; i < rhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + RHS(asm_map[i].vidx()) += rhs(i); + } + } + + // Acoustic cell–DoF mapping; Construction of assembly indices; Computation of global offsets for acoustic cell unknowns; + // Insertion of local RHS contributions into the global vector. + void scatter_a_rhs_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& rhs) { + + size_t n_cbs = get_a_cell_basis_data(); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + } + + assert( asm_map.size() == rhs.rows()); + for (size_t i = 0; i < rhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + RHS(asm_map[i].vidx()) += rhs(i); + } + } + + // Elastic Dirichlet face identification; Construction of assembly indices for cell and face DoFs; + // Computation of Dirichlet face contributions via local mass matrices; Insertion of bc into the global RHS using local-to-global mapping. + void scatter_e_bc_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& lhs) { + + auto fcs = faces(msh, cl); + size_t n_cbs = get_e_cell_basis_data(); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + } + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + bool dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < n_fbs; i++) { + asm_map.push_back(assembly_index(face_LHS_offset+i, !dirichlet) ); + } + if (dirichlet) { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_e_bnd.dirichlet_boundary_func(fc_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + } + + assert(asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + for (size_t i = 0; i < lhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + for (size_t j = 0; j < lhs.cols(); j++) { + if (!asm_map[j].assemble() ) { + RHS(asm_map[i].vidx()) -= lhs(i,j) * dirichlet_data(j); + } + } + } + } + + // Acoustic Dirichlet face identification; construction of assembly indices for cell and face DoFs; + // Computation of Dirichlet face contributions via local mass matrices; Insertion of bc into the global RHS using local-to-global mapping. + void scatter_a_bc_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& lhs) { + + auto fcs = faces(msh, cl); + size_t n_cbs = get_a_cell_basis_data(); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + for (size_t i = 0; i < n_cbs; i++) { + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + } + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + bool dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < n_fbs; i++) { + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + } + if (dirichlet) { + auto fb = make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_a_bnd.dirichlet_boundary_func(fc_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + for (size_t i = 0; i < lhs.rows(); i++) { + if (!asm_map[i].assemble()) { + continue; + } + for (size_t j = 0; j < lhs.cols(); j++) { + if (!asm_map[j].assemble()) { + RHS(asm_map[i].vidx()) -= lhs(i,j) * dirichlet_data(j); + } + } + } + } + + // Application of boundary conditions; local elastic and acoustic cell operator computation for cells with boundary faces; + // Scattering of Dirichlet contributions into the global RHS; + void apply_bc(const Mesh& msh, bool explicit_scheme){ + + #ifdef HAVE_INTEL_TBB2 + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, laplacian_operator_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto& cell_ind : m_e_elements_with_bc_eges) { + auto& cell = storage->surfaces[cell_ind]; + size_t e_cell_ind = m_e_cell_index[cell_ind]; + elastic_material_data e_mat = m_e_material.find(cell_ind)->second; + Matrix mixed_operator_loc = e_mixed_operator(e_mat,msh,cell,explicit_scheme); + scatter_e_bc_data(e_cell_ind, msh, cell, mixed_operator_loc); + } + + for (auto& cell_ind : m_a_elements_with_bc_eges) { + auto& cell = storage->surfaces[cell_ind]; + size_t a_cell_ind = m_a_cell_index[cell_ind]; + acoustic_material_data a_mat = m_a_material.find(cell_ind)->second; + Matrix mixed_operator_loc = a_mixed_operator(a_mat, msh, cell, explicit_scheme); + scatter_a_bc_data(a_cell_ind, msh, cell, mixed_operator_loc); + } + + #endif + + } + + // Assembly of global RHS vector; Local elastic and acoustic cell RHS computation; + // Scattering of local RHS contributions into the global vector; Application of boundary condition corrections. + void assemble_rhs(const Mesh& msh, std::function(const typename Mesh::point_type& )> e_rhs_fun, std::function a_rhs_fun, bool explicit_scheme) { + + RHS.setZero(); + auto storage = msh.backend_storage(); + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + Matrix f_loc = e_mixed_rhs(msh, cell, e_rhs_fun); + scatter_e_rhs_data(e_cell_ind, msh, cell, f_loc); + } + + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + Matrix f_loc = a_mixed_rhs(msh, cell, a_rhs_fun); + scatter_a_rhs_data(a_cell_ind, msh, cell, f_loc); + } + apply_bc(msh, explicit_scheme); + } + + // Assembly of acoustic and elastic part separately; + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type& )> e_rhs_fun, std::function a_rhs_fun, bool explicit_scheme) { + + auto storage = msh.backend_storage(); + LHS.setZero(); + RHS.setZero(); + + // Elastic block + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + Matrix mixed_operator_loc = e_mixed_operator(e_chunk.second, msh, cell, explicit_scheme); + Matrix f_loc = e_mixed_rhs(msh, cell, e_rhs_fun); + scatter_e_data(e_cell_ind, msh, cell, mixed_operator_loc, f_loc); + } + + // Acoustic block + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + Matrix mixed_operator_loc = a_mixed_operator(a_chunk.second, msh, cell, explicit_scheme); + Matrix f_loc = a_mixed_rhs(msh, cell, a_rhs_fun); + scatter_a_data(a_cell_ind, msh, cell, mixed_operator_loc, f_loc); + } + + finalize(); + + } + + // Elasto–acoustic interface face identification; Construction of Interface matrix. + void scatter_ea_interface_data(const Mesh& msh, const typename Mesh::face_type& face, const Matrix& interface_matrix) { + + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + auto sfbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + std::vector asm_map_e, asm_map_a; + asm_map_e.reserve(vfbs); + asm_map_a.reserve(sfbs); + auto fc_id = msh.lookup(face); + + auto e_face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*vfbs; + bool e_dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < vfbs; i++){ + asm_map_e.push_back( assembly_index(e_face_LHS_offset+i, !e_dirichlet) ); + } + + auto a_face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*sfbs; + bool a_dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < sfbs; i++){ + asm_map_a.push_back( assembly_index(a_face_LHS_offset+i, !a_dirichlet) ); + } + + assert( asm_map_e.size() == interface_matrix.rows() && asm_map_a.size() == interface_matrix.cols() ); + for (size_t i = 0; i < interface_matrix.rows(); i++) { + for (size_t j = 0; j < interface_matrix.cols(); j++) { + m_c_triplets.push_back( Triplet(asm_map_e[i].vidx(), asm_map_a[j].vidx(), interface_matrix(i,j)) ); + m_c_triplets.push_back( Triplet(asm_map_a[j].vidx(), asm_map_e[i].vidx(), - interface_matrix(i,j)) ); + } + } + + } + + // Assembly of global coupling matrix; Local elasto–acoustic interface operator computation for each interface face; + // Scattering of interface contributions into global coupling triplets; finalization of coupling assembly. + void assemble_coupling_terms(const Mesh& msh){ + + auto storage = msh.backend_storage(); + COUPLING.setZero(); + + // coupling blocks + for (auto chunk : m_interface_cell_indexes) { + auto& face = storage->edges[chunk.first]; + auto& e_cell = storage->surfaces[chunk.second.first]; + auto& a_cell = storage->surfaces[chunk.second.second]; + Matrix interface_operator_loc = e_interface_operator(msh, face, e_cell, a_cell); + scatter_ea_interface_data(msh, face, interface_operator_loc); + } + + finalize_coupling(); + } + + // Computation of local elastic mixed operator; Strain reconstruction & Stabilization operator; + Matrix e_mixed_operator(elastic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell, bool explicit_scheme) { + + T rho = material.rho(); + T vp = material.vp(); + T vs = material.vs(); + T mu = rho * vs * vs; + T lambda = rho * vp * vp - 2*mu; + + auto reconstruction_operator = strain_tensor_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + + if (explicit_scheme) { + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di, false, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + else { + if(m_hho_stabilization_Q) { + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + else { + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di, false, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + } + + // COEF SPECTRAL RADIUS + T equal_order_eta = 1.50; + T mixed_order_eta = 0.95; + + T coef = 1.0; + T eta = coef * equal_order_eta; + + return R_operator + eta*(rho*vs)*S_operator; + } + + // Computation of local symmetric tensor mass matrix; + Matrix + symmetric_tensor_mass_matrix(const Mesh& msh, const typename Mesh::cell_type& cell) { + + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + Matrix mass_matrix = Matrix::Zero(ten_bs, ten_bs); + + auto qps = integrate(msh, cell, 2 * gradeg); + // number of tensor components + size_t dec = 0; + if (dim == 3) { + dec = 6; + } + else if (dim == 2) { + dec = 3; + } + else { + std::logic_error("Expected 3 >= dim > 1"); + } + + for (auto& qp : qps) { + auto phi = ten_b.eval_functions(qp.point()); + for (size_t j = 0; j < ten_bs; j++) { + auto qp_phi_j = disk::priv::inner_product(qp.weight(), phi[j]); + for (size_t i = j; i < ten_bs; i += dec) { + mass_matrix(i, j) += disk::priv::inner_product(phi[i], qp_phi_j); + } + } + } + + for (size_t j = 0; j < ten_bs; j++) { + for (size_t i = 0; i < j; i++) { + mass_matrix(i, j) = mass_matrix(j, i); + } + } + + return mass_matrix; + } + + // Computation of local symmetric tensor trace mass matrix; + Matrix + symmetric_tensor_trace_mass_matrix(const Mesh& msh, const typename Mesh::cell_type& cell) { + + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + Matrix mass_matrix = Matrix::Zero(ten_bs, ten_bs); + + auto qps = integrate(msh, cell, 2 * gradeg); + // number of tensor components + size_t dec = 0; + if (dim == 3) { + dec = 6; + } + else if (dim == 2) { + dec = 3; + } + else { + std::logic_error("Expected 3 >= dim > 1"); + } + + for (auto& qp : qps) { + auto phi = ten_b.eval_functions(qp.point()); + for (size_t j = 0; j < ten_bs; j++) { + auto identity = phi[j]; + identity.setZero(); + for(size_t d = 0; d < dim; d++) { + identity(d,d) = 1.0; + } + auto trace = phi[j].trace(); + auto trace_phi_j = disk::priv::inner_product(phi[j].trace(), identity); + auto qp_phi_j = disk::priv::inner_product(qp.weight(), trace_phi_j); + for (size_t i = 0; i < ten_bs; i ++) { + mass_matrix(i, j) += disk::priv::inner_product(phi[i], qp_phi_j); + } + } + } + + return mass_matrix; + } + + // Computation of local elastic RHS vector; + Matrix + e_mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function(const typename Mesh::point_type& )> & rhs_fun, size_t di = 0) { + + auto recdeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_bs = disk::sym_matrix_basis_size(recdeg, Mesh::dimension, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + size_t n_cbs = ten_bs + vec_bs; + auto cell_basis = make_vector_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(n_cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + for (auto& qp : qps) { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(ten_bs,0,vec_bs,1) = ret_loc; + return ret; + + } + + // Computation of local elastic mass operator; + Matrix e_mass_operator(elastic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell, bool add_vector_mass_Q = true) { + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + + T rho = material.rho(); + T vp = material.vp(); + T vs = material.vs(); + T mu = rho * vs * vs; + T lambda = rho * vp * vp - 2*mu; + + Matrix mass_matrix = Matrix::Zero(n_cbs, n_cbs); + + // Symmetric stress tensor mass block + // Stress tensor + Matrix mass_matrix_sigma = symmetric_tensor_mass_matrix(msh, cell); + // Tensor trace + Matrix mass_matrix_trace_sigma = symmetric_tensor_trace_mass_matrix(msh, cell); + + // Constitutive relationship inverse + mass_matrix_trace_sigma *= (lambda/(2.0*mu+2.0*lambda)); + mass_matrix_sigma -= mass_matrix_trace_sigma; + mass_matrix_sigma *= (1.0/(2.0*mu)); + mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs) = mass_matrix_sigma; + + if (add_vector_mass_Q) { + // vector velocity mass mass block + auto vec_basis = disk::make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix_v = disk::make_mass_matrix(msh, cell, vec_basis); + mass_matrix_v *= rho; + mass_matrix.block(n_ten_cbs, n_ten_cbs, n_vec_cbs, n_vec_cbs) = mass_matrix_v; + } + + return mass_matrix; + } + + // Computation of local acoustic mass operator; + Matrix a_mass_operator(acoustic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell, bool add_scalar_mass_Q = true){ + + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + Matrix mass_matrix = Matrix::Zero(n_cbs, n_cbs); + + auto recdeg = m_hho_di.reconstruction_degree(); + auto rec_basis = make_scalar_monomial_basis(msh, cell, recdeg); + auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + + Matrix mass_matrix_q_full = make_stiffness_matrix(msh, cell, rec_basis); + Matrix mass_matrix_q = Matrix::Zero(rbs-1, rbs-1); + mass_matrix_q = mass_matrix_q_full.block(1, 1, rbs-1, rbs-1); + mass_matrix_q *= material.rho(); + mass_matrix.block(0, 0, n_vec_cbs, n_vec_cbs) = mass_matrix_q; + + if (add_scalar_mass_Q) { + auto scal_basis = disk::make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix_v = disk::make_mass_matrix(msh, cell, scal_basis); + mass_matrix_v *= (1.0/(material.rho()*material.vp()*material.vp())); + mass_matrix.block(n_vec_cbs, n_vec_cbs, n_scal_cbs, n_scal_cbs) = mass_matrix_v; + } + + return mass_matrix; + } + + // Computation of local strain tensor reconstruction; + std::pair, Matrix> + strain_tensor_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) { + + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + + const size_t N = Mesh::dimension; + + auto graddeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, graddeg); + auto vec_b = make_vector_monomial_basis(msh, cell, celdeg); + + auto ten_bs = disk::sym_matrix_basis_size(graddeg, Mesh::dimension, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + auto fbs = disk::vector_basis_size(facdeg, Mesh::dimension - 1, Mesh::dimension); + + auto num_faces = howmany_faces(msh, cell); + + matrix_type gr_lhs = matrix_type::Zero(ten_bs, ten_bs); + matrix_type gr_rhs = matrix_type::Zero(ten_bs, vec_bs + num_faces * fbs); + + const auto qps = integrate(msh, cell, 2 * graddeg); + size_t dec = 0; + if (N == 3) { + dec = 6; + } + else if (N == 2) { + dec = 3; + } + else { + std::logic_error("Expected 3 >= dim > 1"); + } + + for (auto& qp : qps) { + const auto gphi = ten_b.eval_functions(qp.point()); + for (size_t j = 0; j < ten_bs; j++) { + auto qp_gphi_j = disk::priv::inner_product(qp.weight(), gphi[j]); + for (size_t i = j; i < ten_bs; i += dec) { + gr_lhs(i, j) += disk::priv::inner_product(gphi[i], qp_gphi_j); + } + } + } + + for (size_t j = 0; j < ten_bs; j++) { + for (size_t i = 0; i < j; i++) { + gr_lhs(i, j) = gr_lhs(j, i); + } + } + + if (celdeg > 0) { + const auto qpc = integrate(msh, cell, graddeg + celdeg - 1); + for (auto& qp : qpc) { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto dphi = vec_b.eval_sgradients(qp.point()); + const auto qp_dphi = disk::priv::inner_product(qp.weight(), dphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) += disk::priv::outer_product(gphi, qp_dphi); + } + } + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + const auto fb = make_vector_monomial_basis(msh, fc, facdeg); + const auto qps_f = integrate(msh, fc, graddeg + std::max(celdeg, facdeg)); + for (auto& qp : qps_f) { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto cphi = vec_b.eval_functions(qp.point()); + const auto fphi = fb.eval_functions(qp.point()); + const auto qp_gphi_n = disk::priv::inner_product(gphi, disk::priv::inner_product(qp.weight(), n)); + gr_rhs.block(0, vec_bs + i * fbs, ten_bs, fbs) += disk::priv::outer_product(qp_gphi_n, fphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) -= disk::priv::outer_product(qp_gphi_n, cphi); + } + } + + auto n_rows = gr_rhs.cols() + ten_bs; + auto n_cols = gr_rhs.cols() + ten_bs; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(n_rows,n_cols); + data_mixed.block(0, (ten_bs), ten_bs, n_cols-(ten_bs)) = -gr_rhs; + data_mixed.block((ten_bs), 0, n_rows-(ten_bs), ten_bs) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + // Computation of local acoustic mixed operator; Gradient reconstruction & Stabilization operator; + Matrix a_mixed_operator(acoustic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell, bool explicit_scheme){ + + auto reconstruction_operator = mixed_scalar_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + if (explicit_scheme) { + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di, false, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + else { + if (m_hho_stabilization_Q) { + auto stabilization_operator = make_scalar_hho_stabilization(msh, cell, reconstruction_operator.first, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + else { + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di, false, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + } + + // COEF SPECTRAL RADIUS + T equal_order_eta = 0.8; + T mixed_order_eta = 0.4; + + + T coef = 1.0; + T eta = coef * equal_order_eta; + + T rho = material.rho(); + T vp = material.vp(); + + return R_operator + (eta/(vp*rho))*S_operator; + } + + // Computation of local scalar (acoustic) mixed reconstruction; + std::pair, Matrix> + mixed_scalar_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) { + + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + typedef Matrix vector_type; + + const size_t DIM = Mesh::dimension; + + const auto recdeg = m_hho_di.reconstruction_degree(); + const auto celdeg = m_hho_di.cell_degree(); + const auto facdeg = m_hho_di.face_degree(); + + auto cb = make_scalar_monomial_basis(msh, cell, recdeg); + + const auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + const auto cbs = disk::scalar_basis_size(celdeg, Mesh::dimension); + const auto fbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + const auto num_faces = howmany_faces(msh, cell); + + const matrix_type stiff = make_stiffness_matrix(msh, cell, cb); + matrix_type gr_lhs = matrix_type::Zero(rbs-1, rbs-1); + matrix_type gr_rhs = matrix_type::Zero(rbs-1, cbs + num_faces*fbs); + + gr_lhs = stiff.block(1, 1, rbs-1, rbs-1); + gr_rhs.block(0, 0, rbs-1, cbs) = stiff.block(1, 0, rbs-1, cbs); + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) { + + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + auto fb = make_scalar_monomial_basis(msh, fc, facdeg); + + auto qps_f = integrate(msh, fc, recdeg - 1 + std::max(facdeg,celdeg)); + for (auto& qp : qps_f) { + vector_type c_phi_tmp = cb.eval_functions(qp.point()); + vector_type c_phi = c_phi_tmp.head(cbs); + Matrix c_dphi_tmp = cb.eval_gradients(qp.point()); + Matrix c_dphi = c_dphi_tmp.block(1, 0, rbs-1, DIM); + vector_type f_phi = fb.eval_functions(qp.point()); + gr_rhs.block(0, cbs+i*fbs, rbs-1, fbs) += qp.weight() * (c_dphi * n) * f_phi.transpose(); + gr_rhs.block(0, 0, rbs-1, cbs) -= qp.weight() * (c_dphi * n) * c_phi.transpose(); + } + } + + auto vec_cell_size = gr_lhs.cols(); + auto nrows = gr_rhs.cols()+vec_cell_size; + auto ncols = gr_rhs.cols()+vec_cell_size; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(nrows,ncols); + data_mixed.block(0, vec_cell_size, vec_cell_size, ncols-vec_cell_size) = -gr_rhs; + data_mixed.block(vec_cell_size, 0, nrows-vec_cell_size, vec_cell_size) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + // Computation of local acoustic RHS vector; + Matrix + a_mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function & rhs_fun, size_t di = 0) { + + const auto recdeg = m_hho_di.reconstruction_degree(); + const auto celdeg = m_hho_di.cell_degree(); + const auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension) - 1; + const auto cbs = disk::scalar_basis_size(celdeg, Mesh::dimension) + rbs; + auto cell_basis = make_scalar_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + for (auto& qp : qps) { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(rbs,0,cell_basis.size(),1) = ret_loc; + return ret; + } + + // Computation of local elasto–acoustic interface operator; Quadrature over the face to integrate normal component of elastic basis with acoustic basis; + Matrix e_interface_operator(const Mesh& msh, const typename Mesh::face_type& face, const typename Mesh::cell_type& e_cell, const typename Mesh::cell_type& a_cell) { + + Matrix interface_operator; + auto facdeg = m_hho_di.face_degree(); + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + auto sfbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + interface_operator = Matrix::Zero(vfbs, sfbs); + + auto vfb = make_vector_monomial_basis(msh, face, facdeg); + auto sfb = make_scalar_monomial_basis(msh, face, facdeg); + const auto qps = integrate(msh, face, facdeg); + const auto n = disk::normal(msh, e_cell, face); + for (auto& qp : qps) { + const auto v_f_phi = vfb.eval_functions(qp.point()); + const auto s_f_phi = sfb.eval_functions(qp.point()); + assert(v_f_phi.rows() == vfbs); + assert(s_f_phi.rows() == sfbs); + auto q_n = disk::priv::inner_product(qp.weight(), n); + const auto n_dot_v_f_phi = disk::priv::inner_product(v_f_phi,q_n); + const auto result = (-1.0*disk::priv::outer_product(n_dot_v_f_phi, s_f_phi)).eval(); + interface_operator += result; + } + return interface_operator; + } + + // Computation of local Neumann boundary operator for elastic cell; + Matrix e_neumman_bc_operator(const Mesh& msh, const typename Mesh::face_type& face, const typename Mesh::cell_type& e_cell, const typename Mesh::cell_type& a_cell, std::function a_vel_fun) { + + Matrix neumann_operator; + auto facdeg = m_hho_di.face_degree(); + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + neumann_operator = Matrix::Zero(vfbs, 1); + + auto vfb = make_vector_monomial_basis(msh, face, facdeg); + auto sfb = make_scalar_monomial_basis(msh, face, facdeg); + const auto qps = integrate(msh, face, facdeg); + const auto n = disk::normal(msh, e_cell, face); + for (auto& qp : qps) { + const auto v_f_phi = vfb.eval_functions(qp.point()); + const auto s_f_phi = sfb.eval_functions(qp.point()); + assert(v_f_phi.rows() == vfbs); + const auto n_dot_v_f_phi = disk::priv::inner_product(v_f_phi,disk::priv::inner_product(qp.weight(), n)); + const auto result = disk::priv::outer_product(n_dot_v_f_phi, a_vel_fun(qp.point())); + neumann_operator += result; + } + + return neumann_operator; + + } + + // Computation of local Neumann boundary operator for acoustic cell; + Matrix a_neumman_bc_operator(const Mesh& msh, const typename Mesh::face_type& face, const typename Mesh::cell_type& e_cell, const typename Mesh::cell_type& a_cell, std::function(const typename Mesh::point_type& )> e_vel_fun) { + + Matrix neumann_operator; + auto facdeg = m_hho_di.face_degree(); + auto sfbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + neumann_operator = Matrix::Zero(sfbs, 1); + + auto vfb = make_vector_monomial_basis(msh, face, facdeg); + auto sfb = make_scalar_monomial_basis(msh, face, facdeg); + const auto qps = integrate(msh, face, facdeg); + const auto n = disk::normal(msh, a_cell, face); + for (auto& qp : qps) { + const auto v_f_phi = vfb.eval_functions(qp.point()); + const auto s_f_phi = sfb.eval_functions(qp.point()); + assert(s_f_phi.rows() == sfbs); + const auto n_dot_v_f = disk::priv::inner_product(e_vel_fun(qp.point()),disk::priv::inner_product(qp.weight(), n)); + const auto result = disk::priv::inner_product(n_dot_v_f, s_f_phi); + neumann_operator += result; + } + + return neumann_operator; + + } + + // Classification of mesh cells by boundary conditions; Identification of cells with at least one Dirichlet face; + // Only for conv tests + void classify_cells(const Mesh& msh) { + + m_e_elements_with_bc_eges.clear(); + for (auto& cell : msh) { + auto cell_ind = msh.lookup(cell); + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_e_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) { + m_e_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + } + + m_a_elements_with_bc_eges.clear(); + for (auto& cell : msh) { + typename Mesh::point_type bar = barycenter(msh, cell); + if (bar.x() < 0) { + continue; + } + auto cell_ind = msh.lookup(cell); + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_a_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) { + m_a_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + } + } + + // Construction of cell-to-index maps; + void build_cells_maps() { + + // elastic data + size_t e_cell_ind = 0; + for (auto chunk : m_e_material) { + m_e_cell_index.insert(std::make_pair(chunk.first,e_cell_ind)); + e_cell_ind++; + } + m_n_elastic_cells = e_cell_ind; + + // acoustic data + size_t a_cell_ind = 0; + for (auto chunk : m_a_material) { + m_a_cell_index.insert(std::make_pair(chunk.first,a_cell_ind)); + a_cell_ind++; + } + m_n_acoustic_cells = a_cell_ind; + + } + + // Function projection onto cell dofs + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> v_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::function v_s_fun, std::function(const typename Mesh::point_type& )> flux_s_fun) { + + auto storage = msh.backend_storage(); + size_t n_dof = MASS.rows(); + x_glob = Matrix::Zero(n_dof); + + // elastic block + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_e_cbs = n_ten_cbs + n_vec_cbs; + + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + Matrix x_proj_ten_dof = project_ten_function(msh, cell, flux_fun); + Matrix x_proj_vec_dof = project_function(msh, cell, m_hho_di.cell_degree(), v_fun); + Matrix x_proj_dof = Matrix::Zero(n_e_cbs); + x_proj_dof.block(0, 0, n_ten_cbs, 1) = x_proj_ten_dof; + x_proj_dof.block(n_ten_cbs, 0, n_vec_cbs, 1) = x_proj_vec_dof; + scatter_e_cell_dof_data(e_cell_ind, msh, cell, x_glob, x_proj_dof); + } + + // acoustic block + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_v_s_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_a_cbs = n_v_s_cbs + n_scal_cbs; + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + Matrix x_proj_vec_dof = project_vec_function(msh, cell, flux_s_fun); + Matrix x_proj_sca_dof = project_function(msh, cell, m_hho_di.cell_degree(), v_s_fun); + Matrix x_proj_dof = Matrix::Zero(n_a_cbs); + x_proj_dof.block(0, 0, n_v_s_cbs, 1) = x_proj_vec_dof; + x_proj_dof.block(n_v_s_cbs, 0, n_scal_cbs, 1) = x_proj_sca_dof; + scatter_a_cell_dof_data(a_cell_ind, msh, cell, x_glob, x_proj_dof); + } + + } + + // Vector function projection onto cell dofs. + Matrix project_vec_function(const Mesh& msh, const typename Mesh::cell_type& cell, std::function(const typename Mesh::point_type& )> vec_fun) { + + auto recdeg = m_hho_di.reconstruction_degree(); + auto rec_basis = make_scalar_monomial_basis(msh, cell, recdeg); + auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + Matrix mass_matrix_q_full = make_stiffness_matrix(msh, cell, rec_basis); + Matrix mass_matrix_q = Matrix::Zero(rbs-1, rbs-1); + mass_matrix_q = mass_matrix_q_full.block(1, 1, rbs-1, rbs-1); + + Matrix rhs = Matrix::Zero(rbs-1); + Matrix f_vec = Matrix::Zero(1, 2); + const auto qps = integrate(msh, cell, 2*recdeg); + for (auto& qp : qps) { + auto dphi = rec_basis.eval_gradients(qp.point()); + f_vec(0,0) = vec_fun(qp.point())[0]; + f_vec(0,1) = vec_fun(qp.point())[1]; + for (size_t i = 0; i < rbs-1; i++){ + Matrix phi_i = dphi.block(i+1, 0, 1, 2).transpose(); + rhs(i,0) = rhs(i,0) + (qp.weight() * f_vec*phi_i)(0,0); + } + } + Matrix x_dof = mass_matrix_q.llt().solve(rhs); + return x_dof; + } + + // Symmetric tensor function projection onto cell dofs. + Matrix project_ten_function(const Mesh& msh, const typename Mesh::cell_type& cell, std::function(const typename Mesh::point_type& )> ten_fun) { + + Matrix mass_matrix = symmetric_tensor_mass_matrix(msh, cell); + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + Matrix rhs = Matrix::Zero(ten_bs); + + const auto qps = integrate(msh, cell, 2 * gradeg); + for (auto& qp : qps) { + auto phi = ten_b.eval_functions(qp.point()); + disk::static_matrix sigma = ten_fun(qp.point()); + for (size_t i = 0; i < ten_bs; i++){ + auto qp_phi_i = disk::priv::inner_product(qp.weight(), phi[i]); + rhs(i,0) += disk::priv::inner_product(qp_phi_i,sigma); + } + } + Matrix x_dof = mass_matrix.llt().solve(rhs); + return x_dof; + } + + // Elastic cell dofs update with projected values. + void + scatter_e_cell_dof_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, Matrix& x_glob, Matrix x_proj_dof) const { + size_t n_cbs = get_e_cell_basis_data(); + auto cell_ofs = e_cell_ind * n_cbs; + x_glob.block(cell_ofs, 0, n_cbs, 1) = x_proj_dof; + } + + // Acoustic cell dofs update with projected values. + void + scatter_a_cell_dof_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, Matrix& x_glob, Matrix x_proj_dof) const { + size_t n_cbs = get_a_cell_basis_data(); + auto cell_ofs = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + x_glob.block(cell_ofs, 0, n_cbs, 1) = x_proj_dof; + } + + // Function projection onto face dofs + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun, std::function scal_fun) { + + auto storage = msh.backend_storage(); + + // elastic block + for (auto e_chunk : m_e_material) { + auto& cell = storage->surfaces[e_chunk.first]; + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_e_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), vec_fun); + scatter_e_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + + // acoustic block + for (auto a_chunk : m_a_material) { + auto& cell = storage->surfaces[a_chunk.first]; + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_a_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), scal_fun); + scatter_a_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + // Updating elastic face dofs projection + void scatter_e_face_dof_data(const Mesh& msh, const typename Mesh::face_type& face, Matrix& x_glob, Matrix x_proj_dof) const { + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + auto fc_id = msh.lookup(face); + auto glob_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + // Updating acoustic face dofs projection + void scatter_a_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, Matrix& x_glob, Matrix x_proj_dof) const { + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + auto fc_id = msh.lookup(face); + auto glob_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + // Gathering of elastic cell and face DoFs. + Matrix gather_e_dof_data(size_t cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& x_glob) const { + + auto e_cell_ind = m_e_cell_index.find(cell_ind)->second; + auto num_faces = howmany_faces(msh, cl); + size_t n_cbs = get_e_cell_basis_data(); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(e_cell_ind * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) { + throw std::invalid_argument("This is a bug: face not found"); + } + const auto face_id = eid.second; + + if (m_e_bnd.is_dirichlet_face( face_id)) { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_e_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else { + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(face_LHS_offset, 0, n_fbs, 1); + } + } + return x_el; + } + + // Gathering of acoustic cell and face DoFs. + Matrix + gather_a_dof_data(size_t cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, const Matrix& x_glob) const { + + auto a_cell_ind = m_a_cell_index.find(cell_ind)->second; + auto num_faces = howmany_faces(msh, cl); + size_t n_cbs = get_a_cell_basis_data(); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + Matrix x_local(n_cbs + num_faces * n_fbs ); + x_local.block(0, 0, n_cbs, 1) = x_glob.block(a_cell_ind * n_cbs + m_n_elastic_cell_dof, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) { + throw std::invalid_argument("This is a bug: face not found"); + } + const auto face_id = eid.second; + if (m_a_bnd.is_dirichlet_face( face_id)) { + auto fb = disk::make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, fc, fb, m_hho_di.face_degree()); + auto velocity = m_a_bnd.dirichlet_boundary_func(face_id); + Matrix rhs = make_rhs(msh, fc, fb, velocity, m_hho_di.face_degree()); + x_local.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else { + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + x_local.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(face_LHS_offset, 0, n_fbs, 1); + } + } + return x_local; + } + + // Projection matrix assembly for LTS + void assemble_P(const Mesh& msh, T h_c) { + + auto storage = msh.backend_storage(); + P.setZero(); + IminusP.setZero(); + + const T hc = std::round(h_c * T(1000)) / T(1000); + + const size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + const size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(), Mesh::dimension, Mesh::dimension); + const size_t n_v_s_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension) - 1; + const size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + + size_t elastic_tensor_offset = 0; + size_t elastic_vector_offset = n_ten_cbs * m_e_material.size(); + size_t acoustic_vector_offset = elastic_vector_offset + n_vec_cbs * m_e_material.size(); + size_t acoustic_scalar_offset = acoustic_vector_offset + n_v_s_cbs * m_a_material.size(); + + std::vector< Triplet > P_triplets; + std::vector< Triplet > IP_triplets; + P_triplets.reserve(m_n_elastic_cell_dof + m_n_acoustic_cell_dof); + IP_triplets.reserve(m_n_elastic_cell_dof + m_n_acoustic_cell_dof); + + // Elastic cells + for (auto &chunk : m_e_material) { + size_t cell_id = chunk.first; + size_t e_idx = m_e_cell_index[cell_id]; + auto &cell = storage->surfaces[cell_id]; + + T h = std::round(diameter(msh, cell) * T(1000)) / T(1000); + T val = (h < hc) ? T(1) : T(0); + + if (val != T(0)) { + size_t ten_offset = elastic_tensor_offset + e_idx * n_ten_cbs; + size_t vec_offset = elastic_vector_offset + e_idx * n_vec_cbs; + for (size_t i = 0; i < n_ten_cbs; ++i) { + P_triplets.emplace_back(ten_offset+i, ten_offset+i, val); + IP_triplets.emplace_back(ten_offset+i, ten_offset+i, T(1)-val); + } + for (size_t i = 0; i < n_vec_cbs; ++i) { + P_triplets.emplace_back(vec_offset+i, vec_offset+i, val); + IP_triplets.emplace_back(vec_offset+i, vec_offset+i, T(1)-val); + } + } + } + + // Acoustic cells + for (auto &chunk : m_a_material) { + size_t cell_id = chunk.first; + size_t a_idx = m_a_cell_index[cell_id]; + auto &cell = storage->surfaces[cell_id]; + + T h = std::round(diameter(msh, cell) * T(1000)) / T(1000); + T val = (h < hc) ? T(1) : T(0); + + if (val != T(0)) { + size_t vec_offset = acoustic_vector_offset + a_idx * n_v_s_cbs; + size_t scal_offset = acoustic_scalar_offset + a_idx * n_scal_cbs; + for (size_t i = 0; i < n_v_s_cbs; ++i) { + P_triplets.emplace_back(vec_offset+i, vec_offset+i, val); + IP_triplets.emplace_back(vec_offset+i, vec_offset+i, T(1)-val); + } + for (size_t i = 0; i < n_scal_cbs; ++i) { + P_triplets.emplace_back(scal_offset+i, scal_offset+i, val); + IP_triplets.emplace_back(scal_offset+i, scal_offset+i, T(1)-val); + } + } + } + + P.setFromTriplets(P_triplets.begin(), P_triplets.end()); + IminusP.setFromTriplets(IP_triplets.begin(), IP_triplets.end()); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////// Sparse matrices triplet assembly finalization ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void finalize() { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + LHS_STAB.setFromTriplets( m_triplets_stab.begin(), m_triplets_stab.end() ); + m_triplets_stab.clear(); + } + + void finalize_mass() { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + void finalize_coupling() { + COUPLING.setFromTriplets( m_c_triplets.begin(), m_c_triplets.end() ); + m_c_triplets.clear(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////// Stabilization setting //////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void set_coupling_stabilization() { + m_hho_stabilization_Q = false; + } + + void set_hdg_stabilization() { + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) { + m_hho_stabilization_Q = false; + } + else { + m_hho_stabilization_Q = true; + } + } + + void set_interface_cell_indexes(std::map> & interface_cell_indexes) { + m_interface_cell_indexes = interface_cell_indexes; + } + + void set_hho_stabilization() { + m_hho_stabilization_Q = true; + } + + void set_scaled_stabilization() { + m_scaled_stabilization_Q = true; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////// Getter functions for DOFs, basis sizes, materials, boundaries, and interface data ////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + e_boundary_type & get_e_bc_conditions() { + return m_e_bnd; + } + + a_boundary_type & get_a_bc_conditions() { + return m_a_bnd; + } + + std::map> & get_e_material_data() { + return m_e_material; + } + + std::map> & get_a_material_data() { + return m_a_material; + } + + size_t get_a_n_cells_dof() const { + return m_n_acoustic_cell_dof; + } + + size_t get_e_n_cells_dof() const { + return m_n_elastic_cell_dof; + } + + size_t get_n_face_dof() const { + size_t n_face_dof = m_n_elastic_face_dof + m_n_acoustic_face_dof; + return n_face_dof; + } + + size_t get_e_face_dof() const { + return m_n_elastic_face_dof; + } + + size_t get_a_face_dof() const { + return m_n_acoustic_face_dof; + } + + size_t get_e_cell_basis_data() const { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + return n_cbs; + } + + size_t get_a_cell_basis_data() const { + size_t n_vel_scal_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_cbs = n_vel_scal_cbs + n_scal_cbs; + return n_cbs; + } + + size_t get_cell_basis_data(){ + + // Elastic cell basis + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs1 = n_ten_cbs + n_vec_cbs; + + // Acoustic cell basis + size_t n_vel_scal_cbs = disk::scalar_basis_size(m_hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_cbs2 = n_vel_scal_cbs + n_scal_cbs; + + size_t n_cbs = n_cbs1 + n_cbs2; + + return n_cbs; + } + + size_t get_n_faces() { + return m_n_edges - m_n_essential_edges; + } + + size_t get_face_basis_data() { + size_t n_fbs1 = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_fbs2 = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + size_t n_fbs = n_fbs1 + n_fbs2; + return n_fbs; + } + + size_t get_e_face_basis_data() { + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + return n_fbs; + } + + size_t get_a_face_basis_data() { + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + return n_fbs; + } + + size_t get_acoustic_cells() { + return m_n_acoustic_cells; + } + + size_t get_elastic_cells() { + return m_n_elastic_cells; + } + + size_t get_elastic_faces() { + return n_e_edges; + } + + size_t get_acoustic_faces() { + return n_a_edges; + } + + std::map> get_interfaces() { + return m_interface_cell_indexes; + } + + std::vector get_e_compress() { + return m_e_compress_indexes; + } + + std::vector get_a_compress() { + return m_a_compress_indexes; + } + + std::vector get_e_expand() { + return m_e_expand_indexes; + } + + std::vector get_a_expand() { + return m_a_expand_indexes; + } + +}; + +#endif /* elastoacoustic_four_fields_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/elastoacoustic_two_fields_assembler.hpp b/apps/wave_propagation/src/common/elastoacoustic_two_fields_assembler.hpp new file mode 100644 index 00000000..017a2f46 --- /dev/null +++ b/apps/wave_propagation/src/common/elastoacoustic_two_fields_assembler.hpp @@ -0,0 +1,1181 @@ +// +// elastoacoustic_two_fields_assembler.hpp +// acoustics +// +// Created by Omar Durán on 6/3/20. +// + +#pragma once +#ifndef elastoacoustic_two_fields_assembler_hpp +#define elastoacoustic_two_fields_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/acoustic_material_data.hpp" +#include "../common/elastic_material_data.hpp" +#include + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class elastoacoustic_two_fields_assembler +{ + + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_e_compress_indexes; + std::vector m_e_expand_indexes; + + std::vector m_a_compress_indexes; + std::vector m_a_expand_indexes; + + disk::hho_degree_info m_hho_di; + e_boundary_type m_e_bnd; + a_boundary_type m_a_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_c_triplets; + std::vector< Triplet > m_mass_triplets; + std::map> m_e_material; + std::map> m_a_material; + std::map m_e_cell_index; + std::map m_a_cell_index; + std::vector< size_t > m_e_elements_with_bc_eges; + std::vector< size_t > m_a_elements_with_bc_eges; + std::map> m_interface_cell_indexes; + +public: + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + size_t m_n_elastic_cell_dof; + size_t m_n_acoustic_cell_dof; + size_t m_n_elastic_face_dof; + size_t m_n_acoustic_face_dof; + + SparseMatrix LHS; + Matrix RHS; + SparseMatrix MASS; + SparseMatrix COUPLING; + + elastoacoustic_two_fields_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const e_boundary_type& e_bnd, const a_boundary_type& a_bnd, std::map> & e_material, std::map> & a_material) + : m_hho_di(hho_di), m_e_bnd(e_bnd), m_a_bnd(a_bnd), m_e_material(e_material), m_a_material(a_material), m_hho_stabilization_Q(true) + { + + auto storage = msh.backend_storage(); + auto is_e_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return e_bnd.is_dirichlet_face(fc_id); + }; + + auto is_a_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return a_bnd.is_dirichlet_face(fc_id); + }; + + size_t n_e_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_e_dirichlet); + size_t n_a_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_a_dirichlet); + + + std::set e_egdes; + for (auto &chunk : m_e_material) { + size_t cell_i = chunk.first; + auto& cell = storage->surfaces[cell_i]; + auto cell_faces = faces(msh,cell); + for (auto &face : cell_faces) { + if (!is_e_dirichlet(face)) { + auto fc_id = msh.lookup(face); + e_egdes.insert(fc_id); + } + } + } + size_t n_e_edges = e_egdes.size(); + + std::set a_egdes; + for (auto &chunk : m_a_material) { + size_t cell_i = chunk.first; + auto& cell = storage->surfaces[cell_i]; + auto cell_faces = faces(msh,cell); + for (auto &face : cell_faces) { + if (!is_a_dirichlet(face)) { + auto fc_id = msh.lookup(face); + a_egdes.insert(fc_id); + } + } + } + size_t n_a_edges = a_egdes.size(); + + m_n_edges = msh.faces_size(); + m_n_essential_edges = n_e_essential_edges + n_a_essential_edges; + + m_e_compress_indexes.resize( m_n_edges ); + m_e_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + m_a_compress_indexes.resize( m_n_edges ); + m_a_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + + + size_t e_compressed_offset = 0; + for (auto face_id : e_egdes) + { + m_e_compress_indexes.at(face_id) = e_compressed_offset; + m_e_expand_indexes.at(e_compressed_offset) = face_id; + e_compressed_offset++; + } + + size_t a_compressed_offset = 0; + for (auto face_id : a_egdes) + { + m_a_compress_indexes.at(face_id) = a_compressed_offset; + m_a_expand_indexes.at(a_compressed_offset) = face_id; + a_compressed_offset++; + } + + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t n_s_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_s_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + m_n_elastic_cell_dof = (n_cbs * m_e_material.size()); + m_n_acoustic_cell_dof = (n_s_cbs * m_a_material.size()); + + m_n_elastic_face_dof = (n_fbs * n_e_edges); + m_n_acoustic_face_dof = (n_s_fbs * n_a_edges); + size_t system_size = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_n_acoustic_face_dof; + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + COUPLING = SparseMatrix( system_size, system_size ); + + classify_cells(msh); + build_cells_maps(); + } + + void scatter_e_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + bool dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_a_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + + bool dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_e_mass_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + + } + + void scatter_a_mass_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + + } + + void scatter_ea_interface_data(const Mesh& msh, const typename Mesh::face_type& face, + const Matrix& interface_matrix) + { + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + auto sfbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + std::vector asm_map_e, asm_map_a; + asm_map_e.reserve(vfbs); + asm_map_a.reserve(sfbs); + + auto fc_id = msh.lookup(face); + + auto e_face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*vfbs; + bool e_dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < vfbs; i++){ + asm_map_e.push_back( assembly_index(e_face_LHS_offset+i, !e_dirichlet) ); + } + + auto a_face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*sfbs; + bool a_dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < sfbs; i++){ + asm_map_a.push_back( assembly_index(a_face_LHS_offset+i, !a_dirichlet) ); + } + + assert( asm_map_e.size() == interface_matrix.rows() && asm_map_a.size() == interface_matrix.cols() ); + + for (size_t i = 0; i < interface_matrix.rows(); i++) + { + for (size_t j = 0; j < interface_matrix.cols(); j++) + { + m_c_triplets.push_back( Triplet(asm_map_e[i], asm_map_a[j], interface_matrix(i,j)) ); + m_c_triplets.push_back( Triplet(asm_map_a[j], asm_map_e[i], - interface_matrix(i,j)) ); + } + } + + } + + void scatter_e_interface_neumann_data(const Mesh& msh, const typename Mesh::face_type& face, + const Matrix& interface_bc_data) + { + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + std::vector asm_map_e; + asm_map_e.reserve(vfbs); + + auto fc_id = msh.lookup(face); + + auto e_face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*vfbs; + bool e_dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < vfbs; i++){ + asm_map_e.push_back( assembly_index(e_face_LHS_offset+i, !e_dirichlet) ); + } + + assert( asm_map_e.size() == interface_bc_data.rows()); + + for (size_t i = 0; i < interface_bc_data.rows(); i++) + { + if (!asm_map_e[i].assemble()) + continue; + RHS(int(asm_map_e[i])) += interface_bc_data(i,0); + } + + } + + + void scatter_a_interface_neumann_data(const Mesh& msh, const typename Mesh::face_type& face, + const Matrix& interface_bc_data) + { + + auto sfbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + std::vector asm_map_a; + asm_map_a.reserve(sfbs); + + auto fc_id = msh.lookup(face); + + auto a_face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*sfbs; + bool a_dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + for (size_t i = 0; i < sfbs; i++){ + asm_map_a.push_back( assembly_index(a_face_LHS_offset+i, !a_dirichlet) ); + } + + assert( asm_map_a.size() == interface_bc_data.rows() ); + + for (size_t i = 0; i < interface_bc_data.rows(); i++) + { + if (!asm_map_a[i].assemble()) + continue; + RHS(int(asm_map_a[i])) += interface_bc_data(i,0); + } + + } + + void scatter_e_rhs_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows() ); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_a_rhs_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows()); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_e_bc_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + + auto fcs = faces(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = e_cell_ind * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + + bool dirichlet = m_e_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_e_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + } + } + + } + + void scatter_a_bc_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_LHS_offset = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + + bool dirichlet = m_a_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_a_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + + } + } + + } + + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type& )> e_rhs_fun, std::function a_rhs_fun){ + + auto storage = msh.backend_storage(); + LHS.setZero(); + RHS.setZero(); + + // elastic block + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + Matrix vectorial_laplacian_operator_loc = e_laplacian_operator(e_chunk.second,msh,cell); + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, e_rhs_fun); + scatter_e_data(e_cell_ind, msh, cell, vectorial_laplacian_operator_loc, f_loc); + } + + // acoustic block + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + + Matrix laplacian_operator_loc = a_laplacian_operator(a_chunk.second, msh, cell); + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, a_rhs_fun); + scatter_a_data(a_cell_ind, msh, cell, laplacian_operator_loc, f_loc); + } + finalize(); + } + + + void assemble_coupling_terms(const Mesh& msh){ + + auto storage = msh.backend_storage(); + COUPLING.setZero(); + // coupling blocks + for (auto chunk : m_interface_cell_indexes) { + auto& face = storage->edges[chunk.first]; + auto& e_cell = storage->surfaces[chunk.second.first]; + auto& a_cell = storage->surfaces[chunk.second.second]; + Matrix interface_operator_loc = e_interface_operator(msh, face, e_cell, a_cell); + scatter_ea_interface_data(msh, face, interface_operator_loc); + } + finalize_coupling(); + } + + void apply_bc_conditions_on_interface(const Mesh& msh, std::function(const typename Mesh::point_type& )> e_vel_fun, std::function a_vel_fun){ + + auto storage = msh.backend_storage(); + // Applying transmission conditions as neumann data for the case of uncoupled problems + for (auto chunk : m_interface_cell_indexes) { + auto& face = storage->edges[chunk.first]; + auto& e_cell = storage->surfaces[chunk.second.first]; + auto& a_cell = storage->surfaces[chunk.second.second]; + + Matrix e_neumann_operator_loc = e_neumman_bc_operator(msh, face, e_cell, a_cell, a_vel_fun); + scatter_e_interface_neumann_data(msh, face, e_neumann_operator_loc); + + Matrix a_neumann_operator_loc = a_neumman_bc_operator(msh, face, e_cell, a_cell, e_vel_fun); + scatter_a_interface_neumann_data(msh, face, a_neumann_operator_loc); + + } + } + + void assemble_mass(const Mesh& msh){ + + auto storage = msh.backend_storage(); + MASS.setZero(); + + // elastic block + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + Matrix mass_matrix = e_mass_operator(e_chunk.second,msh, cell); + scatter_e_mass_data(e_cell_ind,msh, cell, mass_matrix); + } + + // acoustic block + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + Matrix mass_matrix = a_mass_operator(a_chunk.second,msh, cell); + scatter_a_mass_data(a_cell_ind,msh, cell, mass_matrix); + } + + finalize_mass(); + } + + void assemble_rhs(const Mesh& msh, std::function(const typename Mesh::point_type& )> e_rhs_fun, std::function a_rhs_fun){ + + RHS.setZero(); + #ifdef HAVE_INTEL_TBB2 + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, e_rhs_fun); + scatter_e_rhs_data(e_cell_ind, msh, cell, f_loc); + } + + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + auto cell_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, a_rhs_fun); + scatter_a_rhs_data(a_cell_ind, msh, cell, f_loc); + } + + #endif + apply_bc(msh); + } + + void apply_bc(const Mesh& msh){ + + #ifdef HAVE_INTEL_TBB2 + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, laplacian_operator_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto& cell_ind : m_e_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + elastic_material_data e_mat = m_e_material.find(cell_ind)->second; + Matrix vectorial_laplacian_operator_loc = e_laplacian_operator(e_mat,msh,cell); + scatter_e_bc_data(cell_ind, msh, cell, vectorial_laplacian_operator_loc); + } + + for (auto& cell_ind : m_a_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + acoustic_material_data a_mat = m_a_material.find(cell_ind)->second; + Matrix laplacian_operator_loc = a_laplacian_operator(a_mat, msh, cell); + scatter_a_bc_data(cell_ind, msh, cell, laplacian_operator_loc); + } + + #endif + + } + + Matrix e_mass_operator(elastic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell){ + auto vec_basis = disk::make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix = disk::make_mass_matrix(msh, cell, vec_basis); + mass_matrix *= (material.rho()); + return mass_matrix; + } + + Matrix a_mass_operator(acoustic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell){ + + auto scal_basis = disk::make_scalar_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix = disk::make_mass_matrix(msh, cell, scal_basis); + mass_matrix *= (1.0/(material.rho()*material.vp()*material.vp())); + return mass_matrix; + } + + + Matrix e_laplacian_operator(elastic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell){ + + T mu = material.rho()*material.vs()*material.vs(); + T lambda = material.rho()*material.vp()*material.vp() - 2.0*mu; + auto reconstruction_operator = make_matrix_symmetric_gradrec(msh, cell, m_hho_di); + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto divergence_operator = make_hho_divergence_reconstruction(msh, cell, m_hho_di); + + Matrix R_operator = reconstruction_operator.second; + Matrix S_operator; + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di); + S_operator = stabilization_operator; + }else{ + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di); + S_operator = stabilization_operator; + } + return 2.0 * mu * (R_operator + S_operator) + lambda * divergence_operator.second; + } + + Matrix a_laplacian_operator(acoustic_material_data & material, const Mesh& msh, const typename Mesh::cell_type& cell){ + + auto reconstruction_operator = make_scalar_hho_laplacian(msh, cell, m_hho_di); + Matrix R_operator = reconstruction_operator.second; + + Matrix S_operator; + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_scalar_hho_stabilization(msh, cell, reconstruction_operator.first, m_hho_di); + S_operator = stabilization_operator; + }else{ + auto stabilization_operator = make_scalar_hdg_stabilization(msh, cell, m_hho_di); + S_operator = stabilization_operator; + } + return (1.0/material.rho())*(R_operator + S_operator); + } + + Matrix e_interface_operator(const Mesh& msh, const typename Mesh::face_type& face, const typename Mesh::cell_type& e_cell, const typename Mesh::cell_type& a_cell){ + + Matrix interface_operator; + auto facdeg = m_hho_di.face_degree(); + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + auto sfbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + interface_operator = Matrix::Zero(vfbs, sfbs); + + auto vfb = make_vector_monomial_basis(msh, face, facdeg); + auto sfb = make_scalar_monomial_basis(msh, face, facdeg); + const auto qps = integrate(msh, face, facdeg); + const auto n = disk::normal(msh, e_cell, face); + for (auto& qp : qps) + { + const auto v_f_phi = vfb.eval_functions(qp.point()); + const auto s_f_phi = sfb.eval_functions(qp.point()); + + assert(v_f_phi.rows() == vfbs); + assert(s_f_phi.rows() == sfbs); + const auto n_dot_v_f_phi = disk::priv::inner_product(v_f_phi,disk::priv::inner_product(qp.weight(), n)); + const auto result = -1.0*disk::priv::outer_product(n_dot_v_f_phi, s_f_phi); + interface_operator += result; + } + return interface_operator; + } + + Matrix e_neumman_bc_operator(const Mesh& msh, const typename Mesh::face_type& face, const typename Mesh::cell_type& e_cell, const typename Mesh::cell_type& a_cell, std::function a_vel_fun){ + + Matrix neumann_operator; + auto facdeg = m_hho_di.face_degree(); + auto vfbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + neumann_operator = Matrix::Zero(vfbs, 1); + + auto vfb = make_vector_monomial_basis(msh, face, facdeg); + auto sfb = make_scalar_monomial_basis(msh, face, facdeg); + const auto qps = integrate(msh, face, facdeg); + const auto n = disk::normal(msh, e_cell, face); + for (auto& qp : qps) + { + const auto v_f_phi = vfb.eval_functions(qp.point()); + const auto s_f_phi = sfb.eval_functions(qp.point()); + + assert(v_f_phi.rows() == vfbs); + const auto n_dot_v_f_phi = disk::priv::inner_product(v_f_phi,disk::priv::inner_product(qp.weight(), n)); + const auto result = disk::priv::outer_product(n_dot_v_f_phi, a_vel_fun(qp.point())); + neumann_operator += result; + + } + return neumann_operator; + } + + Matrix a_neumman_bc_operator(const Mesh& msh, const typename Mesh::face_type& face, const typename Mesh::cell_type& e_cell, const typename Mesh::cell_type& a_cell, std::function(const typename Mesh::point_type& )> e_vel_fun){ + + Matrix neumann_operator; + auto facdeg = m_hho_di.face_degree(); + auto sfbs = disk::scalar_basis_size(facdeg, Mesh::dimension - 1); + + neumann_operator = Matrix::Zero(sfbs, 1); + + auto vfb = make_vector_monomial_basis(msh, face, facdeg); + auto sfb = make_scalar_monomial_basis(msh, face, facdeg); + const auto qps = integrate(msh, face, facdeg); + const auto n = disk::normal(msh, a_cell, face); + for (auto& qp : qps) + { + const auto v_f_phi = vfb.eval_functions(qp.point()); + const auto s_f_phi = sfb.eval_functions(qp.point()); + + assert(s_f_phi.rows() == sfbs); + const auto n_dot_v_f = disk::priv::inner_product(e_vel_fun(qp.point()),disk::priv::inner_product(qp.weight(), n)); + const auto result = disk::priv::inner_product(n_dot_v_f, s_f_phi); + neumann_operator += result; + } + return neumann_operator; + } + + void classify_cells(const Mesh& msh){ + + m_e_elements_with_bc_eges.clear(); + for (auto& cell : msh) + { + auto cell_ind = msh.lookup(cell); + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_e_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_e_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + } + + m_a_elements_with_bc_eges.clear(); + for (auto& cell : msh) + { + typename Mesh::point_type bar = barycenter(msh, cell); + if (bar.x() < 0) { + continue; + } + + auto cell_ind = msh.lookup(cell); + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_a_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_a_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + } + } + + void build_cells_maps(){ + + // elastic data + size_t e_cell_ind = 0; + for (auto chunk : m_e_material) { + m_e_cell_index.insert(std::make_pair(chunk.first,e_cell_ind)); + e_cell_ind++; + } + + // acoustic data + size_t a_cell_ind = 0; + for (auto chunk : m_a_material) { + m_a_cell_index.insert(std::make_pair(chunk.first,a_cell_ind)); + a_cell_ind++; + } + } + + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun, std::function scal_fun){ + + auto storage = msh.backend_storage(); + size_t n_dof = MASS.rows(); + x_glob = Matrix::Zero(n_dof); + + // elastic block + for (auto e_chunk : m_e_material) { + size_t e_cell_ind = m_e_cell_index[e_chunk.first]; + auto& cell = storage->surfaces[e_chunk.first]; + Matrix x_proj_dof = project_function(msh, cell, m_hho_di.cell_degree(), vec_fun); + scatter_e_cell_dof_data(e_cell_ind, msh, cell, x_glob, x_proj_dof); + } + + // acoustic block + for (auto a_chunk : m_a_material) { + size_t a_cell_ind = m_a_cell_index[a_chunk.first]; + auto& cell = storage->surfaces[a_chunk.first]; + Matrix x_proj_dof = project_function(msh, cell, m_hho_di.cell_degree(), scal_fun); + scatter_a_cell_dof_data(a_cell_ind, msh, cell, x_glob, x_proj_dof); + } + + } + + void + scatter_e_cell_dof_data(size_t e_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix x_proj_dof) const + { + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + auto cell_ofs = e_cell_ind * n_cbs; + x_glob.block(cell_ofs, 0, n_cbs, 1) = x_proj_dof; + } + + void + scatter_a_cell_dof_data(size_t a_cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix x_proj_dof) const + { + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + auto cell_ofs = a_cell_ind * n_cbs + m_n_elastic_cell_dof; + x_glob.block(cell_ofs, 0, n_cbs, 1) = x_proj_dof; + } + + + + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun, std::function scal_fun){ + + auto storage = msh.backend_storage(); + + // elastic block + for (auto e_chunk : m_e_material) { + auto& cell = storage->surfaces[e_chunk.first]; + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_e_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), vec_fun); + scatter_e_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + + // acoustic block + for (auto a_chunk : m_a_material) { + auto& cell = storage->surfaces[a_chunk.first]; + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_a_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), scal_fun); + scatter_a_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + void + scatter_e_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix x_proj_dof) const + { + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + auto fc_id = msh.lookup(face); + auto glob_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + void + scatter_a_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix x_proj_dof) const + { + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + auto fc_id = msh.lookup(face); + auto glob_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + + } + + Matrix + gather_e_dof_data(size_t cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto e_cell_ind = m_e_cell_index.find(cell_ind)->second; + auto num_faces = howmany_faces(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(e_cell_ind * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_e_bnd.is_dirichlet_face( face_id)) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_e_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_e_compress_indexes.at(fc_id)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(face_LHS_offset, 0, n_fbs, 1); + } + } + return x_el; + } + + Matrix + gather_a_dof_data(size_t cell_ind, const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto a_cell_ind = m_a_cell_index.find(cell_ind)->second; + auto num_faces = howmany_faces(msh, cl); + size_t n_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + size_t n_fbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1); + + Matrix x_local(n_cbs + num_faces * n_fbs ); + x_local.block(0, 0, n_cbs, 1) = x_glob.block(a_cell_ind * n_cbs + m_n_elastic_cell_dof, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_a_bnd.is_dirichlet_face( face_id)) + { + auto fb = disk::make_scalar_monomial_basis(msh, fc, m_hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, fc, fb, m_hho_di.face_degree()); + auto velocity = m_a_bnd.dirichlet_boundary_func(face_id); + Matrix rhs = make_rhs(msh, fc, fb, velocity, m_hho_di.face_degree()); + x_local.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto fc_id = msh.lookup(fc); + auto face_LHS_offset = m_n_elastic_cell_dof + m_n_acoustic_cell_dof + m_n_elastic_face_dof + m_a_compress_indexes.at(fc_id)*n_fbs; + x_local.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(face_LHS_offset, 0, n_fbs, 1); + } + } + return x_local; + } + + void finalize() + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + void finalize_mass() + { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + void finalize_coupling() + { + COUPLING.setFromTriplets( m_c_triplets.begin(), m_c_triplets.end() ); + m_c_triplets.clear(); + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + + void set_interface_cell_indexes(std::map> & interface_cell_indexes){ + m_interface_cell_indexes = interface_cell_indexes; + } + + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } + + e_boundary_type & get_e_bc_conditions(){ + return m_e_bnd; + } + + a_boundary_type & get_a_bc_conditions(){ + return m_a_bnd; + } + + std::map> & get_e_material_data(){ + return m_e_material; + } + + std::map> & get_a_material_data(){ + return m_a_material; + } + + size_t get_a_n_cells_dof(){ + return m_n_acoustic_cell_dof; + } + + size_t get_e_n_cells_dof(){ + return m_n_elastic_cell_dof; + } + + size_t get_n_face_dof(){ + size_t n_face_dof = m_n_elastic_face_dof + m_n_acoustic_face_dof; + return n_face_dof; + } + + size_t get_e_cell_basis_data(){ + size_t n_v_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + return n_v_cbs; + } + + size_t get_a_cell_basis_data(){ + size_t n_s_cbs = disk::scalar_basis_size(m_hho_di.cell_degree(), Mesh::dimension); + return n_s_cbs; + } + +}; + +#endif /* elastoacoustic_two_fields_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/elastodynamic_one_field_assembler.hpp b/apps/wave_propagation/src/common/elastodynamic_one_field_assembler.hpp new file mode 100644 index 00000000..19f9a0be --- /dev/null +++ b/apps/wave_propagation/src/common/elastodynamic_one_field_assembler.hpp @@ -0,0 +1,562 @@ +// +// elastodynamic_one_field_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/14/20. +// + +#pragma once +#ifndef elastodynamic_one_field_assembler_hpp +#define elastodynamic_one_field_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/elastic_material_data.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class elastodynamic_one_field_assembler +{ + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_mass_triplets; + std::vector< elastic_material_data > m_material; + std::vector< size_t > m_elements_with_bc_eges; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + +public: + + SparseMatrix LHS; + Matrix RHS; + SparseMatrix MASS; + + elastodynamic_one_field_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + + classify_cells(msh); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_bc_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + + auto fcs = faces(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + } + } + + } + + void scatter_rhs_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows() ); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_mass_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + + } + + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type&)> rhs_fun){ + + LHS.setZero(); + RHS.setZero(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + Matrix vectorial_laplacian_operator_loc = laplacian_operator(cell_ind,msh,cell); + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + scatter_data(msh, cell, vectorial_laplacian_operator_loc, f_loc); + cell_ind++; + } + finalize(); + } + + void apply_bc(const Mesh& msh, T scale = T(1.0)){ + + auto storage = msh.backend_storage(); + #ifdef HAVE_INTEL_TBB2 + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&storage] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = storage->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + laplacian_operator_loc *= scale; + scatter_bc_data(msh, cell, laplacian_operator_loc); + } + ); + #else + for (auto& cell_ind : m_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + Matrix laplacian_operator_loc = laplacian_operator(cell_ind, msh, cell); + laplacian_operator_loc *= scale; + scatter_bc_data(msh, cell, laplacian_operator_loc); + } + #endif + + } + + void assemble_rhs(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun, T scale = T(1.0)){ + + RHS.setZero(); + #ifdef HAVE_INTEL_TBB2 + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + } + ); + #else + auto contribute = [this,&msh,&rhs_fun] (const typename Mesh::cell_type& cell){ + auto cell_basis = make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix f_loc = make_rhs(msh, cell, cell_basis, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + }; + + for (auto& cell : msh){ + contribute(cell); + } + #endif + apply_bc(msh,scale); + } + + void assemble_mass(const Mesh& msh){ + + MASS.setZero(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + Matrix mass_matrix = mass_operator(cell_ind,msh, cell); + scatter_mass_data(msh, cell, mass_matrix); + cell_ind++; + } + finalize_mass(); + } + + Matrix laplacian_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + + elastic_material_data & material = m_material[cell_ind]; + T mu = material.rho()*material.vs()*material.vs(); + T lambda = material.rho()*material.vp()*material.vp() - 2.0*mu; + auto reconstruction_operator = make_matrix_symmetric_gradrec(msh, cell, m_hho_di); + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto divergence_operator = make_hho_divergence_reconstruction(msh, cell, m_hho_di); + + Matrix R_operator = reconstruction_operator.second; + Matrix S_operator; + if(m_hho_stabilization_Q) + { + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di); + S_operator = stabilization_operator; + }else{ + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di); + S_operator = stabilization_operator; + } + return 2.0 * mu * (R_operator + S_operator) + lambda * divergence_operator.second; + } + + Matrix mass_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + + elastic_material_data & material = m_material[cell_ind]; + auto vec_basis = disk::make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix = disk::make_mass_matrix(msh, cell, vec_basis); + mass_matrix *= (material.rho()); + return mass_matrix; + } + + void classify_cells(const Mesh& msh){ + + m_elements_with_bc_eges.clear(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + cell_ind++; + } + } + + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun){ + size_t n_dof = MASS.rows(); + x_glob = Matrix::Zero(n_dof); + for (auto& cell : msh) + { + Matrix x_proj_dof = project_function(msh, cell, m_hho_di.cell_degree(), vec_fun); + scatter_cell_dof_data(msh, cell, x_glob, x_proj_dof); + } + } + + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun){ + + for (auto& cell : msh) + { + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), vec_fun); + scatter_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + void finalize_mass(void) + { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + Matrix x_el(n_cbs + num_faces * n_fbs ); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + void + scatter_cell_dof_data( const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix x_proj_dof) const + { + auto cell_ofs = disk::offset(msh, cell); + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1) = x_proj_dof; + } + + void + scatter_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix x_proj_dof) const + { + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_cells = msh.cells_size(); + auto face_offset = disk::offset(msh, face); + auto glob_offset = n_cbs * n_cells + m_compress_indexes.at(face_offset)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + void load_material_data(const Mesh& msh, elastic_material_data material){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, std::function(const typename Mesh::point_type& )> elastic_mat_fun){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + std::vector mat_data = elastic_mat_fun(bar); + T rho = mat_data[0]; + T vp = mat_data[1]; + T vs = mat_data[2]; + elastic_material_data material(rho,vp,vs); + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + T rho = 1.0; + T vp = std::sqrt(3.0); + T vs = 1.0; + elastic_material_data material(rho,vp,vs); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } + + boundary_type & get_bc_conditions(){ + return m_bnd; + } + + std::vector< elastic_material_data > & get_material_data(){ + return m_material; + } + + size_t get_n_face_dof(){ + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_face_dof = (m_n_edges - m_n_essential_edges) * n_fbs; + return n_face_dof; + } + + size_t get_cell_basis_data(){ + size_t n_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + return n_cbs; + } + +}; + +#endif /* elastodynamic_one_field_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/elastodynamic_three_fields_assembler.hpp b/apps/wave_propagation/src/common/elastodynamic_three_fields_assembler.hpp new file mode 100644 index 00000000..0b2051df --- /dev/null +++ b/apps/wave_propagation/src/common/elastodynamic_three_fields_assembler.hpp @@ -0,0 +1,908 @@ +// +// elastodynamic_three_fields_assembler.hpp +// acoustics +// +// Created by Omar Durán on 4/23/20. +// + +#pragma once +#ifndef elastodynamic_three_fields_assembler_hpp +#define elastodynamic_three_fields_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/elastic_material_data.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class elastodynamic_three_fields_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_mass_triplets; + std::vector< elastic_material_data > m_material; + std::vector< size_t > m_elements_with_bc_eges; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + bool m_scaled_stabilization_Q; + +public: + + SparseMatrix LHS; + Matrix RHS; + SparseMatrix MASS; + + elastodynamic_three_fields_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true), m_scaled_stabilization_Q(false) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + + classify_cells(msh); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_bc_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + auto fcs = faces(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + } + } + + } + + void scatter_rhs_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows()); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_mass_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + } + + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun){ + + LHS.setZero(); + RHS.setZero(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + Matrix mixed_operator_loc = mixed_operator(cell_ind,msh,cell); + Matrix f_loc = mixed_rhs(msh, cell, rhs_fun); + scatter_data(msh, cell, mixed_operator_loc, f_loc); + cell_ind++; + } + finalize(); + } + + void apply_bc(const Mesh& msh){ + + #ifdef HAVE_INTEL_TBB + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, mixed_operator_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto& cell_ind : m_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, mixed_operator_loc); + } + #endif + + } + + void assemble_rhs(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun){ + + RHS.setZero(); + + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix f_loc = this->mixed_rhs(msh, cell, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + } + ); + #else + auto contribute = [this,&msh,&rhs_fun] (const typename Mesh::cell_type& cell){ + Matrix f_loc = this->mixed_rhs(msh, cell, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + }; + + for (auto& cell : msh){ + contribute(cell); + } + #endif + apply_bc(msh); + } + + void assemble_mass(const Mesh& msh, bool add_vector_mass_Q = true){ + + MASS.setZero(); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = mass_operator(cell_ind, msh, cell, add_vector_mass_Q); + scatter_mass_data(msh, cell, mass_matrix); + } + finalize_mass(); + } + + Matrix mixed_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + + elastic_material_data & material = m_material[cell_ind]; + T rho = material.rho(); + T vs = material.vs(); + + auto reconstruction_operator = strain_tensor_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + + // Weak hydrostatic component + auto divergence_operator = div_vector_reconstruction(msh, cell); + Matrix D_operator = divergence_operator.second; + + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + if(m_hho_stabilization_Q) + { + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + }else{ + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + + return R_operator + D_operator + (rho*vs)*S_operator; + } + + Matrix + symmetric_tensor_mass_matrix(const Mesh& msh, const typename Mesh::cell_type& cell) + { + + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + Matrix mass_matrix = Matrix::Zero(ten_bs, ten_bs); + + auto qps = integrate(msh, cell, 2 * gradeg); + + // number of tensor components + size_t dec = 0; + if (dim == 3) + dec = 6; + else if (dim == 2) + dec = 3; + else + std::logic_error("Expected 3 >= dim > 1"); + + for (auto& qp : qps) + { + auto phi = ten_b.eval_functions(qp.point()); + + for (size_t j = 0; j < ten_bs; j++) + { + + auto qp_phi_j = disk::priv::inner_product(qp.weight(), phi[j]); + for (size_t i = j; i < ten_bs; i += dec){ + mass_matrix(i, j) += disk::priv::inner_product(phi[i], qp_phi_j); + } + } + } + + for (size_t j = 0; j < ten_bs; j++){ + for (size_t i = 0; i < j; i++){ + mass_matrix(i, j) = mass_matrix(j, i); + } + } + + return mass_matrix; + } + + Matrix mass_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, bool add_vector_mass_Q = true){ + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + + elastic_material_data & material = m_material[cell_ind]; + T rho = material.rho(); + T vp = material.vp(); + T vs = material.vs(); + T mu = rho * vs * vs; + T lamda = rho * vp * vp - 2*mu; + + Matrix mass_matrix = Matrix::Zero(n_cbs, n_cbs); + + // Symmetric tensor mass block + Matrix mass_matrix_sigma = symmetric_tensor_mass_matrix(msh, cell); + mass_matrix_sigma *= (1.0/(2.0*mu)); + mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs) = mass_matrix_sigma; + + // scalar hydrostatic component mass mass block + auto scal_basis = make_scalar_monomial_basis(msh, cell, m_hho_di.face_degree()); + Matrix mass_matrix_sigma_v = make_mass_matrix(msh, cell, scal_basis); + mass_matrix_sigma_v *= (1.0/(lamda)); + mass_matrix.block(n_ten_cbs, n_ten_cbs, n_sca_cbs, n_sca_cbs) = mass_matrix_sigma_v; + + if (add_vector_mass_Q) { + // vector velocity mass mass block + auto vec_basis = disk::make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix_v = disk::make_mass_matrix(msh, cell, vec_basis); + mass_matrix_v *= rho; + mass_matrix.block(n_ten_cbs+n_sca_cbs, n_ten_cbs+n_sca_cbs, n_vec_cbs, n_vec_cbs) = mass_matrix_v; + } + + return mass_matrix; + } + + void classify_cells(const Mesh& msh){ + + m_elements_with_bc_eges.clear(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + cell_ind++; + } + } + + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> ten_fun){ + size_t n_dof = MASS.rows(); + x_glob = Matrix::Zero(n_dof); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + for (auto& cell : msh) + { + Matrix x_proj_ten_dof = project_ten_function(msh, cell, ten_fun); + Matrix x_proj_sca_dof = project_hydrostatic_function(msh, cell, ten_fun); + Matrix x_proj_vec_dof = project_function(msh, cell, m_hho_di.cell_degree(), vec_fun); + + Matrix x_proj_dof = Matrix::Zero(n_cbs); + x_proj_dof.block(0, 0, n_ten_cbs, 1) = x_proj_ten_dof; + x_proj_dof.block(n_ten_cbs, 0, n_sca_cbs, 1) = x_proj_sca_dof; + x_proj_dof.block(n_ten_cbs+n_sca_cbs, 0, n_vec_cbs, 1) = x_proj_vec_dof; + scatter_cell_dof_data(msh, cell, x_glob, x_proj_dof); + } + } + + Matrix project_ten_function(const Mesh& msh, const typename Mesh::cell_type& cell, + std::function(const typename Mesh::point_type& )> ten_fun){ + + Matrix mass_matrix = symmetric_tensor_mass_matrix(msh, cell); + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + Matrix rhs = Matrix::Zero(ten_bs); + + const auto qps = integrate(msh, cell, 2 * gradeg); + for (auto& qp : qps) + { + auto phi = ten_b.eval_functions(qp.point()); + disk::static_matrix sigma = ten_fun(qp.point()); + T trace = 0.0; + for (size_t d = 0; d < dim; d++){ + trace += sigma(d,d); + } + disk::static_matrix sigma_s = sigma - (trace)*disk::static_matrix::Identity(); + for (size_t i = 0; i < ten_bs; i++){ + auto qp_phi_i = disk::priv::inner_product(qp.weight(), phi[i]); + rhs(i,0) += disk::priv::inner_product(qp_phi_i,sigma_s); + } + } + Matrix x_dof = mass_matrix.llt().solve(rhs); + return x_dof; + } + + Matrix project_hydrostatic_function(const Mesh& msh, const typename Mesh::cell_type& cell, + std::function(const typename Mesh::point_type& )> ten_fun){ + + size_t dim = Mesh::dimension; + auto facedeg = m_hho_di.face_degree(); + size_t sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), dim); + auto sca_basis = make_scalar_monomial_basis(msh, cell, facedeg); + Matrix mass_matrix = make_mass_matrix(msh, cell, sca_basis); + + Matrix rhs = Matrix::Zero(sca_cbs); + const auto qps = integrate(msh, cell, (2*facedeg+1)); + for (auto& qp : qps) + { + auto phi = sca_basis.eval_functions(qp.point()); + disk::static_matrix sigma = ten_fun(qp.point()); + T trace = 0.0; + for (size_t d = 0; d < dim; d++){ + trace += sigma(d,d); + } + trace *= qp.weight(); + for (size_t i = 0; i < sca_cbs; i++){ + rhs(i,0) += disk::priv::inner_product(phi[i], trace);; + } + } + Matrix x_dof = mass_matrix.llt().solve(rhs); + return x_dof; + } + + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun){ + + for (auto& cell : msh) + { + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), vec_fun); + scatter_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + void finalize_mass(void) + { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_dof = n_cbs + num_faces * n_fbs; + + Matrix x_el(n_dof); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + void scatter_cell_dof_data( const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix & x_proj_dof) const + { + auto cell_ofs = disk::offset(msh, cell); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1) = x_proj_dof; + } + + void scatter_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix & x_proj_dof) const + { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_cells = msh.cells_size(); + auto face_offset = disk::offset(msh, face); + auto glob_offset = n_cbs * n_cells + m_compress_indexes.at(face_offset)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + std::pair< Matrix, + Matrix > + strain_tensor_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) + { + + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + + const size_t N = Mesh::dimension; + + auto graddeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, graddeg); + auto vec_b = make_vector_monomial_basis(msh, cell, celdeg); + + auto ten_bs = disk::sym_matrix_basis_size(graddeg, Mesh::dimension, Mesh::dimension); + auto sca_bs = disk::scalar_basis_size(facdeg, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + auto fbs = disk::vector_basis_size(facdeg, Mesh::dimension - 1, Mesh::dimension); + + auto num_faces = howmany_faces(msh, cell); + + matrix_type gr_lhs = matrix_type::Zero(ten_bs, ten_bs); + matrix_type gr_rhs = matrix_type::Zero(ten_bs, vec_bs + num_faces * fbs); + + const auto qps = integrate(msh, cell, 2 * graddeg); + + size_t dec = 0; + if (N == 3) + dec = 6; + else if (N == 2) + dec = 3; + else + std::logic_error("Expected 3 >= dim > 1"); + + for (auto& qp : qps) + { + const auto gphi = ten_b.eval_functions(qp.point()); + + for (size_t j = 0; j < ten_bs; j++) + { + + auto qp_gphi_j = disk::priv::inner_product(qp.weight(), gphi[j]); + for (size_t i = j; i < ten_bs; i += dec){ + gr_lhs(i, j) += disk::priv::inner_product(gphi[i], qp_gphi_j); + } + } + } + + for (size_t j = 0; j < ten_bs; j++) + for (size_t i = 0; i < j; i++) + gr_lhs(i, j) = gr_lhs(j, i); + + if (celdeg > 0) + { + const auto qpc = integrate(msh, cell, graddeg + celdeg - 1); + for (auto& qp : qpc) + { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto dphi = vec_b.eval_sgradients(qp.point()); + const auto qp_dphi = disk::priv::inner_product(qp.weight(), dphi); + + gr_rhs.block(0, 0, ten_bs, vec_bs) += disk::priv::outer_product(gphi, qp_dphi); + + } + } + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + const auto fb = make_vector_monomial_basis(msh, fc, facdeg); + + const auto qps_f = integrate(msh, fc, graddeg + std::max(celdeg, facdeg)); + for (auto& qp : qps_f) + { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto cphi = vec_b.eval_functions(qp.point()); + const auto fphi = fb.eval_functions(qp.point()); + + const auto qp_gphi_n = disk::priv::inner_product(gphi, disk::priv::inner_product(qp.weight(), n)); + gr_rhs.block(0, vec_bs + i * fbs, ten_bs, fbs) += disk::priv::outer_product(qp_gphi_n, fphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) -= disk::priv::outer_product(qp_gphi_n, cphi); + } + } + + auto n_rows = gr_rhs.cols() + ten_bs + sca_bs; + auto n_cols = gr_rhs.cols() + ten_bs + sca_bs; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(n_rows,n_cols); + data_mixed.block(0, (ten_bs + sca_bs), ten_bs, n_cols-(ten_bs + sca_bs)) = -gr_rhs; + data_mixed.block((ten_bs + sca_bs), 0, n_rows-(ten_bs + sca_bs), ten_bs) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + std::pair< Matrix, + Matrix > + div_vector_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) + { + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + + auto graddeg = m_hho_di.grad_degree(); + auto facedeg = m_hho_di.face_degree(); + auto ten_bs = disk::sym_matrix_basis_size(graddeg, Mesh::dimension, Mesh::dimension); + auto sca_bs = disk::scalar_basis_size(facedeg, Mesh::dimension); + + auto cbas_s = make_scalar_monomial_basis(msh, cell, m_hho_di.face_degree()); + auto dr_lhs = make_mass_matrix(msh, cell, cbas_s); + auto dr_rhs = make_hho_divergence_reconstruction_rhs(msh, cell, m_hho_di); + + assert( dr_lhs.rows() == sca_bs && dr_lhs.cols() == sca_bs ); + + // Shrinking data + auto n_rows = dr_rhs.cols() + ten_bs + sca_bs; + auto n_cols = dr_rhs.cols() + ten_bs + sca_bs; + matrix_type data_mixed = matrix_type::Zero(n_rows,n_cols); + data_mixed.block(ten_bs, (ten_bs + sca_bs), sca_bs, n_cols-(ten_bs + sca_bs)) = -dr_rhs; + data_mixed.block((ten_bs + sca_bs), ten_bs, n_rows-(ten_bs + sca_bs), sca_bs) = dr_rhs.transpose(); + + matrix_type oper = dr_lhs.ldlt().solve(dr_rhs); + return std::make_pair(oper, data_mixed); + } + + Matrix + mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function(const typename Mesh::point_type& )> & rhs_fun, size_t di = 0) + { + auto recdeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_bs = disk::sym_matrix_basis_size(recdeg, Mesh::dimension, Mesh::dimension); + auto sca_bs = disk::scalar_basis_size(facdeg, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + size_t n_cbs = ten_bs + sca_bs + vec_bs; + auto cell_basis = make_vector_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(n_cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + + for (auto& qp : qps) + { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(ten_bs + sca_bs,0,vec_bs,1) = ret_loc; + return ret; + } + + void load_material_data(const Mesh& msh, elastic_material_data material){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, std::function(const typename Mesh::point_type& )> elastic_mat_fun){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + std::vector mat_data = elastic_mat_fun(bar); + T rho = mat_data[0]; + T vp = mat_data[1]; + T vs = mat_data[2]; + elastic_material_data material(rho,vp,vs); + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + T rho = 1.0; + T vp = sqrt(3.0); + T vs = 1.0; + elastic_material_data material(rho,vp,vs); + size_t cell_i = 0; + for (auto& cell : msh) + { + m_material.push_back(material); + cell_i++; + } + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } + + void set_scaled_stabilization(){ + m_scaled_stabilization_Q = true; + } + + boundary_type & get_bc_conditions(){ + return m_bnd; + } + + std::vector< elastic_material_data > & get_material_data(){ + return m_material; + } + + size_t get_n_face_dof(){ + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_face_dof = (m_n_edges - m_n_essential_edges) * n_fbs; + return n_face_dof; + } + + size_t get_n_faces(){ + return m_n_edges - m_n_essential_edges; + } + + size_t get_face_basis_data(){ + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + return n_fbs; + } + + size_t get_cell_basis_data(){ + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(m_hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_sca_cbs + n_vec_cbs; + return n_cbs; + } +}; + +#endif /* elastodynamic_three_fields_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/elastodynamic_two_fields_assembler.hpp b/apps/wave_propagation/src/common/elastodynamic_two_fields_assembler.hpp new file mode 100644 index 00000000..cd427618 --- /dev/null +++ b/apps/wave_propagation/src/common/elastodynamic_two_fields_assembler.hpp @@ -0,0 +1,879 @@ +// +// elastodynamic_two_fields_assembler.hpp +// elastodynamics +// +// Created by Omar Durán on 4/25/20. +// + +#pragma once +#ifndef elastodynamic_two_fields_assembler_hpp +#define elastodynamic_two_fields_assembler_hpp + +#include "diskpp/bases/bases.hpp" +#include "diskpp/methods/hho" +#include "../common/assembly_index.hpp" +#include "../common/elastic_material_data.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class elastodynamic_two_fields_assembler +{ + + + typedef disk::BoundaryConditions boundary_type; + using T = typename Mesh::coordinate_type; + + std::vector m_compress_indexes; + std::vector m_expand_indexes; + + disk::hho_degree_info m_hho_di; + boundary_type m_bnd; + std::vector< Triplet > m_triplets; + std::vector< Triplet > m_mass_triplets; + std::vector< elastic_material_data > m_material; + std::vector< size_t > m_elements_with_bc_eges; + + size_t m_n_edges; + size_t m_n_essential_edges; + bool m_hho_stabilization_Q; + bool m_scaled_stabilization_Q; + +public: + + SparseMatrix LHS; + Matrix RHS; + SparseMatrix MASS; + + elastodynamic_two_fields_assembler(const Mesh& msh, const disk::hho_degree_info& hho_di, const boundary_type& bnd) + : m_hho_di(hho_di), m_bnd(bnd), m_hho_stabilization_Q(true), m_scaled_stabilization_Q(false) + { + + auto is_dirichlet = [&](const typename Mesh::face& fc) -> bool { + + auto fc_id = msh.lookup(fc); + return bnd.is_dirichlet_face(fc_id); + }; + + m_n_edges = msh.faces_size(); + m_n_essential_edges = std::count_if(msh.faces_begin(), msh.faces_end(), is_dirichlet); + + m_compress_indexes.resize( m_n_edges ); + m_expand_indexes.resize( m_n_edges - m_n_essential_edges ); + + size_t compressed_offset = 0; + for (size_t i = 0; i < m_n_edges; i++) + { + auto fc = *std::next(msh.faces_begin(), i); + if ( !is_dirichlet(fc) ) + { + m_compress_indexes.at(i) = compressed_offset; + m_expand_indexes.at(compressed_offset) = i; + compressed_offset++; + } + } + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + + size_t system_size = n_cbs * msh.cells_size() + n_fbs * (m_n_edges - m_n_essential_edges); + + LHS = SparseMatrix( system_size, system_size ); + RHS = Matrix::Zero( system_size ); + MASS = SparseMatrix( system_size, system_size ); + + classify_cells(msh); + } + + void scatter_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs, + const Matrix& rhs) + { + auto fcs = faces(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_triplets.push_back( Triplet(asm_map[i], asm_map[j], lhs(i,j)) ); + } + } + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_bc_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& lhs) + { + auto fcs = faces(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + std::vector asm_map; + asm_map.reserve(n_cbs + n_fbs*fcs.size()); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + Matrix dirichlet_data = Matrix::Zero(n_cbs + fcs.size()*n_fbs); + for (size_t face_i = 0; face_i < fcs.size(); face_i++) + { + auto fc = fcs[face_i]; + auto face_offset = disk::offset(msh, fc); + auto face_LHS_offset = n_cbs * msh.cells_size() + m_compress_indexes.at(face_offset)*n_fbs; + + auto fc_id = msh.lookup(fc); + bool dirichlet = m_bnd.is_dirichlet_face(fc_id); + + for (size_t i = 0; i < n_fbs; i++) + asm_map.push_back( assembly_index(face_LHS_offset+i, !dirichlet) ); + + if (dirichlet) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(fc_id); + + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + dirichlet_data.block(n_cbs + face_i*n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + + } + + assert( asm_map.size() == lhs.rows() && asm_map.size() == lhs.cols() ); + + for (size_t i = 0; i < lhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < lhs.cols(); j++) + { + if ( !asm_map[j].assemble() ) + RHS(int(asm_map[i])) -= lhs(i,j) * dirichlet_data(j); + } + } + + } + + void scatter_rhs_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& rhs) + { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == rhs.rows()); + + for (size_t i = 0; i < rhs.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + RHS(int(asm_map[i])) += rhs(i); + } + + } + + void scatter_mass_data(const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& mass_matrix) + { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + std::vector asm_map; + asm_map.reserve(n_cbs); + + auto cell_offset = disk::offset(msh, cl); + auto cell_LHS_offset = cell_offset * n_cbs; + + for (size_t i = 0; i < n_cbs; i++) + asm_map.push_back( assembly_index(cell_LHS_offset+i, true) ); + + assert( asm_map.size() == mass_matrix.rows() && asm_map.size() == mass_matrix.cols() ); + + for (size_t i = 0; i < mass_matrix.rows(); i++) + { + if (!asm_map[i].assemble()) + continue; + + for (size_t j = 0; j < mass_matrix.cols(); j++) + { + if ( asm_map[j].assemble() ) + m_mass_triplets.push_back( Triplet(asm_map[i], asm_map[j], mass_matrix(i,j)) ); + } + } + } + + void assemble(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun){ + + LHS.setZero(); + RHS.setZero(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + Matrix mixed_operator_loc = mixed_operator(cell_ind,msh,cell); + Matrix f_loc = mixed_rhs(msh, cell, rhs_fun); + scatter_data(msh, cell, mixed_operator_loc, f_loc); + cell_ind++; + } + finalize(); + } + + void apply_bc(const Mesh& msh){ + + #ifdef HAVE_INTEL_TBB + size_t n_cells = m_elements_with_bc_eges.size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh] (size_t & i){ + size_t cell_ind = m_elements_with_bc_eges[i]; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, mixed_operator_loc); + } + ); + #else + auto storage = msh.backend_storage(); + for (auto& cell_ind : m_elements_with_bc_eges) + { + auto& cell = storage->surfaces[cell_ind]; + Matrix mixed_operator_loc = mixed_operator(cell_ind, msh, cell); + scatter_bc_data(msh, cell, mixed_operator_loc); + } + #endif + + } + + void assemble_rhs(const Mesh& msh, std::function(const typename Mesh::point_type& )> rhs_fun){ + + RHS.setZero(); + + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&msh,&rhs_fun] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix f_loc = this->mixed_rhs(msh, cell, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + } + ); + #else + auto contribute = [this,&msh,&rhs_fun] (const typename Mesh::cell_type& cell){ + Matrix f_loc = this->mixed_rhs(msh, cell, rhs_fun); + this->scatter_rhs_data(msh, cell, f_loc); + }; + + for (auto& cell : msh){ + contribute(cell); + } + #endif + apply_bc(msh); + } + + void assemble_mass(const Mesh& msh, bool add_vector_mass_Q = true){ + + MASS.setZero(); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = mass_operator(cell_ind, msh, cell, add_vector_mass_Q); + scatter_mass_data(msh, cell, mass_matrix); + } + finalize_mass(); + } + + Matrix mixed_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell){ + + elastic_material_data & material = m_material[cell_ind]; + T rho = material.rho(); + T vp = material.vp(); + T vs = material.vs(); + T mu = rho * vs * vs; + T lambda = rho * vp * vp - 2*mu; + + auto reconstruction_operator = strain_tensor_reconstruction(msh, cell); + Matrix R_operator = reconstruction_operator.second; + auto n_rows = R_operator.rows(); + auto n_cols = R_operator.cols(); + + Matrix S_operator = Matrix::Zero(n_rows, n_cols); + if(m_hho_stabilization_Q) + { + auto rec_for_stab = make_vector_hho_symmetric_laplacian(msh, cell, m_hho_di); + auto stabilization_operator = make_vector_hho_stabilization(msh, cell, rec_for_stab.first, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + }else{ + auto stabilization_operator = make_vector_hdg_stabilization(msh, cell, m_hho_di, m_scaled_stabilization_Q); + auto n_s_rows = stabilization_operator.rows(); + auto n_s_cols = stabilization_operator.cols(); + S_operator.block(n_rows-n_s_rows, n_cols-n_s_cols, n_s_rows, n_s_cols) = stabilization_operator; + } + + return R_operator + (rho*vs)*S_operator; + } + + Matrix + symmetric_tensor_mass_matrix(const Mesh& msh, const typename Mesh::cell_type& cell) + { + + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + Matrix mass_matrix = Matrix::Zero(ten_bs, ten_bs); + + auto qps = integrate(msh, cell, 2 * gradeg); + + // number of tensor components + size_t dec = 0; + if (dim == 3) + dec = 6; + else if (dim == 2) + dec = 3; + else + std::logic_error("Expected 3 >= dim > 1"); + + for (auto& qp : qps) + { + auto phi = ten_b.eval_functions(qp.point()); + + for (size_t j = 0; j < ten_bs; j++) + { + + auto qp_phi_j = disk::priv::inner_product(qp.weight(), phi[j]); + for (size_t i = j; i < ten_bs; i += dec){ + mass_matrix(i, j) += disk::priv::inner_product(phi[i], qp_phi_j); + } + } + } + + for (size_t j = 0; j < ten_bs; j++){ + for (size_t i = 0; i < j; i++){ + mass_matrix(i, j) = mass_matrix(j, i); + } + } + + return mass_matrix; + } + + Matrix + symmetric_tensor_trace_mass_matrix(const Mesh& msh, const typename Mesh::cell_type& cell) + { + + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + Matrix mass_matrix = Matrix::Zero(ten_bs, ten_bs); + + auto qps = integrate(msh, cell, 2 * gradeg); + + // number of tensor components + size_t dec = 0; + if (dim == 3) + dec = 6; + else if (dim == 2) + dec = 3; + else + std::logic_error("Expected 3 >= dim > 1"); + + for (auto& qp : qps) + { + auto phi = ten_b.eval_functions(qp.point()); + + for (size_t j = 0; j < ten_bs; j++) + { + auto identity = phi[j]; + identity.setZero(); + for(size_t d = 0; d < dim; d++){ + identity(d,d) = 1.0; + } + auto trace = phi[j].trace(); + auto trace_phi_j = disk::priv::inner_product(phi[j].trace(), identity); + auto qp_phi_j = disk::priv::inner_product(qp.weight(), trace_phi_j); + for (size_t i = 0; i < ten_bs; i ++){ + mass_matrix(i, j) += disk::priv::inner_product(phi[i], qp_phi_j); + } + } + } + + return mass_matrix; + } + + Matrix mass_operator(size_t & cell_ind, const Mesh& msh, const typename Mesh::cell_type& cell, bool add_vector_mass_Q = true){ + + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + + elastic_material_data & material = m_material[cell_ind]; + T rho = material.rho(); + T vp = material.vp(); + T vs = material.vs(); + T mu = rho * vs * vs; + T lambda = rho * vp * vp - 2*mu; + + Matrix mass_matrix = Matrix::Zero(n_cbs, n_cbs); + + // Symmetric stress tensor mass block + + // Stress tensor + Matrix mass_matrix_sigma = symmetric_tensor_mass_matrix(msh, cell); + + // Tensor trace + Matrix mass_matrix_trace_sigma = symmetric_tensor_trace_mass_matrix(msh, cell); + + // Constitutive relationship inverse + mass_matrix_trace_sigma *= (lambda/(2.0*mu+2.0*lambda)); + mass_matrix_sigma -= mass_matrix_trace_sigma; + mass_matrix_sigma *= (1.0/(2.0*mu)); + mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs) = mass_matrix_sigma; + + if (add_vector_mass_Q) { + // vector velocity mass mass block + auto vec_basis = disk::make_vector_monomial_basis(msh, cell, m_hho_di.cell_degree()); + Matrix mass_matrix_v = disk::make_mass_matrix(msh, cell, vec_basis); + mass_matrix_v *= rho; + mass_matrix.block(n_ten_cbs, n_ten_cbs, n_vec_cbs, n_vec_cbs) = mass_matrix_v; + } + + return mass_matrix; + } + + void classify_cells(const Mesh& msh){ + + m_elements_with_bc_eges.clear(); + size_t cell_ind = 0; + for (auto& cell : msh) + { + auto face_list = faces(msh, cell); + for (size_t face_i = 0; face_i < face_list.size(); face_i++) + { + auto fc = face_list[face_i]; + auto fc_id = msh.lookup(fc); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + m_elements_with_bc_eges.push_back(cell_ind); + break; + } + } + cell_ind++; + } + } + + void project_over_cells(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> ten_fun){ + size_t n_dof = MASS.rows(); + x_glob = Matrix::Zero(n_dof); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + for (auto& cell : msh) + { + Matrix x_proj_ten_dof = project_ten_function(msh, cell, ten_fun); + Matrix x_proj_vec_dof = project_function(msh, cell, m_hho_di.cell_degree(), vec_fun); + + Matrix x_proj_dof = Matrix::Zero(n_cbs); + x_proj_dof.block(0, 0, n_ten_cbs, 1) = x_proj_ten_dof; + x_proj_dof.block(n_ten_cbs, 0, n_vec_cbs, 1) = x_proj_vec_dof; + scatter_cell_dof_data(msh, cell, x_glob, x_proj_dof); + } + } + + Matrix project_ten_function(const Mesh& msh, const typename Mesh::cell_type& cell, + std::function(const typename Mesh::point_type& )> ten_fun){ + + Matrix mass_matrix = symmetric_tensor_mass_matrix(msh, cell); + size_t dim = Mesh::dimension; + auto gradeg = m_hho_di.grad_degree(); + auto ten_bs = disk::sym_matrix_basis_size(gradeg, dim, dim); + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, gradeg); + Matrix rhs = Matrix::Zero(ten_bs); + + const auto qps = integrate(msh, cell, 2 * gradeg); + for (auto& qp : qps) + { + auto phi = ten_b.eval_functions(qp.point()); + disk::static_matrix sigma = ten_fun(qp.point()); + for (size_t i = 0; i < ten_bs; i++){ + auto qp_phi_i = disk::priv::inner_product(qp.weight(), phi[i]); + rhs(i,0) += disk::priv::inner_product(qp_phi_i,sigma); + } + } + Matrix x_dof = mass_matrix.llt().solve(rhs); + return x_dof; + } + + void project_over_faces(const Mesh& msh, Matrix & x_glob, std::function(const typename Mesh::point_type& )> vec_fun){ + + for (auto& cell : msh) + { + auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) + { + auto face = fcs[i]; + auto fc_id = msh.lookup(face); + bool is_dirichlet_Q = m_bnd.is_dirichlet_face(fc_id); + if (is_dirichlet_Q) + { + continue; + } + Matrix x_proj_dof = project_function(msh, face, m_hho_di.face_degree(), vec_fun); + scatter_face_dof_data(msh, face, x_glob, x_proj_dof); + } + } + } + + void finalize(void) + { + LHS.setFromTriplets( m_triplets.begin(), m_triplets.end() ); + m_triplets.clear(); + } + + void finalize_mass(void) + { + MASS.setFromTriplets( m_mass_triplets.begin(), m_mass_triplets.end() ); + m_mass_triplets.clear(); + } + + Matrix + gather_dof_data( const Mesh& msh, const typename Mesh::cell_type& cl, + const Matrix& x_glob) const + { + auto num_faces = howmany_faces(msh, cl); + auto cell_ofs = disk::offset(msh, cl); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_dof = n_cbs + num_faces * n_fbs; + + Matrix x_el(n_dof); + x_el.block(0, 0, n_cbs, 1) = x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1); + auto fcs = faces(msh, cl); + for (size_t i = 0; i < fcs.size(); i++) + { + auto fc = fcs[i]; + auto eid = find_element_id(msh.faces_begin(), msh.faces_end(), fc); + if (!eid.first) throw std::invalid_argument("This is a bug: face not found"); + const auto face_id = eid.second; + + if (m_bnd.is_dirichlet_face( face_id)) + { + auto fb = make_vector_monomial_basis(msh, fc, m_hho_di.face_degree()); + auto dirichlet_fun = m_bnd.dirichlet_boundary_func(face_id); + Matrix mass = make_mass_matrix(msh, fc, fb); + Matrix rhs = make_rhs(msh, fc, fb, dirichlet_fun); + x_el.block(n_cbs + i * n_fbs, 0, n_fbs, 1) = mass.llt().solve(rhs); + } + else + { + auto face_ofs = disk::offset(msh, fc); + auto global_ofs = n_cbs * msh.cells_size() + m_compress_indexes.at(face_ofs)*n_fbs; + x_el.block(n_cbs + i*n_fbs, 0, n_fbs, 1) = x_glob.block(global_ofs, 0, n_fbs, 1); + } + } + return x_el; + } + + void scatter_cell_dof_data( const Mesh& msh, const typename Mesh::cell_type& cell, + Matrix& x_glob, Matrix & x_proj_dof) const + { + auto cell_ofs = disk::offset(msh, cell); + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + x_glob.block(cell_ofs * n_cbs, 0, n_cbs, 1) = x_proj_dof; + } + + void scatter_face_dof_data( const Mesh& msh, const typename Mesh::face_type& face, + Matrix& x_glob, Matrix & x_proj_dof) const + { + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_cells = msh.cells_size(); + auto face_offset = disk::offset(msh, face); + auto glob_offset = n_cbs * n_cells + m_compress_indexes.at(face_offset)*n_fbs; + x_glob.block(glob_offset, 0, n_fbs, 1) = x_proj_dof; + } + + std::pair< Matrix, + Matrix > + strain_tensor_reconstruction(const Mesh& msh, const typename Mesh::cell_type& cell) { + + using T = typename Mesh::coordinate_type; + typedef Matrix matrix_type; + + const size_t N = Mesh::dimension; + + auto graddeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_b = make_sym_matrix_monomial_basis(msh, cell, graddeg); + auto vec_b = make_vector_monomial_basis(msh, cell, celdeg); + + auto ten_bs = disk::sym_matrix_basis_size(graddeg, Mesh::dimension, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + auto fbs = disk::vector_basis_size(facdeg, Mesh::dimension - 1, Mesh::dimension); + + auto num_faces = howmany_faces(msh, cell); + + matrix_type gr_lhs = matrix_type::Zero(ten_bs, ten_bs); + matrix_type gr_rhs = matrix_type::Zero(ten_bs, vec_bs + num_faces * fbs); + + const auto qps = integrate(msh, cell, 2 * graddeg); + + size_t dec = 0; + if (N == 3) + dec = 6; + else if (N == 2) + dec = 3; + else + std::logic_error("Expected 3 >= dim > 1"); + + for (auto& qp : qps) { + const auto gphi = ten_b.eval_functions(qp.point()); + for (size_t j = 0; j < ten_bs; j++) { + auto qp_gphi_j = disk::priv::inner_product(qp.weight(), gphi[j]); + for (size_t i = j; i < ten_bs; i += dec){ + gr_lhs(i, j) += disk::priv::inner_product(gphi[i], qp_gphi_j); + } + } + } + + for (size_t j = 0; j < ten_bs; j++) + for (size_t i = 0; i < j; i++) + gr_lhs(i, j) = gr_lhs(j, i); + if (celdeg > 0) { + const auto qpc = integrate(msh, cell, graddeg + celdeg - 1); + for (auto& qp : qpc) { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto dphi = vec_b.eval_sgradients(qp.point()); + const auto qp_dphi = disk::priv::inner_product(qp.weight(), dphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) += disk::priv::outer_product(gphi, qp_dphi); + } + } + + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + const auto fcs = faces(msh, cell); + for (size_t i = 0; i < fcs.size(); i++) { + const auto fc = fcs[i]; + const auto n = normal(msh, cell, fc); + const auto fb = make_vector_monomial_basis(msh, fc, facdeg); + const auto qps_f = integrate(msh, fc, graddeg + std::max(celdeg, facdeg)); + for (auto& qp : qps_f) { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto cphi = vec_b.eval_functions(qp.point()); + const auto fphi = fb.eval_functions(qp.point()); + const auto qp_gphi_n = disk::priv::inner_product(gphi,disk::priv::inner_product(qp.weight(), n)); + gr_rhs.block(0, vec_bs + i * fbs, ten_bs, fbs) += disk::priv::outer_product(qp_gphi_n, fphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) -= disk::priv::outer_product(qp_gphi_n, cphi); + } + } + const auto fb = make_vector_monomial_basis(msh, fc, facdeg); + + const auto qps_f = integrate(msh, fc, graddeg + std::max(celdeg, facdeg)); + for (auto& qp : qps_f) { + const auto gphi = ten_b.eval_functions(qp.point()); + const auto cphi = vec_b.eval_functions(qp.point()); + const auto fphi = fb.eval_functions(qp.point()); + const auto qp_gphi_n = disk::priv::inner_product(gphi, disk::priv::inner_product(qp.weight(), n)); + gr_rhs.block(0, vec_bs + i * fbs, ten_bs, fbs) += disk::priv::outer_product(qp_gphi_n, fphi); + gr_rhs.block(0, 0, ten_bs, vec_bs) -= disk::priv::outer_product(qp_gphi_n, cphi); + } + } + + auto n_rows = gr_rhs.cols() + ten_bs; + auto n_cols = gr_rhs.cols() + ten_bs; + + // Shrinking data + matrix_type data_mixed = matrix_type::Zero(n_rows,n_cols); + data_mixed.block(0, (ten_bs), ten_bs, n_cols-(ten_bs)) = -gr_rhs; + data_mixed.block((ten_bs), 0, n_rows-(ten_bs), ten_bs) = gr_rhs.transpose(); + + matrix_type oper = gr_lhs.llt().solve(gr_rhs); + return std::make_pair(oper, data_mixed); + } + + Matrix + mixed_rhs(const Mesh& msh, const typename Mesh::cell_type& cell, std::function(const typename Mesh::point_type& )> & rhs_fun, size_t di = 0) + { + auto recdeg = m_hho_di.grad_degree(); + auto celdeg = m_hho_di.cell_degree(); + auto facdeg = m_hho_di.face_degree(); + + auto ten_bs = disk::sym_matrix_basis_size(recdeg, Mesh::dimension, Mesh::dimension); + auto vec_bs = disk::vector_basis_size(celdeg, Mesh::dimension, Mesh::dimension); + size_t n_cbs = ten_bs + vec_bs; + auto cell_basis = make_vector_monomial_basis(msh, cell, celdeg); + using T = typename Mesh::coordinate_type; + + Matrix ret_loc = Matrix::Zero(cell_basis.size()); + Matrix ret = Matrix::Zero(n_cbs); + + const auto qps = integrate(msh, cell, 2 * (celdeg + di)); + + for (auto& qp : qps) + { + const auto phi = cell_basis.eval_functions(qp.point()); + const auto qp_f = disk::priv::inner_product(qp.weight(), rhs_fun(qp.point())); + ret_loc += disk::priv::outer_product(phi, qp_f); + } + ret.block(ten_bs,0,vec_bs,1) = ret_loc; + return ret; + } + + void load_material_data(const Mesh& msh, elastic_material_data material){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh, std::function(const typename Mesh::point_type& )> elastic_mat_fun){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + std::vector mat_data = elastic_mat_fun(bar); + T rho = mat_data[0]; + T vp = mat_data[1]; + T vs = mat_data[2]; + elastic_material_data material(rho,vp,vs); + m_material.push_back(material); + } + } + + void load_material_data(const Mesh& msh){ + m_material.clear(); + m_material.reserve(msh.cells_size()); + T rho = 1.0; + T vp = sqrt(3.0); + T vs = 1.0; + elastic_material_data material(rho,vp,vs); + size_t cell_i = 0; + for (auto& cell : msh) + { + m_material.push_back(material); + cell_i++; + } + } + + void set_hdg_stabilization(){ + if(m_hho_di.cell_degree() > m_hho_di.face_degree()) + { + m_hho_stabilization_Q = false; + std::cout << "Proceeding with HDG stabilization cell degree is higher than face degree." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + }else{ + std::cout << "Proceeding with HHO stabilization cell and face degree are equal." << std::endl; + std::cout << "cell degree = " << m_hho_di.cell_degree() << std::endl; + std::cout << "face degree = " << m_hho_di.face_degree() << std::endl; + } + } + + void set_hho_stabilization(){ + m_hho_stabilization_Q = true; + } + + void set_scaled_stabilization(){ + m_scaled_stabilization_Q = true; + } + + boundary_type & get_bc_conditions(){ + return m_bnd; + } + + std::vector< elastic_material_data > & get_material_data(){ + return m_material; + } + + size_t get_n_face_dof(){ + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + size_t n_face_dof = (m_n_edges - m_n_essential_edges) * n_fbs; + return n_face_dof; + } + + size_t get_n_faces(){ + return m_n_edges - m_n_essential_edges; + } + + size_t get_face_basis_data(){ + size_t n_fbs = disk::vector_basis_size(m_hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + return n_fbs; + } + + size_t get_cell_basis_data(){ + size_t n_ten_cbs = disk::sym_matrix_basis_size(m_hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(m_hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t n_cbs = n_ten_cbs + n_vec_cbs; + return n_cbs; + } +}; + +#endif /* elastodynamic_two_fields_assembler_hpp */ diff --git a/apps/wave_propagation/src/common/erk_butcher_tableau.hpp b/apps/wave_propagation/src/common/erk_butcher_tableau.hpp new file mode 100644 index 00000000..699d01b4 --- /dev/null +++ b/apps/wave_propagation/src/common/erk_butcher_tableau.hpp @@ -0,0 +1,253 @@ +// +// erk_butcher_tableau.hpp +// acoustics +// +// Created by Omar Durán on 5/8/20. +// + +#pragma once +#ifndef erk_butcher_tableau_hpp +#define erk_butcher_tableau_hpp + +#include + +class erk_butcher_tableau +{ + public: + + static void erk_tables(int s, Matrix &a, Matrix &b, Matrix &c){ + + // Mathematical Aspects of Discontinuous Galerkin Methods + // Authors: Di Pietro, Daniele Antonio, Ern, Alexandre + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, 1); + c = Matrix::Zero(s, 1); + + switch (s) { + case 1: + { + a(0,0) = 0.0; + b(0,0) = 1.0; + c(0,0) = 0.0; + } + break; + case 2: + { +// a(0,0) = 0.0; +// a(1,0) = 1.0; +// a(1,1) = 0.0; +// +// b(0,0) = 0.5; +// b(1,0) = 0.5; +// +// c(0,0) = 0.0; +// c(1,0) = 1.0; + + a(0,0) = 0.0; + a(1,0) = 0.5; + a(1,1) = 0.0; + + b(0,0) = 0.0; + b(1,0) = 1.0; + + c(0,0) = 0.0; + c(1,0) = 0.5; + + } + break; + case 3: + { + +// a(0,0) = 0.0; +// a(1,0) = 1.0/3.0; +// a(1,1) = 0.0; +// a(2,0) = 0.0; +// a(2,1) = 2.0/3.0; +// a(2,2) = 0.0; +// +// b(0,0) = 1.0/4.0; +// b(1,0) = 0.0; +// b(2,0) = 3.0/4.0; +// +// c(0,0) = 0.0; +// c(1,0) = 1.0/3.0; +// c(2,0) = 2.0/3.0; + + a(0,0) = 0.0; + a(1,0) = 1.0/2.0; + a(1,1) = 0.0; + a(2,0) = -1.0; + a(2,1) = 2.0; + a(2,2) = 0.0; + + b(0,0) = 1.0/6.0; + b(1,0) = 2.0/3.0; + b(2,0) = 1.0/6.0; + + c(0,0) = 0.0; + c(1,0) = 1.0/2.0; + c(2,0) = 1.0; + + } + break; + case 4: + { + + a(0,0) = 0.0; + a(1,0) = 1.0/2.0; + a(2,0) = 0.0; + a(3,0) = 0.0; + a(1,1) = 0.0; + a(2,1) = 1.0/2.0; + a(3,1) = 0.0; + a(2,2) = 0.0; + a(3,2) = 1.0; + a(3,3) = 0.0; + + b(0,0) = 1.0/6.0; + b(1,0) = 1.0/3.0; + b(2,0) = 1.0/3.0; + b(3,0) = 1.0/6.0; + + c(0,0) = 0.0; + c(1,0) = 1.0/2.0; + c(2,0) = 1.0/2.0; + c(3,0) = 1.0; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + + static void ssprk_tables(int s, Matrix &a, Matrix &b, Matrix &c){ + + // A New Class of Optimal High-Order Strong-Stability-Preserving Time Discretization Methods + // Authors: Raymond J. Spiteri and Steven J. Ruuth + // Apendix B + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, 1); + c = Matrix::Zero(s, 1); + + switch (s) { + case 1: // Order 1 + { + a(0,0) = 0.0; + b(0,0) = 1.0; + c(0,0) = 0.0; + } + break; + case 2: // Order 1 + { + a(0,0) = 0.0; + a(1,0) = 0.5; + a(1,1) = 0.0; + + b(0,0) = 0.5; + b(1,0) = 0.5; + + c(0,0) = 0.0; + c(1,0) = 0.5; + + + } + break; + case 3: // Order 2 + { + + a(0,0) = 0.0; + a(1,0) = 0.5; + a(1,1) = 0.0; + a(2,0) = 0.5; + a(2,1) = 0.5; + a(2,2) = 0.0; + + b(0,0) = 1.0/3.0; + b(1,0) = 1.0/3.0; + b(2,0) = 1.0/3.0; + + c(0,0) = 0.0; + c(1,0) = 1.0/2.0; + c(2,0) = 1.0; + + + } + break; + case 4: // Order 3 + { + + a(0,0) = 0.0; + a(1,0) = 1.0/2.0; + a(2,0) = 1.0/2.0; + a(3,0) = 1.0/6.0; + a(1,1) = 0.0; + a(2,1) = 1.0/2.0; + a(3,1) = 1.0/6.0; + a(2,2) = 0.0; + a(3,2) = 1.0/6.0; + a(3,3) = 0.0; + + b(0,0) = 1.0/6.0; + b(1,0) = 1.0/6.0; + b(2,0) = 1.0/6.0; + b(3,0) = 1.0/2.0; + + c(0,0) = 0.0; + c(1,0) = 1.0/2.0; + c(2,0) = 1.0; + c(3,0) = 1.0/2.0; + + } + break; + case 5: // Order 4 + { + + a(0,0) = 0.0; + a(1,0) = 0.39175222700392; + a(2,0) = 0.21766909633821; + a(3,0) = 0.08269208670950; + a(4,0) = 0.06796628370320; + + a(1,1) = 0.0; + a(2,1) = 0.36841059262959; + a(3,1) = 0.13995850206999; + a(4,1) = 0.11503469844438; + + a(2,2) = 0.0; + a(3,2) = 0.2518917742473; + a(4,2) = 0.20703489864929; + + a(3,3) = 0.0; + a(4,3) = 0.54497475021237; + + b(0,0) = 0.14681187618661; + b(1,0) = 0.24848290924556; + b(2,0) = 0.10425883036650; + b(3,0) = 0.27443890091960; + b(4,0) = 0.22600748319395; + + c(0,0) = 0.0; + c(1,0) = 0.39175222700392; + c(2,0) = 0.58607968896779; + c(3,0) = 0.47454236302687; + c(4,0) = 0.93501063100924; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + +}; + +#endif /* erk_butcher_tableau_hpp */ diff --git a/apps/wave_propagation/src/common/erk_coupling_hho_scheme.hpp b/apps/wave_propagation/src/common/erk_coupling_hho_scheme.hpp new file mode 100644 index 00000000..906e7c63 --- /dev/null +++ b/apps/wave_propagation/src/common/erk_coupling_hho_scheme.hpp @@ -0,0 +1,634 @@ +#ifndef erk_coupling_hho_scheme_hpp +#define erk_coupling_hho_scheme_hpp + +#include +#include +#include +#include +#include "../common/assembly_index.hpp" +#include // Pour std::setw + + +template +class erk_coupling_hho_scheme +{ + private: + + SparseMatrix m_Mc; + SparseMatrix m_Kcc; + SparseMatrix m_Kcf; + SparseMatrix m_Kfc; + SparseMatrix m_Sff; + SparseMatrix m_Scc; + SparseMatrix m_Mc_inv; + SparseMatrix m_Sff_inv; + SparseMatrix m_inv_Sff; + SparseMatrix m_Cg; + + Matrix m_Fc; + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> m_analysis_f; + #else + SimplicialLDLT> m_analysis_f; + #endif + + ConjugateGradient> m_analysis_cg; + + size_t m_n_ec_dof; + size_t m_n_ac_dof; + size_t m_n_c_dof; + size_t m_n_ef_dof; + size_t m_n_af_dof; + size_t m_n_f_dof; + + bool m_sff_is_block_diagonal_Q; + bool m_iterative_solver_Q; + + public: + + erk_coupling_hho_scheme(SparseMatrix & Kg, Matrix & Fg, SparseMatrix & Mg, SparseMatrix & Cg, size_t elastic_cell_dofs, size_t acoustic_cell_dofs, size_t e_face_dofs, size_t a_face_dofs){ + + m_n_ec_dof = elastic_cell_dofs; + m_n_ac_dof = acoustic_cell_dofs; + // m_n_c_dof = m_n_ec_dof + m_n_ac_dof; + m_n_ef_dof = e_face_dofs; + m_n_af_dof = a_face_dofs; + m_n_f_dof = e_face_dofs + a_face_dofs; + m_n_c_dof = Kg.rows() - m_n_f_dof; + + m_Mc = Mg.block( 0, 0, m_n_c_dof, m_n_c_dof); + m_Kcc = Kg.block( 0, 0, m_n_c_dof, m_n_c_dof); + m_Kcf = Kg.block( 0, m_n_c_dof, m_n_c_dof, m_n_f_dof); + m_Kfc = Kg.block(m_n_c_dof, 0, m_n_f_dof, m_n_c_dof); + m_Sff = Kg.block(m_n_c_dof, m_n_c_dof, m_n_f_dof, m_n_f_dof); + + m_Cg = Cg.block(m_n_c_dof, m_n_c_dof, m_n_f_dof, m_n_f_dof); + + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + + m_sff_is_block_diagonal_Q = true; + m_iterative_solver_Q = false; + + } + + void Mcc_inverse(size_t e_cells, size_t a_cells, size_t e_cbs, size_t a_cbs) { + + size_t nnz_cc = e_cbs*e_cbs*e_cells + a_cbs*a_cbs*a_cells; + std::vector< Triplet > triplets_cc; + triplets_cc.resize(nnz_cc); + m_Mc_inv = SparseMatrix(m_n_c_dof, m_n_c_dof); + + #ifdef HAVE_INTEL_TBB + + tbb::parallel_for(size_t(0), size_t(e_cells), size_t(1), + [this,&triplets_cc,&e_cbs] (size_t & cell_ind) { + + size_t stride_eq = cell_ind * e_cbs; + size_t stride_l = cell_ind * e_cbs * e_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, e_cbs, e_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(e_cbs, e_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + }); + tbb::parallel_for(size_t(0), size_t(a_cells), size_t(1), + [this,&triplets_cc,&a_cbs,&e_cbs,&e_cells] (size_t & cell_ind) { + + size_t stride_eq = cell_ind*a_cbs + e_cells*e_cbs; + size_t stride_l = cell_ind*a_cbs*a_cbs + e_cells*e_cbs*e_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, a_cbs, a_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(a_cbs, a_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + }); + + #else + + for (size_t cell_ind = 0; cell_ind < e_cells; cell_ind++) { + size_t stride_eq = cell_ind * e_cbs; + size_t stride_l = cell_ind * e_cbs * e_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, e_cbs, e_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(e_cbs, e_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + } + for (size_t cell_ind = 0; cell_ind < a_cells; cell_ind++) { + size_t stride_eq = cell_ind*a_cbs + e_cells*e_cbs; + size_t stride_l = cell_ind*a_cbs*a_cbs + e_cells*e_cbs*e_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, a_cbs, a_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(a_cbs, a_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + } + + #endif + + m_Mc_inv.setFromTriplets(triplets_cc.begin(), triplets_cc.end()); + triplets_cc.clear(); + return; + + } + + + void Sff_inverse(size_t e_faces, size_t a_faces, size_t e_fbs, size_t a_fbs, std::vector e_compress, std::vector a_compress, std::set elastic_internal_faces, std::set acoustic_internal_faces, std::set interfaces_index) { + + size_t n_interfaces = interfaces_index.size(); // Number of interfaces + size_t nnz_ff = e_fbs*e_fbs*e_faces + a_fbs*a_fbs*a_faces + 2*e_fbs*a_fbs*n_interfaces; // Number of nonzeros + std::vector< Triplet > triplets_ff; + triplets_ff.resize(nnz_ff); + m_Sff_inv = SparseMatrix(m_n_f_dof, m_n_f_dof); // size: number of faces x number of faces + + // Inversion of elastic stabilization + for (size_t face_ind = 0; face_ind < e_faces; face_ind++) { + // std::cout << "Elastic face: " << face_ind << std::endl << std::endl; + size_t stride_eq = face_ind * e_fbs; + size_t stride_l = face_ind * e_fbs * e_fbs; + SparseMatrix S_ff_loc = m_Sff.block(stride_eq, stride_eq, e_fbs, e_fbs); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(S_ff_loc); + analysis_ff.factorize(S_ff_loc); + Matrix S_ff_inv_loc = analysis_ff.solve(Matrix::Identity(e_fbs, e_fbs)); + size_t l = 0; + for (size_t i = 0; i < S_ff_inv_loc.rows(); i++) { + for (size_t j = 0; j < S_ff_inv_loc.cols(); j++) { + triplets_ff[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, S_ff_inv_loc(i,j)); + l++; + } + } + } + + // Inversion of acoustic stabilization + for (size_t face_ind = 0; face_ind < a_faces; face_ind++) { + // std::cout << "Acoutic face: " << e_faces + face_ind << std::endl << std::endl; + size_t stride_eq = e_faces*e_fbs + face_ind*a_fbs ; + size_t stride_l = e_faces*e_fbs*e_fbs + face_ind*a_fbs*a_fbs; + SparseMatrix S_ff_loc = m_Sff.block(stride_eq, stride_eq, a_fbs, a_fbs); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(S_ff_loc); + analysis_ff.factorize(S_ff_loc); + Matrix S_ff_inv_loc = analysis_ff.solve(Matrix::Identity(a_fbs, a_fbs)); + size_t l = 0; + for (size_t i = 0; i < S_ff_inv_loc.rows(); i++) { + for (size_t j = 0; j < S_ff_inv_loc.cols(); j++) { + triplets_ff[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, S_ff_inv_loc(i,j)); + l++; + } + } + } + + // Inversion of coupling terms + size_t cpt = 0; + for (auto face : interfaces_index) { // Parcours des interfaces + size_t e_face_LHS_offset = e_compress.at(face)*e_fbs; // Indice de la face elastique + size_t a_face_LHS_offset = e_faces*e_fbs + a_compress.at(face)*a_fbs; // Indice de la face acoustique + // std::cout << "Interface: " << face << std::endl; + // std::cout << "Elastic interface: " << e_compress.at(face) << std::endl; + // std::cout << "Acoustic interface: " << e_faces + a_compress.at(face) << std::endl << std::endl; + size_t fbs = e_fbs + a_fbs; + size_t e_stride_l = e_compress.at(face)*e_fbs*e_fbs; + size_t a_stride_l = e_faces*e_fbs*e_fbs + a_compress.at(face)*a_fbs*a_fbs; + size_t i_stride_l = e_faces*e_fbs*e_fbs + a_faces*a_fbs*a_fbs + 2*cpt*a_fbs*e_fbs; + + // Extraction du bloc stabilisation local + Matrix dense_SC_ff(fbs, fbs); + SparseMatrix elastic_stab = m_Sff.block(e_face_LHS_offset, e_face_LHS_offset, e_fbs, e_fbs); + SparseMatrix acoustic_stab = m_Sff.block(a_face_LHS_offset, a_face_LHS_offset, a_fbs, a_fbs); + dense_SC_ff.block(0, 0, e_fbs, e_fbs) = elastic_stab; + dense_SC_ff.block(e_fbs, e_fbs, a_fbs, a_fbs) = acoustic_stab; + + // Extraction du bloc coupling + SparseMatrix coupling_ela = m_Cg.block(e_face_LHS_offset, a_face_LHS_offset, e_fbs, a_fbs); + SparseMatrix coupling_acou = m_Cg.block(a_face_LHS_offset, e_face_LHS_offset, a_fbs, e_fbs); + dense_SC_ff.block(0, e_fbs, e_fbs, a_fbs) = coupling_ela; + dense_SC_ff.block(e_fbs, 0, a_fbs, e_fbs) = coupling_acou; + + // Inversion + SparseMatrix SC_ff_loc = dense_SC_ff.sparseView(); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(SC_ff_loc); + analysis_ff.factorize(SC_ff_loc); + Matrix SC_ff_inv_loc = analysis_ff.solve(Matrix::Identity(fbs, fbs)); + + size_t l = 0; + for (size_t i = 0; i < e_fbs; i++) { + for (size_t j = 0; j < e_fbs; j++) { + triplets_ff[e_stride_l+l] = Triplet(e_face_LHS_offset+i, e_face_LHS_offset+j, SC_ff_inv_loc(i,j)); + l++; + } + } + l = 0; + for (size_t i = 0; i < a_fbs; i++) { + for (size_t j = 0; j < a_fbs; j++) { + triplets_ff[a_stride_l+l] = Triplet(a_face_LHS_offset+i, a_face_LHS_offset+j, SC_ff_inv_loc(e_fbs+i,e_fbs+j)); + l++; + } + } + l = 0; + // Upper right bloc + for (size_t i = 0; i < e_fbs; i++) { + for (size_t j = 0; j < a_fbs; j++) { + triplets_ff[i_stride_l+l] = Triplet(e_face_LHS_offset+i, a_face_LHS_offset+j, SC_ff_inv_loc(i,e_fbs+j)); + l++; + } + } + // Lower left bloc + for (size_t i = 0; i < a_fbs; i++) { + for (size_t j = 0; j < e_fbs; j++) { + triplets_ff[i_stride_l+l] = Triplet(a_face_LHS_offset+i, e_face_LHS_offset+j, SC_ff_inv_loc(e_fbs+i,j)); + l++; + } + } + cpt++; + } + + m_Sff_inv.setFromTriplets(triplets_ff.begin(), triplets_ff.end()); + triplets_ff.clear(); + return; + + } + + + void inverse_Sff() { + + // Bi CG + BiCGSTAB> solverBiCG; + solverBiCG.compute(m_Sff); + if (solverBiCG.info() != Success) + std::cout << "Error: Matrix decomposition failed, the matrix may not be invertible"; + SparseMatrix identity(m_Sff.rows(), m_Sff.cols()); + identity.setIdentity(); + m_inv_Sff = solverBiCG.solve(identity); + if (solverBiCG.info() != Success) + std::cout << "Error: Solving the system failed, the matrix may not be invertible"; + + return; + + } + + void setIterativeSolver(T tolerance = 1.0e-11){ + m_iterative_solver_Q = true; + m_analysis_cg.setTolerance(tolerance); + } + + void DecomposeFaceTerm(){ + + if (m_iterative_solver_Q) { + m_analysis_cg.compute(m_Sff); + m_analysis_cg.setMaxIterations(m_Sff.rows()); + } + + else { + m_analysis_f.analyzePattern(m_Sff); + m_analysis_f.factorize(m_Sff); + } + m_sff_is_block_diagonal_Q = false; + } + + void refresh_faces_unknowns(Matrix & x) { + + Matrix x_c_dof = x.block(0, 0, m_n_c_dof, 1); + + // Faces update from cells data + Matrix RHSf = Kfc()*x_c_dof; + if (m_sff_is_block_diagonal_Q) { + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + } + else { + inverse_Sff(); + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_inv_Sff * RHSf; + } + } + + void erk_weight(Matrix & y, Matrix & k) { + + k=y; + Matrix y_c_dof = y.block(0, 0, m_n_c_dof, 1); + Matrix y_f_dof = y.block(m_n_c_dof, 0, m_n_f_dof, 1); + + ////////// CELLS UPDATE + Matrix RHSc = Fc() - Kcc()*y_c_dof - Kcf()*y_f_dof; + Matrix k_c_dof = m_Mc_inv * RHSc; + k.block(0, 0, m_n_c_dof, 1) = k_c_dof; + + // FACES UPDATE + Matrix RHSf = Kfc()*k_c_dof ; + if (m_sff_is_block_diagonal_Q) { + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + } + else { + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_inv_Sff * RHSf; + } + + } + + void erk_lts_weight(const Matrix & y, Matrix & k, const Matrix & w_stage) { + + k=y; + Matrix y_c = y.block(0,0,m_n_c_dof,1); + Matrix y_f = y.block(m_n_c_dof,0,m_n_f_dof,1); + + // CELLS UPDATE + Matrix RHSc = w_stage + Kcc()*y_c + Kcf()*y_f; // w_stage contient déjà les termes (I-P) + Matrix k_c = m_Mc_inv * RHSc; + k.block(0,0,m_n_c_dof,1) = k_c; + + // FACES UPDATE (condensation) + Matrix RHSf = Kfc()*k_c; + if (m_sff_is_block_diagonal_Q) { + k.block(m_n_c_dof,0,m_n_f_dof,1) = - m_Sff_inv * RHSf; + } + else { + k.block(m_n_c_dof,0,m_n_f_dof,1) = - m_inv_Sff * RHSf; + } + + } + + void compute_wi(const Matrix &y, const int n_w, const Eigen::SparseMatrix &IminusP, std::vector &w, std::vector &k) { + + w.resize(n_w); + k.resize(n_w); + int total_dof = m_n_c_dof + m_n_f_dof; + for(int i=0;i Biy = y; // B^i y0 + Matrix tmp(total_dof); + Matrix By_c(m_n_c_dof), By_f(m_n_f_dof); + + for(int i=0; i 0) { + Matrix y_c = Biy.block(0, 0, m_n_c_dof, 1); + Matrix y_f = Biy.block(m_n_c_dof, 0, m_n_f_dof, 1); + + Matrix kc = - m_Mc_inv * (Kcc()*y_c + Kcf()*y_f ); + Matrix kf = - m_Sff_inv * (Kfc()*kc); + + Biy.block(0,0,m_n_c_dof,1) = kc; + Biy.block(m_n_c_dof,0,m_n_f_dof,1) = kf; + } + auto tmp_c = IminusP * Biy.block(0,0,m_n_c_dof,1); + auto tmp_f = - m_Sff_inv * (Kfc()*tmp_c); + + By_c = - m_Mc_inv * ( Kcc() * tmp_c + Kcf() * tmp_f ); + w[i] = By_c; + } + } + + void erk_LTS_weight(Matrix & y, Matrix & k) { + + k=y; + Matrix y_c_dof = y.block(0, 0, m_n_c_dof, 1); + Matrix y_f_dof = y.block(m_n_c_dof, 0, m_n_f_dof, 1); + + ////////// CELLS UPDATE + Matrix RHSc = Fc() - Kcc()*y_c_dof - Kcf()*y_f_dof; + Matrix k_c_dof = m_Mc_inv * RHSc; + k.block(0, 0, m_n_c_dof, 1) = k_c_dof; + + // FACES UPDATE + Matrix RHSf = Kfc()*k_c_dof ; + if (m_sff_is_block_diagonal_Q) { + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + } + else { + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_inv_Sff * RHSf; + } + + } + + Matrix + apply_B(const Matrix& vT) { + Matrix Kcc_v = Kcc() * vT; + Matrix Kfc_v = Kfc() * vT; + Matrix tmpF; + if (m_sff_is_block_diagonal_Q) { + tmpF = m_Sff_inv * Kfc_v; + } + else { + tmpF = m_inv_Sff * Kfc_v; + } + Matrix corr = Kcf() * tmpF; + Matrix result = - m_Mc_inv * (Kcc_v - corr); + return result; + } + + Matrix + apply_B_power(const Matrix& vT, int n) { + Matrix result = vT; + for (int i = 0; i < n; ++i) { + result = apply_B(result); + } + return result; + } + + Matrix + coarse_predictor(int s, Matrix &b, Matrix &c, Matrix & y, SparseMatrix IminusP) { + + Matrix W = Matrix::Zero(m_n_c_dof, s); + Matrix y_c_dof = y.block(0, 0, m_n_c_dof, 1); + + for (int i = 0; i < s; ++i) { + Matrix S = Matrix::Zero(m_n_c_dof); + for (int j = 0; j < s; ++j) { + T coeff = b(j,0) * std::pow(c(j,0), i); + Matrix term = apply_B_power(y_c_dof, i); + for (int ell = 1; ell <= i; ++ell) { + // term += apply_B_power(H(ell-1), i-ell); + } + S += coeff * term; + } + T factor = T(i+1) / tgamma(i+1); + S *= factor; + W.col(i) = apply_B(IminusP * S); + } + + return W; + } + + void compute_k(int r, int m, int s, T Delta_tau, Matrix W, Matrix c, Matrix & y,Matrix k, Matrix a, SparseMatrix P, SparseMatrix IminusP) { + + Matrix k_T = Matrix::Zero(m_n_c_dof,1); + Matrix k_F = Matrix::Zero(m_n_f_dof,1); + + // CELL UPDATE + T alpha = (m + c(r-1,0)) * Delta_tau; + for(int j = 0; j < s; ++j) { + k_T += std::pow(alpha, j) * W.col(j); + } + Matrix tmp = Matrix::Zero(m_n_c_dof,1); + for(int i = 1; i <= r-1; ++i) { + tmp += a(r,i) * k_T; + } + tmp *= Delta_tau; + Matrix y_c = y.block(0, 0, m_n_c_dof, 1); + tmp += y_c; + k_T = apply_B(P * tmp); + + // FACE UPDATE + Matrix RHSf = Kfc()*k_T; + if (m_sff_is_block_diagonal_Q) { + k_F = - m_Sff_inv * RHSf; + } + else { + k_F = - m_inv_Sff * RHSf; + } + + k.block(0, r, m_n_c_dof, 1) = k_T; + k.block(m_n_c_dof, r, m_n_f_dof, 1) = k_F; + + } + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> & FacesAnalysis(){ + return m_analysis_f; + } + #else + SimplicialLDLT> & FacesAnalysis(){ + return m_analysis_f; + } + #endif + + SparseMatrix & Mc(){ + return m_Mc; + } + + SparseMatrix & invMc(){ + return m_Mc_inv; + } + + SparseMatrix & Kcc(){ + return m_Kcc; + } + + SparseMatrix & Kcf(){ + return m_Kcf; + } + + SparseMatrix & Kfc(){ + return m_Kfc; + } + + SparseMatrix & Sff(){ + return m_Sff; + } + + Matrix & Fc(){ + return m_Fc; + } + + void SetFg(Matrix & Fg){ + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + } + + void compute_eigenvalues(std::ostream & simulation_log = std::cout){ + + SparseMatrix A_SCHUR = m_Kcc - m_Kcf*m_Sff_inv*m_Kfc; + SparseMatrix A = A_SCHUR.transpose()*m_Mc_inv*A_SCHUR; + Spectra::SparseSymMatProd opA(A); + Spectra::SparseCholesky opB(m_Mc); + Spectra::SymGEigsSolver, Spectra::SparseCholesky, Spectra::GEigsMode::Cholesky> eigs(opA, opB, 1, 10); + // Initialize and compute + eigs.init(); + eigs.compute(Spectra::SortRule::LargestMagn); + std::cout << std::endl << bold << red << " Computation of the eigenvalues: " << reset; + std::cout << std::endl << bold << cyan << " State of the computation: " << reset; + bool debug = true; + if (debug) { + if(eigs.info() == Spectra::CompInfo::Successful) + std::cout << cyan << bold << "Successful\n"; + if(eigs.info() == Spectra::CompInfo::NotComputed) + std::cout << cyan << bold << "NotComputed\n"; + if(eigs.info() == Spectra::CompInfo::NotConverging) + std::cout << cyan << bold << "NotConverging\n"; + if(eigs.info() == Spectra::CompInfo::NumericalIssue) + std::cout << cyan << bold << "NumericalIssue\n"; + } + eigs.eigenvalues(); + std::cout << bold << cyan << " Eigenvalue found: " << reset << cyan << eigs.eigenvalues() << std::endl << std::endl; + simulation_log << "Eigenvalue found: " << eigs.eigenvalues() << std::endl; + + } + + void compute_eigenvalues_bis(SparseMatrix LHS_STAB, std::pair block_dimension, std::ostream & simulation_log = std::cout){ + + auto ten_bs = block_dimension.first; // Elastic block + auto vec_cell_size = block_dimension.second; // Acoustic block + SparseMatrix m_Scc = LHS_STAB.block(0,0, m_n_c_dof, m_n_c_dof); // Stabilisation + + SparseMatrix Delta = m_Kcf*m_Sff_inv*m_Kfc; + SparseMatrix A_SCHUR = m_Kcc - Delta; + SparseMatrix S_SCHUR = m_Scc - Delta; + SparseMatrix A = A_SCHUR.transpose()*m_Mc_inv*A_SCHUR - S_SCHUR.transpose()*m_Mc_inv*S_SCHUR; + Spectra::SparseSymMatProd opA(A); + Spectra::SparseCholesky opB(m_Mc); + Spectra::SymGEigsSolver, Spectra::SparseCholesky, Spectra::GEigsMode::Cholesky> eigs(opA, opB, 1, 10); + // Initialize and compute + eigs.init(); + eigs.compute(Spectra::SortRule::LargestMagn); + bool debug = true; + if (debug) { + if(eigs.info() == Spectra::CompInfo::Successful) + std::cout << "Successful\n"; + if(eigs.info() == Spectra::CompInfo::NotComputed) + std::cout << "NotComputed\n"; + if(eigs.info() == Spectra::CompInfo::NotConverging) + std::cout << "NotConverging\n"; + if(eigs.info() == Spectra::CompInfo::NumericalIssue) + std::cout << "NumericalIssue\n"; + } + eigs.eigenvalues(); + std::cout << std::endl; + std::cout << bold << red << " Eigenvalue found: " << reset << eigs.eigenvalues(); + simulation_log << "Eigenvalue found: " << eigs.eigenvalues() << std::endl; + + } + +}; + + + + +#endif /* erk_hho_scheme_hpp */ diff --git a/apps/wave_propagation/src/common/erk_hho_scheme.hpp b/apps/wave_propagation/src/common/erk_hho_scheme.hpp new file mode 100644 index 00000000..88c78209 --- /dev/null +++ b/apps/wave_propagation/src/common/erk_hho_scheme.hpp @@ -0,0 +1,292 @@ +// +// erk_hho_scheme.hpp +// acoustics +// +// Created by Omar Durán on 5/8/20. +// + +#ifndef erk_hho_scheme_hpp +#define erk_hho_scheme_hpp + +#include +#include +#include + +template +class erk_hho_scheme +{ + private: + + SparseMatrix m_Mc; + SparseMatrix m_Kcc; + SparseMatrix m_Kcf; + SparseMatrix m_Kfc; + SparseMatrix m_Sff; + SparseMatrix m_Mc_inv; + SparseMatrix m_Sff_inv; + Matrix m_Fc; + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> m_analysis_f; + #else + SimplicialLDLT> m_analysis_f; + #endif + + ConjugateGradient> m_analysis_cg; + + size_t m_n_c_dof; + size_t m_n_f_dof; + bool m_sff_is_block_diagonal_Q; + bool m_iterative_solver_Q; + + public: + + erk_hho_scheme(SparseMatrix & Kg, Matrix & Fg, SparseMatrix & Mg, size_t n_f_dof){ + + + m_n_c_dof = Kg.rows() - n_f_dof; + m_n_f_dof = n_f_dof; + + // Building blocks + m_Mc = Mg.block(0, 0, m_n_c_dof, m_n_c_dof); + m_Kcc = Kg.block(0, 0, m_n_c_dof, m_n_c_dof); + m_Kcf = Kg.block(0, m_n_c_dof, m_n_c_dof, n_f_dof); + m_Kfc = Kg.block(m_n_c_dof,0, n_f_dof, m_n_c_dof); + m_Sff = Kg.block(m_n_c_dof,m_n_c_dof, n_f_dof, n_f_dof); + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + m_sff_is_block_diagonal_Q = false; + m_iterative_solver_Q = false; + } + + void setIterativeSolver(T tolerance = 1.0e-11){ + m_iterative_solver_Q = true; + m_analysis_cg.setTolerance(tolerance); + } + + void DecomposeFaceTerm(){ + + if (m_iterative_solver_Q) { + m_analysis_cg.compute(m_Sff); + m_analysis_cg.setMaxIterations(m_Sff.rows()); + }else{ + m_analysis_f.analyzePattern(m_Sff); + m_analysis_f.factorize(m_Sff); + } + m_sff_is_block_diagonal_Q = false; + } + + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> & FacesAnalysis(){ + return m_analysis_f; + } + #else + SimplicialLDLT> & FacesAnalysis(){ + return m_analysis_f; + } + #endif + + SparseMatrix & Mc(){ + return m_Mc; + } + + SparseMatrix & Kcc(){ + return m_Kcc; + } + + SparseMatrix & Kcf(){ + return m_Kcf; + } + + SparseMatrix & Kfc(){ + return m_Kfc; + } + + SparseMatrix & Sff(){ + return m_Sff; + } + + Matrix & Fc(){ + return m_Fc; + } + + void SetFg(Matrix & Fg){ + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + } + + void Kcc_inverse(std::pair cell_basis_data){ + + size_t n_cells = cell_basis_data.first; + size_t n_cbs = cell_basis_data.second; + size_t nnz_cc = n_cbs*n_cbs*n_cells; + std::vector< Triplet > triplets_cc; + triplets_cc.resize(nnz_cc); + m_Mc_inv = SparseMatrix( m_n_c_dof, m_n_c_dof ); + #ifdef HAVE_INTEL_TBB + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&triplets_cc,&n_cbs] (size_t & cell_ind){ + + size_t stride_eq = cell_ind * n_cbs; + size_t stride_l = cell_ind * n_cbs * n_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, n_cbs, n_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(n_cbs, n_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) + { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) + { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + } + ); + #else + + for (size_t cell_ind = 0; cell_ind < n_cells; cell_ind++) + { + size_t stride_eq = cell_ind * n_cbs; + size_t stride_l = cell_ind * n_cbs * n_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, n_cbs, n_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(n_cbs, n_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) + { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) + { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + + } + #endif + m_Mc_inv.setFromTriplets( triplets_cc.begin(), triplets_cc.end() ); + triplets_cc.clear(); + return; + + } + + void Sff_inverse(std::pair face_basis_data){ + + size_t n_faces = face_basis_data.first; + size_t n_fbs = face_basis_data.second; + size_t nnz_ff = n_fbs*n_fbs*n_faces; + std::vector< Triplet > triplets_ff; + triplets_ff.resize(nnz_ff); + m_Sff_inv = SparseMatrix( m_n_f_dof, m_n_f_dof ); + #ifdef HAVE_INTEL_TBB + tbb::parallel_for(size_t(0), size_t(n_faces), size_t(1), + [this,&triplets_ff,&n_fbs] (size_t & face_ind){ + + size_t stride_eq = face_ind * n_fbs; + size_t stride_l = face_ind * n_fbs * n_fbs; + + SparseMatrix S_ff_loc = m_Sff.block(stride_eq, stride_eq, n_fbs, n_fbs); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(S_ff_loc); + analysis_ff.factorize(S_ff_loc); + Matrix S_ff_inv_loc = analysis_ff.solve(Matrix::Identity(n_fbs, n_fbs)); + + size_t l = 0; + for (size_t i = 0; i < S_ff_inv_loc.rows(); i++) + { + for (size_t j = 0; j < S_ff_inv_loc.cols(); j++) + { + triplets_ff[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, S_ff_inv_loc(i,j)); + l++; + } + } + } + ); + #else + + for (size_t face_ind = 0; face_ind < n_faces; face_ind++) + { + size_t stride_eq = face_ind * n_fbs; + size_t stride_l = face_ind * n_fbs * n_fbs; + + SparseMatrix S_ff_loc = m_Sff.block(stride_eq, stride_eq, n_fbs, n_fbs); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(S_ff_loc); + analysis_ff.factorize(S_ff_loc); + Matrix S_ff_inv_loc = analysis_ff.solve(Matrix::Identity(n_fbs, n_fbs)); + size_t l = 0; + for (size_t i = 0; i < S_ff_inv_loc.rows(); i++) + { + for (size_t j = 0; j < S_ff_inv_loc.cols(); j++) + { + triplets_ff[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, S_ff_inv_loc(i,j)); + l++; + } + } + + } + #endif + m_Sff_inv.setFromTriplets( triplets_ff.begin(), triplets_ff.end() ); + triplets_ff.clear(); + m_sff_is_block_diagonal_Q = true; + return; + + } + + void refresh_faces_unknowns(Matrix & x){ + + Matrix x_c_dof = x.block(0, 0, m_n_c_dof, 1); + + // Faces update from cells data + Matrix RHSf = Kfc()*x_c_dof; + if (m_sff_is_block_diagonal_Q) { + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + }else{ + if (m_iterative_solver_Q) { + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = -m_analysis_cg.solve(RHSf); // new state + }else{ + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = -FacesAnalysis().solve(RHSf); // new state + } + } + + } + + void erk_weight(Matrix & y, Matrix & k){ + + k=y; + Matrix y_c_dof = y.block(0, 0, m_n_c_dof, 1); + Matrix y_f_dof = y.block(m_n_c_dof, 0, m_n_f_dof, 1); + + // Cells update + Matrix RHSc = Fc() - Kcc()*y_c_dof - Kcf()*y_f_dof; + Matrix k_c_dof = m_Mc_inv * RHSc; + k.block(0, 0, m_n_c_dof, 1) = k_c_dof; + + // Faces update + Matrix RHSf = Kfc()*k_c_dof; + if (m_sff_is_block_diagonal_Q) { + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + }else{ + if (m_iterative_solver_Q) { + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = -m_analysis_cg.solve(RHSf); // new state + std::cout << "Number of iterations (CG): " << m_analysis_cg.iterations() << std::endl; + std::cout << "Estimated error: " << m_analysis_cg.error() << std::endl; + }else{ + k.block(m_n_c_dof, 0, m_n_f_dof, 1) = -FacesAnalysis().solve(RHSf); // new state + } + } + + } + + + +}; + +#endif /* erk_hho_scheme_hpp */ diff --git a/apps/wave_propagation/src/common/fitted_geometry_builders.hpp b/apps/wave_propagation/src/common/fitted_geometry_builders.hpp new file mode 100644 index 00000000..1c27edc5 --- /dev/null +++ b/apps/wave_propagation/src/common/fitted_geometry_builders.hpp @@ -0,0 +1,945 @@ +// +// fitted_geometry_builder.hpp +// +// Created by Omar Durán +// Contributor: Romain Mottier + + +#pragma once +#ifndef fitted_geometry_builder_hpp +#define fitted_geometry_builder_hpp + +#include +#include +#include +#include +#include +#include +#include +#include "diskpp/geometry/geometry.hpp" +#include + + +template +class fitted_geometry_builder { + +protected: + + std::string m_log_file = "mesh_log.txt"; + + size_t m_dimension = 0; + + size_t m_n_elements = 0; + +public: + + fitted_geometry_builder() { + + } + + // set the log file name + void set_log_file(std::string log_file) { + m_log_file = log_file; + } + + // get the geometry dimension + size_t get_dimension() { + return m_dimension; + } + + // get the number of elements + size_t get_n_elements() { + return m_n_elements; + } + + // build the mesh + virtual bool build_mesh() = 0; + + // move generated mesh data to an external mesh storage + virtual void move_to_mesh_storage(MESH& msh) = 0; + + // Print in log file relevant mesh information + virtual void print_log_file() = 0; + + virtual ~ fitted_geometry_builder() { + + } + +}; + +template +class cartesian_2d_mesh_builder : public fitted_geometry_builder> +{ + typedef disk::generic_mesh mesh_type; + typedef typename mesh_type::point_type point_type; + typedef typename mesh_type::node_type node_type; + typedef typename mesh_type::edge_type edge_type; + typedef typename mesh_type::surface_type surface_type; + + struct polygon_2d + { + std::vector m_member_nodes; + std::set> m_member_edges; + bool operator<(const polygon_2d & other) { + return m_member_nodes < other.m_member_nodes; + } + }; + + std::vector points; + std::vector vertices; + std::vector> facets; + std::vector> skeleton_edges; + std::vector> boundary_edges; + std::vector polygons; + + + T m_lx = 0.0; + T m_ly = 0.0; + + T m_x_t = 0.0; + T m_y_t = 0.0; + + size_t m_nx = 0; + size_t m_ny = 0; + + void reserve_storage(){ + size_t n_points = (m_nx + 1) * (m_ny + 1); + points.reserve(n_points); + vertices.reserve(n_points); + + size_t n_edges = 2*m_nx*m_ny + m_nx + m_ny; + size_t n_skel_edges = 2*m_nx*m_ny + m_nx + m_ny; + size_t n_bc_edges = n_edges - n_skel_edges; + skeleton_edges.reserve(n_skel_edges); + boundary_edges.reserve(n_bc_edges); + + size_t n_polygons = m_nx * m_ny; + polygons.reserve(n_polygons); + } + + void validate_edge(std::array & edge){ + assert(edge[0] != edge[1]); + if (edge[0] > edge[1]){ + std::swap(edge[0], edge[1]); + } + } + +public: + + cartesian_2d_mesh_builder(T lx, T ly, size_t nx, size_t ny) : fitted_geometry_builder() + { + m_lx = lx; + m_ly = ly; + m_nx = nx; + m_ny = ny; + fitted_geometry_builder::m_dimension = 2; + } + + // uniform refinement x-direction + void refine_mesh_x_direction(size_t n_refinements){ + for (unsigned int i = 0; i < n_refinements; i++) { + m_nx *= 2; + } + } + + // uniform refinement y-direction + void refine_mesh_y_direction(size_t n_refinements){ + for (unsigned int i = 0; i < n_refinements; i++) { + m_ny *= 2; + } + } + + // uniform refinement + void refine_mesh(size_t n_refinements){ + refine_mesh_x_direction(n_refinements); + refine_mesh_y_direction(n_refinements); + } + + // build the mesh + bool build_mesh(){ + + reserve_storage(); + + std::vector range_x(m_nx+1,0.0); + T dx = m_lx/T(m_nx); + for (unsigned int i = 0; i <= m_nx; i++) { + range_x[i] = i*dx; + } + + std::vector range_y(m_ny+1,0.0); + T dy = m_ly/T(m_ny); + for (unsigned int i = 0; i <= m_ny; i++) { + range_y[i] = i*dy; + } + + size_t node_id = 0; + for (unsigned int j = 0; j <= m_ny; j++) { + T yv = range_y[j] + m_y_t; + for (unsigned int i = 0; i <= m_nx; i++) { + T xv = range_x[i] + m_x_t; + point_type point(xv, yv); + points.push_back(point); + vertices.push_back(node_type(disk::point_identifier<2>(node_id))); + node_id++; + } + } + + size_t edge_id = 0; + for (size_t j = 0; j < m_ny; j++) { + for (size_t i = 0; i < m_nx; i++) { + + size_t id_0 = i + j * (m_nx + 1); + size_t id_1 = id_0 + 1; + size_t id_2 = i + (m_nx + 1) + 1 + j* (m_nx + 1); + size_t id_3 = id_2 - 1; + + // Adding edges: Cases to avoid edge duplicity + if (i==0 && j==0) { + + std::array e0 = {id_0,id_1}; + validate_edge(e0); + facets.push_back( e0 ); + boundary_edges.push_back( e0 ); + edge_id++; + + std::array e1 = {id_1,id_2}; + validate_edge(e1); + facets.push_back( e1 ); + if(j == m_ny - 1) boundary_edges.push_back( e1 ); + edge_id++; + + std::array e2 = {id_2,id_3}; + validate_edge(e2); + facets.push_back( e2 ); + edge_id++; + + std::array e3 = {id_3,id_0}; + validate_edge(e3); + facets.push_back( e3 ); + boundary_edges.push_back( e3 ); + edge_id++; + } + + if ((i>0 && i < m_nx) && j==0) { + std::array e0 = {id_0,id_1}; + validate_edge(e0); + facets.push_back( e0 ); + boundary_edges.push_back( e0 ); + edge_id++; + + std::array e1 = {id_1,id_2}; + validate_edge(e1); + facets.push_back( e1 ); + if(i == m_nx - 1) boundary_edges.push_back( e1 ); + edge_id++; + + std::array e2 = {id_2,id_3}; + validate_edge(e2); + facets.push_back( e2 ); + if(j == m_ny - 1) boundary_edges.push_back( e2 ); + edge_id++; + } + if (i==0 && j>0) { + + std::array e1 = {id_1,id_2}; + validate_edge(e1); + facets.push_back( e1 ); + edge_id++; + + std::array e2 = {id_2,id_3}; + validate_edge(e2); + facets.push_back( e2 ); + if(j == m_ny - 1) boundary_edges.push_back( e2 ); + edge_id++; + + std::array e3 = {id_3,id_0}; + validate_edge(e3); + boundary_edges.push_back( e3 ); + facets.push_back( e3 ); + edge_id++; + } + + if (i>0 && j>0) { + + std::array e1 = {id_1,id_2}; + validate_edge(e1); + facets.push_back( e1 ); + if(i == m_nx - 1) boundary_edges.push_back( e1 ); + edge_id++; + + std::array e2 = {id_2,id_3}; + validate_edge(e2); + facets.push_back( e2 ); + if(j == m_ny - 1) boundary_edges.push_back( e2 ); + edge_id++; + + } + } + } + + size_t surface_id = 0; + for (size_t j = 0; j < m_ny; j++) { + for (size_t i = 0; i < m_nx; i++) { + + size_t id_0 = i + j * (m_nx + 1); + size_t id_1 = id_0 + 1; + size_t id_2 = i + (m_nx + 1) + 1 + j* (m_nx + 1); + size_t id_3 = id_2 - 1; + + polygon_2d polygon; + polygon.m_member_nodes = {id_0,id_1,id_2,id_3}; + std::array e0 = {id_0,id_1}; + validate_edge(e0); + std::array e1 = {id_1,id_2}; + validate_edge(e1); + std::array e2 = {id_2,id_3}; + validate_edge(e2); + std::array e3 = {id_3,id_0}; + validate_edge(e3); + + polygon.m_member_edges = {e0,e1,e2,e3}; + polygons.push_back( polygon ); + surface_id++; + + } + } + + // std::cout << bold << red << std::endl << std::endl; + // std::cout << "Debug mesh" << std::endl; + // std::cout << reset << "Points: " << vertices.size() << std::endl; + // std::cout << reset << "Polygons: " << polygons.size() << std::endl; + // std::cout << reset << "Boundaries: " << boundary_edges.size() << std::endl; + // std::cout << reset << "Facets: " << facets.size() << std::endl; + return true; + } + + void move_to_mesh_storage(mesh_type& msh){ + + auto storage = msh.backend_storage(); + storage->points = std::move(points); + storage->nodes = std::move(vertices); + + std::vector edges; + edges.reserve(facets.size()); + for (size_t i = 0; i < facets.size(); i++) + { + assert(facets[i][0] < facets[i][1]); + auto node1 = typename node_type::id_type(facets[i][0]); + auto node2 = typename node_type::id_type(facets[i][1]); + + auto e = edge_type(node1, node2); + + // e.set_point_ids(facets[i].begin(), facets[i].end()); + edges.push_back(e); + + } + std::sort(edges.begin(), edges.end()); + + storage->boundary_info.resize(edges.size()); + for (size_t i = 0; i < boundary_edges.size(); i++) + { + assert(boundary_edges[i][0] < boundary_edges[i][1]); + auto node1 = typename node_type::id_type(boundary_edges[i][0]); + auto node2 = typename node_type::id_type(boundary_edges[i][1]); + + auto e = edge_type(node1, node2); + + auto position = find_element_id(edges.begin(), edges.end(), e); + + if (position.first == false) + { + std::cout << "Bad bug at " << __FILE__ << "(" + << __LINE__ << ")" << std::endl; + return; + } + + disk::boundary_descriptor bi{0, true}; + storage->boundary_info.at(position.second) = bi; + } + + storage->edges = std::move(edges); + + std::vector surfaces; + surfaces.reserve( polygons.size() ); + + for (auto& p : polygons) + { + std::vector surface_edges; + for (auto& e : p.m_member_edges) + { + assert(e[0] < e[1]); + auto n1 = typename node_type::id_type(e[0]); + auto n2 = typename node_type::id_type(e[1]); + + edge_type edge(n1, n2); + auto edge_id = find_element_id(storage->edges.begin(), + storage->edges.end(), edge); + if (!edge_id.first) + { + std::cout << "Bad bug at " << __FILE__ << "(" + << __LINE__ << ")" << std::endl; + return; + } + + surface_edges.push_back(edge_id.second); + } + auto surface = surface_type(surface_edges); + surface.set_point_ids(p.m_member_nodes.begin(), p.m_member_nodes.end()); + surfaces.push_back( surface ); + } + + std::sort(surfaces.begin(), surfaces.end()); + storage->surfaces = std::move(surfaces); + + } + + void set_translation_data(T x_t, T y_t){ + m_x_t = x_t; + m_y_t = y_t; + } + + size_t get_nx(){ + return m_nx; + } + + size_t get_ny(){ + return m_ny; + } + + // Print in log file relevant mesh information + void print_log_file(){ + fitted_geometry_builder::m_n_elements = polygons.size(); + std::ofstream file; + file.open (fitted_geometry_builder::m_log_file.c_str()); + file << "Number of surfaces : " << polygons.size() << std::endl; + file << "Number of skeleton edges : " << skeleton_edges.size() << std::endl; + file << "Number of boundary edges : " << boundary_edges.size() << std::endl; + file << "Number of vertices : " << vertices.size() << std::endl; + file.close(); + } + +}; + + +template +class polygon_2d_mesh_reader : + +public fitted_geometry_builder> { + + typedef disk::generic_mesh mesh_type; + typedef typename mesh_type::point_type point_type; + typedef typename mesh_type::node_type node_type; + typedef typename mesh_type::edge_type edge_type; + typedef typename mesh_type::surface_type surface_type; + +public: + + struct polygon_2d { + std::vector m_member_nodes; + std::set> m_member_edges; + int m_material; + bool m_elastic_material; + + bool operator<(const polygon_2d & other) { + return m_member_nodes < other.m_member_nodes; + } + }; + + // struct FaceInfo { + // size_t face_id; + // size_t cell1_id = -1; + // size_t cell2_id = -1; + // }; + + std::vector points; + std::vector vertices; + std::vector> facets; + std::vector> interfaces; + std::vector> skeleton_edges; + std::vector> boundary_edges; + std::vector polygons; + std::string poly_mesh_file; + std::set bc_points; + + void clear_storage() { + points.clear(); + vertices.clear(); + skeleton_edges.clear(); + boundary_edges.clear(); + polygons.clear(); + bc_points.clear(); + } + + void reserve_storage(){ + + std::ifstream input; + input.open(poly_mesh_file.c_str()); + + size_t n_points, n_polygons, n_bc_curves, n_bc_edges, n_edges; + if (input.is_open()) { + std::string line; + std::getline(input, line); + std::stringstream(line) >> n_points >> n_polygons >> n_bc_curves; + for(size_t id = 0; id < n_points; id++){ + if(std::getline(input, line)){ + + } + else{ + break; + } + } + + n_edges = 0; + n_bc_edges = 0; + size_t n_polygon_vertices; + for(size_t surface_id=0; surface_id < n_polygons; surface_id++) + { + if(std::getline(input, line)){ + std::stringstream(line) >> n_polygon_vertices; + n_edges += n_polygon_vertices; + } + else{ + break; + } + } + + bc_points.clear(); + size_t bc_point_id; + for(size_t bc_id=0; bc_id < n_bc_curves; bc_id++) + { + if(std::getline(input, line)){ + std::stringstream input_line(line); + while(!input_line.eof()){ + input_line >> bc_point_id; + bc_point_id--; + bc_points.insert(bc_point_id); + } + } + else{ + break; + } + } + n_bc_edges = bc_points.size(); + + points.reserve(n_points); + vertices.reserve(n_points); + + size_t n_skel_edges = n_edges - n_bc_edges; + skeleton_edges.reserve(n_skel_edges); + boundary_edges.reserve(n_bc_edges); + polygons.reserve(n_polygons); + + } + } + + void validate_edge(std::array & edge){ + assert(edge[0] != edge[1]); + if (edge[0] > edge[1]){ + std::swap(edge[0], edge[1]); + } + } + + polygon_2d_mesh_reader() : fitted_geometry_builder() + { + fitted_geometry_builder::m_dimension = 2; + } + + void set_poly_mesh_file(std::string mesh_file){ + poly_mesh_file = mesh_file; + } + + // build the mesh + bool build_mesh(){ + + clear_storage(); + reserve_storage(); + + std::ifstream input; + input.open(poly_mesh_file.c_str()); + + size_t n_points, n_polygons, n_bc_curves; + if (input.is_open()) { + std::string line; + std::getline(input, line); + std::stringstream(line) >> n_points >> n_polygons >> n_bc_curves; + + T xv, yv; + for(size_t id = 0; id < n_points; id++){ + if(std::getline(input, line)){ + std::stringstream(line) >> xv >> yv; + point_type point(xv, yv); + points.push_back(point); + vertices.push_back(node_type(disk::point_identifier<2>(id))); + } + else{ + break; + } + } + + size_t n_polygon_vertices, id; + for(size_t surface_id=0; surface_id < n_polygons; surface_id++) { + + if(std::getline(input, line)){ + std::stringstream input_line(line); + input_line >> n_polygon_vertices; + + polygon_2d polygon; + std::vector member_nodes; + for (size_t i = 0; i < n_polygon_vertices; i++) { + input_line >> id; + id--; + member_nodes.push_back(id); + } + polygon.m_member_nodes = member_nodes; + assert(member_nodes.size() == n_polygon_vertices); + + std::set< std::array > member_edges; + std::array edge; + for (size_t i = 0; i < member_nodes.size(); i++) { + + if (i == n_polygon_vertices - 1) { + edge = {member_nodes[i],member_nodes[0]}; + } + + else { + edge = {member_nodes[i],member_nodes[i+1]}; + } + + validate_edge(edge); + facets.push_back( edge ); + member_edges.insert(edge); + + bool is_bc_point_l_Q = bc_points.find(edge.at(0)) != bc_points.end(); + bool is_bc_point_r_Q = bc_points.find(edge.at(1)) != bc_points.end(); + if (is_bc_point_l_Q && is_bc_point_r_Q) { + boundary_edges.push_back( edge ); + } + } + + polygon.m_member_edges = member_edges; + + polygons.push_back( polygon ); + + } + + else { + break; + } + } + } + + // Duplicated facets are eliminated + std::sort( facets.begin(), facets.end() ); + facets.erase( std::unique( facets.begin(), facets.end() ), facets.end() ); + + // std::cout << bold << red << std::endl << std::endl; + // std::cout << "Debug mesh" << std::endl; + // std::cout << reset << "Points: " << vertices.size() << std::endl; + // std::cout << reset << "Polygons: " << polygons.size() << std::endl; + // std::cout << reset << "Boundaries: " << boundary_edges.size() << std::endl; + // std::cout << reset << "Facets: " << facets.size() << std::endl; + + return true; + } + + // build the mesh + bool build_bassin(){ + + clear_storage(); + reserve_storage(); + + std::ifstream input; + input.open(poly_mesh_file.c_str()); + + size_t n_points, n_polygons, n_bc_curves; + if (input.is_open()) { + std::string line; + std::getline(input, line); + std::stringstream(line) >> n_points >> n_polygons >> n_bc_curves; + + T xv, yv; + for(size_t id = 0; id < n_points; id++){ + if(std::getline(input, line)){ + std::stringstream(line) >> xv >> yv; + point_type point(xv, yv); + points.push_back(point); + vertices.push_back(node_type(disk::point_identifier<2>(id))); + } + else{ + break; + } + } + + size_t n_polygon_vertices, id; + for(size_t surface_id=0; surface_id < n_polygons; surface_id++) { + + if(std::getline(input, line)){ + std::stringstream input_line(line); + input_line >> n_polygon_vertices; + + polygon_2d polygon; + std::vector member_nodes; + int material; + for (size_t i = 0; i < n_polygon_vertices; i++) { + input_line >> id; + id--; + member_nodes.push_back(id); + } + polygon.m_member_nodes = member_nodes; + assert(member_nodes.size() == n_polygon_vertices); + + // FaceInfo face_info; + std::set< std::array > member_edges; + std::array edge; + for (size_t i = 0; i < member_nodes.size(); i++) { + + if (i == n_polygon_vertices - 1) { + edge = {member_nodes[i],member_nodes[0]}; + } + + else { + edge = {member_nodes[i],member_nodes[i+1]}; + } + + validate_edge(edge); + facets.push_back( edge ); + member_edges.insert(edge); + + + bool is_bc_point_l_Q = bc_points.find(edge.at(0)) != bc_points.end(); + bool is_bc_point_r_Q = bc_points.find(edge.at(1)) != bc_points.end(); + if (is_bc_point_l_Q && is_bc_point_r_Q) { + boundary_edges.push_back( edge ); + } + } + + polygon.m_member_edges = member_edges; + polygons.push_back( polygon ); + + } + else { + break; + } + } + + + for(size_t bord=0; bord < 4; bord++) { + if(std::getline(input, line)){ + std::stringstream input_line(line); + } + } + + + for(size_t polygon=0; polygon < n_polygons; polygon++) { + size_t material; + if(std::getline(input, line)){ + std::stringstream input_line(line); + input_line >> material; + } + polygons[polygon].m_material = material; + } + + + } + + // Duplicated facets are eliminated + std::sort( facets.begin(), facets.end() ); + facets.erase( std::unique( facets.begin(), facets.end() ), facets.end() ); + + // std::cout << bold << red << std::endl << std::endl; + // std::cout << "Debug mesh" << std::endl; + // std::cout << reset << "Points: " << vertices.size() << std::endl; + // std::cout << reset << "Polygons: " << polygons.size() << std::endl; + // std::cout << reset << "Boundaries: " << boundary_edges.size() << std::endl; + // std::cout << reset << "Facets: " << facets.size() << std::endl; + + return true; + } + + void move_to_mesh_storage(mesh_type& msh){ + + auto storage = msh.backend_storage(); + storage->points = std::move(points); + storage->nodes = std::move(vertices); + + std::vector edges; + edges.reserve(facets.size()); + for (size_t i = 0; i < facets.size(); i++) { + assert(facets[i][0] < facets[i][1]); + auto node1 = typename node_type::id_type(facets[i][0]); + auto node2 = typename node_type::id_type(facets[i][1]); + + auto e = edge_type(node1, node2); + + // e.set_point_ids(facets[i].begin(), facets[i].end()); + edges.push_back(e); + } + std::sort(edges.begin(), edges.end()); + + storage->boundary_info.resize(edges.size()); + for (size_t i = 0; i < boundary_edges.size(); i++) { + assert(boundary_edges[i][0] < boundary_edges[i][1]); + auto node1 = typename node_type::id_type(boundary_edges[i][0]); + auto node2 = typename node_type::id_type(boundary_edges[i][1]); + auto e = edge_type(node1, node2); + auto position = find_element_id(edges.begin(), edges.end(), e); + if (position.first == false) { + std::cout << "Bad bug at " << __FILE__ << "(" + << __LINE__ << ")" << std::endl; + return; + } + disk::boundary_descriptor bi{0, true}; + storage->boundary_info.at(position.second) = bi; + } + + storage->edges = std::move(edges); + + std::vector surfaces; + surfaces.reserve( polygons.size() ); + + std::vector materials; + materials.reserve( polygons.size() ); + + int compteur = 0; + for (auto& p : polygons) { + compteur = compteur + 1; + std::vector surface_edges; + for (auto& e : p.m_member_edges) { + assert(e[0] < e[1]); + auto n1 = typename node_type::id_type(e[0]); + auto n2 = typename node_type::id_type(e[1]); + + edge_type edge(n1, n2); + auto edge_id = find_element_id(storage->edges.begin(), + storage->edges.end(), edge); + if (!edge_id.first) + { + std::cout << "Bad bug at " << __FILE__ << "(" + << __LINE__ << ")" << std::endl; + return; + } + + surface_edges.push_back(edge_id.second); + + + } + auto surface = surface_type(surface_edges); + surface.set_point_ids(p.m_member_nodes.begin(), p.m_member_nodes.end()); + surfaces.push_back( surface ); + materials.push_back(p.m_material); + } + + ////////////////////////////// Trie pour les matériaux + std::vector> pairedVec; + for (size_t i = 0; i < surfaces.size(); ++i) { + pairedVec.push_back(std::make_pair(surfaces[i], materials[i])); + } + // Trier les paires en fonction des valeurs (les surfaces dans ce cas) + std::sort(pairedVec.begin(), pairedVec.end(), [](const auto& left, const auto& right) { + return left.first < right.first; + }); + // Réorganiser le vecteur material en fonction des indices triés + std::vector sortedMaterial; + for (const auto& pair : pairedVec) { + sortedMaterial.push_back(pair.second); + } + // Mettre à jour le vecteur material + for (size_t i = 0; i < surfaces.size(); ++i) { + polygons[i].m_material = sortedMaterial[i]; + if (polygons[i].m_material == 1 || polygons[i].m_material == 2) { + polygons[i].m_elastic_material = true; + } + else { + polygons[i].m_elastic_material = false; + } + } + ////////////////////////////////////////////////// + + std::sort(surfaces.begin(), surfaces.end()); + storage->surfaces = std::move(surfaces); + + } + + // Print in log file relevant mesh information + void print_log_file(){ + fitted_geometry_builder::m_n_elements = polygons.size(); + std::ofstream file; + file.open (fitted_geometry_builder::m_log_file.c_str()); + file << "Number of polygons : " << polygons.size() << std::endl; + file << "Number of skeleton edges : " << skeleton_edges.size() << std::endl; + file << "Number of boundary edges : " << boundary_edges.size() << std::endl; + file << "Number of vertices : " << vertices.size() << std::endl; + file.close(); + } + + const std::vector& getPoints() const { + return points; + } + + const std::vector& getVertices() const { + return vertices; + } + + const std::vector>& getFacets() const { + return facets; + } + + const std::vector>& getSkeletonEdges() const { + return skeleton_edges; + } + + const std::vector>& getBoundaryEdges() const { + return boundary_edges; + } + + const std::vector& getPolygons() const { + return polygons; + } + + // Définissez la fonction remove_duplicate_points comme membre de la classe + void remove_duplicate_points() { + std::unordered_map point_mapping; // Map old point indices to new point indices + std::vector unique_points; // Unique points + + for (size_t i = 0; i < points.size(); ++i) { + if (point_mapping.find(i) == point_mapping.end()) { + // This is a new unique point + point_mapping[i] = unique_points.size(); + unique_points.push_back(points[i]); + } + } + + // Update cell and face data with unique point indices + for (auto& polygon : polygons) { + for (size_t i = 0; i < polygon.m_member_nodes.size(); ++i) { + size_t old_point_index = polygon.m_member_nodes[i]; + polygon.m_member_nodes[i] = point_mapping[old_point_index]; + } + + std::set> updated_edges; + for (const auto& edge : polygon.m_member_edges) { + size_t old_point1 = edge[0]; + size_t old_point2 = edge[1]; + size_t new_point1 = point_mapping[old_point1]; + size_t new_point2 = point_mapping[old_point2]; + updated_edges.insert({new_point1, new_point2}); + } + polygon.m_member_edges = updated_edges; + } + + // Update the internal mesh_reader data with the unique points + points = unique_points; + + // Update the vertices + vertices.clear(); + for (size_t i = 0; i < unique_points.size(); ++i) { + vertices.push_back(node_type()); + } + } + +}; + +#endif /* fitted_geometry_builder_hpp */ + + + diff --git a/apps/wave_propagation/src/common/linear_solver.hpp b/apps/wave_propagation/src/common/linear_solver.hpp new file mode 100644 index 00000000..7e254815 --- /dev/null +++ b/apps/wave_propagation/src/common/linear_solver.hpp @@ -0,0 +1,339 @@ +// +// linear_solver.hpp +// acoustics +// +// Created by Omar Durán on 5/2/20. +// + +#pragma once +#ifndef linear_solver_hpp +#define linear_solver_hpp + +#include "diskpp/solvers/solver.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class linear_solver +{ + + private: + + SparseMatrix m_Kcc; + SparseMatrix m_Kcf; + SparseMatrix m_Kfc; + SparseMatrix m_Kff; + Matrix m_Fc; + Matrix m_Ff; + + SparseMatrix m_Kcc_inv; + SparseMatrix m_K; + Matrix m_F; + + #ifdef HAVE_INTEL_MKL + PardisoLU> m_analysis; + #else + SparseLU> m_analysis; + #endif + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> m_symm_analysis; + #else + SimplicialLDLT> m_symm_analysis; + #endif + + ConjugateGradient> m_analysis_cg; + BiCGSTAB,IncompleteLUT> m_analysis_bi_cg; + + size_t m_n_c_dof; + size_t m_n_f_dof; + bool m_global_sc_Q; + bool m_is_decomposed_Q; + std::pair m_iterative_solver_Q; + T m_tolerance; + + + void DecomposeK(){ + if (!m_iterative_solver_Q.first) { + if (m_iterative_solver_Q.second) { + m_symm_analysis.analyzePattern(m_K); + m_symm_analysis.factorize(m_K); + } + else{ + m_analysis.analyzePattern(m_K); + m_analysis.factorize(m_K); + } + } + } + + Matrix solve_global(Matrix & Fg){ + if (m_iterative_solver_Q.first) { + if (m_iterative_solver_Q.second) { + Matrix x_dof = m_analysis_cg.solve(Fg); + std::cout << "Number of iterations (CG): " << m_analysis_cg.iterations() << std::endl; + std::cout << "Estimated error: " << m_analysis_cg.error() << std::endl; + return x_dof; + } + else { + Matrix x_dof = m_analysis_bi_cg.solve(Fg); + std::cout << "Number of iterations (BiCG): " << m_analysis_bi_cg.iterations() << std::endl; + std::cout << "Estimated error: " << m_analysis_bi_cg.error() << std::endl; + return x_dof; + } + } + else { + if (m_iterative_solver_Q.second) { + return m_symm_analysis.solve(Fg); + }else{ + return m_analysis.solve(Fg); + } + } + } + + void scatter_segments(Matrix & Fg){ + assert(m_n_c_dof + m_n_f_dof == Fg.rows()); + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + m_Ff = Fg.block(m_n_c_dof, 0, m_n_f_dof, 1); + } + + Matrix solve_sc(Matrix & Fg){ + + // Split vector into cells and faces dofs + scatter_segments(Fg); + + // Condense vector + Matrix delta_c = m_Kcc_inv*m_Fc; + m_F = m_Ff - m_Kfc*delta_c; + + // face linear solver step + Matrix x_n_f_dof; + if (m_iterative_solver_Q.first) { + if (m_iterative_solver_Q.second) { + x_n_f_dof = m_analysis_cg.solve(m_F); + std::cout << "Number of iterations (CG): " << m_analysis_cg.iterations() << std::endl; + std::cout << "Estimated error: " << m_analysis_cg.error() << std::endl; + } + else { + // std::cout << "HERE" << std::endl; + x_n_f_dof = m_analysis_bi_cg.solve(m_F); + std::cout << bold << cyan << " Iterative solver for stage s: " << reset << std::endl; + std::cout << yellow << bold << " Number of iterations (BiCG): " << m_analysis_bi_cg.iterations() << std::endl; + std::cout << yellow << bold << " Estimated error: " << m_analysis_bi_cg.error() << std::endl; + } + } + else { + if (m_iterative_solver_Q.second) { + x_n_f_dof = m_symm_analysis.solve(m_F); + } + else { + x_n_f_dof = m_analysis.solve(m_F); + } + } + + + Matrix Kcf_x_f_dof = m_Kcf*x_n_f_dof; + Matrix delta_f = m_Kcc_inv*Kcf_x_f_dof; + Matrix x_n_c_dof = delta_c - delta_f; + + // Composing global solution + Matrix x_dof = Matrix::Zero(m_n_c_dof+m_n_f_dof,1); + x_dof.block(0, 0, m_n_c_dof, 1) = x_n_c_dof; + x_dof.block(m_n_c_dof, 0, m_n_f_dof, 1) = x_n_f_dof; + return x_dof; + + } + + void scatter_blocks(SparseMatrix & Kg){ + + m_n_c_dof = Kg.rows() - m_n_f_dof; + + // scattering matrix blocks + m_Kcc = Kg.block(0, 0, m_n_c_dof, m_n_c_dof); + m_Kcf = Kg.block(0, m_n_c_dof, m_n_c_dof, m_n_f_dof); + m_Kfc = Kg.block(m_n_c_dof,0, m_n_f_dof, m_n_c_dof); + m_Kff = Kg.block(m_n_c_dof,m_n_c_dof, m_n_f_dof, m_n_f_dof); + m_is_decomposed_Q = false; + } + + public: + + linear_solver() : m_global_sc_Q(false), m_is_decomposed_Q(false) { + m_iterative_solver_Q = std::make_pair(false,false); + } + + linear_solver(SparseMatrix & Kg) : m_K(Kg), m_global_sc_Q(false), m_is_decomposed_Q(false) { + m_iterative_solver_Q = std::make_pair(false,false); + } + + linear_solver(SparseMatrix & Kg, size_t n_f_dof) : + m_n_f_dof(n_f_dof), + m_global_sc_Q(true), + m_is_decomposed_Q(false) { + scatter_blocks(Kg); + } + + void set_Kg(SparseMatrix & Kg){ + m_global_sc_Q = false; + m_K = Kg; + } + + void set_Kg(SparseMatrix & Kg, size_t n_f_dof){ + m_global_sc_Q = true; + m_n_f_dof = n_f_dof; + scatter_blocks(Kg); + } + + void set_direct_solver(bool symmetric_matrix_Q = false){ + m_iterative_solver_Q = std::make_pair(false,symmetric_matrix_Q); + } + + void set_iterative_solver(bool symmetric_matrix_Q = false, T tolerance = 1.0e-11){ + m_iterative_solver_Q = std::make_pair(true, symmetric_matrix_Q); + m_is_decomposed_Q = true; + m_tolerance = tolerance; + } + + SparseMatrix & Kcc(){ + return m_Kcc; + } + + SparseMatrix & Kcf(){ + return m_Kcf; + } + + SparseMatrix & Kfc(){ + return m_Kfc; + } + + Matrix & Fc(){ + return m_Fc; + } + + void condense_equations(std::vector> vec_cell_basis_data){ + + if (!m_global_sc_Q) { + return; + } + + size_t nnz_cc = 0; + for (auto chunk : vec_cell_basis_data) { + nnz_cc += chunk.second*chunk.second*chunk.first; + } + std::vector< Triplet > triplets_cc; + triplets_cc.resize(nnz_cc); + m_Kcc_inv = SparseMatrix( m_n_c_dof, m_n_c_dof ); + #ifdef HAVE_INTEL_TBB + size_t stride_n_block_eq = 0; + size_t stride_n_block_l = 0; + for (auto chunk : vec_cell_basis_data) { + size_t n_cells = chunk.first; + size_t n_cbs = chunk.second; + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&triplets_cc,&n_cbs,&stride_n_block_eq,&stride_n_block_l] (size_t & cell_ind){ + + size_t stride_eq = cell_ind * n_cbs + stride_n_block_eq; + size_t stride_l = cell_ind * n_cbs * n_cbs + stride_n_block_l; + + SparseMatrix K_cc_loc = m_Kcc.block(stride_eq, stride_eq, n_cbs, n_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(K_cc_loc); + analysis_cc.factorize(K_cc_loc); + Matrix K_cc_inv_loc = analysis_cc.solve(Matrix::Identity(n_cbs, n_cbs)); + + size_t l = 0; + for (size_t i = 0; i < K_cc_inv_loc.rows(); i++) + { + for (size_t j = 0; j < K_cc_inv_loc.cols(); j++) + { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, K_cc_inv_loc(i,j)); + l++; + } + } + } + ); + stride_n_block_eq += n_cells * n_cbs; + stride_n_block_l += n_cells * n_cbs * n_cbs; + } + #else + + size_t stride_n_block_eq = 0; + size_t stride_n_block_l = 0; + for (auto chunk : vec_cell_basis_data) { + size_t n_cells = chunk.first; + size_t n_cbs = chunk.second; + for (size_t cell_ind = 0; cell_ind < n_cells; cell_ind++) { + + size_t stride_eq = cell_ind * n_cbs + stride_n_block_eq; + size_t stride_l = cell_ind * n_cbs * n_cbs + stride_n_block_l; + + SparseMatrix K_cc_loc = m_Kcc.block(stride_eq, stride_eq, n_cbs, n_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(K_cc_loc); + analysis_cc.factorize(K_cc_loc); + Matrix K_cc_inv_loc = analysis_cc.solve(Matrix::Identity(n_cbs, n_cbs)); + + size_t l = 0; + for (size_t i = 0; i < K_cc_inv_loc.rows(); i++) { + for (size_t j = 0; j < K_cc_inv_loc.cols(); j++) { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, K_cc_inv_loc(i,j)); + l++; + } + } + + } + stride_n_block_eq += n_cells * n_cbs; + stride_n_block_l += n_cells * n_cbs * n_cbs; + } + #endif + + m_Kcc_inv.setFromTriplets( triplets_cc.begin(), triplets_cc.end() ); + triplets_cc.clear(); + m_K = m_Kff - m_Kfc*m_Kcc_inv*m_Kcf; + m_is_decomposed_Q = false; + return; + + } + + void condense_equations(std::pair cell_basis_data){ + std::vector> vec_cell_basis_data(1); + vec_cell_basis_data[0] = cell_basis_data; + condense_equations(vec_cell_basis_data); + } + + void factorize(){ + if (m_is_decomposed_Q) { + if (m_iterative_solver_Q.first) { + if (m_iterative_solver_Q.second) { + m_analysis_cg.compute(m_K); + m_analysis_cg.setTolerance(m_tolerance); + m_analysis_cg.setMaxIterations(m_K.rows()); + }else{ + m_analysis_bi_cg.compute(m_K); + m_analysis_bi_cg.setTolerance(m_tolerance); + m_analysis_bi_cg.setMaxIterations(m_K.rows()); + } + } + return; + } + DecomposeK(); + m_is_decomposed_Q = true; + } + + size_t n_equations(){ + size_t n_equations = m_K.rows(); + return n_equations; + } + + Matrix solve(Matrix & Fg){ + if (m_global_sc_Q) + return solve_sc(Fg); + else + return solve_global(Fg); + } + + +}; + +#endif /* linear_solver_hpp */ diff --git a/apps/wave_propagation/src/common/lsrk_butcher_tableau.hpp b/apps/wave_propagation/src/common/lsrk_butcher_tableau.hpp new file mode 100644 index 00000000..a019f86a --- /dev/null +++ b/apps/wave_propagation/src/common/lsrk_butcher_tableau.hpp @@ -0,0 +1,79 @@ +// +// lsrk_butcher_tableau.hpp +// acoustics +// +// Created by Omar Durán on 4/25/20. +// + +#ifndef lsrk_butcher_tableau_hpp +#define lsrk_butcher_tableau_hpp + +#include + +class lsrk_butcher_tableau +{ + public: + + static void lsrk_tables(int s, Matrix &a, Matrix &b, Matrix &c){ + + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, 1); + c = Matrix::Zero(s, 1); + + + // Nodal Discontinuous Galerkin Methods + // Fourth-order 2n-storage Runge- Kutta schemes + switch (s) { + case 1: + { + a(0,0) = 0.0; + b(0,0) = 1.0; + c(0,0) = 1.0; + } + break; + case 2: + { + a(0,0) = 1.0/3.0; + a(1,0) = 3.0/4.0; + a(1,1) = 1.0/4.0; + + b(0,0) = 3.0/4.0; + b(1,0) = 1.0/4.0; + + c(0,0) = 1.0/3.0; + c(1,0) = 1.0; + + } + break; + case 3: + { + + a(0,0) = 1.0; + a(1,0) = -1.0/12.0; + a(1,1) = 5.0/12.0; + a(2,0) = 0.0; + a(2,1) = 3.0/4.0; + a(2,2) = 1.0/4.0; + + b(0,0) = 0.0; + b(1,0) = 3.0/4.0; + b(2,0) = 3.0/4.0; + + c(0,0) = 1.0; + c(1,0) = 1.0/3.0; + c(2,0) = 1.0; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + +}; + +#endif /* lsrk_butcher_tableau_hpp */ diff --git a/apps/wave_propagation/src/common/postprocessor.hpp b/apps/wave_propagation/src/common/postprocessor.hpp new file mode 100644 index 00000000..c2b2a7d4 --- /dev/null +++ b/apps/wave_propagation/src/common/postprocessor.hpp @@ -0,0 +1,3447 @@ + // +// postprocessor.hpp +// acoustics +// +// Created by Omar Durán on 4/10/20. +// Contributor: Romain Mottier + +#pragma once +#ifndef postprocessor_hpp +#define postprocessor_hpp + +#include +#include "../common/acoustic_one_field_assembler.hpp" +#include "../common/acoustic_two_fields_assembler.hpp" +#include "../common/elastodynamic_one_field_assembler.hpp" +#include "../common/elastodynamic_two_fields_assembler.hpp" +#include "../common/elastodynamic_three_fields_assembler.hpp" +#include "../common/elastoacoustic_two_fields_assembler.hpp" +#include "../common/elastoacoustic_four_fields_assembler.hpp" +#include "diskpp/bases/bases.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + + +template +class postprocessor { + +public: + + // FIND CELLS & PICK CELLS & MESH QUALITY + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + static std::set find_cells(typename Mesh::point_type & pt, Mesh & msh, bool verbose_Q = false) { + + using RealType = double; + auto norm = [](const typename Mesh::point_type& a, const typename Mesh::point_type& b ) -> RealType { + RealType dx = (b.x() - a.x()); + RealType dy = (b.y() - a.y()); + RealType norm = std::sqrt(dx*dx + dy*dy); + return norm; + }; + + // find minimum distance to the requested point + size_t np = msh.points_size(); + std::vector distances(np); + + size_t ip = 0; + for (auto& point : msh.backend_storage()->points) { + RealType dist = norm(pt,point); + distances[ip] = dist; + ip++; + } + + size_t index = std::min_element(distances.begin(),distances.end()) - distances.begin(); + if(verbose_Q){ + RealType min_dist = *std::min_element(distances.begin(), distances.end()); + typename Mesh::point_type nearest_point = msh.backend_storage()->points.at(index); + } + + std::set cell_indexes; + size_t cell_i = 0; + for (auto& cell : msh) { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) { + auto pt_id = points[l]; + if (index == pt_id) + cell_indexes.insert(cell_i); + } + cell_i++; + } + + if(verbose_Q){ + // std::cout << "Detected cells indexes : " << std::endl; + for(auto index : cell_indexes){ + // std::cout << index << std::endl; + } + } + + return cell_indexes; + } + + static std::set find_elastic_cells(typename Mesh::point_type & pt, Mesh & msh, bool verbose_Q = false) { + + using RealType = double; + auto norm = [](const typename Mesh::point_type& a, const typename Mesh::point_type& b) -> RealType { + RealType dx = (b.x() - a.x()); + RealType dy = (b.y() - a.y()); + return std::sqrt(dx * dx + dy * dy); + }; + + // Trouver le point du maillage le plus proche + size_t np = msh.points_size(); + std::vector distances(np); + + size_t ip = 0; + for (auto& point : msh.backend_storage()->points) { + distances[ip] = norm(pt, point); + ip++; + } + + size_t index = std::min_element(distances.begin(), distances.end()) - distances.begin(); + + if (verbose_Q) { + RealType min_dist = *std::min_element(distances.begin(), distances.end()); + typename Mesh::point_type nearest_point = msh.backend_storage()->points.at(index); + } + + std::set cell_indexes; + size_t cell_i = 0; + for (auto& cell : msh) { + auto points = cell.point_ids(); + size_t n_p = points.size(); + + for (size_t l = 0; l < n_p; l++) { + if (index == points[l]) { + auto bar = barycenter(msh, cell); + if (bar.y() <= 0.0) + cell_indexes.insert(cell_i); + } + } + cell_i++; + } + return cell_indexes; + } + + static std::set find_acoustic_cells(typename Mesh::point_type & pt, Mesh & msh, bool verbose_Q = false) { + + using RealType = double; + auto norm = [](const typename Mesh::point_type& a, const typename Mesh::point_type& b) -> RealType { + RealType dx = (b.x() - a.x()); + RealType dy = (b.y() - a.y()); + return std::sqrt(dx * dx + dy * dy); + }; + + // Trouver le point du maillage le plus proche + size_t np = msh.points_size(); + std::vector distances(np); + + size_t ip = 0; + for (auto& point : msh.backend_storage()->points) { + distances[ip] = norm(pt, point); + ip++; + } + + size_t index = std::min_element(distances.begin(), distances.end()) - distances.begin(); + + if (verbose_Q) { + RealType min_dist = *std::min_element(distances.begin(), distances.end()); + typename Mesh::point_type nearest_point = msh.backend_storage()->points.at(index); + } + + std::set cell_indexes; + size_t cell_i = 0; + for (auto& cell : msh) { + auto points = cell.point_ids(); + size_t n_p = points.size(); + + for (size_t l = 0; l < n_p; l++) { + if (index == points[l]) { + auto bar = barycenter(msh, cell); + if (bar.y() >= 0) + cell_indexes.insert(cell_i); + } + } + cell_i++; + } + + return cell_indexes; + } + + static void mesh_quality(Mesh & msh, elastoacoustic_four_fields_assembler & assembler,std::ostream & mesh_file = std::cout){ + + using RealType = double; + auto dim = Mesh::dimension; + + RealType o_to_ten = 0.0; + RealType ten_to_twenty = 0.0; + RealType twenty_to_thirty = 0.0; + RealType thirty_to_forty = 0.0; + RealType forty_to_fifty = 0.0; + RealType fifty_to_sixty = 0.0; + RealType sixty_to_seventy = 0.0; + RealType seventy_to_eighty = 0.0; + RealType eighty_to_ninety = 0.0; + RealType ninety_to_hundred = 0.0; + + // Determination h + RealType h = 10.0; + auto storage = msh.backend_storage(); + for (auto& e_chunk : assembler.get_e_material_data()) { + auto& cell = storage->surfaces[e_chunk.first]; + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + for (auto& a_chunk : assembler.get_a_material_data()) { + auto& cell = storage->surfaces[a_chunk.first]; + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + // Determination of small edges + RealType nb_faces = 0.0; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++){ + const auto face = *face_it; + auto pts = points(msh, face); + RealType longueur = (pts[1] - pts[0]).to_vector().norm(); + if (longueur <= 1.e-1*h) { + o_to_ten++; + } else if (longueur <= 2e-1*h) { + ten_to_twenty++; + } else if (longueur <= 3e-1*h) { + twenty_to_thirty++; + } else if (longueur <= 4e-1*h) { + thirty_to_forty++; + } else if (longueur <= 5e-1*h) { + forty_to_fifty++; + } else if (longueur <= 6e-1*h) { + fifty_to_sixty++; + } else if (longueur <= 7e-1*h) { + sixty_to_seventy++; + } else if (longueur <= 8e-1*h) { + seventy_to_eighty++; + } else if (longueur <= 9e-1*h) { + eighty_to_ninety++; + } else { + ninety_to_hundred++; + } + nb_faces++; + } + // Number of faces + mesh_file << "Number of faces: " << nb_faces << std::endl<< std::endl; + + mesh_file << " ratio <= 10% : " << " " << o_to_ten << std::endl; + mesh_file << "10% < ratio <= 20% : " << " " << ten_to_twenty << std::endl; + mesh_file << "20% < ratio <= 30% : " << " " << twenty_to_thirty << std::endl; + mesh_file << "30% < ratio <= 40% : " << " " << thirty_to_forty << std::endl; + mesh_file << "40% < ratio <= 50% : " << " " << forty_to_fifty << std::endl; + mesh_file << "50% < ratio <= 60% : " << " " << fifty_to_sixty << std::endl; + mesh_file << "60% < ratio <= 70% : " << " " << sixty_to_seventy << std::endl; + mesh_file << "70% < ratio <= 80% : " << " " << seventy_to_eighty << std::endl; + mesh_file << "80% < ratio <= 90% : " << " " << eighty_to_ninety << std::endl; + mesh_file << "90% < ratio <= 100%: " << " " << ninety_to_hundred << std::endl; + + RealType prct_o_to_ten = o_to_ten/nb_faces; + RealType prct_ten_to_twenty = ten_to_twenty/nb_faces; + RealType prct_twenty_to_thirty = twenty_to_thirty/nb_faces; + RealType prct_thirty_to_forty = thirty_to_forty/nb_faces; + RealType prct_forty_to_fifty = forty_to_fifty/nb_faces; + RealType prct_fifty_to_sixty = fifty_to_sixty/nb_faces; + RealType prct_sixty_to_seventy = sixty_to_seventy/nb_faces; + RealType prct_seventy_to_eighty = seventy_to_eighty/nb_faces; + RealType prct_eighty_to_ninety = eighty_to_ninety/nb_faces; + RealType prct_ninety_to_hundred = ninety_to_hundred/nb_faces; + + // Percentage of faces + mesh_file << "Percentage: " << std::endl; + mesh_file << " ratio <= 10% : " << " " << prct_o_to_ten << std::endl; + mesh_file << "10% < ratio <= 20% : " << " " << prct_ten_to_twenty << std::endl; + mesh_file << "20% < ratio <= 30% : " << " " << prct_twenty_to_thirty << std::endl; + mesh_file << "30% < ratio <= 40% : " << " " << prct_thirty_to_forty << std::endl; + mesh_file << "40% < ratio <= 50% : " << " " << prct_forty_to_fifty << std::endl; + mesh_file << "50% < ratio <= 60% : " << " " << prct_fifty_to_sixty << std::endl; + mesh_file << "60% < ratio <= 70% : " << " " << prct_sixty_to_seventy << std::endl; + mesh_file << "70% < ratio <= 80% : " << " " << prct_seventy_to_eighty << std::endl; + mesh_file << "80% < ratio <= 90% : " << " " << prct_eighty_to_ninety << std::endl; + mesh_file << "90% < ratio <= 100%: " << " " << prct_ninety_to_hundred << std::endl; + RealType total = prct_o_to_ten + prct_ten_to_twenty + prct_twenty_to_thirty + prct_thirty_to_forty + prct_forty_to_fifty + prct_fifty_to_sixty + prct_sixty_to_seventy + prct_seventy_to_eighty + prct_eighty_to_ninety + prct_ninety_to_hundred; + mesh_file << " TOTAL: " << " " << total << std::endl << std::endl; + + } + + static size_t pick_cell(typename Mesh::point_type & pt, Mesh & msh, std::set & cell_indexes, bool verbose_Q = false){ + + using RealType = double; + + auto triangle_member_Q = [] (typename Mesh::point_type & p, typename Mesh::point_type & p0, typename Mesh::point_type & p1, typename Mesh::point_type & p2) { + RealType dx = p.x()-p2.x(); + RealType dy = p.y()-p2.y(); + RealType dx21 = p2.x()-p1.x(); + RealType dy12 = p1.y()-p2.y(); + RealType d = dy12*(p0.x()-p2.x()) + dx21*(p0.y()-p2.y()); + RealType s = dy12*dx + dx21*dy; + RealType t = (p2.y()-p0.y())*dx + (p0.x()-p2.x())*dy; + if (d < 0.0) { + return s<=0.0 && t<=0.0 && s+t>=d; + } + return s>=0 && t>=0 && s+t<=d; + }; + + size_t n_cells = cell_indexes.size(); + if (n_cells == 1) { + size_t first_index = *cell_indexes.begin(); + return first_index; + } + bool is_member_Q = false; + for(auto index : cell_indexes){ + auto& cell = msh.backend_storage()->surfaces[index]; + auto bar = barycenter(msh, cell); + auto points = cell.point_ids(); + size_t n_p = points.size(); + + // building teselation + std::vector> triangles(n_p); + for (size_t l = 0; l < n_p; l++) { + std::vector chunk(3); + if( l == n_p - 1){ + chunk[0] = msh.backend_storage()->points.at(points[l]); + chunk[1] = msh.backend_storage()->points.at(points[0]); + chunk[2] = bar; + } + else { + chunk[0] = msh.backend_storage()->points.at(points[l]); + chunk[1] = msh.backend_storage()->points.at(points[l+1]); + chunk[2] = bar; + } + triangles[l] = chunk; + } + // check whether the point is memeber of any triangle + for (auto triangle : triangles) { + is_member_Q = triangle_member_Q(pt,triangle[0],triangle[1],triangle[2]); + if (is_member_Q) { + // std::cout << "Detected cell index = " << index << std::endl; + return index; + } + } + + } + + if(!is_member_Q){ + if(verbose_Q){ + std::cout << "Point is not member of cells set. Returning cell_indexes[0] " << std::endl; + } + size_t first_index = *cell_indexes.begin(); + return first_index; + } + + return -1; + } + + // COMPUTE ERRORS UNCOUPLED PROBLEM + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + /// Compute L2 and H1 errors for one field approximation + static void compute_errors_one_field(Mesh & msh, disk::hho_degree_info & hho_di, acoustic_one_field_assembler & assembler, Matrix & x_dof,std::function scal_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + + RealType scalar_l2_error = 0.0; + RealType flux_l2_error = 0.0; + size_t cell_i = 0; + RealType h = 10.0; + for (auto& cell : msh) + { + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix scalar_cell_dof = x_dof.block(cell_i*cell_dof, 0, cell_dof, 1); + + // scalar evaluation + { + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, scal_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - scalar_cell_dof; + scalar_l2_error += diff.dot(mass*diff); + + } + + // flux evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + auto rec_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto gr = make_scalar_hho_laplacian(msh, cell, hho_di); + Matrix all_dofs = assembler.gather_dof_data(msh, cell, x_dof); + Matrix recdofs = gr.first * all_dofs; + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + auto t_dphi = rec_basis.eval_gradients( point_pair.point() ); + Matrix grad_uh = Matrix::Zero(); + + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + recdofs(i-1)*t_dphi.block(i, 0, 1, 2); + } + + Matrix grad_u_exact = Matrix::Zero(); + grad_u_exact(0,0) = flux_fun(point_pair.point())[0]; + grad_u_exact(0,1) = flux_fun(point_pair.point())[1]; + flux_l2_error += omega * (grad_u_exact - grad_uh).dot(grad_u_exact - grad_uh); + + } + } + + cell_i++; + } + tc.toc(); + std::cout << bold << cyan << "Error completed: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << std::setprecision(16) << h << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(scalar_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + + + } + + /// Compute L2 and H1 errors for two fields approximation + static void compute_errors_two_fields(Mesh & msh, disk::hho_degree_info & hho_di, acoustic_two_fields_assembler & assembler, Matrix & x_dof,std::function scal_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout, bool recons_error_Q = false){ + + timecounter tc; + tc.tic(); + + using RealType = double; + size_t n_scal_dof = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_dof = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t cell_dof = n_scal_dof + n_vec_dof; + + RealType scalar_l2_error = 0.0; + RealType flux_l2_error = 0.0; + size_t cell_i = 0; + RealType h = 10.0; + for (auto& cell : msh) + { + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + // scalar evaluation + if(recons_error_Q){ + auto rec_cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto gr = make_scalar_hho_laplacian(msh, cell, hho_di); + Matrix all_dofs = assembler.gather_dof_data(msh, cell, x_dof); + size_t n_cell_dof = all_dofs.rows() - n_vec_dof; + + Matrix cell_dofs = all_dofs.block(n_vec_dof, 0, n_cell_dof, 1); + Matrix rec_scalar_cell_dof = gr.first * cell_dofs; + + size_t n_rbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension); + Matrix rec_scalar_dof = Matrix::Zero(n_rbs, 1); + + rec_scalar_dof(0, 0) = cell_dofs(0, 0); // The constant is the same. + rec_scalar_dof.block(1, 0, n_rbs-1, 1) = rec_scalar_cell_dof; + + + Matrix mass = make_mass_matrix(msh, cell, rec_cell_basis, hho_di.reconstruction_degree()); + Matrix rhs = make_rhs(msh, cell, rec_cell_basis, scal_fun, 1); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - rec_scalar_dof; + scalar_l2_error += diff.dot(mass*diff); + }else{ + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(cell_i*cell_dof+n_vec_dof, 0, n_scal_dof, 1); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, scal_fun); + Matrix real_dofs = mass.llt().solve(rhs); + + Matrix diff = real_dofs - scalar_cell_dof; + scalar_l2_error += diff.dot(mass*diff); + } + + // flux evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + Matrix flux_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_vec_dof, 1); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + auto t_dphi = cell_basis.eval_gradients( point_pair.point() ); + + Matrix grad_uh = Matrix::Zero(); + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + flux_cell_dof(i-1)*t_dphi.block(i, 0, 1, 2); + } + + Matrix grad_u_exact = Matrix::Zero(); + grad_u_exact(0,0) = flux_fun(point_pair.point())[0]; + grad_u_exact(0,1) = flux_fun(point_pair.point())[1]; + flux_l2_error += omega * (grad_u_exact - grad_uh).dot(grad_u_exact - grad_uh); + + } + } + + cell_i++; + } + tc.toc(); + + std::cout << bold << cyan << "Error completed: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << std::setprecision(16) << h << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(scalar_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + + } + + /// Compute L2 and H1 errors for one field vectorial approximation + static void compute_errors_one_field_vectorial(Mesh & msh, disk::hho_degree_info & hho_di, elastodynamic_one_field_assembler & assembler, Matrix & x_dof, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + + RealType vector_l2_error = 0.0; + RealType flux_l2_error = 0.0; + RealType h = 10.0; + size_t cell_ind = 0; + for (auto& cell : msh) + { + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix vec_cell_dof = x_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + + // scalar evaluation + { + auto cell_basis = disk::make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, vec_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - vec_cell_dof; + vector_l2_error += diff.dot(mass*diff); + + } + + elastic_material_data material = assembler.get_material_data()[cell_ind]; + RealType mu = material.rho()*material.vs()*material.vs(); + RealType lambda = material.rho()*material.vp()*material.vp() - 2.0*mu; + + // flux evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + Matrix all_dofs = assembler.gather_dof_data(msh, cell, x_dof); + + auto sgr = make_vector_hho_symmetric_laplacian(msh, cell, hho_di); + disk::dynamic_vector GTu = sgr.first * all_dofs; + + auto dr = make_hho_divergence_reconstruction(msh, cell, hho_di); + disk::dynamic_vector divu = dr.first * all_dofs; + + auto cbas_v = disk::make_vector_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto cbas_s = disk::make_scalar_monomial_basis(msh, cell, hho_di.face_degree()); + + auto rec_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + + auto t_dphi = rec_basis.eval_gradients( point_pair.point() ); + auto gphi = cbas_v.eval_sgradients(point_pair.point()); + auto epsilon = disk::eval(GTu, gphi, dim); + auto divphi = cbas_s.eval_functions(point_pair.point()); + auto trace_epsilon = disk::eval(divu, divphi); + auto sigma = 2.0 * mu * epsilon + lambda * trace_epsilon * disk::static_matrix::Identity(); + auto flux_diff = (flux_fun(point_pair.point()) - sigma).eval(); + flux_l2_error += omega * flux_diff.squaredNorm(); + + } + } + + cell_ind++; + } + tc.toc(); + std::cout << bold << cyan << "Error completed: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << std::setprecision(16) << h << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(vector_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + + + } + + /// Compute L2 and H1 errors for two fields vectorial approximation + static void compute_errors_two_fields_vectorial(Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), dim, dim); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t cell_dof = n_ten_cbs + n_vec_cbs; + + RealType vector_l2_error = 0.0; + RealType flux_l2_error = 0.0; + size_t cell_i = 0; + RealType h = 10.0; + for (auto& cell : msh) + { + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix vec_cell_dof = x_dof.block(cell_i*cell_dof+n_ten_cbs, 0, n_vec_cbs, 1); + + // vector evaluation + { + auto cell_basis = disk::make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, vec_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - vec_cell_dof; + vector_l2_error += diff.dot(mass*diff); + + } + + + // tensor evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_ten_cbs, 1); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + + auto t_ten_phi = ten_basis.eval_functions( point_pair.point() ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + auto flux_diff = (flux_fun(point_pair.point()) - sigma_h).eval(); + flux_l2_error += omega * flux_diff.squaredNorm(); + + } + + } + + cell_i++; + } + tc.toc(); + std::cout << bold << cyan << "Error completed: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << std::setprecision(16) << h << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(vector_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + + } + + /// Compute L2 and H1 errors for three fields vectorial approximation + static void compute_errors_three_fields_vectorial(Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), dim, dim); + size_t n_sca_cbs = disk::scalar_basis_size(hho_di.face_degree(), dim); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t cell_dof = n_ten_cbs + n_sca_cbs + n_vec_cbs; + + RealType vector_l2_error = 0.0; + RealType flux_l2_error = 0.0; + size_t cell_i = 0; + RealType h = 10.0; + for (auto& cell : msh) + { + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix vec_cell_dof = x_dof.block(cell_i*cell_dof+n_ten_cbs+n_sca_cbs, 0, n_vec_cbs, 1); + + // vector evaluation + { + auto cell_basis = disk::make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, vec_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - vec_cell_dof; + vector_l2_error += diff.dot(mass*diff); + + } + + // tensor evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_ten_cbs, 1); + + auto sca_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.face_degree()); + Matrix sigma_v_x_cell_dof = x_dof.block(cell_i*cell_dof+n_ten_cbs, 0, n_sca_cbs, 1); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + + auto t_ten_phi = ten_basis.eval_functions( point_pair.point() ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + auto t_sca_phi = sca_basis.eval_functions( point_pair.point() ); + assert(t_sca_phi.size() == sca_basis.size()); + auto sigma_v_h = disk::eval(sigma_v_x_cell_dof, t_sca_phi); + + sigma_h += sigma_v_h * disk::static_matrix::Identity(); + + auto flux_diff = (flux_fun(point_pair.point()) - sigma_h).eval(); + flux_l2_error += omega * flux_diff.squaredNorm(); + + } + + } + + cell_i++; + } + tc.toc(); + std::cout << bold << cyan << "Error completed: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << std::setprecision(16) << h << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(vector_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + + } + + // COMPUTE ENERGY UNCOUPLED PROBLEM + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + /// Compute the discrete acoustic energy for one field approximation + static double compute_acoustic_energy_one_field(Mesh & msh, disk::hho_degree_info & hho_di, acoustic_one_field_assembler & assembler, double & time, Matrix & p_dof, Matrix & v_dof, std::ostream & energy_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + + std::vector energy_vec(msh.cells_size()); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [&msh,&assembler,&energy_vec,&p_dof,&v_dof,&cell_dof] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix cell_alpha_dof_n_v = v_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + Matrix cell_mass_tested = mass_matrix * cell_alpha_dof_n_v; + Matrix term_1 = cell_alpha_dof_n_v.transpose() * cell_mass_tested; + + energy_vec[cell_ind] = term_1(0,0); + + Matrix laplacian_loc = assembler.laplacian_operator(cell_ind, msh, cell); + Matrix cell_p_dofs = assembler.gather_dof_data(msh, cell, p_dof); + Matrix cell_stiff_tested = laplacian_loc * cell_p_dofs; + Matrix term_2 = cell_p_dofs.transpose() * cell_stiff_tested; + + energy_vec[cell_ind] += term_2(0,0); + } + ); + #else + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix cell_alpha_dof_n_v = v_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + Matrix cell_mass_tested = mass_matrix * cell_alpha_dof_n_v; + Matrix term_1 = cell_alpha_dof_n_v.transpose() * cell_mass_tested; + + energy_vec[cell_ind] = term_1(0,0); + + Matrix laplacian_loc = assembler.laplacian_operator(cell_ind, msh, cell); + Matrix cell_p_dofs = assembler.gather_dof_data(msh, cell, p_dof); + Matrix cell_stiff_tested = laplacian_loc * cell_p_dofs; + Matrix term_2 = cell_p_dofs.transpose() * cell_stiff_tested; + + energy_vec[cell_ind] += term_2(0,0); + + } + #endif + + RealType energy_h = std::accumulate(energy_vec.begin(), energy_vec.end(),0.0); + energy_h *= 0.5; + + tc.toc(); + std::cout << bold << cyan << "Energy completed: " << tc << " seconds" << reset << std::endl; + energy_file << time << " " << std::setprecision(16) << energy_h << std::endl; + return energy_h; + } + + /// Compute the discrete acoustic energy for one field approximation + static double compute_acoustic_energy_two_fields(Mesh & msh, disk::hho_degree_info & hho_di, acoustic_two_fields_assembler & assembler, double & time, Matrix & x_dof, std::ostream & energy_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_cbs = n_scal_cbs + n_vec_cbs; + + std::vector energy_vec(msh.cells_size()); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [&msh,&assembler,&energy_vec,&x_dof,&n_cbs] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix cell_dof = x_dof.block(cell_ind*n_cbs, 0, n_cbs, 1); + Matrix cell_mass_tested = mass_matrix * cell_dof; + Matrix term = cell_dof.transpose() * cell_mass_tested; + energy_vec[cell_ind] = term(0,0); + } + ); + #else + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix cell_dof = x_dof.block(cell_ind*n_cbs, 0, n_cbs, 1); + Matrix cell_mass_tested = mass_matrix * cell_dof; + Matrix term = cell_dof.transpose() * cell_mass_tested; + + energy_vec[cell_ind] = term(0,0); + + } + #endif + + RealType energy_h = std::accumulate(energy_vec.begin(), energy_vec.end(),0.0); + energy_h *= 0.5; + + tc.toc(); + std::cout << bold << cyan << "Energy completed: " << tc << " seconds" << reset << std::endl; + energy_file << time << " " << std::setprecision(16) << energy_h << std::endl; + + return energy_h; + } + + /// Compute the discrete elastic energy for one field approximation + static double compute_elastic_energy_one_field(Mesh & msh, disk::hho_degree_info & hho_di, elastodynamic_one_field_assembler & assembler, double & time, Matrix & u_dof, Matrix & v_dof, std::ostream & energy_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + + std::vector energy_vec(msh.cells_size()); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [&msh,&assembler,&energy_vec,&u_dof,&v_dof,&cell_dof] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix cell_alpha_dof_n_v = v_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + Matrix cell_mass_tested = mass_matrix * cell_alpha_dof_n_v; + Matrix term_1 = cell_alpha_dof_n_v.transpose() * cell_mass_tested; + + energy_vec[cell_ind] = term_1(0,0); + + Matrix laplacian_loc = assembler.laplacian_operator(cell_ind, msh, cell); + Matrix cell_p_dofs = assembler.gather_dof_data(msh, cell, u_dof); + Matrix cell_stiff_tested = laplacian_loc * cell_p_dofs; + Matrix term_2 = cell_p_dofs.transpose() * cell_stiff_tested; + + energy_vec[cell_ind] += term_2(0,0); + } + ); + #else + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix cell_alpha_dof_n_v = v_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + Matrix cell_mass_tested = mass_matrix * cell_alpha_dof_n_v; + Matrix term_1 = cell_alpha_dof_n_v.transpose() * cell_mass_tested; + + energy_vec[cell_ind] = term_1(0,0); + + Matrix laplacian_loc = assembler.laplacian_operator(cell_ind, msh, cell); + Matrix cell_u_dofs = assembler.gather_dof_data(msh, cell, u_dof); + Matrix cell_stiff_tested = laplacian_loc * cell_u_dofs; + Matrix term_2 = cell_u_dofs.transpose() * cell_stiff_tested; + + energy_vec[cell_ind] += term_2(0,0); + + } + #endif + + RealType energy_h = std::accumulate(energy_vec.begin(), energy_vec.end(),0.0); + energy_h *= 0.5; + + tc.toc(); + std::cout << bold << cyan << "Energy completed: " << tc << " seconds" << reset << std::endl; + energy_file << time << " " << std::setprecision(16) << energy_h << std::endl; + return energy_h; + } + + /// Compute the discrete elastic energy for two fields approximation + static double compute_elastic_energy_two_fields(Mesh & msh, disk::hho_degree_info & hho_di, elastodynamic_two_fields_assembler & assembler, double & time, Matrix & x_dof, std::ostream & energy_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + + std::vector energy_vec(msh.cells_size()); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [&msh,&assembler,&energy_vec,&x_dof,&n_ten_cbs,&n_vec_cbs] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix x_dof_loc = assembler.gather_dof_data(msh, cell, x_dof); + + Matrix mass_matrix_v = mass_matrix.block(n_ten_cbs, n_ten_cbs, n_vec_cbs, n_vec_cbs); + Matrix v_dof = x_dof_loc.block(n_ten_cbs, 0, n_vec_cbs, 1); + Matrix v_mass_tested = mass_matrix_v * v_dof; + Matrix term_1 = v_dof.transpose() * v_mass_tested; + energy_vec[cell_ind] = term_1(0,0); + + Matrix mass_matrix_stress = mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs); + Matrix sigma_dof = x_dof_loc.block(0, 0, n_ten_cbs, 1); + Matrix epsilon_mass = mass_matrix_stress * sigma_dof; + Matrix term_2 = sigma_dof.transpose() * epsilon_mass; + energy_vec[cell_ind] += term_2(0,0); + } + ); + #else + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix x_dof_loc = assembler.gather_dof_data(msh, cell, x_dof); + + Matrix mass_matrix_v = mass_matrix.block(n_ten_cbs, n_ten_cbs, n_vec_cbs, n_vec_cbs); + Matrix v_dof = x_dof_loc.block(n_ten_cbs, 0, n_vec_cbs, 1); + Matrix v_mass_tested = mass_matrix_v * v_dof; + Matrix term_1 = v_dof.transpose() * v_mass_tested; + energy_vec[cell_ind] = term_1(0,0); + + Matrix mass_matrix_stress = mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs); + Matrix sigma_dof = x_dof_loc.block(0, 0, n_ten_cbs, 1); + Matrix epsilon_mass = mass_matrix_stress * sigma_dof; + Matrix term_2 = sigma_dof.transpose() * epsilon_mass; + energy_vec[cell_ind] += term_2(0,0); + + } + #endif + + RealType energy_h = std::accumulate(energy_vec.begin(), energy_vec.end(),0.0); + energy_h *= 0.5; + + tc.toc(); + std::cout << bold << cyan << "Energy completed: " << tc << " seconds" << reset << std::endl; + energy_file << time << " " << std::setprecision(16) << energy_h << std::endl; + return energy_h; + } + + /// Compute the discrete elastic energy for three field approximation + static double compute_elastic_energy_three_fields(Mesh & msh, disk::hho_degree_info & hho_di, elastodynamic_three_fields_assembler & assembler, double & time, Matrix & x_dof, std::ostream & energy_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_sca_cbs = disk::scalar_basis_size(hho_di.face_degree(), Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + + std::vector energy_vec(msh.cells_size()); + #ifdef HAVE_INTEL_TBB + size_t n_cells = msh.cells_size(); + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [&msh,&assembler,&energy_vec,&x_dof,&n_ten_cbs,&n_sca_cbs,&n_vec_cbs] (size_t & cell_ind){ + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix x_dof_loc = assembler.gather_dof_data(msh, cell, x_dof); + + Matrix mass_matrix_v = mass_matrix.block(n_ten_cbs + n_sca_cbs, n_ten_cbs + n_sca_cbs, n_vec_cbs, n_vec_cbs); + Matrix v_dof = x_dof_loc.block(n_ten_cbs + n_sca_cbs, 0, n_vec_cbs, 1); + Matrix v_mass_tested = mass_matrix_v * v_dof; + Matrix term_1 = v_dof.transpose() * v_mass_tested; + energy_vec[cell_ind] = term_1(0,0); + + Matrix mass_matrix_stress = mass_matrix.block(0, 0, n_ten_cbs + n_sca_cbs, n_ten_cbs + n_sca_cbs); + Matrix sigma_dof = x_dof_loc.block(0, 0, n_ten_cbs + n_sca_cbs, 1); + Matrix epsilon_mass = mass_matrix_stress * sigma_dof; + Matrix term_2 = sigma_dof.transpose() * epsilon_mass; + energy_vec[cell_ind] += term_2(0,0); + } + ); + #else + for (size_t cell_ind = 0; cell_ind < msh.cells_size(); cell_ind++) + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + + Matrix mass_matrix = assembler.mass_operator(cell_ind, msh, cell); + Matrix x_dof_loc = assembler.gather_dof_data(msh, cell, x_dof); + + Matrix mass_matrix_v = mass_matrix.block(n_ten_cbs + n_sca_cbs, n_ten_cbs + n_sca_cbs, n_vec_cbs, n_vec_cbs); + Matrix v_dof = x_dof_loc.block(n_ten_cbs + n_sca_cbs, 0, n_vec_cbs, 1); + Matrix v_mass_tested = mass_matrix_v * v_dof; + Matrix term_1 = v_dof.transpose() * v_mass_tested; + energy_vec[cell_ind] = term_1(0,0); + + Matrix mass_matrix_stress = mass_matrix.block(0, 0, n_ten_cbs + n_sca_cbs, n_ten_cbs + n_sca_cbs); + Matrix sigma_dof = x_dof_loc.block(0, 0, n_ten_cbs + n_sca_cbs, 1); + Matrix epsilon_mass = mass_matrix_stress * sigma_dof; + Matrix term_2 = sigma_dof.transpose() * epsilon_mass; + energy_vec[cell_ind] += term_2(0,0); + + } + #endif + + RealType energy_h = std::accumulate(energy_vec.begin(), energy_vec.end(),0.0); + energy_h *= 0.5; + + tc.toc(); + std::cout << bold << cyan << "Energy completed: " << tc << " seconds" << reset << std::endl; + energy_file << time << " " << std::setprecision(16) << energy_h << std::endl; + return energy_h; + } + + // SENSORS UNCOUPLED PROBELM + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + /// Record data at provided point for one field approximation + static void record_data_acoustic_one_field(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + + RealType vh = 0.0; + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vh\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + // scalar evaluation + { + Matrix scalar_cell_dof = x_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + auto t_phi = cell_basis.eval_functions( pt ); + vh = scalar_cell_dof.dot( t_phi ); + } + + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh << std::endl; + seismogram_file.flush(); + + } + + /// Record velocity data at provided point for one field approximation + static void record_velocity_data_acoustic_one_field(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, acoustic_one_field_assembler & assembler, Matrix & x_dof, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + // reconstructed velocity evaluation + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto rec_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto gr = make_scalar_hho_laplacian(msh, cell, hho_di); + Matrix all_dofs = assembler.gather_dof_data(msh, cell, x_dof); + Matrix recdofs = gr.first * all_dofs; + + auto t_dphi = rec_basis.eval_gradients( pt ); + Matrix grad_uh = Matrix::Zero(); + + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + recdofs(i-1)*t_dphi.block(i, 0, 1, 2); + } + + RealType rho = assembler.get_material_data()[cell_ind].rho(); + vh = (1.0/rho)*(grad_uh); + } + + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + + } + + /// Record data at provided point for two fields approximation + static void record_data_acoustic_two_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t n_scal_dof = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_dof = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t cell_dof = n_scal_dof + n_vec_dof; + + RealType vh = 0.0; + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vh\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + // scalar evaluation + { + + Matrix scalar_cell_dof = x_dof.block(cell_ind*cell_dof+n_vec_dof, 0, n_scal_dof, 1); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + auto t_phi = cell_basis.eval_functions( pt ); + vh = scalar_cell_dof.dot( t_phi ); + } + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh << std::endl; + seismogram_file.flush(); + + } + + /// Record data at provided point for one field vectorial approximation + static void record_data_elastic_one_field(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + // vector evaluation + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_ind*cell_dof, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions( pt ); + assert(t_phi.rows() == cell_basis.size()); + vh = disk::eval(vec_x_cell_dof, t_phi); + } + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + + } + + /// Record data at provided point for two fields vectorial approximation + static void record_data_elastic_two_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), dim, dim); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t cell_dof = n_ten_cbs + n_vec_cbs; + + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + // vector evaluation + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_ind*cell_dof + n_ten_cbs , 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( pt ); + assert(t_phi.rows() == cell_basis.size()); + vh = disk::eval(vec_x_cell_dof, t_phi); + } + + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + + } + + /// Record data at provided point for three fields vectorial approximation + static void record_data_elastic_three_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), dim, dim); + size_t n_sca_cbs = disk::scalar_basis_size(hho_di.face_degree(), dim); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t cell_dof = n_ten_cbs + n_sca_cbs + n_vec_cbs; + + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + // vector evaluation + { + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_ind*cell_dof + n_ten_cbs + n_sca_cbs, 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( pt ); + assert(t_phi.rows() == cell_basis.size()); + vh = disk::eval(vec_x_cell_dof, t_phi); + } + + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + + } + + // WRITE SILO UNCOUPLED PROBLEM + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + // Write a silo file for one field approximation + static void write_silo_one_field(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, + std::function scal_fun, bool cell_centered_Q){ + + timecounter tc; + tc.tic(); + + auto dim = Mesh::dimension; + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + using RealType = double; + std::vector exact_u, approx_u; + size_t cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + + if (cell_centered_Q) { + exact_u.reserve( num_cells ); + approx_u.reserve( num_cells ); + + size_t cell_i = 0; + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + exact_u.push_back( scal_fun(bar) ); + + // scalar evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(cell_i*cell_dof, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.push_back(uh); + } + cell_i++; + } + + }else{ + + exact_u.reserve( num_points ); + approx_u.reserve( num_points ); + + // scan for selected cells, common cells are discardable + std::map point_to_cell; + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + point_to_cell[pt_id] = cell_i; + } + cell_i++; + } + + for (auto& pt_id : point_to_cell) + { + auto bar = *std::next(msh.points_begin(), pt_id.first); + exact_u.push_back( scal_fun(bar) ); + + cell_i = pt_id.second; + auto cell = *std::next(msh.cells_begin(), cell_i); + // scalar evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(cell_i*cell_dof, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.push_back(uh); + } + } + + } + + disk::silo_database silo; + silo_file_name += std::to_string(it) + ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + if (cell_centered_Q) { + disk::silo_zonal_variable v_silo("v", exact_u); + disk::silo_zonal_variable vh_silo("vh", approx_u); + silo.add_variable("mesh", v_silo); + silo.add_variable("mesh", vh_silo); + }else{ + disk::silo_nodal_variable v_silo("v", exact_u); + disk::silo_nodal_variable vh_silo("vh", approx_u); + silo.add_variable("mesh", v_silo); + silo.add_variable("mesh", vh_silo); + } + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // Write a silo file for two fields approximation + static void write_silo_two_fields(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, + std::function scal_fun, std::function(const typename Mesh::point_type& )> flux_fun, bool cell_centered_Q){ + + timecounter tc; + tc.tic(); + + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + using RealType = double; + std::vector exact_u, approx_u; + std::vector exact_dux, exact_duy, approx_dux, approx_duy; + + size_t n_scal_dof = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_dof = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t cell_dof = n_scal_dof + n_vec_dof; + + if (cell_centered_Q) { + exact_u.reserve( num_cells ); + approx_u.reserve( num_cells ); + exact_dux.reserve( num_cells ); + exact_duy.reserve( num_cells ); + approx_dux.reserve( num_cells ); + approx_duy.reserve( num_cells ); + + size_t cell_i = 0; + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + exact_u.push_back( scal_fun(bar) ); + exact_dux.push_back( flux_fun(bar)[0] ); + exact_duy.push_back( flux_fun(bar)[1] ); + + // scalar evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(cell_i*cell_dof+n_vec_dof, 0, n_scal_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.push_back(uh); + } + + // flux evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + Matrix flux_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_vec_dof, 1); + auto t_dphi = cell_basis.eval_gradients( bar ); + + Matrix grad_uh = Matrix::Zero(); + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + flux_cell_dof(i-1)*t_dphi.block(i, 0, 1, 2); + } + + approx_dux.push_back(grad_uh(0,0)); + approx_duy.push_back(grad_uh(0,1)); + } + + cell_i++; + } + + }else{ + + exact_u.reserve( num_points ); + approx_u.reserve( num_points ); + exact_dux.reserve( num_points ); + exact_duy.reserve( num_points ); + approx_dux.reserve( num_points ); + approx_duy.reserve( num_points ); + + // scan for selected cells, common cells are discardable + std::map point_to_cell; + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + point_to_cell[pt_id] = cell_i; + } + cell_i++; + } + + for (auto& pt_id : point_to_cell) + { + auto bar = *std::next(msh.points_begin(), pt_id.first); + cell_i = pt_id.second; + auto cell = *std::next(msh.cells_begin(), cell_i); + + exact_u.push_back( scal_fun(bar) ); + exact_dux.push_back( flux_fun(bar)[0] ); + exact_duy.push_back( flux_fun(bar)[1] ); + + // scalar evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(cell_i*cell_dof+n_vec_dof, 0, n_scal_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.push_back(uh); + } + + // flux evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + Matrix flux_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_vec_dof, 1); + auto t_dphi = cell_basis.eval_gradients( bar ); + + Matrix grad_uh = Matrix::Zero(); + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + flux_cell_dof(i-1)*t_dphi.block(i, 0, 1, 2); + } + + approx_dux.push_back(grad_uh(0,0)); + approx_duy.push_back(grad_uh(0,1)); + } + } + + } + + disk::silo_database silo; + silo_file_name += std::to_string(it) + ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + if (cell_centered_Q) { + disk::silo_zonal_variable v_silo("v", exact_u); + disk::silo_zonal_variable qx_silo("qx", exact_dux); + disk::silo_zonal_variable qy_silo("qy", exact_duy); + disk::silo_zonal_variable vh_silo("vh", approx_u); + disk::silo_zonal_variable qhx_silo("qhx", approx_dux); + disk::silo_zonal_variable qhy_silo("qhy", approx_duy); + silo.add_variable("mesh", v_silo); + silo.add_variable("mesh", qx_silo); + silo.add_variable("mesh", qy_silo); + silo.add_variable("mesh", vh_silo); + silo.add_variable("mesh", qhx_silo); + silo.add_variable("mesh", qhy_silo); + }else{ + disk::silo_nodal_variable v_silo("v", exact_u); + disk::silo_nodal_variable qx_silo("qx", exact_dux); + disk::silo_nodal_variable qy_silo("qy", exact_duy); + disk::silo_nodal_variable vh_silo("vh", approx_u); + disk::silo_nodal_variable qhx_silo("qhx", approx_dux); + disk::silo_nodal_variable qhy_silo("qhy", approx_duy); + silo.add_variable("mesh", v_silo); + silo.add_variable("mesh", qx_silo); + silo.add_variable("mesh", qy_silo); + silo.add_variable("mesh", vh_silo); + silo.add_variable("mesh", qhx_silo); + silo.add_variable("mesh", qhy_silo); + } + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // Write a silo file for one field vectorial approximation + static void write_silo_one_field_vectorial(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, + std::function(const typename Mesh::point_type& )> vec_fun, bool cell_centered_Q){ + + timecounter tc; + tc.tic(); + + auto dim = Mesh::dimension; + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + using RealType = double; + std::vector exact_ux, exact_uy, approx_ux, approx_uy; + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + + if (cell_centered_Q) { + exact_ux.reserve( num_cells ); + exact_uy.reserve( num_cells ); + approx_ux.reserve( num_cells ); + approx_uy.reserve( num_cells ); + + size_t cell_i = 0; + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + exact_ux.push_back( vec_fun(bar)(0,0) ); + exact_uy.push_back( vec_fun(bar)(1,0) ); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.push_back(uh(0,0)); + approx_uy.push_back(uh(1,0)); + } + cell_i++; + } + + }else{ + + exact_ux.reserve( num_points ); + exact_uy.reserve( num_points ); + approx_ux.reserve( num_points ); + approx_uy.reserve( num_points ); + + // scan for selected cells, common cells are discardable + std::map point_to_cell; + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + point_to_cell[pt_id] = cell_i; + } + cell_i++; + } + + for (auto& pt_id : point_to_cell) + { + auto bar = *std::next(msh.points_begin(), pt_id.first); + cell_i = pt_id.second; + auto cell = *std::next(msh.cells_begin(), cell_i); + + exact_ux.push_back( vec_fun(bar)(0,0) ); + exact_uy.push_back( vec_fun(bar)(1,0) ); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.push_back(uh(0,0)); + approx_uy.push_back(uh(1,0)); + } + } + + } + + disk::silo_database silo; + silo_file_name += std::to_string(it) + ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + if (cell_centered_Q) { + disk::silo_zonal_variable vx_silo("vx", exact_ux); + disk::silo_zonal_variable vy_silo("vy", exact_uy); + disk::silo_zonal_variable vhx_silo("vhx", approx_ux); + disk::silo_zonal_variable vhy_silo("vhy", approx_uy); + silo.add_variable("mesh", vx_silo); + silo.add_variable("mesh", vy_silo); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + }else{ + disk::silo_nodal_variable vx_silo("vx", exact_ux); + disk::silo_nodal_variable vy_silo("vy", exact_uy); + disk::silo_nodal_variable vhx_silo("vhx", approx_ux); + disk::silo_nodal_variable vhy_silo("vhy", approx_uy); + silo.add_variable("mesh", vx_silo); + silo.add_variable("mesh", vy_silo); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + } + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // Write a silo file for two fields vectorial approximation + static void write_silo_two_fields_vectorial(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof,std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> flux_fun, bool cell_centered_Q){ + + timecounter tc; + tc.tic(); + + auto dim = Mesh::dimension; + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + using RealType = double; + std::vector exact_ux, exact_uy, approx_ux, approx_uy; + std::vector exact_sxx, exact_sxy, exact_syy; + std::vector approx_sxx, approx_sxy, approx_syy; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), dim, dim); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t cell_dof = n_ten_cbs + n_vec_cbs; + + if (cell_centered_Q) { + exact_ux.reserve( num_cells ); + exact_uy.reserve( num_cells ); + approx_ux.reserve( num_cells ); + approx_uy.reserve( num_cells ); + + exact_sxx.reserve( num_cells ); + exact_sxy.reserve( num_cells ); + exact_syy.reserve( num_cells ); + approx_sxx.reserve( num_cells ); + approx_sxy.reserve( num_cells ); + approx_syy.reserve( num_cells ); + + size_t cell_i = 0; + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + exact_ux.push_back( vec_fun(bar)(0,0) ); + exact_uy.push_back( vec_fun(bar)(1,0) ); + + exact_sxx.push_back( flux_fun(bar)(0,0) ); + exact_sxy.push_back( flux_fun(bar)(0,1) ); + exact_syy.push_back( flux_fun(bar)(1,1) ); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_i*cell_dof + n_ten_cbs, 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.push_back(uh(0,0)); + approx_uy.push_back(uh(1,0)); + } + + // tensor evaluation + { + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_ten_cbs, 1); + + auto t_ten_phi = ten_basis.eval_functions( bar ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + approx_sxx.push_back(sigma_h(0,0)); + approx_sxy.push_back(sigma_h(0,1)); + approx_syy.push_back(sigma_h(1,1)); + } + + cell_i++; + } + + }else{ + + exact_ux.reserve( num_points ); + exact_uy.reserve( num_points ); + approx_ux.reserve( num_points ); + approx_uy.reserve( num_points ); + + exact_sxx.reserve( num_points ); + exact_sxy.reserve( num_points ); + exact_syy.reserve( num_points ); + approx_sxx.reserve( num_points ); + approx_sxy.reserve( num_points ); + approx_syy.reserve( num_points ); + + // scan for selected cells, common cells are discardable + std::map point_to_cell; + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + point_to_cell[pt_id] = cell_i; + } + cell_i++; + } + + for (auto& pt_id : point_to_cell) + { + auto bar = *std::next(msh.points_begin(), pt_id.first); + cell_i = pt_id.second; + auto cell = *std::next(msh.cells_begin(), cell_i); + + exact_ux.push_back( vec_fun(bar)(0,0) ); + exact_uy.push_back( vec_fun(bar)(1,0) ); + + exact_sxx.push_back( flux_fun(bar)(0,0) ); + exact_sxy.push_back( flux_fun(bar)(0,1) ); + exact_syy.push_back( flux_fun(bar)(1,1) ); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_i*cell_dof + n_ten_cbs, 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.push_back(uh(0,0)); + approx_uy.push_back(uh(1,0)); + } + + // tensor evaluation + { + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_ten_cbs, 1); + + auto t_ten_phi = ten_basis.eval_functions( bar ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + approx_sxx.push_back(sigma_h(0,0)); + approx_sxy.push_back(sigma_h(0,1)); + approx_syy.push_back(sigma_h(1,1)); + } + + } + + } + + disk::silo_database silo; + silo_file_name += std::to_string(it) + ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + if (cell_centered_Q) { + disk::silo_zonal_variable vx_silo("vx", exact_ux); + disk::silo_zonal_variable vy_silo("vy", exact_uy); + disk::silo_zonal_variable vhx_silo("vhx", approx_ux); + disk::silo_zonal_variable vhy_silo("vhy", approx_uy); + + disk::silo_nodal_variable sxx_silo("sxx", exact_sxx); + disk::silo_nodal_variable sxy_silo("sxy", exact_sxy); + disk::silo_nodal_variable syy_silo("syy", exact_syy); + disk::silo_nodal_variable shxx_silo("shxx", approx_sxx); + disk::silo_nodal_variable shxy_silo("shxy", approx_sxy); + disk::silo_nodal_variable shyy_silo("shyy", approx_syy); + + silo.add_variable("mesh", vx_silo); + silo.add_variable("mesh", vy_silo); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", sxx_silo); + silo.add_variable("mesh", sxy_silo); + silo.add_variable("mesh", syy_silo); + silo.add_variable("mesh", shxx_silo); + silo.add_variable("mesh", shxy_silo); + silo.add_variable("mesh", shyy_silo); + }else{ + disk::silo_nodal_variable vx_silo("vx", exact_ux); + disk::silo_nodal_variable vy_silo("vy", exact_uy); + disk::silo_nodal_variable vhx_silo("vhx", approx_ux); + disk::silo_nodal_variable vhy_silo("vhy", approx_uy); + + disk::silo_nodal_variable sxx_silo("sxx", exact_sxx); + disk::silo_nodal_variable sxy_silo("sxy", exact_sxy); + disk::silo_nodal_variable syy_silo("syy", exact_syy); + disk::silo_nodal_variable shxx_silo("shxx", approx_sxx); + disk::silo_nodal_variable shxy_silo("shxy", approx_sxy); + disk::silo_nodal_variable shyy_silo("shyy", approx_syy); + + silo.add_variable("mesh", vx_silo); + silo.add_variable("mesh", vy_silo); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", sxx_silo); + silo.add_variable("mesh", sxy_silo); + silo.add_variable("mesh", syy_silo); + silo.add_variable("mesh", shxx_silo); + silo.add_variable("mesh", shxy_silo); + silo.add_variable("mesh", shyy_silo); + + } + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // Write a silo file for three fields vectorial approximation + static void write_silo_three_fields_vectorial(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof,std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> flux_fun, bool cell_centered_Q){ + + timecounter tc; + tc.tic(); + + auto dim = Mesh::dimension; + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + using RealType = double; + std::vector exact_ux, exact_uy, approx_ux, approx_uy; + std::vector exact_sxx, exact_sxy, exact_syy; + std::vector approx_sxx, approx_sxy, approx_syy; + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), dim, dim); + size_t n_sca_cbs = disk::scalar_basis_size(hho_di.face_degree(), dim); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t cell_dof = n_ten_cbs + n_sca_cbs + n_vec_cbs; + + if (cell_centered_Q) { + exact_ux.reserve( num_cells ); + exact_uy.reserve( num_cells ); + approx_ux.reserve( num_cells ); + approx_uy.reserve( num_cells ); + + exact_sxx.reserve( num_cells ); + exact_sxy.reserve( num_cells ); + exact_syy.reserve( num_cells ); + approx_sxx.reserve( num_cells ); + approx_sxy.reserve( num_cells ); + approx_syy.reserve( num_cells ); + + size_t cell_i = 0; + for (auto& cell : msh) + { + auto bar = barycenter(msh, cell); + exact_ux.push_back( vec_fun(bar)(0,0) ); + exact_uy.push_back( vec_fun(bar)(1,0) ); + + exact_sxx.push_back( flux_fun(bar)(0,0) ); + exact_sxy.push_back( flux_fun(bar)(0,1) ); + exact_syy.push_back( flux_fun(bar)(1,1) ); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_i*cell_dof + n_ten_cbs + n_sca_cbs, 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.push_back(uh(0,0)); + approx_uy.push_back(uh(1,0)); + } + + // tensor evaluation + { + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_ten_cbs, 1); + + auto sca_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.face_degree()); + Matrix sigma_v_x_cell_dof = x_dof.block(cell_i*cell_dof+n_ten_cbs, 0, n_sca_cbs, 1); + + auto t_ten_phi = ten_basis.eval_functions( bar ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + auto t_sca_phi = sca_basis.eval_functions( bar ); + assert(t_sca_phi.size() == sca_basis.size()); + auto sigma_v_h = disk::eval(sigma_v_x_cell_dof, t_sca_phi); + + sigma_h += sigma_v_h * disk::static_matrix::Identity(); + + approx_sxx.push_back(sigma_h(0,0)); + approx_sxy.push_back(sigma_h(0,1)); + approx_syy.push_back(sigma_h(1,1)); + } + + cell_i++; + } + + }else{ + + exact_ux.reserve( num_points ); + exact_uy.reserve( num_points ); + approx_ux.reserve( num_points ); + approx_uy.reserve( num_points ); + + exact_sxx.reserve( num_points ); + exact_sxy.reserve( num_points ); + exact_syy.reserve( num_points ); + approx_sxx.reserve( num_points ); + approx_sxy.reserve( num_points ); + approx_syy.reserve( num_points ); + + // scan for selected cells, common cells are discardable + std::map point_to_cell; + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + point_to_cell[pt_id] = cell_i; + } + cell_i++; + } + + for (auto& pt_id : point_to_cell) + { + auto bar = *std::next(msh.points_begin(), pt_id.first); + cell_i = pt_id.second; + auto cell = *std::next(msh.cells_begin(), cell_i); + + exact_ux.push_back( vec_fun(bar)(0,0) ); + exact_uy.push_back( vec_fun(bar)(1,0) ); + + exact_sxx.push_back( flux_fun(bar)(0,0) ); + exact_sxy.push_back( flux_fun(bar)(0,1) ); + exact_syy.push_back( flux_fun(bar)(1,1) ); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(cell_i*cell_dof + n_ten_cbs + n_sca_cbs, 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.push_back(uh(0,0)); + approx_uy.push_back(uh(1,0)); + } + + // tensor evaluation + { + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(cell_i*cell_dof, 0, n_ten_cbs, 1); + + auto sca_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.face_degree()); + Matrix sigma_v_x_cell_dof = x_dof.block(cell_i*cell_dof+n_ten_cbs, 0, n_sca_cbs, 1); + + auto t_ten_phi = ten_basis.eval_functions( bar ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + auto t_sca_phi = sca_basis.eval_functions( bar ); + assert(t_sca_phi.size() == sca_basis.size()); + auto sigma_v_h = disk::eval(sigma_v_x_cell_dof, t_sca_phi); + + sigma_h += sigma_v_h * disk::static_matrix::Identity(); + + approx_sxx.push_back(sigma_h(0,0)); + approx_sxy.push_back(sigma_h(0,1)); + approx_syy.push_back(sigma_h(1,1)); + } + + } + + } + + disk::silo_database silo; + silo_file_name += std::to_string(it) + ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + if (cell_centered_Q) { + disk::silo_zonal_variable vx_silo("vx", exact_ux); + disk::silo_zonal_variable vy_silo("vy", exact_uy); + disk::silo_zonal_variable vhx_silo("vhx", approx_ux); + disk::silo_zonal_variable vhy_silo("vhy", approx_uy); + + disk::silo_nodal_variable sxx_silo("sxx", exact_sxx); + disk::silo_nodal_variable sxy_silo("sxy", exact_sxy); + disk::silo_nodal_variable syy_silo("syy", exact_syy); + disk::silo_nodal_variable shxx_silo("shxx", approx_sxx); + disk::silo_nodal_variable shxy_silo("shxy", approx_sxy); + disk::silo_nodal_variable shyy_silo("shyy", approx_syy); + + silo.add_variable("mesh", vx_silo); + silo.add_variable("mesh", vy_silo); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", sxx_silo); + silo.add_variable("mesh", sxy_silo); + silo.add_variable("mesh", syy_silo); + silo.add_variable("mesh", shxx_silo); + silo.add_variable("mesh", shxy_silo); + silo.add_variable("mesh", shyy_silo); + }else{ + disk::silo_nodal_variable vx_silo("vx", exact_ux); + disk::silo_nodal_variable vy_silo("vy", exact_uy); + disk::silo_nodal_variable vhx_silo("vhx", approx_ux); + disk::silo_nodal_variable vhy_silo("vhy", approx_uy); + + disk::silo_nodal_variable sxx_silo("sxx", exact_sxx); + disk::silo_nodal_variable sxy_silo("sxy", exact_sxy); + disk::silo_nodal_variable syy_silo("syy", exact_syy); + disk::silo_nodal_variable shxx_silo("shxx", approx_sxx); + disk::silo_nodal_variable shxy_silo("shxy", approx_sxy); + disk::silo_nodal_variable shyy_silo("shyy", approx_syy); + + silo.add_variable("mesh", vx_silo); + silo.add_variable("mesh", vy_silo); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", sxx_silo); + silo.add_variable("mesh", sxy_silo); + silo.add_variable("mesh", syy_silo); + silo.add_variable("mesh", shxx_silo); + silo.add_variable("mesh", shxy_silo); + silo.add_variable("mesh", shyy_silo); + + } + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // Write a silo file with acoustic properties as zonal variables + static void write_silo_acoustic_property_map(std::string silo_file_name, Mesh & msh, std::vector< acoustic_material_data > & material){ + + timecounter tc; + tc.tic(); + + auto num_cells = msh.cells_size(); + std::vector rho_data, vp_data; + vp_data.reserve( num_cells ); + rho_data.reserve( num_cells ); + + for (size_t cell_id = 0; cell_id < num_cells; cell_id++) + { + acoustic_material_data acoustic_data = material[cell_id]; + rho_data.push_back( acoustic_data.rho() ); + vp_data.push_back( acoustic_data.vp() ); + } + + disk::silo_database silo; + silo_file_name += ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + disk::silo_zonal_variable rho_silo("rho", rho_data); + disk::silo_zonal_variable vp_silo("vp", vp_data); + silo.add_variable("mesh", rho_silo); + silo.add_variable("mesh", vp_silo); + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Properties file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // Write a silo file with elastic properties as zonal variables + static void write_silo_elastic_property_map(std::string silo_file_name, Mesh & msh, std::vector< elastic_material_data > & material){ + + timecounter tc; + tc.tic(); + + auto num_cells = msh.cells_size(); + std::vector rho_data, vp_data, vs_data; + rho_data.reserve( num_cells ); + vp_data.reserve( num_cells ); + vs_data.reserve( num_cells ); + + for (size_t cell_id = 0; cell_id < num_cells; cell_id++) { + elastic_material_data elastic_data = material[cell_id]; + rho_data.push_back( elastic_data.rho() ); + vp_data.push_back( elastic_data.vp() ); + vs_data.push_back( elastic_data.vs() ); + } + + disk::silo_database silo; + silo_file_name += ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + disk::silo_zonal_variable rho_silo("rho", rho_data); + disk::silo_zonal_variable vp_silo("vp", vp_data); + disk::silo_zonal_variable vs_silo("vs", vs_data); + silo.add_variable("mesh", rho_silo); + silo.add_variable("mesh", vp_silo); + silo.add_variable("mesh", vs_silo); + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Properties file rendered in : " << tc << " seconds" << reset << std::endl; + } + + // COUPLING POSTPROCESS UNCOUPLED PROBLEM + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + /// Compute errors + static void compute_errors_two_fields_elastoacoustic(Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_two_fields_assembler & assembler, Matrix & x_dof, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> sigma_fun,std::function scal_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + RealType scalar_l2_error = 0.0; + RealType flux_l2_error = 0.0; + RealType vector_l2_error = 0.0; + RealType sigma_l2_error = 0.0; + RealType h = 10.0; + size_t e_cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t a_cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + auto storage = msh.backend_storage(); + + size_t e_cell_ind = 0; + for (auto& e_chunk : assembler.get_e_material_data()) { + + auto& cell = storage->surfaces[e_chunk.first]; + + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix vec_cell_dof = x_dof.block(e_cell_ind*e_cell_dof, 0, e_cell_dof, 1); + + // scalar evaluation + { + auto cell_basis = disk::make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, vec_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - vec_cell_dof; + vector_l2_error += diff.dot(mass*diff); + + } + + elastic_material_data material = e_chunk.second; + RealType mu = material.rho()*material.vs()*material.vs(); + RealType lambda = material.rho()*material.vp()*material.vp() - 2.0*mu; + + // sigma evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + Matrix all_dofs = assembler.gather_e_dof_data(e_cell_ind, msh, cell, x_dof); + + auto sgr = make_vector_hho_symmetric_laplacian(msh, cell, hho_di); + disk::dynamic_vector GTu = sgr.first * all_dofs; + + auto dr = make_hho_divergence_reconstruction(msh, cell, hho_di); + disk::dynamic_vector divu = dr.first * all_dofs; + + auto cbas_v = disk::make_vector_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto cbas_s = disk::make_scalar_monomial_basis(msh, cell, hho_di.face_degree()); + + auto rec_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + + auto t_dphi = rec_basis.eval_gradients( point_pair.point() ); + auto gphi = cbas_v.eval_sgradients(point_pair.point()); + auto epsilon = disk::eval(GTu, gphi, dim); + auto divphi = cbas_s.eval_functions(point_pair.point()); + auto trace_epsilon = disk::eval(divu, divphi); + auto sigma = 2.0 * mu * epsilon + lambda * trace_epsilon * disk::static_matrix::Identity(); + auto flux_diff = (sigma_fun(point_pair.point()) - sigma).eval(); + sigma_l2_error += omega * flux_diff.squaredNorm(); + + } + } + + e_cell_ind++; + } + + size_t n_elastic_cell_dof = assembler.get_e_material_data().size() * e_cell_dof; + size_t a_cell_ind = 0; + for (auto& a_chunk : assembler.get_a_material_data()) { + + auto& cell = storage->surfaces[a_chunk.first]; + + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix scalar_cell_dof = x_dof.block(a_cell_ind*a_cell_dof+n_elastic_cell_dof, 0, a_cell_dof, 1); + + // scalar evaluation + { + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, scal_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - scalar_cell_dof; + scalar_l2_error += diff.dot(mass*diff); + + } + + // flux evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + auto rec_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto gr = make_scalar_hho_laplacian(msh, cell, hho_di); + Matrix all_dofs = assembler.gather_a_dof_data(a_cell_ind, msh, cell, x_dof); + Matrix recdofs = gr.first * all_dofs; + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + auto t_dphi = rec_basis.eval_gradients( point_pair.point() ); + Matrix grad_uh = Matrix::Zero(); + + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + recdofs(i-1)*t_dphi.block(i, 0, 1, 2); + } + + Matrix grad_u_exact = flux_fun(point_pair.point()); + flux_l2_error += omega * (grad_u_exact - grad_uh).dot(grad_u_exact - grad_uh); + + } + } + a_cell_ind++; + } + + tc.toc(); + std::cout << bold << cyan << "Error completed: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << h << std::endl; + error_file << "Elastic region : " << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(vector_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(sigma_l2_error) << std::endl; + error_file << "Acoustic region : " << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(scalar_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + } + + static void compute_errors_four_fields_elastoacoustic(Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> sigma_fun,std::function scal_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + RealType scalar_l2_error = 0.0; + RealType flux_l2_error = 0.0; + RealType vector_l2_error = 0.0; + RealType sigma_l2_error = 0.0; + RealType h = 10.0; + + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t e_cell_dof = n_ten_cbs + n_vec_cbs; + + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_cell_dof = n_vel_scal_cbs + n_scal_cbs; + + auto storage = msh.backend_storage(); + size_t e_cell_ind = 0; + for (auto& e_chunk : assembler.get_e_material_data()) { + auto& cell = storage->surfaces[e_chunk.first]; + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + Matrix vec_cell_dof = x_dof.block(e_cell_ind*e_cell_dof+n_ten_cbs, 0, n_vec_cbs, 1); + + // scalar evaluation + { + auto cell_basis = disk::make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, vec_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - vec_cell_dof; + vector_l2_error += diff.dot(mass*diff); + + } + + elastic_material_data material = e_chunk.second; + RealType mu = material.rho()*material.vs()*material.vs(); + RealType lambda = material.rho()*material.vp()*material.vp() - 2.0*mu; + + + // tensor evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix ten_x_cell_dof = x_dof.block(e_cell_ind*e_cell_dof, 0, n_ten_cbs, 1); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + + auto t_ten_phi = ten_basis.eval_functions( point_pair.point() ); + assert(t_ten_phi.size() == ten_basis.size()); + auto sigma_h = disk::eval(ten_x_cell_dof, t_ten_phi); + + auto flux_diff = (sigma_fun(point_pair.point()) - sigma_h).eval(); + sigma_l2_error += omega * flux_diff.squaredNorm(); + + } + + } + + e_cell_ind++; + } + + size_t n_elastic_cell_dof = assembler.get_e_material_data().size() * e_cell_dof; + size_t a_cell_ind = 0; + for (auto& a_chunk : assembler.get_a_material_data()) { + + auto& cell = storage->surfaces[a_chunk.first]; + + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + Matrix scalar_cell_dof = x_dof.block(a_cell_ind*a_cell_dof+n_elastic_cell_dof+n_vel_scal_cbs, 0, n_scal_cbs, 1); + + // scalar evaluation + { + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.cell_degree()); + Matrix rhs = make_rhs(msh, cell, cell_basis, scal_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - scalar_cell_dof; + scalar_l2_error += diff.dot(mass*diff); + + } + + // flux evaluation + { + auto int_rule = integrate(msh, cell, 2*(hho_di.cell_degree()+1)); + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + Matrix flux_cell_dof = x_dof.block(a_cell_ind*a_cell_dof+n_elastic_cell_dof, 0, n_vel_scal_cbs, 1); + + // Error integrals + for (auto & point_pair : int_rule) { + + RealType omega = point_pair.weight(); + auto t_dphi = cell_basis.eval_gradients( point_pair.point() ); + + Matrix grad_uh = Matrix::Zero(); + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + flux_cell_dof(i-1)*t_dphi.block(i, 0, 1, 2); + } + + Matrix grad_u_exact = Matrix::Zero(); + grad_u_exact(0,0) = flux_fun(point_pair.point())[0]; + grad_u_exact(0,1) = flux_fun(point_pair.point())[1]; + flux_l2_error += omega * (grad_u_exact - grad_uh).dot(grad_u_exact - grad_uh); + + } + } + a_cell_ind++; + } + + tc.toc(); + // std::cout << bold << red << " ERROR COMPLETED: " << tc << " seconds" << reset << std::endl; + error_file << "Characteristic h size = " << h << std::endl; + error_file << "Elastic region : " << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(vector_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(sigma_l2_error) << std::endl; + error_file << "Acoustic region : " << std::endl; + error_file << "L2-norm error = " << std::setprecision(16) << std::sqrt(scalar_l2_error) << std::endl; + error_file << "H1-norm error = " << std::setprecision(16) << std::sqrt(flux_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + } + + static void compute_errors_four_fields_elastoacoustic_energy_norm(Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, std::function(const typename Mesh::point_type& )> vec_fun, std::function(const typename Mesh::point_type& )> sigma_fun,std::function scal_fun, std::function(const typename Mesh::point_type& )> flux_fun, std::ostream & error_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + RealType dg_acoutic_l2_error = 0.0; + RealType dg_elastic_l2_error = 0.0; + RealType h = 10.0; + + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.face_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t e_cell_dof = n_ten_cbs + n_vec_cbs; + + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_cell_dof = n_vel_scal_cbs + n_scal_cbs; + + auto storage = msh.backend_storage(); + + // Elastic dG unknowns + size_t e_cell_ind = 0; + for (auto& e_chunk : assembler.get_e_material_data()) { + + auto& cell = storage->surfaces[e_chunk.first]; + + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + { // tensor evaluation + Matrix ten_x_cell_dof = x_dof.block(e_cell_ind*e_cell_dof, 0, n_ten_cbs, 1); + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.face_degree()); + Matrix mass = make_mass_matrix(msh, cell, ten_basis, hho_di.face_degree()); + Matrix rhs = make_rhs(msh, cell, ten_basis, sigma_fun); + Matrix real_dofs = mass.llt().solve(rhs); + Matrix diff = real_dofs - ten_x_cell_dof; + dg_elastic_l2_error += diff.dot(mass*diff); + } + + e_cell_ind++; + } + + size_t n_elastic_cell_dof = assembler.get_e_material_data().size() * e_cell_dof; + + // Acoustic dG unknowns + size_t a_cell_ind = 0; + for (auto& a_chunk : assembler.get_a_material_data()) { + + auto& cell = storage->surfaces[a_chunk.first]; + + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + + + { // Vectorial evaluation + Matrix flux_cell_dof = x_dof.block(a_cell_ind*a_cell_dof+n_elastic_cell_dof, 0, n_vel_scal_cbs, 1); + Matrix real_dofs = flux_cell_dof; + + auto recdeg = hho_di.reconstruction_degree(); + auto rec_basis = make_scalar_monomial_basis(msh, cell, recdeg); + auto rbs = disk::scalar_basis_size(recdeg, Mesh::dimension); + Matrix mass_matrix_q_full = make_stiffness_matrix(msh, cell, rec_basis); + Matrix mass_matrix_q = Matrix::Zero(rbs-1, rbs-1); + mass_matrix_q = mass_matrix_q_full.block(1, 1, rbs-1, rbs-1); + + Matrix rhs = Matrix::Zero(rbs-1); + Matrix f_vec = Matrix::Zero(1, 2); + const auto qps = integrate(msh, cell, 2*recdeg); + for (auto& qp : qps) { + auto dphi = rec_basis.eval_gradients(qp.point()); + f_vec(0,0) = flux_fun(qp.point())[0]; + f_vec(0,1) = flux_fun(qp.point())[1]; + for (size_t i = 0; i < rbs-1; i++){ + Matrix phi_i = dphi.block(i+1, 0, 1, 2).transpose(); + rhs(i,0) = rhs(i,0) + (qp.weight() * f_vec*phi_i)(0,0); + } + } + real_dofs = mass_matrix_q.llt().solve(rhs); + + // std::cout << "flux_cell_dof = " << flux_cell_dof.size() << std::endl; + // auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + // std::cout << "cell_basis = " << cell_basis.size() << std::endl; + // Matrix mass = make_mass_matrix(msh, cell, cell_basis, hho_di.face_degree()); + // std::cout << "mass = " << mass_matrix_q.size() << std::endl; + // Matrix rhs = make_rhs(msh, cell, cell_basis, flux_fun); + // std::cout << "rhs = " << rhs.size() << std::endl; + // Matrix real_dofs = mass.llt().solve(rhs); + // std::cout << "real_dofs = " << real_dofs.size() << std::endl; + Matrix diff = real_dofs - flux_cell_dof; + // std::cout << "diff = " << diff.size() << std::endl; + dg_acoutic_l2_error += diff.dot(mass_matrix_q*diff); + // std::cout << std::endl; + + } + + a_cell_ind++; + } + + tc.toc(); + error_file << "L2 errors of dG unknowns: " << std::endl; + error_file << "Acoustic region : " << std::setprecision(16) << std::sqrt(dg_acoutic_l2_error) << std::endl; + error_file << "Elastic region : " << std::setprecision(16) << std::sqrt(dg_elastic_l2_error) << std::endl; + error_file << std::endl; + error_file.flush(); + } + + /// Compute energy + static double compute_elasto_acoustic_energy_four_field(Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, double & time, Matrix & x_dof, std::ostream & energy_file = std::cout) { + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + // Elastic basis functions + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(),Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), Mesh::dimension, Mesh::dimension); + size_t e_cell_dof = n_ten_cbs + n_vec_cbs; + + // Acoustic basis functions + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension) - 1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_cell_dof = n_vel_scal_cbs + n_scal_cbs; + + + auto storage = msh.backend_storage(); + std::vector elastic_energy_vec(msh.cells_size()); + std::vector acoustic_energy_vec(msh.cells_size()); + + // Computation of the elastic energy + size_t e_cell_ind = 0; + + //Loop on elastic elements + for (auto& e_chunk : assembler.get_e_material_data()) { + auto& cell = storage->surfaces[e_chunk.first]; + + Matrix mass_matrix = assembler.e_mass_operator(e_chunk.second, msh, cell); + Matrix x_dof_loc = assembler.gather_e_dof_data(e_chunk.first, msh, cell, x_dof); + + // Evaluation of the L2 norm of the velocity (vectorial component) + Matrix mass_matrix_v = mass_matrix.block(n_ten_cbs, n_ten_cbs, n_vec_cbs, n_vec_cbs); + Matrix vec_cell_dof = x_dof_loc.block(n_ten_cbs, 0, n_vec_cbs, 1); + Matrix v_mass_tested = mass_matrix_v * vec_cell_dof; + Matrix term_1 = vec_cell_dof.transpose() * v_mass_tested; + elastic_energy_vec[e_cell_ind] = term_1(0,0); + + // Evaluation of the L2 norm of the strain tensor + Matrix mass_sigma = mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs); + Matrix sigma_dof = x_dof_loc.block(0, 0, n_ten_cbs, 1); + Matrix epsilon_mass = mass_sigma * sigma_dof; + Matrix term_2 = sigma_dof.transpose() * epsilon_mass; + elastic_energy_vec[e_cell_ind] += term_2(0,0); + + e_cell_ind++; + + } + + // // Computation of the acoustic energy + size_t a_cell_ind = 0; + + // Loop on acoustic elements + for (auto& a_chunk : assembler.get_a_material_data()) { + auto& cell = storage->surfaces[a_chunk.first]; + + Matrix mass_matrix = assembler.a_mass_operator(a_chunk.second, msh, cell); + Matrix x_dof_loc = assembler.gather_a_dof_data(a_chunk.first, msh, cell, x_dof); + + // Evaluation of the L2 norm of the pressure (scalar component) + Matrix mass_matrix_p = mass_matrix.block(n_vel_scal_cbs, n_vel_scal_cbs, n_scal_cbs, n_scal_cbs); + Matrix p_cell_dof = x_dof_loc.block(n_vel_scal_cbs, 0, n_scal_cbs, 1); + Matrix p_cell_mass_tested = mass_matrix_p * p_cell_dof; + Matrix term_3 = p_cell_dof.transpose() * p_cell_mass_tested; + acoustic_energy_vec[a_cell_ind] = term_3(0,0); + + // Evaluation of the L2 norm of the acoustic velocity (vectorial component) + Matrix mass_matrix_v = mass_matrix.block(0, 0, n_vel_scal_cbs, n_vel_scal_cbs); + Matrix v_cell_dof = x_dof_loc.block(0, 0, n_vel_scal_cbs, 1); + Matrix v_cell_mass_tested = mass_matrix_v * v_cell_dof; + Matrix term_4 = v_cell_dof.transpose() * v_cell_mass_tested; + acoustic_energy_vec[a_cell_ind] += term_4(0,0); + + a_cell_ind++; + } + + RealType elastic_energy_h = std::accumulate(elastic_energy_vec.begin(), elastic_energy_vec.end(), 0.0); + RealType acoustic_energy_h = std::accumulate(acoustic_energy_vec.begin(), acoustic_energy_vec.end(), 0.0); + elastic_energy_h *= 0.5; + acoustic_energy_h *= 0.5; + RealType total_energy = elastic_energy_h + acoustic_energy_h; + tc.toc(); + + // std::cout << bold << cyan << " Energy completed: " << tc << " seconds" << reset; + energy_file << time << " " << std::setprecision(16) + << elastic_energy_h << " " + << acoustic_energy_h << " " << total_energy << std::endl; + + return total_energy; + } + + static double compute_elasto_acoustic_energy_four_field_bassin(polygon_2d_mesh_reader mesh_builder, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, double & time, Matrix & x_dof, std::ostream & energy_file = std::cout) { + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + // Elastic basis functions + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(),Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), Mesh::dimension, Mesh::dimension); + size_t e_cell_dof = n_ten_cbs + n_vec_cbs; + + // Acoustic basis functions + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension) - 1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_cell_dof = n_vel_scal_cbs + n_scal_cbs; + + auto storage = msh.backend_storage(); + std::vector elastic_energy_vec(msh.cells_size()); + std::vector socle_energy_vec(msh.cells_size()); + std::vector sediment_energy_vec(msh.cells_size()); + std::vector acoustic_energy_vec(msh.cells_size()); + + // Computation of the elastic energy + size_t e_cell_ind = 0; + + //Loop on elastic elements + for (auto& e_chunk : assembler.get_e_material_data()) { + auto& cell = storage->surfaces[e_chunk.first]; + Matrix mass_matrix = assembler.e_mass_operator(e_chunk.second, msh, cell); + Matrix x_dof_loc = assembler.gather_e_dof_data(e_chunk.first, msh, cell, x_dof); + + // Evaluation of the L2 norm of the velocity (vectorial component) + Matrix mass_matrix_v = mass_matrix.block(n_ten_cbs, n_ten_cbs, n_vec_cbs, n_vec_cbs); + Matrix vec_cell_dof = x_dof_loc.block(n_ten_cbs, 0, n_vec_cbs, 1); + Matrix v_mass_tested = mass_matrix_v * vec_cell_dof; + Matrix term_1 = vec_cell_dof.transpose() * v_mass_tested; + elastic_energy_vec[e_cell_ind] = term_1(0,0); + + // Evaluation of the L2 norm of the strain tensor + Matrix mass_sigma = mass_matrix.block(0, 0, n_ten_cbs, n_ten_cbs); + Matrix sigma_dof = x_dof_loc.block(0, 0, n_ten_cbs, 1); + Matrix epsilon_mass = mass_sigma * sigma_dof; + Matrix term_2 = sigma_dof.transpose() * epsilon_mass; + if (mesh_builder.polygons[e_chunk.first].m_material == 1) { + socle_energy_vec[e_cell_ind] = term_1(0,0) + term_2(0,0); + } + if (mesh_builder.polygons[e_chunk.first].m_material == 2) { + sediment_energy_vec[e_cell_ind] = term_1(0,0) + term_2(0,0); + } + elastic_energy_vec[e_cell_ind] += term_2(0,0); + + e_cell_ind++; + + } + + // // Computation of the acoustic energy + size_t a_cell_ind = 0; + + // Loop on acoustic elements + for (auto& a_chunk : assembler.get_a_material_data()) { + auto& cell = storage->surfaces[a_chunk.first]; + + Matrix mass_matrix = assembler.a_mass_operator(a_chunk.second, msh, cell); + Matrix x_dof_loc = assembler.gather_a_dof_data(a_chunk.first, msh, cell, x_dof); + + // Evaluation of the L2 norm of the pressure (scalar component) + Matrix mass_matrix_p = mass_matrix.block(n_vel_scal_cbs, n_vel_scal_cbs, n_scal_cbs, n_scal_cbs); + Matrix p_cell_dof = x_dof_loc.block(n_vel_scal_cbs, 0, n_scal_cbs, 1); + Matrix p_cell_mass_tested = mass_matrix_p * p_cell_dof; + Matrix term_3 = p_cell_dof.transpose() * p_cell_mass_tested; + acoustic_energy_vec[a_cell_ind] = term_3(0,0); + + // Evaluation of the L2 norm of the acoustic velocity (vectorial component) + Matrix mass_matrix_v = mass_matrix.block(0, 0, n_vel_scal_cbs, n_vel_scal_cbs); + Matrix v_cell_dof = x_dof_loc.block(0, 0, n_vel_scal_cbs, 1); + Matrix v_cell_mass_tested = mass_matrix_v * v_cell_dof; + Matrix term_4 = v_cell_dof.transpose() * v_cell_mass_tested; + acoustic_energy_vec[a_cell_ind] += term_4(0,0); + + a_cell_ind++; + } + + RealType socle_energy_h = std::accumulate(socle_energy_vec.begin(), socle_energy_vec.end(), 0.0); + RealType sediment_energy_h = std::accumulate(sediment_energy_vec.begin(), sediment_energy_vec.end(), 0.0); + RealType elastic_energy_h = std::accumulate(elastic_energy_vec.begin(), elastic_energy_vec.end(), 0.0); + RealType acoustic_energy_h = std::accumulate(acoustic_energy_vec.begin(), acoustic_energy_vec.end(), 0.0); + socle_energy_h *= 0.5; + sediment_energy_h *= 0.5; + elastic_energy_h *= 0.5; + acoustic_energy_h *= 0.5; + RealType total_energy = elastic_energy_h + acoustic_energy_h; + tc.toc(); + + // std::cout << bold << cyan << " Energy completed: " << tc << " seconds" << reset; + energy_file << time << " " << std::setprecision(16) + << socle_energy_h << " " + << sediment_energy_h << " " + << elastic_energy_h << " " + << acoustic_energy_h << " " << total_energy << std::endl; + + return total_energy; + + } + + // Write silo file + static void write_silo_two_fields_elastoacoustic(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::map> & e_material, std::map> & a_material, bool cell_centered_Q){ + + timecounter tc; + tc.tic(); + + auto dim = Mesh::dimension; + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + using RealType = double; + std::vector approx_ux, approx_uy; + std::vector approx_u; + size_t e_cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + size_t a_cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + auto storage = msh.backend_storage(); + + if (cell_centered_Q) { + approx_ux.resize( num_cells ); + approx_uy.resize( num_cells ); + approx_u.resize( num_cells ); + + size_t e_cell_ind = 0; + for (auto& e_chunk : e_material) { + + auto& cell = storage->surfaces[e_chunk.first]; + auto bar = barycenter(msh, cell); + approx_u.at(e_chunk.first) =( 0.0/ 0.0); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(e_cell_ind*e_cell_dof, 0, e_cell_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.at(e_chunk.first) = (uh(0,0)); + approx_uy.at(e_chunk.first) = (uh(1,0)); + } + e_cell_ind++; + } + + size_t n_elastic_cell_dof = e_material.size() * e_cell_dof; + size_t a_cell_ind = 0; + for (auto& a_chunk : a_material) { + + auto& cell = storage->surfaces[a_chunk.first]; + auto bar = barycenter(msh, cell); + approx_ux.at(a_chunk.first) = ( 0.0/0.0 ); + approx_uy.at(a_chunk.first) = ( 0.0/0.0 ); + + // scalar evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(a_cell_ind*a_cell_dof + n_elastic_cell_dof, 0, a_cell_dof, 1); + auto t_phi = cell_basis.eval_functions( bar ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.at(a_chunk.first) = (uh); + } + a_cell_ind++; + } + + + }else{ + + // Filling with nan (It is weird but useful in Paraview) + approx_ux.resize( num_points , 0.0/ 0.0); + approx_uy.resize( num_points , 0.0/ 0.0); + approx_u.resize( num_points , 0.0/ 0.0); + + std::map e_cell_index; + std::map a_cell_index; + + // elastic data + size_t e_cell_ind = 0; + for (auto chunk : e_material) { + e_cell_index.insert(std::make_pair(chunk.first,e_cell_ind)); + e_cell_ind++; + } + + // acoustic data + size_t a_cell_ind = 0; + for (auto chunk : a_material) { + a_cell_index.insert(std::make_pair(chunk.first,a_cell_ind)); + a_cell_ind++; + } + + for (auto& e_chunk : e_material) { + + auto& cell = storage->surfaces[e_chunk.first]; + size_t e_cell_ind = e_cell_index[e_chunk.first]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(e_cell_ind*e_cell_dof, 0, e_cell_dof, 1); + + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + auto pt_coord = *std::next(msh.points_begin(), pt_id); + // vector evaluation + { + auto t_phi = cell_basis.eval_functions( pt_coord ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.at(pt_id) = uh(0,0); + approx_uy.at(pt_id) = uh(1,0); + } + } + } + + size_t n_elastic_cell_dof = e_material.size() * e_cell_dof; + for (auto& a_chunk : a_material) { + + auto& cell = storage->surfaces[a_chunk.first]; + size_t a_cell_ind = a_cell_index[a_chunk.first]; + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(a_cell_ind*a_cell_dof + n_elastic_cell_dof, 0, a_cell_dof, 1); + + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + auto pt_coord = *std::next(msh.points_begin(), pt_id); + // scalar evaluation + { + auto t_phi = cell_basis.eval_functions( pt_coord ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.at(pt_id) = uh; + } + } + } + + } + + disk::silo_database silo; + silo_file_name += std::to_string(it) + ".silo"; + silo.create(silo_file_name.c_str()); + silo.add_mesh(msh, "mesh"); + if (cell_centered_Q) { + disk::silo_zonal_variable vhx_silo("vhx", approx_ux); + disk::silo_zonal_variable vhy_silo("vhy", approx_uy); + disk::silo_zonal_variable vh_silo("vh", approx_u); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", vh_silo); + }else{ + disk::silo_nodal_variable vhx_silo("vhx", approx_ux); + disk::silo_nodal_variable vhy_silo("vhy", approx_uy); + disk::silo_nodal_variable vh_silo("vh", approx_u); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", vh_silo); + } + + silo.close(); + tc.toc(); + std::cout << std::endl; + std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset << std::endl; + } + + static void write_silo_four_fields_elastoacoustic(std::string silo_file_name, size_t it, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof, std::map> & e_material, std::map> & a_material, bool cell_centered_Q) { + + timecounter tc; + tc.tic(); + + auto dim = Mesh::dimension; + auto num_cells = msh.cells_size(); + auto num_points = msh.points_size(); + + using RealType = double; + std::vector approx_ux, approx_uy, approx_uy_bis; + std::vector approx_u; + + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(), Mesh::dimension, Mesh::dimension); + size_t e_cell_dof = n_ten_cbs + n_vec_cbs; + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension) -1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_cell_dof = n_vel_scal_cbs + n_scal_cbs; + + auto storage = msh.backend_storage(); + + if (cell_centered_Q) { + approx_ux.resize(num_cells); + approx_uy.resize(num_cells); + approx_uy_bis.resize(num_cells); + approx_u.resize (num_cells); + + size_t e_cell_ind = 0; + for (auto& e_chunk : e_material) { + + auto& cell = storage->surfaces[e_chunk.first]; + auto bar = barycenter(msh, cell); + approx_u.at(e_chunk.first) = (0.0/0.0); + + // vector evaluation + { + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(e_cell_ind*e_cell_dof + + n_ten_cbs, 0, n_vec_cbs, 1); + auto t_phi = cell_basis.eval_functions( bar ); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + approx_ux.at(e_chunk.first) = (uh(0,0)); + approx_uy.at(e_chunk.first) = (uh(1,0)); + approx_uy_bis.at(e_chunk.first) = (uh(1,0)); + } + e_cell_ind++; + } + + size_t n_elastic_cell_dof = e_material.size() * e_cell_dof; + size_t a_cell_ind = 0; + for (auto& a_chunk : a_material) { + + auto& cell = storage->surfaces[a_chunk.first]; + auto bar = barycenter(msh, cell); + approx_ux.at(a_chunk.first) = (0.0/0.0); + approx_uy.at(a_chunk.first) = (0.0/0.0); + approx_uy_bis.at(a_chunk.first) = (0.0/0.0); + + // scalar evaluation + { + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(a_cell_ind*a_cell_dof + + n_vel_scal_cbs + + n_elastic_cell_dof, 0, + n_scal_cbs, 1); + auto t_phi = cell_basis.eval_functions( bar ); + RealType uh = scalar_cell_dof.dot( t_phi ); + approx_u.at(a_chunk.first) = (uh); + } + a_cell_ind++; + } + } + + else { + + // Filling with nan (It is weird but useful in Paraview) + approx_ux.resize(num_points,0.0/0.0); + approx_uy.resize(num_points,0.0/0.0); + approx_uy_bis.resize(num_points,0.0/0.0); + approx_u.resize(num_points,0.0/0.0); + + std::map e_cell_index; + std::map a_cell_index; + size_t e_cell_ind = 0; + for (auto chunk : e_material) { + e_cell_index.insert(std::make_pair(chunk.first,e_cell_ind)); + e_cell_ind++; + } + + // acoustic data + size_t a_cell_ind = 0; + for (auto chunk : a_material) { + a_cell_index.insert(std::make_pair(chunk.first,a_cell_ind)); + a_cell_ind++; + } + + for (auto& e_chunk : e_material) { + + auto& cell = storage->surfaces[e_chunk.first]; + size_t e_cell_ind = e_cell_index[e_chunk.first]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix vec_x_cell_dof = x_dof.block(e_cell_ind*e_cell_dof + + n_ten_cbs, 0, n_vec_cbs, 1); + + auto points = cell.point_ids(); + size_t n_p = points.size(); + // problème sur cette boucle + for (size_t l = 0; l < n_p; l++) { + auto pt_id = points[l]; + auto pt_coord = *std::next(msh.points_begin(), pt_id); + + // vector evaluation + { + auto t_phi = cell_basis.eval_functions(pt_coord); + assert(t_phi.rows() == cell_basis.size()); + auto uh = disk::eval(vec_x_cell_dof, t_phi); + + approx_ux.at(pt_id) = uh(0,0); + approx_uy.at(pt_id) = uh(1,0); + approx_uy_bis.at(pt_id) = std::sqrt( std::abs(uh(0,0))*std::abs(uh(0,0)) + + std::abs(uh(1,0))*std::abs(uh(1,0)) ); + } + } + } + + size_t n_elastic_cell_dof = e_material.size() * e_cell_dof; + for (auto& a_chunk : a_material) { + auto& cell = storage->surfaces[a_chunk.first]; + size_t a_cell_ind = a_cell_index[a_chunk.first]; + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix scalar_cell_dof = x_dof.block(a_cell_ind*a_cell_dof + + n_vel_scal_cbs + n_elastic_cell_dof, + 0, n_scal_cbs, 1); + + auto points = cell.point_ids(); + size_t n_p = points.size(); + // std::cout << n_p < vhx_silo("vhx", approx_ux); + disk::silo_zonal_variable vhy_silo("vhy", approx_uy); + disk::silo_zonal_variable vhy_bis_silo("norm_v", approx_uy_bis); + disk::silo_zonal_variable vh_silo("vh", approx_u); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", vhy_bis_silo); + silo.add_variable("mesh", vh_silo); + } + else { + disk::silo_nodal_variable vhx_silo("vhx", approx_ux); + disk::silo_nodal_variable vhy_silo("vhy", approx_uy); + disk::silo_nodal_variable vhy_bis_silo("norm_v", approx_uy_bis); + disk::silo_nodal_variable vh_silo("vh", approx_u); + silo.add_variable("mesh", vhx_silo); + silo.add_variable("mesh", vhy_silo); + silo.add_variable("mesh", vhy_bis_silo); + silo.add_variable("mesh", vh_silo); + } + + silo.close(); + tc.toc(); + // std::cout << " "; + // std::cout << bold << cyan << "Silo file rendered in : " << tc << " seconds" << reset + // << std::endl; + + } + + /// Record acoustic data + static void record_acoustic_data_elasto_acoustic_four_fields( size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, bool e_side_Q, std::ostream & seismogram_file = std::cout) { + + using RealType = double; + auto dim = Mesh::dimension; + + // Basis + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_n_cbs = n_vel_scal_cbs + n_scal_cbs; + size_t a_n_cell_dof = assembler.get_a_n_cells_dof(); + + RealType vh = 0.0; + + typename Mesh::point_type pt = pt_cell_index.first; + + // FIND CELL + if (pt_cell_index.second == -1){ + std::set cell_indexes = find_acoustic_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vh\"" << std::endl; + } + + size_t cell_ind = pt_cell_index.second; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix all_dofs = assembler.gather_a_dof_data(cell_ind, msh, cell, x_dof); + Matrix scalar_cell_dof = all_dofs.block(n_vel_scal_cbs,0,n_scal_cbs,1); + auto t_phi = cell_basis.eval_functions( pt ); + vh = scalar_cell_dof.dot( t_phi ); + + seismogram_file << it << "," << std::setprecision(16) << vh << std::endl; + seismogram_file.flush(); + + } + + /// Record elastic data + static void record_elastic_data_elasto_acoustic_four_fields( size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, bool e_side_Q, std::ostream & seismogram_file = std::cout) { + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t e_n_cbs = n_ten_cbs + n_vec_cbs; + size_t e_n_cell_dof = assembler.get_e_n_cells_dof(); + + Matrix eh = Matrix::Zero(2, 2); + + typename Mesh::point_type pt = pt_cell_index.first; + if (pt_cell_index.second == -1){ + std::set cell_indexes = find_elastic_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"Sxx\"" << "," << "\"Sxy\"" << "," << "\"Syy\"" << std::endl; + } + size_t cell_ind = pt_cell_index.second; + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + + // stress tensor evaluation + size_t ten_dofs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + auto ten_basis = make_sym_matrix_monomial_basis(msh, cell, hho_di.grad_degree()); + Matrix all_dofs = assembler.gather_e_dof_data(cell_ind, msh, cell, x_dof); + Matrix ten_x_cell_dof = all_dofs.block(0, 0, ten_dofs, 1); + auto t_phi = ten_basis.eval_functions(pt); + eh = disk::eval(ten_x_cell_dof, t_phi); + + tc.toc(); + seismogram_file << it << "," << std::setprecision(16) << eh(0,0) << "," << std::setprecision(16) << eh(0,1) << "," << std::setprecision(16) << eh(1,1) << std::endl; + seismogram_file.flush(); + + } + + /// Record velocity + static void record_velocity_data_elasto_acoustic_two_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_two_fields_assembler & assembler, Matrix & u_dof, Matrix & v_dof, bool e_side_Q, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + + { + size_t cell_ind = pt_cell_index.second; + + + if(e_side_Q){// vector evaluation + + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix all_dofs = assembler.gather_e_dof_data(cell_ind, msh, cell, v_dof); + Matrix vec_x_cell_dof = all_dofs.block(0, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions( pt ); + assert(t_phi.rows() == cell_basis.size()); + vh = disk::eval(vec_x_cell_dof, t_phi); + } + else + {// reconstructed velocity evaluation + + size_t cell_dof = disk::scalar_basis_size(hho_di.cell_degree(), dim); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto rec_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + auto gr = make_scalar_hho_laplacian(msh, cell, hho_di); + Matrix all_dofs = assembler.gather_a_dof_data(cell_ind, msh, cell, u_dof); + Matrix recdofs = gr.first * all_dofs; + + auto t_dphi = rec_basis.eval_gradients( pt ); + Matrix grad_uh = Matrix::Zero(); + + for (size_t i = 1; i < t_dphi.rows(); i++){ + grad_uh = grad_uh + recdofs(i-1)*t_dphi.block(i, 0, 1, 2); + } + acoustic_material_data a_mat = assembler.get_a_material_data().find(cell_ind)->second; + RealType rho = a_mat.rho(); + vh = (1.0/rho)*(grad_uh); + } + + } + tc.toc(); + std::cout << bold << cyan << "Value recorded: " << tc << " seconds" << reset << std::endl; + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + + } + + static void record_velocity_data_elasto_acoustic_four_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, bool e_side_Q, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t e_n_cbs = n_ten_cbs + n_vec_cbs; + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_n_cbs = n_vel_scal_cbs + n_scal_cbs; + size_t e_n_cell_dof = assembler.get_e_n_cells_dof(); + size_t a_n_cell_dof = assembler.get_a_n_cells_dof(); + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + + if (e_side_Q) { + // FIND CELL + if (pt_cell_index.second == -1){ + std::set cell_indexes = find_elastic_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + // RECORD DATA + size_t cell_ind = pt_cell_index.second; + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_vector_monomial_basis(msh, cell, hho_di.cell_degree()); + Matrix all_dofs = assembler.gather_e_dof_data(cell_ind, msh, cell, x_dof); + Matrix vec_x_cell_dof = all_dofs.block(0 + n_ten_cbs, 0, cell_dof, 1); + auto t_phi = cell_basis.eval_functions(pt); + assert(t_phi.rows() == cell_basis.size()); + vh = disk::eval(vec_x_cell_dof, t_phi); + } + else { + // FIND CELL + if (pt_cell_index.second == -1){ + std::set cell_indexes = find_acoustic_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + } + // RECORD DATA + size_t cell_ind = pt_cell_index.second; + size_t cell_dof = disk::vector_basis_size(hho_di.cell_degree(), dim, dim); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = make_scalar_monomial_basis(msh, cell, hho_di.reconstruction_degree()); + Matrix all_dofs = assembler.gather_a_dof_data(cell_ind, msh, cell, x_dof); + Matrix flux_cell_dof = all_dofs.block(0, 0, cell_dof, 1); + auto t_dphi = cell_basis.eval_gradients( pt ); + Matrix flux_uh = Matrix::Zero(); + for (size_t i = 1; i < t_dphi.rows(); i++) + flux_uh = flux_uh + flux_cell_dof(i-1)*t_dphi.block(i, 0, 1, 2); + vh = flux_uh; + } + + tc.toc(); + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + } + + /// Record interface data + static void record_acoustic_pressure_coupling_data_elasto_acoustic_four_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, bool e_side_Q, std::set interface_face_indexes, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + size_t n_vel_scal_cbs = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t n_scal_cbs = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t a_n_cbs = n_vel_scal_cbs + n_scal_cbs; + size_t a_n_fbs = disk::scalar_basis_size(hho_di.face_degree(), Mesh::dimension - 1); + RealType vh = 0.0; + + typename Mesh::point_type pt = pt_cell_index.first; + typename Mesh::face_type fb; + + // FIND FACE + if (pt_cell_index.second == -1) { + seismogram_file << "\"Time\"" << "," << "\"vh\"" << std::endl; + std::set cell_indexes = find_acoustic_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + } + auto& cell = msh.backend_storage()->surfaces[pt_cell_index.second]; + auto cell_faces = faces(msh, cell); + for (auto face : cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) + fb = face; + } + + auto fc_id = msh.lookup(fb); + auto face_basis = make_scalar_monomial_basis(msh, fb, hho_di.face_degree()); + Matrix all_dofs = assembler.gather_a_dof_data(pt_cell_index.second, msh, cell, x_dof); + Matrix face_dofs = all_dofs.block(a_n_cbs, 0, a_n_fbs, 1); + auto t_phi = face_basis.eval_functions(pt); + vh = face_dofs.dot(t_phi); + + seismogram_file << it << "," << std::setprecision(16) << vh << std::endl; + seismogram_file.flush(); + + } + + static void record_elastic_velocity_coupling_data_elasto_acoustic_four_fields(size_t it, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, elastoacoustic_four_fields_assembler & assembler, Matrix & x_dof, bool e_side_Q, std::set interface_face_indexes, std::ostream & seismogram_file = std::cout){ + + timecounter tc; + tc.tic(); + + using RealType = double; + auto dim = Mesh::dimension; + + size_t n_ten_cbs = disk::sym_matrix_basis_size(hho_di.grad_degree(), Mesh::dimension, Mesh::dimension); + size_t n_vec_cbs = disk::vector_basis_size(hho_di.cell_degree(),Mesh::dimension, Mesh::dimension); + size_t e_n_cbs = n_ten_cbs + n_vec_cbs; + size_t e_n_cell_dof = assembler.get_e_n_cells_dof(); + size_t e_n_fbs = disk::vector_basis_size(hho_di.face_degree(), Mesh::dimension - 1, Mesh::dimension); + Matrix vh = Matrix::Zero(2, 1); + + typename Mesh::point_type pt = pt_cell_index.first; + typename Mesh::face_type fb; + + // FIND FACE + if (pt_cell_index.second == -1) { + seismogram_file << "\"Time\"" << "," << "\"vhx\"" << "," << "\"vhy\"" << std::endl; + std::set cell_indexes = find_elastic_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + } + auto& cell = msh.backend_storage()->surfaces[pt_cell_index.second]; + auto cell_faces = faces(msh, cell); + for (auto face : cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) + fb = face; + } + + // RECORD DATA + auto fc_id = msh.lookup(fb); + auto face_basis = make_vector_monomial_basis(msh, fb, hho_di.face_degree()); + Matrix all_dofs = assembler.gather_e_dof_data(pt_cell_index.second, msh, cell, x_dof); + Matrix face_dofs = all_dofs.block(e_n_cbs, 0, e_n_fbs, 1); + auto t_phi = face_basis.eval_functions(pt); + vh = disk::eval(face_dofs, t_phi); + + seismogram_file << it << "," << std::setprecision(16) << vh(0,0) << "," << std::setprecision(16) << vh(1,0) << std::endl; + seismogram_file.flush(); + + } + +}; + + + +#endif /* postprocessor_hpp */ + diff --git a/apps/wave_propagation/src/common/preprocessor.hpp b/apps/wave_propagation/src/common/preprocessor.hpp new file mode 100644 index 00000000..f9c99078 --- /dev/null +++ b/apps/wave_propagation/src/common/preprocessor.hpp @@ -0,0 +1,274 @@ + +// +// preprocessor.hpp +// acoustics +// +// Created by Omar Durán on 4/10/20. +// + +#pragma once +#ifndef preprocessor_hpp +#define preprocessor_hpp + +#include +#include "../../../../contrib/sol2/include/sol/sol.hpp" + + +class simulation_data { + +public: + + size_t m_k_degree; + size_t m_n_divs; + bool m_hdg_stabilization_Q; + bool m_scaled_stabilization_Q; + bool m_sc_Q; + size_t m_nt_divs; + bool m_render_silo_files_Q; + bool m_report_energy_Q; + bool m_iterative_solver_Q; + bool m_polygonal_mesh_Q; + + simulation_data() : m_k_degree(2), m_n_divs(2), m_hdg_stabilization_Q(false), m_scaled_stabilization_Q(false), m_sc_Q(false), m_nt_divs(0), m_render_silo_files_Q(true), m_report_energy_Q(false), m_iterative_solver_Q(false), m_polygonal_mesh_Q(false) {} + + simulation_data(const simulation_data & other) { + m_k_degree = other.m_k_degree; + m_n_divs = other.m_n_divs; + m_hdg_stabilization_Q = other.m_hdg_stabilization_Q; + m_scaled_stabilization_Q = other.m_scaled_stabilization_Q; + m_sc_Q = other.m_sc_Q; + m_nt_divs = other.m_nt_divs; + m_render_silo_files_Q = other.m_render_silo_files_Q; + m_report_energy_Q = other.m_report_energy_Q; + m_iterative_solver_Q = other.m_iterative_solver_Q; + m_polygonal_mesh_Q = other.m_polygonal_mesh_Q; + } + + const simulation_data & operator=(const simulation_data & other) { + + if (&other == this) { + return *this; + } + + m_k_degree = other.m_k_degree; + m_n_divs = other.m_n_divs; + m_hdg_stabilization_Q = other.m_hdg_stabilization_Q; + m_scaled_stabilization_Q = other.m_scaled_stabilization_Q; + m_sc_Q = other.m_sc_Q; + m_nt_divs = other.m_nt_divs; + m_render_silo_files_Q = other.m_render_silo_files_Q; + m_report_energy_Q = other.m_report_energy_Q; + m_iterative_solver_Q = other.m_iterative_solver_Q; + m_polygonal_mesh_Q = other.m_polygonal_mesh_Q; + + return *this; + + } + + ~simulation_data(){} + + void write_simulation_data(std::ostream & simulation_log = std::cout) { + simulation_log << " Input parameters:" << std::endl; + simulation_log << " Iterative solver: " << m_iterative_solver_Q << std::endl; + simulation_log << " HHO setting: " << std::endl; + simulation_log << " - Polynomial degree -k: " << m_k_degree << " (Face unknowns)" << std::endl; + simulation_log << " - Stabilization type -s: " << m_hdg_stabilization_Q << " (Equal-order=0, Mixed-order=1)" << std::endl; + simulation_log << " - Scaled stabilization -r: " << m_scaled_stabilization_Q << " (O(1)=0, O(1/h)=1)" << std::endl; + simulation_log << " - Static condensation -c: " << m_sc_Q << std::endl; + simulation_log << " Mesh:" << "- Refinement level -l : " << m_n_divs << std::endl; + simulation_log << " Time refinement level -n : " << m_nt_divs << std::endl; + }; + + void print_simulation_data() { + std::cout << "\n " << bold << red << "HHO SETTING: " << reset; + std::cout << bold << cyan + << "\n " << bold << "Discretization: "; + if (m_hdg_stabilization_Q) { + std::cout << bold << yellow << "Mixed-order" << " -s" + << "\n Cell degree = " << m_k_degree+1 << " -k" + << "\n Face degree = " << m_k_degree << std::endl; + } + else { + std::cout << bold << yellow << "Equal-order" << " -s" + << "\n Cell degree = " << m_k_degree << " -k" + << "\n Face degree = " << m_k_degree << std::endl; + } + std::cout << bold << cyan << " Stabilization scaling: "; + if (m_scaled_stabilization_Q) { + std::cout << "O(1/h) -r" << std::endl; + } + else { + std::cout << "O(1) -r " << std::endl; + } + std::cout << cyan << " Static condensation = "; + if (m_sc_Q) { + std::cout << "YES" << " -c" << reset << std::endl; + } + else { + std::cout << "NO" << " -c" << reset << std::endl; + } + + std::cout << "\n " << bold << red << "SIMULATION PARAMETERS: " + << "\n " << bold << cyan << "Mesh:" << yellow << bold << " Cartesian mesh: "; + if (m_polygonal_mesh_Q) { + std::cout << "NO" << " -p"; + } + else { + std::cout << "YES" << " -p"; + } + std::cout << "\n " << "Mesh refinement level: " << m_n_divs << " -l"; + if (m_nt_divs > 12) { + std::cout << "\n " << bold << cyan << "Number of time steps: " << m_nt_divs << " -n"; + } + else { + std::cout << "\n " << bold << cyan << "Time refinement level: " << m_nt_divs << " -n"; + } + std::cout << "\n " << bold << cyan << "Solver:"; + if (m_iterative_solver_Q) { + std::cout << " Iterative" << " -i" << std::endl; + } + else { + std::cout << " Direct" << " -i" << std::endl; + } + + std::cout << "\n " << bold << red << "POSTPROCESS:" << reset + << cyan + << "\n " << bold << "Silo files: "; + if (m_render_silo_files_Q) { + std::cout << " YES" << " -f"; + } + else { + std::cout << " NO" << " -f"; + } + std::cout << "\n " << bold << "Energy file: "; + if (m_report_energy_Q) { + std::cout << "YES" << " -e"; + } + else { + std::cout << "NO" << " -e"; + } + } + +}; + +class preprocessor { + +public: + + static void PrintHelp() { + + std::cout << + "-k : blabla Face polynomial degree: default 0\n" + "-l : Number of uniform space refinements: default 0\n" + "-s <0-1>: Stabilization type 0 -> HHO, 1 -> HDG-like: default 0 \n" + "-r <0-1>: Scaled stabilization 0 -> without, 1 -> with: default 0 \n" + "-n : Number of uniform time refinements: default 0\n" + "-f <0-1>: Write silo files: default 0\n" + "-e <0-1>: Report (time,energy) pairs: default 0\n" + "-c <0-1>: Static Condensation (implicit schemes): default 0 \n" + "-help: Show help\n"; + exit(1); + } + + static simulation_data process_args(int argc, char** argv) { + + const char* const short_opts = "k:s:r:c:p:l:n:i:f:e:?"; + + const option long_opts[] = { + // HHO SETTING + {"degree", required_argument, nullptr, 'k'}, + {"stab", required_argument, nullptr, 's'}, + {"scal", required_argument, nullptr, 'r'}, + {"c", optional_argument, nullptr, 'c'}, + // SIMULATION PARAMETERS + {"poly_mesh", required_argument, nullptr, 'p'}, + {"xref", required_argument, nullptr, 'l'}, + {"tref", required_argument, nullptr, 'n'}, + {"solv", required_argument, nullptr, 'i'}, + // POST PROCESSOR + {"file", optional_argument, nullptr, 'f'}, + {"energy", optional_argument, nullptr, 'e'}, + // HELP + {"help", no_argument, nullptr, '?'}, + {nullptr, no_argument, nullptr, 0} + }; + + size_t k_degree = 0; + size_t n_divs = 0; + size_t nt_divs = 0; + size_t poly_mesh = 0; + bool hdg_Q = false; + bool scaled_Q = false; + bool sc_Q = false; + bool silo_files_Q = true; + bool report_energy_Q = true; + bool it_sol = false; + + while (true) { + const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr); + if (-1 == opt) + break; + switch (opt) { + // HHO SETTING + case 'k': + k_degree = std::stoi(optarg); + break; + case 's': + hdg_Q = std::stoi(optarg); + break; + case 'r': + scaled_Q = std::stoi(optarg); + break; + case 'c': + sc_Q = std::stoi(optarg); + break; + // SIMULATION PARAMETERS + case 'p': + poly_mesh = std::stoi(optarg); + break; + case 'l': + n_divs = std::stoi(optarg); + break; + case 'n': + nt_divs = std::stoi(optarg); + break; + case 'i': + it_sol = std::stoi(optarg); + break; + // POSTPROCESSOR + case 'f': + silo_files_Q = std::stoi(optarg); + break; + case 'e': + report_energy_Q = std::stoi(optarg); + break; + // HELP + case '?': + preprocessor::PrintHelp(); + break; + } + } + + // POPULATING SIM DATA + simulation_data sim_data; + // HHO SETTING + sim_data.m_k_degree = k_degree; + sim_data.m_hdg_stabilization_Q = hdg_Q; + sim_data.m_scaled_stabilization_Q = scaled_Q; + sim_data.m_sc_Q = sc_Q; + // SIMULATION PARAMETERS + sim_data.m_polygonal_mesh_Q = poly_mesh; + sim_data.m_n_divs = n_divs; + sim_data.m_nt_divs = nt_divs; + sim_data.m_iterative_solver_Q = it_sol; + // POSTPROCESSOR + sim_data.m_render_silo_files_Q = silo_files_Q; + sim_data.m_report_energy_Q = report_energy_Q; + + return sim_data; + } + + +}; + +#endif /* preprocessor_hpp */ diff --git a/apps/wave_propagation/src/common/scal_analytic_functions.hpp b/apps/wave_propagation/src/common/scal_analytic_functions.hpp new file mode 100644 index 00000000..aa6281d4 --- /dev/null +++ b/apps/wave_propagation/src/common/scal_analytic_functions.hpp @@ -0,0 +1,471 @@ +// +// scal_analytic_functions.hpp +// acoustics +// +// Created by Omar Durán on 4/9/20. +// + +#pragma once +#ifndef scal_analytic_functions_hpp +#define scal_analytic_functions_hpp + +#define contrast 3.0 +#define n_terms 200 + +class scal_analytic_functions { + +public: + + /// Enumerate defining the function type + enum EFunctionType { EFunctionNonPolynomial = 0, EFunctionQuadraticInTime = 1, + EFunctionQuadraticInSpace = 2, EFunctionQuadraticInSpaceTime = 3, + EFunctionInhomogeneousInSpace = 4, Fluid_pulse = 5}; + + + scal_analytic_functions(){ + m_function_type = EFunctionNonPolynomial; + } + + ~scal_analytic_functions(){ + } + + void set_function_type(EFunctionType function_type){ + m_function_type = function_type; + } + + std::function::point_type& )> Evaluate_u(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return (1.0/(std::sqrt(2.0)*M_PI))*std::sin(std::sqrt(2.0)*M_PI*t) * std::sin(M_PI*pt.x()) * std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return (1 - pt.x())*pt.x()*(1 - pt.y())*pt.y()*std::sin(std::sqrt(2.0)*M_PI*t); + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return t*t*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpaceTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return t*t*(1 - pt.x())*pt.x()*(1 - pt.y())*pt.y(); + }; + } + break; + case EFunctionInhomogeneousInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + + size_t n = n_terms; + double x,y,c1,c2; + c1 = contrast; + c2 = 1.0; + x = pt.x(); + y = pt.y(); + + double p = 0.0; + double c = 1.0; + for (int k = 0; k <= n; k++) { + + if (x < 0.5) { + double plvp, plvm; + plvp = (1.0/100.0)*exp(-(20.0*((k+x-c1*t)-0.2))*(20.0*((k+x-c1*t)-0.2))); + plvm = (1.0/100.0)*exp(-(20.0*((k-x-c1*t)-0.2))*(20.0*((k-x-c1*t)-0.2))); + p+=c*(plvp-plvm); + }else{ + double pr; + pr = (1.0/100.0)*exp(-(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2))*(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2))); + p+=((2.0*c1)/(c2+c1))*c*pr; + } + c*=(c2-c1)/(c2+c1); + } + return p; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + + } + + std::function::point_type& )> Evaluate_v(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return std::cos(std::sqrt(2.0)*M_PI*t) * std::sin(M_PI*pt.x()) * std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return std::sqrt(2.0)*M_PI*(1 - pt.x())*pt.x()*(1 - pt.y())*pt.y()*std::cos(std::sqrt(2.0)*M_PI*t); + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return 2.0*t*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpaceTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return 2.0*t*(1 - pt.x())*pt.x()*(1 - pt.y())*pt.y(); + }; + } + break; + case EFunctionInhomogeneousInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + + size_t n = n_terms; + double x,y,c1,c2; + c1 = contrast; + c2 = 1.0; + x = pt.x(); + y = pt.y(); + + double v = 0.0; + double c = 1.0; + for (int k = 0; k <= n; k++) { + + if (x < 0.5) { + double vlvp, vlvm; + vlvp = (8.0*c1)* exp(-(20.0*((k+x-c1*t)-0.2))*(20.0*((k+x-c1*t)-0.2)))*((k+x-c1*t)-0.2); + vlvm = (8.0*c1)* exp(-(20.0*((k-x-c1*t)-0.2))*(20.0*((k-x-c1*t)-0.2)))*((k-x-c1*t)-0.2); + v+=c*(vlvp-vlvm); + }else{ + double vl; + vl = (8.0*c1)*exp(-(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2))*(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2)))*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2); + v+=((2.0*c1)/(c2+c1))*c*vl; + } + c*=(c2-c1)/(c2+c1); + } + return v; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + + } + + std::function::point_type& )> Evaluate_a(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return -std::sqrt(2.0) * M_PI * std::sin(std::sqrt(2.0)*M_PI*t) * std::sin(M_PI*pt.x()) * std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return -2*M_PI*M_PI*(1 - pt.x())*pt.x()*(1 - pt.y())*pt.y()*std::sin(std::sqrt(2)*M_PI*t); + }; + } + break; + case EFunctionQuadraticInTime: + { + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 2.0*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpaceTime: + { + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 2.0*(1 - pt.x())*pt.x()*(1 - pt.y())*pt.y(); + }; + } + break; + case EFunctionInhomogeneousInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + + size_t n = n_terms; + double x,y,c1,c2; + c1 = contrast; + c2 = 1.0; + x = pt.x(); + y = pt.y(); + + double a = 0.0; + double c = 1.0; + for (int k = 0; k <= n; k++) { + + if (x < 0.5) { + double alvp, alvm, xip, xim; + xip=((k+x-c1*t)-0.2); + alvp = (8.0*c1*c1)* exp(-(20.0*((k+x-c1*t)-0.2))*(20.0*((k+x-c1*t)-0.2)))*(800.0*xip*xip-1.0); + + xim=((k-x-c1*t)-0.2); + alvm = (8.0*c1*c1)* exp(-(20.0*((k-x-c1*t)-0.2))*(20.0*((k-x-c1*t)-0.2)))*(800.0*xim*xim-1.0); + a+=c*(alvp-alvm); + }else{ + double al, xi; + xi= (((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2); + al = (8.0*c1*c1)*exp(-(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2))*(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2)))*(800.0*xi*xi-1.0); + a+=((2.0*c1)/(c2+c1))*c*al; + } + c*=(c2-c1)/(c2+c1); + } + return a; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + + } + + std::function::point_type& )> Evaluate_f(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 2*(x - x*x + y - M_PI*M_PI*(-1 + x)*x*(-1 + y)*y - y*y)*std::sin(std::sqrt(2.0)*M_PI*t); + return f; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return 2.0*(1.0 + M_PI*M_PI*t*t)*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + case EFunctionQuadraticInSpaceTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 2.0*((-1.0 + x)*x*(-1.0 + y)*y + t*t*(x - x*x + y - y*y)); + return f; + }; + } + break; + case EFunctionInhomogeneousInSpace: + { + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + case Fluid_pulse: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x, y, xc, yc, tau, freq, Ricker, alpha, sigma, sigma2, sigma3, eps, f; + + // Source term ponctuel + x = pt.x(); y = pt.y(); + xc = 0.5; yc = 0.5; + + if (x==xc && y==yc) { + + tau = 0.4; + freq = 5.0; + alpha = - M_PI*M_PI * freq*freq; + + if ( t < 0.5*tau ) { + sigma = alpha*(t-tau)*(t-tau); + Ricker = 2.0 * alpha * (1+2*sigma) * exp(sigma); + } + else { + Ricker = 0; + } + + sigma = M_PI*freq*(t-tau); + sigma2 = sigma*sigma; + sigma3 = M_PI*freq; + + f = -4.0*sigma*sigma3*exp(-sigma2)-2.0*sigma*sigma3*Ricker; + + return f; + } + + else { + f = 0; + return f; + } + + return f; + + }; + } + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + + } + + + std::function(const typename disk::generic_mesh::point_type& )> Evaluate_q(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + flux[0] = (std::sin(std::sqrt(2)*M_PI*t)*std::cos(M_PI*x)*std::sin(M_PI*y))/std::sqrt(2.0); + flux[1] = (std::sin(std::sqrt(2)*M_PI*t)*std::sin(M_PI*x)*std::cos(M_PI*y))/std::sqrt(2.0); + return flux; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + flux[0] = (1 - x)*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) - x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + flux[1] = (1 - x)*x*(1 - y)*std::sin(std::sqrt(2.0)*M_PI*t) - (1 - x)*x*y*std::sin(std::sqrt(2.0)*M_PI*t); + return flux; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + flux[0] = M_PI*t*t*std::cos(M_PI*x)*std::sin(M_PI*y); + flux[1] = M_PI*t*t*std::sin(M_PI*x)*std::cos(M_PI*y); + return flux; + }; + } + break; + case EFunctionQuadraticInSpaceTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + flux[0] = t*t*(1 - x)*(1 - y)*y - t*t*x*(1 - y)*y; + flux[1] = t*t*(1 - x)*x*(1 - y) - t*t*(1 - x)*x*y; + return flux; + }; + } + break; + case EFunctionInhomogeneousInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> std::vector { + + size_t n = n_terms; + double x,y,c1,c2; + c1 = contrast; + c2 = 1.0; + x = pt.x(); + y = pt.y(); + + double qx = 0.0; + double c = 1.0; + for (int k = 0; k <= n; k++) { + + if (x < 0.5) { + double qxlvp, qxlvm; + qxlvp = -(8.0)* exp(-(20.0*((k-x-c1*t)-0.2))*(20.0*((k-x-c1*t)-0.2)))*((k-x-c1*t)-0.2); + qxlvm = -(8.0)* exp(-(20.0*((k+x-c1*t)-0.2))*(20.0*((k+x-c1*t)-0.2)))*((k+x-c1*t)-0.2); + qx+=c1*c1*c*(qxlvp+qxlvm); + }else{ + double qxl; + qxl = -(8.0*(c1/c2))*exp(-(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2))*(20.0*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2)))*(((c1/c2)*(x-0.5)+0.5+k-c1*t)-0.2); + qx+=c2*c2*((2.0*c1)/(c2+c1))*c*qxl; + } + c*=(c2-c1)/(c2+c1); + } + + std::vector flux(2); + flux[0] = qx; + flux[1] = 0.0; + return flux; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> std::vector { + std::vector f; + return f; + }; + } + break; + } + + } + + private: + + EFunctionType m_function_type; + +}; + +#endif /* scal_analytic_functions_hpp */ diff --git a/apps/wave_propagation/src/common/scal_vec_analytic_functions.hpp b/apps/wave_propagation/src/common/scal_vec_analytic_functions.hpp new file mode 100644 index 00000000..0c41caf6 --- /dev/null +++ b/apps/wave_propagation/src/common/scal_vec_analytic_functions.hpp @@ -0,0 +1,1161 @@ + +// Created by Omar Durán +// Contributor: Romain Mottier + +#pragma once +#ifndef scal_vec_analytic_functions_hpp +#define scal_vec_analytic_functions_hpp + +class scal_vec_analytic_functions { + + public: + + /// Enumerate defining the function type + enum EFunctionType { + EFunctionNonPolynomial = 0, + EFunctionQuadraticInTime = 1, + EFunctionQuadraticInSpace = 2, + reproduction_acoustic = 3, + reproduction_elastic = 4, + EFunctionNonPolynomial_paper = 5, + EFunctionCubicInTimeAcoustic = 6, + EFunctionQuarticInTimeAcoustic = 7, + EFunctionQuadraticInSpaceAcoustic = 8, + EFunctionPlaneWaveAcoustic = 9}; + + scal_vec_analytic_functions() { + m_function_type = EFunctionNonPolynomial; + } + + ~scal_vec_analytic_functions() { + } + + void set_function_type(EFunctionType function_type) { + m_function_type = function_type; + } + + std::function + (const typename disk::generic_mesh::point_type& )> Evaluate_u(double & t) { + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = x*x*std::sin(M_PI*y)*std::cos((M_PI*x)/2.)*std::cos(std::sqrt(2.0)*M_PI*t); + uy = x*x*std::sin(M_PI*y)*std::cos((M_PI*x)/2.)*std::cos(std::sqrt(2.0)*M_PI*t); + disk::static_vector u{ux,uy}; + return u; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = x*t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + uy = x*t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + disk::static_vector u{ux,uy}; + return u; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = (1 + x)*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + uy = (1 + x)*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + disk::static_vector u{ux,uy}; + return u; + }; + } + break; + + case reproduction_elastic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = -t*t*std::cos(M_PI*y)*std::sin(M_PI*x); + uy = t*t*std::cos(M_PI*x)*std::sin(M_PI*y); + disk::static_vector u{ux,uy}; + return u; + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,ux,uy, w, theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + ux = x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos((M_PI*w*x)/2.); + uy = x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos((M_PI*w*x)/2.); + disk::static_vector u{ux,uy}; + return u; + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + disk::static_vector u; + return u; + }; + } + break; + } + } + + std::function + (const typename disk::generic_mesh::point_type& )> Evaluate_v(double & t){ + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = -(std::sqrt(2.0)*M_PI*x*x*std::cos((M_PI*x)/2.)*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*y)); + vy = -(std::sqrt(2.0)*M_PI*x*x*std::cos((M_PI*x)/2.)*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*y)); + disk::static_vector v{vx,vy}; + return v; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = 2.0*t*x*std::sin(M_PI*x)*std::sin(M_PI*y); + vy = 2.0*t*x*std::sin(M_PI*x)*std::sin(M_PI*y); + disk::static_vector v{vx,vy}; + return v; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = std::sqrt(2.0)*M_PI*(1 + x)*x*x*(1 - y)*y*std::cos(std::sqrt(2.0)*M_PI*t); + vy = std::sqrt(2.0)*M_PI*(1 + x)*x*x*(1 - y)*y*std::cos(std::sqrt(2.0)*M_PI*t); + disk::static_vector v{vx,vy}; + return v; + }; + } + break; + + case reproduction_elastic:{ + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = -2*t*std::cos(M_PI*y)*std::sin(M_PI*x); + vy = 2*t*std::cos(M_PI*x)*std::sin(M_PI*y); + disk::static_vector v{vx,vy}; + return v; + }; + } + break; + + case EFunctionNonPolynomial_paper:{ + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,vx,vy,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + vx = -(theta*x*x*std::sin(theta*t)*std::sin(M_PI*w*y)*std::cos((M_PI*w*x)/2.)); + vy = -(theta*x*x*std::sin(theta*t)*std::sin(M_PI*w*y)*std::cos((M_PI*w*x)/2.)); + disk::static_vector v{vx,vy}; + return v; + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_vector v; + return v; + }; + } + break; + } + } + + std::function + (const typename disk::generic_mesh::point_type& )> Evaluate_a(double & t){ + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = -2*M_PI*M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::sin(M_PI*y); + ay = -2*M_PI*M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::sin(M_PI*y); + disk::static_vector a{ax,ay}; + return a; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = 2.0*x*std::sin(M_PI*x)*std::sin(M_PI*y); + ay = 2.0*x*std::sin(M_PI*x)*std::sin(M_PI*y); + disk::static_vector a{ax,ay}; + return a; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = -2*M_PI*M_PI*(1 + x)*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + ay = -2*M_PI*M_PI*(1 + x)*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + disk::static_vector a{ax,ay}; + return a; + }; + } + break; + + case reproduction_elastic:{ + return [](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = -2*std::cos(M_PI*y)*std::sin(M_PI*x); + ay = 2*std::cos(M_PI*x)*std::sin(M_PI*y); + disk::static_vector a{ax,ay}; + return a; + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,ax,ay,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + ax = -theta*theta*x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos((M_PI*w*x)/2.); + ay = -theta*theta*x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos((M_PI*w*x)/2.); + disk::static_vector a{ax,ay}; + return a; + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + disk::static_vector f; + return f; + }; + } + break; + } + } + + std::function + (const typename disk::generic_mesh::point_type& )> Evaluate_f(double & t){ + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,fx,fy; + x = pt.x(); + y = pt.y(); + fx = -(std::cos(std::sqrt(2.0)*M_PI*t)*(-4*M_PI*x*std::sin((M_PI*x)/2.)*(M_PI*x*std::cos(M_PI*y) + 6*std::sin(M_PI*y)) + std::cos((M_PI*x)/2.)*(16*M_PI*x*std::cos(M_PI*y) + (24 + M_PI*M_PI*x*x)*std::sin(M_PI*y))))/4.0; + fy = (std::cos(std::sqrt(2.0)*M_PI*t)*(4*M_PI*x*std::sin((M_PI*x)/2.)*(M_PI*x*std::cos(M_PI*y) + 2*std::sin(M_PI*y)) + std::cos((M_PI*x)/2.)*(-16*M_PI*x*std::cos(M_PI*y) + (-8 + 5*M_PI*M_PI*x*x)*std::sin(M_PI*y))))/4.; + disk::static_vector f{fx,fy}; + return f; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,fx,fy; + x = pt.x(); + y = pt.y(); + fx = -2 * ( M_PI*t*t*std::cos(M_PI*x)*( M_PI*x*std::cos(M_PI*y) + 3*std::sin(M_PI*y) ) + + std::sin(M_PI*x)*(M_PI*t*t*std::cos(M_PI*y) - (1+2*M_PI*M_PI*t*t)*x*std::sin(M_PI*y))); + fy = (1 + M_PI*M_PI*t*t)*x*std::cos(M_PI*(x - y)) - (1+3*M_PI*M_PI*t*t)*x*std::cos(M_PI*(x+y)) + - 2*M_PI*t*t*std::sin(M_PI*(x+y)); + disk::static_vector f{fx,fy}; + return f; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,fx,fy; + x = pt.x(); + y = pt.y(); + fx = 2 * ( x * (-2+(-2+x)*x) -3*y -x*(5+x*(-6+M_PI*M_PI*(1+x)))*y + + (3+x*(9+M_PI*M_PI*x*(1+x)))*y*y)*std::sin(std::sqrt(2.0)*M_PI*t); + fy = 2 * ( x*x*(6 + M_PI*M_PI*(-1 + y))*y + (-1 + y)*y + x*x*x*(3 + M_PI*M_PI*(-1 + y)*y) + + x*(-2 + y + 3*y*y))*std::sin(std::sqrt(2.0)*M_PI*t); + disk::static_vector f{fx,fy}; + return f; + }; + } + break; + + case reproduction_elastic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,fx,fy; + x = pt.x(); + y = pt.y(); + fx = -2*(1 + M_PI*M_PI*t*t)*std::cos(M_PI*y)*std::sin(M_PI*x); + fy = 2*(1 + M_PI*M_PI*t*t)*std::cos(M_PI*x)*std::sin(M_PI*y); + disk::static_vector f{fx,fy}; + return f; + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,fx,fy,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + + fx = - theta*theta*x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2.0) + + M_PI*M_PI*w*w*x*x*std::sin(M_PI*w*x/2)*std::cos(theta*t)*std::cos(M_PI*w*y) + + 7*M_PI*M_PI*w*w*x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*cos(M_PI*w*x/2)/4.0 + + 6*M_PI*w*x*std::sin(M_PI*w*x/2)*std::sin(M_PI*w*y)*std::cos(theta*t) + - 4*M_PI*w*x*std::cos(theta*t)*std::cos(M_PI*w*x/2)*std::cos(M_PI*w*y) + - 6*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2); + + fy = - theta*theta*x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2.0) + + M_PI*M_PI*w*w*x*x*std::sin(M_PI*w*x/2)*std::cos(theta*t)*std::cos(M_PI*w*y) + + 13*M_PI*M_PI*w*w*x*x*std::sin(M_PI*w*y)*std::cos(theta*t)*cos(M_PI*w*x/2)/4.0 + + 2*M_PI*w*x*std::sin(M_PI*w*x/2)*std::sin(M_PI*w*y)*std::cos(theta*t) + - 4*M_PI*w*x*std::cos(theta*t)*std::cos(M_PI*w*x/2)*std::cos(M_PI*w*y) + - 2*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2); + disk::static_vector f{fx,fy}; + return f; + }; + } + break; + + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + disk::static_vector f; + return f; + }; + } + break; + } + } + + std::function + (const typename disk::generic_mesh::point_type& )> Evaluate_sigma(double & t){ + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + sigma(0,0) = M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::cos(M_PI*y) + 4*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::sin(M_PI*y) - + M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::sin((M_PI*x)/2.)*std::sin(M_PI*y) + + (4*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::sin(M_PI*y) - M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::sin((M_PI*x)/2.)*std::sin(M_PI*y))/2.0; + + sigma(0,1) = M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::cos(M_PI*y) + 2*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::sin(M_PI*y) - + (M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::sin((M_PI*x)/2.)*std::sin(M_PI*y))/2.; + sigma(1,0) = sigma(0,1); + + sigma(1,1) = 3*M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::cos(M_PI*y) + + (4*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::cos((M_PI*x)/2.)*std::sin(M_PI*y) - M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::sin((M_PI*x)/2.)*std::sin(M_PI*y))/2.; + return sigma; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + sigma(0,0) = t*t*(M_PI*x*std::cos(M_PI*y)*std::sin(M_PI*x) + + 3*(M_PI*x*std::cos(M_PI*x) + std::sin(M_PI*x))*std::sin(M_PI*y)); + + sigma(0,1) = t*t*(M_PI*x*std::cos(M_PI*y)*std::sin(M_PI*x) + + (M_PI*x*std::cos(M_PI*x) + std::sin(M_PI*x))*std::sin(M_PI*y)); + + sigma(1,0) = sigma(0,1); + + sigma(1,1) = t*t*(3*M_PI*x*std::cos(M_PI*y)*std::sin(M_PI*x) + + (M_PI*x*std::cos(M_PI*x) + std::sin(M_PI*x))*std::sin(M_PI*y)); + return sigma; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + sigma(0,0) = 2*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + 4*x*(1+x)*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + (2*x*x*(1 + x)*(1 - y)*std::sin(std::sqrt(2.0)*M_PI*t) + - 2*x*x*(1 + x)*y*std::sin(std::sqrt(2.0)*M_PI*t))/2.0 + + (2*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + 4*x*(1 + x)*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t))/2.0; + + sigma(0,1) = x*x*(1 + x)*(1 - y)*std::sin(std::sqrt(2.0)*M_PI*t) + - x*x*(1 + x)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + 2*x*(1 + x)*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + + sigma(1,0) = sigma(0,1); + + sigma(1,1) = 2*x*x*(1 + x)*(1 - y)*std::sin(std::sqrt(2.0)*M_PI*t) + - 2*x*x*(1 + x)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + (2*x*x*(1 + x)*(1 - y)*std::sin(std::sqrt(2.0)*M_PI*t) + - 2*x*x*(1 + x)*y*std::sin(std::sqrt(2.0)*M_PI*t))/2.0 + + (2*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) + + 4*x*(1 + x)*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t))/2.0; + return sigma; + }; + } + break; + + case reproduction_elastic: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + sigma(0,0) = -2*M_PI*t*t*std::cos(M_PI*x)*std::cos(M_PI*y); + sigma(1,1) = 2*M_PI*t*t*std::cos(M_PI*x)*std::cos(M_PI*y); + return sigma; + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_matrix { + double x,y,w,theta; + x = pt.x(); + y = pt.y(); + + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + sigma(0,0) = - 3.0*M_PI*w*x*x*std::sin(M_PI*w*x/2.0)*std::sin(M_PI*w*y)*std::cos(theta*t)/2.0 + + M_PI*w*x*x*std::cos(theta*t)*std::cos(M_PI*w*x/2.0)*std::cos(M_PI*w*y) + + 6.0*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2.0); + + sigma(0,1) = - M_PI*w*x*x*std::sin(M_PI*w*x/2.0)*std::sin(M_PI*w*y)*std::cos(theta*t)/2.0 + + M_PI*w*x*x*std::cos(theta*t)*std::cos(M_PI*w*x/2.0)*std::cos(M_PI*w*y) + + 2.0*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2.0); + + sigma(1,0) = sigma(0,1); + + sigma(1,1) = - M_PI*w*x*x*std::sin(M_PI*w*x/2.0)*std::sin(M_PI*w*y)*std::cos(theta*t)/2.0 + + 3*M_PI*w*x*x*std::cos(theta*t)*std::cos(M_PI*w*x/2.0)*std::cos(M_PI*w*y) + + 2.0*x*std::sin(M_PI*w*y)*std::cos(theta*t)*std::cos(M_PI*w*x/2.0); + return sigma; + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) + -> disk::static_matrix { + disk::static_matrix sigma(2,2); + return sigma; + }; + } + break; + } + + } + + // ACOUSTIC + std::function::point_type& )> Evaluate_s_u(double & t) { + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return x*x*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return t*t*x*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return (1 - x)*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + }; + } + break; + + case EFunctionQuadraticInSpaceAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return y*(1-x*x)*(1-y)*std::sin(M_PI*t); + }; + } + break; + + case reproduction_acoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,w,theta; + x = pt.x(); + y = pt.y(); + + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + + return x*x*std::sin(theta*t)*std::sin(w*M_PI*x)*std::sin(w*M_PI*y); + }; + } + + case EFunctionQuarticInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return t*t*t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionCubicInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return t*t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionPlaneWaveAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y, theta; + x = pt.x(); + y = pt.y(); + theta = x + y - std::sqrt(2)*t; + return -(1.0/std::sqrt(2)) * std::sin(theta); + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + } + + std::function::point_type& )> Evaluate_s_v(double & t){ + + switch (m_function_type) { + + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return std::sqrt(2.0)*M_PI*x*x*std::cos(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 2*t*x*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return std::sqrt(2.0)*M_PI*(1 - x)*x*x*(1 - y)*y*std::cos(std::sqrt(2.0)*M_PI*t); + }; + } + break; + + case EFunctionQuadraticInSpaceAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return M_PI*y*(1-x*x)*(1-y)*std::cos(M_PI*t); + }; + } + break; + + case reproduction_acoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + return 2.0*t*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + return theta*x*x*std::sin(M_PI*w*x)*std::sin(M_PI*w*y)*std::cos(theta*t); + }; + } + break; + + case EFunctionQuarticInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 4.0*t*t*t * std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionCubicInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 3.0*t*t * std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionPlaneWaveAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y, theta; + x = pt.x(); + y = pt.y(); + theta = x + y - std::sqrt(2)*t; + return std::cos(theta); + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + + } + + std::function::point_type& )> Evaluate_s_a(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return -2*M_PI*M_PI*x*x*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 2*x*std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return -2*M_PI*M_PI*(1 - x)*x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + }; + } + break; + + case EFunctionQuadraticInSpaceAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return -M_PI*M_PI*y*(1-x*x)*(1-y)*std::sin(M_PI*t); + }; + } + break; + + case reproduction_acoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 2.0*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + return -theta*theta*x*x*std::sin(theta*t)*std::sin(M_PI*w*x)*std::sin(M_PI*w*y); + }; + } + break; + + case EFunctionQuarticInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 12*t*t * std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionCubicInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y; + x = pt.x(); + y = pt.y(); + return 6*t * std::sin(M_PI*x)*std::sin(M_PI*y); + }; + } + break; + + case EFunctionPlaneWaveAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y, theta; + x = pt.x(); + y = pt.y(); + theta = x + y - std::sqrt(2)*t; + return std::sqrt(2) * std::sin(theta); + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + } + + std::function::point_type& )> Evaluate_s_f(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = -2*std::sin(std::sqrt(2.0)*M_PI*t)*(2*M_PI*x*std::cos(M_PI*x) + std::sin(M_PI*x))*std::sin(M_PI*y); + return f; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 2*(-(M_PI*t*t*std::cos(M_PI*x)) + (1 + M_PI*M_PI*t*t)*x*std::sin(M_PI*x))*std::sin(M_PI*y); + return f; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 2*((-1 + y)*y - 3*x*(-1 + y)*y + x*x*x*(-1 - M_PI*M_PI*(-1 + y)*y) + + x*x*(1 + M_PI*M_PI*(-1 + y)*y))*std::sin(std::sqrt(2.0)*M_PI*t); + return f; + }; + } + break; + + case EFunctionQuadraticInSpaceAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = - M_PI*M_PI*y*(1-x*x)*(1-y)*std::sin(M_PI*t) + + 2*y*(1-y)*std::sin(M_PI*t) + + 2*(1-x*x)*std::sin(M_PI*t); + return f; + }; + } + break; + + case reproduction_acoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + return 2.0*(1.0 + M_PI*M_PI*t*t)*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + f = - theta*theta*x*x*std::sin(theta*t)*std::sin(M_PI*w*x)*std::sin(M_PI*w*y) + + 2*M_PI*M_PI*theta*w*w*x*x*std::sin(theta*t)*std::sin(M_PI*w*x)*std::sin(M_PI*w*y)/theta + - 4*M_PI*theta*w*x*std::sin(theta*t)*std::sin(M_PI*w*y)*std::cos(M_PI*w*x)/theta + - 2*theta*std::sin(theta*t)*std::sin(M_PI*w*x)*std::sin(M_PI*w*y)/theta; + return f; + }; + } + break; + + case EFunctionQuarticInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 2*M_PI*M_PI*t*t*t*t*std::sin(M_PI*x)*std::sin(M_PI*y) + 12*t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + return f; + }; + } + break; + + case EFunctionCubicInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 2*M_PI*M_PI*t*t*t*std::sin(M_PI*x)*std::sin(M_PI*y) + 6*t*std::sin(M_PI*x)*std::sin(M_PI*y); + return f; + }; + } + break; + + case EFunctionPlaneWaveAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> double { + double x,y,f; + x = pt.x(); + y = pt.y(); + f = 0.0; + return f; + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> double { + return 0; + }; + } + break; + } + } + + std::function + (const typename disk::generic_mesh::point_type& )> Evaluate_s_q(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + qx = M_PI*x*x*std::cos(M_PI*x)*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*y) + 2*x*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*x)*std::sin(M_PI*y); + qy = M_PI*x*x*std::cos(M_PI*y)*std::sin(std::sqrt(2.0)*M_PI*t)*std::sin(M_PI*x); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionQuadraticInTime: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + qx = M_PI*t*t*x*std::cos(M_PI*x)*std::sin(M_PI*y) + t*t*std::sin(M_PI*x)*std::sin(M_PI*y); + qy = M_PI*t*t*x*std::cos(M_PI*y)*std::sin(M_PI*x); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionQuadraticInSpace: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + qx = 2*(1 - x)*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t) + - x*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + qy = (1 - x)*x*x*(1 - y)*std::sin(std::sqrt(2.0)*M_PI*t) + - (1 - x)*x*x*y*std::sin(std::sqrt(2.0)*M_PI*t); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionQuadraticInSpaceAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + qx = -2*x*y*(1-y)*std::sin(M_PI*t); + qy = - y*(1-x*x)*std::sin(M_PI*t) + + (1-x*x)*(1-y)*std::sin(M_PI*t); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case reproduction_acoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + qx = M_PI*t*t*t*std::cos(M_PI*x)*std::sin(M_PI*y); + qy = M_PI*t*t*t*std::sin(M_PI*x)*std::cos(M_PI*y); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionNonPolynomial_paper: { + return [&t](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector { + double x,y,qx,qy,w,theta; + x = pt.x(); + y = pt.y(); + w = 1.0; + theta = 10*M_PI; + // w = 5.0; + // theta = std::sqrt(2)*M_PI; + qx = M_PI*theta*w*x*x*std::sin(theta*t)*std::sin(M_PI*w*y)*std::cos(M_PI*w*x)/theta + 2*theta*x*std::sin(theta*t)*std::sin(M_PI*w*x)*std::sin(M_PI*w*y)/theta; + qy = M_PI*theta*w*x*x*std::sin(theta*t)*std::sin(M_PI*w*x)*std::cos(M_PI*w*y)/theta; + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionQuarticInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + qx = M_PI*t*t*t*t*std::cos(M_PI*x)*std::sin(M_PI*y); + qy = M_PI*t*t*t*t*std::sin(M_PI*x)*std::cos(M_PI*y); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionCubicInTimeAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x,y,qx,qy; + x = pt.x(); + y = pt.y(); + qx = M_PI*t*t*t*std::cos(M_PI*x)*std::sin(M_PI*y); + qy = M_PI*t*t*t*std::sin(M_PI*x)*std::cos(M_PI*y); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + case EFunctionPlaneWaveAcoustic: { + return [&t](const typename disk::generic_mesh::point_type& pt) -> disk::static_vector { + double x, y, qx, qy, theta; + x = pt.x(); + y = pt.y(); + theta = x + y - std::sqrt(2)*t; + qx = (1.0/std::sqrt(2.0)) * std::sin(theta); + qy = (1.0/std::sqrt(2.0)) * std::sin(theta); + disk::static_vector q{qx,qy}; + return q; + }; + } + break; + + default: { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) + -> disk::static_vector{ + disk::static_vector f{0,0}; + return f; + }; + } + break; + } + } + + private: + + EFunctionType m_function_type; + + }; + + #endif /* scal_vec_analytic_functions_hpp */ + \ No newline at end of file diff --git a/apps/wave_propagation/src/common/sourceterm.hpp b/apps/wave_propagation/src/common/sourceterm.hpp new file mode 100644 index 00000000..0c637c2a --- /dev/null +++ b/apps/wave_propagation/src/common/sourceterm.hpp @@ -0,0 +1,226 @@ + +#pragma once +#ifndef source_term_hpp +#define source_term_hpp + +#include +#include "../common/acoustic_one_field_assembler.hpp" +#include "../common/acoustic_two_fields_assembler.hpp" +#include "../common/elastodynamic_one_field_assembler.hpp" +#include "../common/elastodynamic_two_fields_assembler.hpp" +#include "../common/elastodynamic_three_fields_assembler.hpp" +#include "../common/elastoacoustic_two_fields_assembler.hpp" +#include "../common/elastoacoustic_four_fields_assembler.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class source_term { + +public: + + /// Find the cells associated to the requested point + static std::set find_cells(typename Mesh::point_type & pt, Mesh & msh, bool verbose_Q = false){ + + using RealType = double; + auto norm = [](const typename Mesh::point_type& a, const typename Mesh::point_type& b ) -> RealType { + RealType dx = (b.x() - a.x()); + RealType dy = (b.y() - a.y()); + RealType norm = std::sqrt(dx*dx + dy*dy); + return norm; + }; + + // find minimum distance to the requested point + size_t np = msh.points_size(); + std::vector distances(np); + + size_t ip = 0; + for (auto& point : msh.backend_storage()->points) + { + RealType dist = norm(pt,point); + distances[ip] = dist; + ip++; + } + + size_t index = std::min_element(distances.begin(),distances.end()) - distances.begin(); + if(verbose_Q){ + RealType min_dist = *std::min_element(distances.begin(), distances.end()); + typename Mesh::point_type nearest_point = msh.backend_storage()->points.at(index); + std::cout << "Nearest point detected : " << std::endl; + std::cout << " x = " << nearest_point.x() << std::endl; + std::cout << " y = " << nearest_point.y() << std::endl; + std::cout << "Distance = " << min_dist << std::endl; + std::cout << "Global index = " << index << std::endl; + } + + std::set cell_indexes; + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + if(index == pt_id){ + cell_indexes.insert(cell_i); + } + } + cell_i++; + } + + if(verbose_Q){ + std::cout << "Detected cells indexes : " << std::endl; + for(auto index : cell_indexes){ + std::cout << index << std::endl; + } + } + + return cell_indexes; + } + + /// Pick the cell that contains the requested point + static size_t pick_cell(typename Mesh::point_type & pt, Mesh & msh, std::set & cell_indexes, bool verbose_Q = false){ + + using RealType = double; + + auto triangle_member_Q = [] (typename Mesh::point_type & p, typename Mesh::point_type & p0, typename Mesh::point_type & p1, typename Mesh::point_type & p2) + { + RealType dx = p.x()-p2.x(); + RealType dy = p.y()-p2.y(); + RealType dx21 = p2.x()-p1.x(); + RealType dy12 = p1.y()-p2.y(); + RealType d = dy12*(p0.x()-p2.x()) + dx21*(p0.y()-p2.y()); + RealType s = dy12*dx + dx21*dy; + RealType t = (p2.y()-p0.y())*dx + (p0.x()-p2.x())*dy; + if (d < 0.0) { + return s<=0.0 && t<=0.0 && s+t>=d; + } + return s>=0 && t>=0 && s+t<=d; + }; + + size_t n_cells = cell_indexes.size(); + if (n_cells == 1) { + size_t first_index = *cell_indexes.begin(); + return first_index; + } + bool is_member_Q = false; + for(auto index : cell_indexes){ + auto& cell = msh.backend_storage()->surfaces[index]; + auto bar = barycenter(msh, cell); + auto points = cell.point_ids(); + size_t n_p = points.size(); + + // building teselation + std::vector> triangles(n_p); + for (size_t l = 0; l < n_p; l++) + { + + std::vector chunk(3); + if( l == n_p - 1){ + chunk[0] = msh.backend_storage()->points.at(points[l]); + chunk[1] = msh.backend_storage()->points.at(points[0]); + chunk[2] = bar; + }else{ + chunk[0] = msh.backend_storage()->points.at(points[l]); + chunk[1] = msh.backend_storage()->points.at(points[l+1]); + chunk[2] = bar; + } + triangles[l] = chunk; + } + + // check whether the point is memeber of any triangle + for (auto triangle : triangles) { + is_member_Q = triangle_member_Q(pt,triangle[0],triangle[1],triangle[2]); + if (is_member_Q) { + std::cout << "Detected cell index = " << index << std::endl; + return index; + } + } + + } + + if(!is_member_Q){ + if(verbose_Q){ + std::cout << "Point is not member of cells set. Returning cell_indexes[0] " << std::endl; + } + size_t first_index = *cell_indexes.begin(); + return first_index; + } + + return -1; + } + + static double ricker_fluid(size_t it, double dt){ + + using RealType = double; + RealType tau, freq, Ricker, Ricker_fl, alpha, sigma, sigmabis, sigma2, sigma3, tn; + + tn = it * dt; + tau = 0.4; + freq = 5.0; + alpha = - M_PI*M_PI * freq*freq; + + if ( tn < 2.5*tau ) { + sigma = alpha*(tn-tau)*(tn-tau); + Ricker = 2.0 * alpha * (1+2*sigma) * exp(sigma); + sigmabis = M_PI*freq*(tn-tau); + sigma2 = sigmabis*sigmabis; + sigma3 = M_PI*freq; + Ricker_fl = -4.0*sigmabis*sigma3*exp(-sigma2)-2.0*sigmabis*sigma3*Ricker; + } + else Ricker_fl = 0.0; + + std::cout << Ricker_fl << std::endl; + + return Ricker_fl; + } + + // Punctual Source + static Matrix punctual_source(size_t it, double dt, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof){ + + using RealType = double; + + auto dim = Mesh::dimension; + size_t n_scal_dof = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_dof = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t cell_dof = n_scal_dof + n_vec_dof; + + typename Mesh::point_type pt = pt_cell_index.first; + + if(pt_cell_index.second == -1){ + std::set cell_indexes = find_cells(pt, msh, true); + size_t cell_index = pick_cell(pt, msh, cell_indexes, true); + assert(cell_index != -1); + pt_cell_index.second = cell_index; + } + + { + size_t cell_ind = pt_cell_index.second; + // scalar evaluation + { + Matrix scalar_cell_dof = x_dof.block(cell_ind*cell_dof+n_vec_dof, 0, n_scal_dof, 1); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + auto t_phi = cell_basis.eval_functions( pt ); + std::cout << cell_ind << std::endl; + + for (int i = scalar_cell_dof.size()-1; i < scalar_cell_dof.size(); i++) { + scalar_cell_dof(i) = scalar_cell_dof(i) - t_phi(i)*ricker_fluid(it,dt); + } + + x_dof.block(cell_ind*cell_dof+n_vec_dof, 0, n_scal_dof, 1) = scalar_cell_dof; + } + } + + + + return x_dof; + } + +}; + + +#endif /* postprocessor_hpp */ diff --git a/apps/wave_propagation/src/common/sourceterm2.hpp b/apps/wave_propagation/src/common/sourceterm2.hpp new file mode 100644 index 00000000..9e643b75 --- /dev/null +++ b/apps/wave_propagation/src/common/sourceterm2.hpp @@ -0,0 +1,271 @@ + +#pragma once +#ifndef source_term_hpp +#define source_term_hpp + +#include +#include "../common/acoustic_one_field_assembler.hpp" +#include "../common/acoustic_two_fields_assembler.hpp" +#include "../common/elastodynamic_one_field_assembler.hpp" +#include "../common/elastodynamic_two_fields_assembler.hpp" +#include "../common/elastodynamic_three_fields_assembler.hpp" +#include "../common/elastoacoustic_two_fields_assembler.hpp" +#include "../common/elastoacoustic_four_fields_assembler.hpp" + +#ifdef HAVE_INTEL_TBB +#include +#endif + +template +class source_term { + +public: + + using RealType = double; + + // find distances to the requested point + static std::vector make_distances(typename Mesh::point_type & pt, Mesh & msh, bool verbose_Q = false) { + + auto norm = [](const typename Mesh::point_type& a, const typename Mesh::point_type& b ) -> RealType { + RealType dx = (b.x() - a.x()); + RealType dy = (b.y() - a.y()); + RealType norm = std::sqrt(dx*dx + dy*dy); + return norm; + }; + + size_t np = msh.points_size(); + std::vector distances(np); + + size_t ip = 0; + for (auto& point : msh.backend_storage()->points) + { + RealType dist = norm(pt,point); + distances[ip] = dist; + ip++; + } + + return distances; + } + + // find minimum distances to the requested point + static RealType min_distance(std::vector distances, bool verbose_Q = false) { + RealType min_dist; + if(verbose_Q){ + min_dist = *std::min_element(distances.begin(), distances.end()); + } + return min_dist; + } + + /// Find the cells associated to the requested point + static std::set find_cells_source(typename Mesh::point_type & pt, Mesh & msh, bool verbose_Q = false){ + + std::vector distances = make_distances(pt, msh, true); + size_t index = std::min_element(distances.begin(),distances.end()) - distances.begin(); + if(verbose_Q){ + RealType min_dist = *std::min_element(distances.begin(), distances.end()); + typename Mesh::point_type nearest_point = msh.backend_storage()->points.at(index); + std::cout << "Nearest point detected : " << std::endl; + std::cout << " x = " << nearest_point.x() << std::endl; + std::cout << " y = " << nearest_point.y() << std::endl; + std::cout << "Distance = " << min_dist << std::endl; + std::cout << "Global index = " << index << std::endl; + } + + std::set cell_indexes; + + size_t cell_i = 0; + for (auto& cell : msh) + { + auto points = cell.point_ids(); + size_t n_p = points.size(); + for (size_t l = 0; l < n_p; l++) + { + auto pt_id = points[l]; + if(index == pt_id){ + cell_indexes.insert(cell_i); + } + } + cell_i++; + } + + if(verbose_Q){ + std::cout << "Detected cells indexes : " << std::endl; + for(auto index : cell_indexes){ + std::cout << index << std::endl; + } + } + + return cell_indexes; + + } + + /// Pick the cell that contains the requested point + static std::vector pick_cell_source(typename Mesh::point_type & pt, Mesh & msh, std::set & cell_indexes, bool verbose_Q = false){ + + std::vector distances = make_distances(pt, msh, true); + + if (min_distance(distances, true) == 0.0) { + std::vector cells_sources(4); + int i = 0; + for (auto cells : cell_indexes) { + cells_sources[i] = cells; + i++; + } + std::cout << "Pas de problème quand on est sur un point du maillage" << std::endl; + std::cout << "Quand on est au milieu d'une maille à implémenter" << std::endl; + return cells_sources; + } + + else { + std::vector cells_sources(1); + auto triangle_member_Q = [] (typename Mesh::point_type & p, typename Mesh::point_type & p0, typename Mesh::point_type & p1, typename Mesh::point_type & p2) + { + RealType dx = p.x()-p2.x(); + RealType dy = p.y()-p2.y(); + RealType dx21 = p2.x()-p1.x(); + RealType dy12 = p1.y()-p2.y(); + RealType d = dy12*(p0.x()-p2.x()) + dx21*(p0.y()-p2.y()); + RealType s = dy12*dx + dx21*dy; + RealType t = (p2.y()-p0.y())*dx + (p0.x()-p2.x())*dy; + if (d < 0.0) { + return s<=0.0 && t<=0.0 && s+t>=d; + } + return s>=0 && t>=0 && s+t<=d; + }; + std::cout << "Problème laaaaaaa" << std::endl; + size_t n_cells = cell_indexes.size(); + if (n_cells == 1) { + size_t first_index = *cell_indexes.begin(); + cells_sources[0] = first_index; + return cells_sources; + } + bool is_member_Q = false; + for(auto index : cell_indexes){ + auto& cell = msh.backend_storage()->surfaces[index]; + auto bar = barycenter(msh, cell); + auto points = cell.point_ids(); + size_t n_p = points.size(); + + // building teselation + std::vector> triangles(n_p); + for (size_t l = 0; l < n_p; l++) + { + + std::vector chunk(3); + if( l == n_p - 1){ + chunk[0] = msh.backend_storage()->points.at(points[l]); + chunk[1] = msh.backend_storage()->points.at(points[0]); + chunk[2] = bar; + }else{ + chunk[0] = msh.backend_storage()->points.at(points[l]); + chunk[1] = msh.backend_storage()->points.at(points[l+1]); + chunk[2] = bar; + } + triangles[l] = chunk; + } + + // check whether the point is memeber of any triangle + int j = 0; + for (auto triangle : triangles) { + is_member_Q = triangle_member_Q(pt,triangle[0],triangle[1],triangle[2]); + if (is_member_Q) { + std::cout << "Detected cell index = " << index << std::endl; + cells_sources[j] = index; + return cells_sources; + } + j++; + } + + } + + if(!is_member_Q){ + if(verbose_Q){ + std::cout << "Point is not member of cells set. Returning cell_indexes[0] " << std::endl; + } + size_t first_index = *cell_indexes.begin(); + cells_sources[0] = first_index; + return cells_sources; + } + + return cells_sources; + + } + } + + // Punctual Source + static Matrix punctual_source(size_t it, double dt, std::pair & pt_cell_index, Mesh & msh, disk::hho_degree_info & hho_di, Matrix & x_dof){ + + auto dim = Mesh::dimension; + size_t n_scal_dof = disk::scalar_basis_size(hho_di.cell_degree(), Mesh::dimension); + size_t n_vec_dof = disk::scalar_basis_size(hho_di.reconstruction_degree(), Mesh::dimension)-1; + size_t cell_dof = n_scal_dof + n_vec_dof; + + typename Mesh::point_type pt = pt_cell_index.first; + + std::vector cells_index; + std::set cell_indexes; + + if(pt_cell_index.second == -1){ + cell_indexes = find_cells_source(pt, msh, true); + cells_index = pick_cell_source(pt, msh, cell_indexes, true); + std::cout << cells_index.size() << std::endl; + assert(cells_index[0] != -1); + pt_cell_index.second = cells_index[0]; + } + + if (cells_index.size() == 4) { + std::cout << "source sur un point du maillage" << std::endl; + } + + else { + size_t cell_ind = pt_cell_index.second; + // scalar evaluation + { + + std::cout << "source sur un point du maillage" << std::endl; + Matrix scalar_cell_dof = x_dof.block(cell_ind*cell_dof+n_vec_dof, 0, n_scal_dof, 1); + auto& cell = msh.backend_storage()->surfaces[cell_ind]; + auto cell_basis = disk::make_scalar_monomial_basis(msh, cell, hho_di.cell_degree()); + auto t_phi = cell_basis.eval_functions( pt ); + std::cout << cell_ind << std::endl; + + for (int i = scalar_cell_dof.size()-1; i < scalar_cell_dof.size(); i++) { + scalar_cell_dof(i) = scalar_cell_dof(i) - t_phi(i)*ricker_fluid(it,dt); + } + + x_dof.block(cell_ind*cell_dof+n_vec_dof, 0, n_scal_dof, 1) = scalar_cell_dof; + } + } + + return x_dof; + + } + + static RealType ricker_fluid(size_t it, RealType dt){ + + RealType tau, freq, Ricker, Ricker_fl, alpha, sigma, sigmabis, sigma2, sigma3, tn; + + tn = it * dt; + tau = 0.4; + freq = 5.0; + alpha = - M_PI*M_PI * freq*freq; + + if ( tn < 2.5*tau ) { + sigma = alpha*(tn-tau)*(tn-tau); + Ricker = 2.0 * alpha * (1+2*sigma) * exp(sigma); + sigmabis = M_PI*freq*(tn-tau); + sigma2 = sigmabis*sigmabis; + sigma3 = M_PI*freq; + Ricker_fl = -4.0*sigmabis*sigma3*exp(-sigma2)-2.0*sigmabis*sigma3*Ricker; + } + else Ricker_fl = 0.0; + + std::cout << Ricker_fl << std::endl; + + return Ricker_fl; + } + +}; + + +#endif /* postprocessor_hpp */ diff --git a/apps/wave_propagation/src/common/ssprk_hho_scheme.hpp b/apps/wave_propagation/src/common/ssprk_hho_scheme.hpp new file mode 100644 index 00000000..dfef4b51 --- /dev/null +++ b/apps/wave_propagation/src/common/ssprk_hho_scheme.hpp @@ -0,0 +1,329 @@ +// +// ssprk_hho_scheme.hpp +// acoustics +// +// Created by Omar Durán on 4/21/20. +// + +#pragma once +#ifndef ssprk_hho_scheme_hpp +#define ssprk_hho_scheme_hpp + +#include +#include +#include + +template +class ssprk_hho_scheme +{ + private: + + SparseMatrix m_Mc; + SparseMatrix m_Kcc; + SparseMatrix m_Kcf; + SparseMatrix m_Kfc; + SparseMatrix m_Sff; + SparseMatrix m_Mc_inv; + SparseMatrix m_Sff_inv; + Matrix m_Fc; + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> m_analysis_f; + #else + SimplicialLDLT> m_analysis_f; + #endif + + ConjugateGradient> m_analysis_cg; + + size_t m_n_c_dof; + size_t m_n_f_dof; + bool m_sff_is_block_diagonal_Q; + bool m_iterative_solver_Q; + + public: + + ssprk_hho_scheme(SparseMatrix & Kg, Matrix & Fg, SparseMatrix & Mg, size_t n_f_dof){ + + + m_n_c_dof = Kg.rows() - n_f_dof; + m_n_f_dof = n_f_dof; + + // Building blocks + m_Mc = Mg.block(0, 0, m_n_c_dof, m_n_c_dof); + m_Kcc = Kg.block(0, 0, m_n_c_dof, m_n_c_dof); + m_Kcf = Kg.block(0, m_n_c_dof, m_n_c_dof, n_f_dof); + m_Kfc = Kg.block(m_n_c_dof,0, n_f_dof, m_n_c_dof); + m_Sff = Kg.block(m_n_c_dof,m_n_c_dof, n_f_dof, n_f_dof); + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + m_sff_is_block_diagonal_Q = false; + m_iterative_solver_Q = false; + } + + void setIterativeSolver(T tolerance = 1.0e-11){ + m_iterative_solver_Q = true; + m_analysis_cg.setTolerance(tolerance); + } + + void DecomposeFaceTerm(){ + + if (m_iterative_solver_Q) { + m_analysis_cg.compute(m_Sff); + m_analysis_cg.setMaxIterations(m_Sff.rows()); + }else{ + m_analysis_f.analyzePattern(m_Sff); + m_analysis_f.factorize(m_Sff); + } + m_sff_is_block_diagonal_Q = false; + } + + + #ifdef HAVE_INTEL_MKL + PardisoLDLT> & FacesAnalysis(){ + return m_analysis_f; + } + #else + SimplicialLDLT> & FacesAnalysis(){ + return m_analysis_f; + } + #endif + + SparseMatrix & Mc(){ + return m_Mc; + } + + SparseMatrix & Kcc(){ + return m_Kcc; + } + + SparseMatrix & Kcf(){ + return m_Kcf; + } + + SparseMatrix & Kfc(){ + return m_Kfc; + } + + SparseMatrix & Sff(){ + return m_Sff; + } + + Matrix & Fc(){ + return m_Fc; + } + + void SetFg(Matrix & Fg){ + m_Fc = Fg.block(0, 0, m_n_c_dof, 1); + } + + void Kcc_inverse(std::pair cell_basis_data){ + + size_t n_cells = cell_basis_data.first; + size_t n_cbs = cell_basis_data.second; + size_t nnz_cc = n_cbs*n_cbs*n_cells; + std::vector< Triplet > triplets_cc; + triplets_cc.resize(nnz_cc); + m_Mc_inv = SparseMatrix( m_n_c_dof, m_n_c_dof ); + #ifdef HAVE_INTEL_TBB + tbb::parallel_for(size_t(0), size_t(n_cells), size_t(1), + [this,&triplets_cc,&n_cbs] (size_t & cell_ind){ + + size_t stride_eq = cell_ind * n_cbs; + size_t stride_l = cell_ind * n_cbs * n_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, n_cbs, n_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(n_cbs, n_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) + { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) + { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + } + ); + #else + + for (size_t cell_ind = 0; cell_ind < n_cells; cell_ind++) + { + size_t stride_eq = cell_ind * n_cbs; + size_t stride_l = cell_ind * n_cbs * n_cbs; + + SparseMatrix m_Mc_loc = m_Mc.block(stride_eq, stride_eq, n_cbs, n_cbs); + SparseLU> analysis_cc; + analysis_cc.analyzePattern(m_Mc_loc); + analysis_cc.factorize(m_Mc_loc); + Matrix m_Mc_inv_loc = analysis_cc.solve(Matrix::Identity(n_cbs, n_cbs)); + + size_t l = 0; + for (size_t i = 0; i < m_Mc_inv_loc.rows(); i++) + { + for (size_t j = 0; j < m_Mc_inv_loc.cols(); j++) + { + triplets_cc[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, m_Mc_inv_loc(i,j)); + l++; + } + } + + } + #endif + m_Mc_inv.setFromTriplets( triplets_cc.begin(), triplets_cc.end() ); + triplets_cc.clear(); + return; + + } + + void Sff_inverse(std::pair face_basis_data){ + + size_t n_faces = face_basis_data.first; + size_t n_fbs = face_basis_data.second; + size_t nnz_ff = n_fbs*n_fbs*n_faces; + std::vector< Triplet > triplets_ff; + triplets_ff.resize(nnz_ff); + m_Sff_inv = SparseMatrix( m_n_f_dof, m_n_f_dof ); + #ifdef HAVE_INTEL_TBB + tbb::parallel_for(size_t(0), size_t(n_faces), size_t(1), + [this,&triplets_ff,&n_fbs] (size_t & face_ind){ + + size_t stride_eq = face_ind * n_fbs; + size_t stride_l = face_ind * n_fbs * n_fbs; + + SparseMatrix S_ff_loc = m_Sff.block(stride_eq, stride_eq, n_fbs, n_fbs); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(S_ff_loc); + analysis_ff.factorize(S_ff_loc); + Matrix S_ff_inv_loc = analysis_ff.solve(Matrix::Identity(n_fbs, n_fbs)); + + size_t l = 0; + for (size_t i = 0; i < S_ff_inv_loc.rows(); i++) + { + for (size_t j = 0; j < S_ff_inv_loc.cols(); j++) + { + triplets_ff[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, S_ff_inv_loc(i,j)); + l++; + } + } + } + ); + #else + + for (size_t face_ind = 0; face_ind < n_faces; face_ind++) + { + size_t stride_eq = face_ind * n_fbs; + size_t stride_l = face_ind * n_fbs * n_fbs; + + SparseMatrix S_ff_loc = m_Sff.block(stride_eq, stride_eq, n_fbs, n_fbs); + SparseLU> analysis_ff; + analysis_ff.analyzePattern(S_ff_loc); + analysis_ff.factorize(S_ff_loc); + Matrix S_ff_inv_loc = analysis_ff.solve(Matrix::Identity(n_fbs, n_fbs)); + size_t l = 0; + for (size_t i = 0; i < S_ff_inv_loc.rows(); i++) + { + for (size_t j = 0; j < S_ff_inv_loc.cols(); j++) + { + triplets_ff[stride_l+l] = Triplet(stride_eq+i, stride_eq+j, S_ff_inv_loc(i,j)); + l++; + } + } + + } + #endif + m_Sff_inv.setFromTriplets( triplets_ff.begin(), triplets_ff.end() ); + triplets_ff.clear(); + m_sff_is_block_diagonal_Q = true; + return; + + } + + void refresh_faces_unknowns(Matrix & x){ + + Matrix x_c_dof = x.block(0, 0, m_n_c_dof, 1); + + // Faces update from cells data + Matrix RHSf = Kfc()*x_c_dof; + if (m_sff_is_block_diagonal_Q) { + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + }else{ + if (m_iterative_solver_Q) { + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = -m_analysis_cg.solve(RHSf); // new state + }else{ + x.block(m_n_c_dof, 0, m_n_f_dof, 1) = -FacesAnalysis().solve(RHSf); // new state + } + } + + } + + void ssprk_weight(Matrix & x_dof, Matrix & x_dof_n, T dt, T a, T b){ + + x_dof_n = x_dof; + Matrix x_c_dof = x_dof.block(0, 0, m_n_c_dof, 1); + Matrix x_f_dof = x_dof.block(m_n_c_dof, 0, m_n_f_dof, 1); + +// // Faces update (last state) +// { +// Matrix RHSf = Kfc()*x_c_dof; +// x_f_dof = -FacesAnalysis().solve(RHSf); +// } + + // Cells update + Matrix RHSc = Fc() - Kcc()*x_c_dof - Kcf()*x_f_dof; + Matrix delta_x_c_dof = m_Mc_inv * RHSc; + Matrix x_n_c_dof = a * x_c_dof + b * dt * delta_x_c_dof; // new state + x_dof_n.block(0, 0, m_n_c_dof, 1) = x_n_c_dof; + + // Faces update + Matrix RHSf = Kfc()*x_n_c_dof; + if (m_sff_is_block_diagonal_Q) { + x_dof_n.block(m_n_c_dof, 0, m_n_f_dof, 1) = - m_Sff_inv * RHSf; + }else{ + if (m_iterative_solver_Q) { + x_dof_n.block(m_n_c_dof, 0, m_n_f_dof, 1) = -m_analysis_cg.solve(RHSf); // new state + std::cout << "Number of iterations (CG): " << m_analysis_cg.iterations() << std::endl; + std::cout << "Estimated error: " << m_analysis_cg.error() << std::endl; + }else{ + x_dof_n.block(m_n_c_dof, 0, m_n_f_dof, 1) = -FacesAnalysis().solve(RHSf); // new state + } + } + +// // Faces update +// Matrix RHSf = Kfc()*x_n_c_dof; +// Matrix x_n_f_dof = -FacesAnalysis().solve(RHSf); // new state +// +// // Composing global solution +// x_dof_n = x_dof; +// x_dof_n.block(0, 0, m_n_c_dof, 1) = x_n_c_dof; +// x_dof_n.block(m_n_c_dof, 0, m_n_f_dof, 1) = x_n_f_dof; + + } + + void ssprk_step(int s, Matrix &alpha, Matrix &beta, T & dt, Matrix & x_dof_n_m, Matrix & x_dof_n){ + + size_t n_dof = x_dof_n_m.rows(); + Matrix ys = Matrix::Zero(n_dof, s+1); + + Matrix yn, ysi, yj; + ys.block(0, 0, n_dof, 1) = x_dof_n_m; + for (int i = 0; i < s; i++) { + + ysi = Matrix::Zero(n_dof, 1); + for (int j = 0; j <= i; j++) { + yn = ys.block(0, j, n_dof, 1); + ssprk_weight(yn, yj, dt, alpha(i,j), beta(i,j)); + ysi += yj; + } + ys.block(0, i+1, n_dof, 1) = ysi; + } + + x_dof_n = ys.block(0, s, n_dof, 1); + + } + +}; + +#endif /* ssprk_hho_scheme_hpp */ diff --git a/apps/wave_propagation/src/common/ssprk_shu_osher_tableau.hpp b/apps/wave_propagation/src/common/ssprk_shu_osher_tableau.hpp new file mode 100644 index 00000000..b71b042f --- /dev/null +++ b/apps/wave_propagation/src/common/ssprk_shu_osher_tableau.hpp @@ -0,0 +1,312 @@ +// +// ssprk_shu_osher_tableau.hpp +// acoustics +// +// Created by Omar Durán on 4/21/20. +// + +#pragma once +#ifndef ssprk_shu_osher_tableau_hpp +#define ssprk_shu_osher_tableau_hpp + +#include + +class ssprk_shu_osher_tableau +{ + public: + + static void ossprk_tables(int s, Matrix &a, Matrix &b){ + + // Optimal Strong-Stability-Preserving Runge-Kutta Time Discretizations for Discontinuous Galerkin Methods + switch (s) { + case 1: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + b(0,0) = 1.0; + } + break; + case 2: + { + // DG book (Alexandre) + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 1.0/2.0; + a(1,1) = 1.0/2.0; + + b(0,0) = 1.0; + b(1,1) = 1.0/2.0; + + } + break; + case 3: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 0.087353119859156; + a(1,1) = 0.912646880140844; + a(2,0) = 0.344956917166841; + a(2,1) = 0.0; + a(2,2) = 0.655043082833159; + + b(0,0) = 0.528005024856522; + b(1,0) = 0.0; + b(1,1) = 0.481882138633993; + b(2,0) = 0.022826837460491; + b(2,1) = 0.0; + b(2,2) = 0.345866039233415; + + + } + break; + case 4: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 0.522361915162541; + a(1,1) = 0.477638084837459; + a(2,0) = 0.368530939472566; + a(2,1) = 0.0; + a(2,2) = 0.631469060527434; + a(3,0) = 0.334082932462285; + a(3,1) = 0.006966183666289; + a(3,2) = 0.0; + a(3,3) = 0.658950883871426; + + b(0,0) = 0.594057152884440; + b(1,0) = 0.0; + b(1,1) = 0.283744320787718; + b(2,0) = 0.000000038023030; + b(2,1) = 0.0; + b(2,2) = 0.375128712231540; + b(3,0) = 0.116941419604231; + b(3,1) = 0.004138311235266; + b(3,2) = 0.0; + b(3,3) = 0.391454485963345; + } + break; + case 5: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 0.261216512493821; + a(1,1) = 0.738783487506179; + a(2,0) = 0.623613752757655; + a(2,1) = 0.0; + a(2,2) = 0.376386247242345; + a(3,0) = 0.444745181201454; + a(3,1) = 0.120932584902288; + a(3,2) = 0.0; + a(3,3) = 0.434322233896258; + a(4,0) = 0.213357715199957; + a(4,1) = 0.209928473023448; + a(4,2) = 0.063353148180384; + a(4,3) = 0.0; + a(4,4) = 0.513360663596212; + + b(0,0) = 0.605491839566400; + b(1,0) = 0.0; + b(1,1) = 0.447327372891397; + b(2,0) = 0.000000844149769; + b(2,1) = 0.0; + b(2,2) = 0.227898801230261; + b(3,0) = 0.002856233144485; + b(3,1) = 0.073223693296006; + b(3,2) = 0.0; + b(3,3) = 0.262978568366434; + b(4,0) = 0.002362549760441; + b(4,1) = 0.127109977308333; + b(4,2) = 0.038359814234063; + b(4,3) = 0.0; + b(4,4) = 0.310835692561898; + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + + static void new_ossprk_tables(int s, Matrix &a, Matrix &b){ + + // NEW OPTIMAL SSPRK TIME DISCRETIZATION M (s,s) + switch (s) { + case 1: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + b(0,0) = 1.0; + } + break; + case 2: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 1.0/2.0; + a(1,1) = 1.0/2.0; + + b(0,0) = 1.0; + b(1,0) = 0.0; + b(1,1) = 1.0/2.0; + + } + break; + case 3: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + + a(0,0) = 1.0; + a(1,0) = 3.0/4.0; + a(1,1) = 1.0/4.0; + a(2,0) = 1.0/3.0; + a(2,1) = 0.0; + a(2,2) = 2.0/3.0; + + b(0,0) = 1.0; + b(1,0) = 0.0; + b(1,1) = 1.0/4.0; + b(2,0) = 0.0; + b(2,1) = 0.0; + b(2,2) = 2.0/3.0; + + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + + static void new_ossprk_s_p_one_tables(int s, Matrix &a, Matrix &b){ + + // NEW OPTIMAL SSPRK TIME DISCRETIZATION M (s+1,s) + switch (s) { + case 1: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + b(0,0) = 1.0; + } + break; + case 2: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,1) = 1.0; + + b(0,0) = 1.0/2.0; + b(1,1) = 1.0/2.0; + + } + break; + case 3: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + + a(0,0) = 1.0; + a(1,0) = 0.0; + a(1,1) = 1.0; + a(2,0) = 1.0/3.0; + a(2,1) = 0.0; + a(2,2) = 2.0/3.0; + + b(0,0) = 1.0/2.0; + b(1,1) = 1.0/2.0; + b(2,2) = 1.0/3.0; + + + } + break; + case 4: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 0.0; + a(1,1) = 1.0; + a(2,0) = 2.0/3.0; + a(2,1) = 0.0; + a(2,2) = 1.0/3.0; + a(3,0) = 0.0; + a(3,1) = 0.0; + a(3,2) = 0.0; + a(3,3) = 1.0; + + b(0,0) = 1.0/2.0; + b(1,0) = 0.0; + b(1,1) = 1.0/2.0; + b(2,0) = 0.0; + b(2,1) = 0.0; + b(2,2) = 1.0/6.0; + b(3,0) = 0.0; + b(3,1) = 0.0; + b(3,2) = 0.0; + b(3,3) = 1.0/2.0; + } + break; + case 5: + { + a = Matrix::Zero(s, s); + b = Matrix::Zero(s, s); + a(0,0) = 1.0; + a(1,0) = 0.44437049406734; + a(1,1) = 0.55562950593266; + a(2,0) = 0.62010185138540; + a(2,1) = 0.0; + a(2,2) = 0.37989814861460; + a(3,0) = 0.17807995410773; + a(3,1) = 0.0; + a(3,2) = 0.0; + a(3,3) = 0.82192004589227; + a(4,0) = 0.00683325884039; + a(4,1) = 0.0; + a(4,2) = 0.51723167208978; + a(4,3) = 0.12759831133288; + a(4,4) = 0.34833675773694; + + b(0,0) = 0.39175222700392; + b(1,0) = 0.0; + b(1,1) = 0.36841059262959; + b(2,0) = 0.0; + b(2,1) = 0.0; + b(2,2) = 0.25189177424738; + b(3,0) = 0.0; + b(3,1) = 0.0; + b(3,2) = 0.0; + b(3,3) = 0.54497475021237; + b(4,0) = 0.0; + b(4,1) = 0.0; + b(4,2) = 0.0; + b(4,3) = 0.08460416338212; + b(4,4) = 0.22600748319395; + } + break; + default: + { + std::cout << "Error:: Method not implemented." << std::endl; + } + break; + } + + } + +}; + +#endif /* ssprk_shu_osher_tableau_hpp */ diff --git a/apps/wave_propagation/src/common/vec_analytic_functions.hpp b/apps/wave_propagation/src/common/vec_analytic_functions.hpp new file mode 100644 index 00000000..648ce2b1 --- /dev/null +++ b/apps/wave_propagation/src/common/vec_analytic_functions.hpp @@ -0,0 +1,325 @@ +// +// vec_analytic_functions.hpp +// acoustics +// +// Created by Omar Durán on 4/14/20. +// + +#pragma once +#ifndef vec_analytic_functions_hpp +#define vec_analytic_functions_hpp + +#include + +class vec_analytic_functions +{ + public: + + /// Enumerate defining the function type + enum EFunctionType { EFunctionNonPolynomial = 0, EFunctionQuadraticInTime = 1, EFunctionQuadraticInSpace = 2}; + + + vec_analytic_functions(){ + m_function_type = EFunctionNonPolynomial; + } + + ~vec_analytic_functions(){ + + } + + void set_function_type(EFunctionType function_type){ + m_function_type = function_type; + } + + std::function(const typename disk::generic_mesh::point_type& )> Evaluate_u(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = -std::cos(M_PI*y)*std::sin(std::sqrt(2)*M_PI*t)*std::sin(M_PI*x); + uy = std::cos(M_PI*x)*std::sin(std::sqrt(2)*M_PI*t)*std::sin(M_PI*y); + static_vector u{ux,uy}; + return u; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = (1.0 - x)*x*(1.0 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + uy = (1.0 - x)*x*(1.0 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + static_vector u{ux,uy}; + return u; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,ux,uy; + x = pt.x(); + y = pt.y(); + ux = -t*t*std::cos(M_PI*y)*std::sin(M_PI*x); + uy = t*t*std::cos(M_PI*x)*std::sin(M_PI*y); + static_vector u{ux,uy}; + return u; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> static_vector { + static_vector u; + return u; + }; + } + break; + } + + } + + std::function(const typename disk::generic_mesh::point_type& )> Evaluate_v(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = -(std::sqrt(2)*M_PI*std::cos(std::sqrt(2)*M_PI*t)*std::cos(M_PI*y)*std::sin(M_PI*x)); + vy = std::sqrt(2)*M_PI*std::cos(std::sqrt(2)*M_PI*t)*std::cos(M_PI*x)*std::sin(M_PI*y); + static_vector v{vx,vy}; + return v; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = std::sqrt(2.0)*M_PI*(1.0 - x)*x*(1.0 - y)*y*std::cos(std::sqrt(2.0)*M_PI*t); + vy = std::sqrt(2.0)*M_PI*(1.0 - x)*x*(1.0 - y)*y*std::cos(std::sqrt(2.0)*M_PI*t); + static_vector v{vx,vy}; + return v; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,vx,vy; + x = pt.x(); + y = pt.y(); + vx = -2*t*std::cos(M_PI*y)*std::sin(M_PI*x); + vy = 2*t*std::cos(M_PI*x)*std::sin(M_PI*y); + static_vector v{vx,vy}; + return v; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y; + x = pt.x(); + y = pt.y(); + static_vector v; + return v; + }; + } + break; + } + + } + + std::function(const typename disk::generic_mesh::point_type& )> Evaluate_a(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = 2*M_PI*M_PI*std::cos(M_PI*y)*std::sin(std::sqrt(2)*M_PI*t)*std::sin(M_PI*x); + ay = -2*M_PI*M_PI*std::cos(M_PI*x)*std::sin(std::sqrt(2)*M_PI*t)*std::sin(M_PI*y); + static_vector a{ax,ay}; + return a; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = -2.0*M_PI*M_PI*(1.0 - x)*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + ay = -2.0*M_PI*M_PI*(1.0 - x)*x*(1 - y)*y*std::sin(std::sqrt(2.0)*M_PI*t); + static_vector a{ax,ay}; + return a; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,ax,ay; + x = pt.x(); + y = pt.y(); + ax = -2*std::cos(M_PI*y)*std::sin(M_PI*x); + ay = 2*std::cos(M_PI*x)*std::sin(M_PI*y); + static_vector a{ax,ay}; + return a; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> static_vector { + static_vector f; + return f; + }; + } + break; + } + + } + + std::function(const typename disk::generic_mesh::point_type& )> Evaluate_f(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,fx,fy; + x = pt.x(); + y = pt.y(); + fx = -2.0*(1.0 + (-3.0 + x)*x - 5.0*y + (4.0 - M_PI*M_PI*(-1.0 + x))*x*y + (3.0 + M_PI*M_PI*(-1.0 + x)*x)*y*y)*std::sin(std::sqrt(2.0)*M_PI*t); + fy = -2*(1 + (-3 + y)*y + x*(-5 + (4 - M_PI*M_PI*(-1 + y))*y) + x*x*(3 + M_PI*M_PI*(-1 + y)*y))*std::sin(std::sqrt(2.0)*M_PI*t); + static_vector f{fx,fy}; + return f; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_vector { + double x,y,fx,fy; + x = pt.x(); + y = pt.y(); + fx = -2*(1 + M_PI*M_PI*t*t)*std::cos(M_PI*y)*std::sin(M_PI*x); + fy = 2*(1 + M_PI*M_PI*t*t)*std::cos(M_PI*x)*std::sin(M_PI*y); + static_vector f{fx,fy}; + return f; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> static_vector { + static_vector f; + return f; + }; + } + break; + } + + } + + + std::function(const typename disk::generic_mesh::point_type& )> Evaluate_sigma(double & t){ + + switch (m_function_type) { + case EFunctionNonPolynomial: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + sigma(0,0) = -2*M_PI*std::cos(M_PI*x)*std::cos(M_PI*y)*std::sin(std::sqrt(2)*M_PI*t); + sigma(1,1) = 2*M_PI*std::cos(M_PI*x)*std::cos(M_PI*y)*std::sin(std::sqrt(2)*M_PI*t); + return sigma; + }; + } + break; + case EFunctionQuadraticInSpace: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + sigma(0,0) = 2*(1 - x)*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t) - 2*x*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t) + + (2*(1 - x)*x*(1 - y)*std::sin(std::sqrt(2)*M_PI*t) - 2*(1 - x)*x*y*std::sin(std::sqrt(2)*M_PI*t))/2. + + (2*(1 - x)*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t) - 2*x*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t))/2.; + sigma(0,1) = (1 - x)*x*(1 - y)*std::sin(std::sqrt(2)*M_PI*t) - (1 - x)*x*y*std::sin(std::sqrt(2)*M_PI*t) + (1 - x)*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t) - + x*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t); + sigma(1,0) = sigma(0,1); + sigma(1,1) = 2*(1 - x)*x*(1 - y)*std::sin(std::sqrt(2)*M_PI*t) - 2*(1 - x)*x*y*std::sin(std::sqrt(2)*M_PI*t) + + (2*(1 - x)*x*(1 - y)*std::sin(std::sqrt(2)*M_PI*t) - 2*(1 - x)*x*y*std::sin(std::sqrt(2)*M_PI*t))/2. + + (2*(1 - x)*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t) - 2*x*(1 - y)*y*std::sin(std::sqrt(2)*M_PI*t))/2.; + return sigma; + }; + } + break; + case EFunctionQuadraticInTime: + { + return [&t](const typename disk::generic_mesh::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + sigma(0,0) = -2*M_PI*t*t*std::cos(M_PI*x)*std::cos(M_PI*y); + sigma(1,1) = 2*M_PI*t*t*std::cos(M_PI*x)*std::cos(M_PI*y); + return sigma; + }; + } + break; + default: + { + std::cout << " Function not implemented " << std::endl; + return [](const typename disk::generic_mesh::point_type& pt) -> static_matrix { + static_matrix sigma(2,2); + return sigma; + }; + } + break; + } + + } + + private: + + EFunctionType m_function_type; + +}; + +#endif /* vec_analytic_functions_hpp */ diff --git a/apps/wave_propagation/src/prototypes/LTS/ELTSAcoustic_conv_test.hpp b/apps/wave_propagation/src/prototypes/LTS/ELTSAcoustic_conv_test.hpp new file mode 100644 index 00000000..513520b2 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/LTS/ELTSAcoustic_conv_test.hpp @@ -0,0 +1,350 @@ + + +// Created by Romain Mottier + +// ../wave_propagation -s0 -k3 -r0 -c0 -p0 -l4 -n300 -i0 -f0 -e0 + +void ELTSAcousticFirstOrder(int argc, char **argv); + +void ELTSAcousticFirstOrder(int argc, char **argv){ + + // ############################################################################################# + // ############################## Simulation paramaters ######################################## + // ############################################################################################# + + std::cout << std::endl << bold << red << " EXPLICIT ACOUSTIC CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ############################################################################################# + // ############################## Mesh generation ############################################## + // ############################################################################################# + + cpu.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + bool use_poly_mesh = false; + bool use_simp_mesh = false; + if (use_poly_mesh) { + for (int i = 0; i <= 9; ++i) { + mesh_files.push_back("../../meshes/conv_test/poly/poly_" + std::to_string(32 * (1 << i)) + ".txt"); + } + } + else if (use_simp_mesh) { + std::vector conv_vals = {1.0, 0.35, 0.15, 0.07, 0.035, 0.026, 0.017, 0.0125, 0.0085, 0.005}; + for (int i = 0; i < conv_vals.size(); ++i) { + mesh_files.push_back( + "../../meshes/conv_test/simplices/unstructured/l" + std::to_string(i) + "_conv_test_" + std::to_string(conv_vals[i]) + ".txt"); + } + } + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + + // ############################################################################################# + // ################################ Time controls ############################################## + // ############################################################################################# + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ############################################################################################# + // ############################## Manufactured solution ######################################## + // ############################################################################################# + + scal_vec_analytic_functions functions; + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionCubicInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuarticInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpaceAcoustic); + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ############################################################################################# + // ################################## HHO setting ############################################## + // ############################################################################################# + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ############################################################################################# + // ################################ Material data ############################################## + // ############################################################################################# + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ############################################################################################# + // ############################## Boundary conditions ########################################## + // ############################################################################################# + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ############################################################################################# + // ###################################### Assembly ############################################# + // ############################################################################################# + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ############################################################################################# + // ###################### Projecting initial data ############################################## + // ############################################################################################# + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + // ############################################################################################# + // ###################################### Solving ############################################## + // ############################################################################################# + + Matrix a; + Matrix b; + Matrix c; + + // ERK schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + assembler.assemble(msh, null_fun, s_f_fun, true); + assembler.LHS += assembler.COUPLING; + assembler.assemble_P(msh, 1); + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + std::cout << std::endl << std::endl; + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + // ################################################## + // ################################################## Time marching + // ################################################## + + size_t p = 1; + size_t dtau = dt / p; + + // DISCRTIZATION INFOS + std::cout << bold << red << " TIME LOOP: " << std::endl; + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + std::cout << bold << cyan << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix k_T = Matrix::Zero(n_dof, s); + Matrix k_F = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + // PREDICTOR STEP + auto W = erk_an.coarse_predictor(s, b, c, x_dof_n, assembler.IminusP); + + // LOOP ON LOCAL REFINEMENT RATIOS + for (int m = 0; m < p; ++m) { + yn = x_dof; + + // LOOP ON ERK STAGES + for (int r = 0; r < s; ++r) { + + t = tn + (m+c(r,0)) * dtau; + + // MANUFACTURED SOLUTION + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + assembler.get_e_bc_conditions().updateDirichletFunction(null_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + + // UPDATE + erk_an.compute_k(r, m, s, dtau, W, c, yn, k, a, assembler.P, assembler.IminusP); + + } + // ACCUMULATED SOLUTION + for (int i = 0; i < s; i++) { + x_dof_n += dtau*b(i,0)*k.block(0, i, n_dof, 1); + } + } + + tc.toc(); + std::cout << bold << yellow << " LTS-ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + if(it == nt) { + std::cout << std::endl; + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ofstream mesh_file("mesh_file.txt"); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/LTS/ERK4_LTS_conv_test.hpp b/apps/wave_propagation/src/prototypes/LTS/ERK4_LTS_conv_test.hpp new file mode 100644 index 00000000..54347c5c --- /dev/null +++ b/apps/wave_propagation/src/prototypes/LTS/ERK4_LTS_conv_test.hpp @@ -0,0 +1,386 @@ + + +// Created by Romain Mottier + +// ../wave_propagation -s0 -k3 -r0 -c0 -p0 -l4 -n300 -i0 -f0 -e0 + +void ERK4_LTS_conv_test(int argc, char **argv); + +void ERK4_LTS_conv_test(int argc, char **argv){ + + // ############################################################################################# + // ############################## Simulation paramaters ######################################## + // ############################################################################################# + + std::cout << std::endl << bold << red << " EXPLICIT ACOUSTIC CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ############################################################################################# + // ############################## Mesh generation ############################################## + // ############################################################################################# + + cpu.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + bool use_poly_mesh = false; + bool use_simp_mesh = false; + if (use_poly_mesh) { + for (int i = 0; i <= 9; ++i) { + mesh_files.push_back("../../meshes/conv_test/poly/poly_" + std::to_string(32 * (1 << i)) + ".txt"); + } + } + else if (use_simp_mesh) { + std::vector conv_vals = {1.0, 0.35, 0.15, 0.07, 0.035, 0.026, 0.017, 0.0125, 0.0085, 0.005}; + for (int i = 0; i < conv_vals.size(); ++i) { + mesh_files.push_back( + "../../meshes/conv_test/simplices/unstructured/l" + std::to_string(i) + "_conv_test_" + std::to_string(conv_vals[i]) + ".txt"); + } + } + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + + // ############################################################################################# + // ################################ Time controls ############################################## + // ############################################################################################# + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ############################################################################################# + // ############################## Manufactured solution ######################################## + // ############################################################################################# + + scal_vec_analytic_functions functions; + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionCubicInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuarticInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpaceAcoustic); + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ############################################################################################# + // ################################## HHO setting ############################################## + // ############################################################################################# + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ############################################################################################# + // ################################ Material data ############################################## + // ############################################################################################# + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ############################################################################################# + // ############################## Boundary conditions ########################################## + // ############################################################################################# + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ############################################################################################# + // ###################################### Assembly ############################################# + // ############################################################################################# + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ############################################################################################# + // ###################### Projecting initial data ############################################## + // ############################################################################################# + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + // ############################################################################################# + // ###################################### Solving ############################################## + // ############################################################################################# + + Matrix a; + Matrix b; + Matrix c; + + // ERK schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + assembler.assemble(msh, null_fun, s_f_fun, true); + assembler.LHS += assembler.COUPLING; + assembler.assemble_P(msh, 1); + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + std::cout << std::endl << std::endl; + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + // ################################################## + // ################################################## Time marching + // ################################################## + + size_t p = 1; + size_t dtau = dt / p; + auto l0 = x_dof; + + // DISCRTIZATION INFOS + std::cout << bold << red << " TIME LOOP: " << std::endl; + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + std::cout << bold << cyan << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + tc.tic(); + + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix k_T = Matrix::Zero(n_dof, s); + Matrix k_F = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + //////////////////////////////////////////////////////////// SOURCE TERMS + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun_tn = functions.Evaluate_s_f(t); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + auto F0 = erk_an.invMc() * erk_an.Fc(); + + auto t_dt = t+dt; + s_v_fun = functions.Evaluate_s_v(t_dt); + s_f_fun = functions.Evaluate_s_f(t_dt); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + auto F1 = erk_an.invMc() * erk_an.Fc(); + + auto t_dt_2 = t+dt/2.0; + s_v_fun = functions.Evaluate_s_v(t_dt_2); + s_f_fun = functions.Evaluate_s_f(t_dt_2); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + auto F2 = erk_an.invMc() * erk_an.Fc(); + + ////////////////////////////////////////////////////////////// COARSE PREDICTOR + Matrix w0, w1, w2, w3; + Eigen::VectorXd tmp; + tmp = assembler.IminusP * x_dof_n; + // w0 + w0 = erk_an.apply_B(tmp) + assembler.IminusP * F0; + // w1 + tmp = assembler.IminusP * (erk_an.apply_B(x_dof_n) + F0); + w1 = erk_an.apply_B(tmp) + assembler.IminusP * ((-3.0*F0 + 4.0*F2 - F1)/dt); + // w2 + tmp = assembler.IminusP * (erk_an.apply_B_power(x_dof_n,2) + erk_an.apply_B(F0) + (-3.0*F0 + 4.0*F2 - F1)/dt); + w2 = erk_an.apply_B(tmp) + assembler.IminusP * ((4.0*F0 - 8.0*F2 + 4.0*F1)/(dt*dt)); + + // w3 + auto tmp1 = (-3*F0+4*F2-F1)/dt; + tmp = assembler.IminusP * (erk_an.apply_B_power(x_dof_n,3) + erk_an.apply_B_power(F0,2) + erk_an.apply_B(tmp1) + ((4.0*F0 - 8.0*F2 + 4.0*F1)/(dt*dt)) ); + w3 = erk_an.apply_B(tmp); + + // LOOP ON LOCAL REFINEMENT RATIOS + for (int m = 0; m < p; ++m) { + + auto tm = tn + m * dtau; + auto tm1 = tn + (m+1)*dtau; + auto tm2 = tn + (m+0.5)*dtau; + + auto tmp1 = assembler.P*l0; + auto k1 = w0 + m*dtau*w1 + (m*m/2)*dtau*dtau*w2 + (m*m*m/6)*dtau*dtau*dtau*w3 + erk_an.apply_B(tmp1); + + auto tmp2 = assembler.P*(l0 + (dtau/2)*k1); + auto k2 = w0 + (m+0.5)*dtau*w1 + 0.5*(m+0.5)*(m+0.5)*dtau*dtau*w2 + (1/6)*(m+0.5)*(m+0.5)*(m+0.5)*dtau*dtau*dtau*w3 + erk_an.apply_B(tmp2); + + auto tmp3 = assembler.P*(l0 + (dtau/2)*k2); + auto k3 = w0 + (m+0.5)*dtau*w1 + 0.5*(m+0.5)*(m+0.5)*dtau*dtau*w2 + (1/6)*(m+0.5)*(m+0.5)*(m+0.5)*dtau*dtau*dtau*w3 + erk_an.apply_B(tmp3); + + auto tmp4 = assembler.P*(l0 + dtau*k3); + auto k4 = w0 + (m+1)*dtau*w1 + 0.5*(m+1)*(m+1)*dtau*dtau*w2 + (1/6)*(m+1)*(m+1)*(m+1)*dtau*dtau*dtau*w3 + erk_an.apply_B(tmp4); + + // ACCUMULATED SOLUTION + auto l1 = l0 + (dtau/6) * (k1 + 2*k2 + 2*k3 + k4); + l0 = l1; + + } + + tc.toc(); + std::cout << bold << yellow << " LTS-ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof_n = l0; + x_dof = x_dof_n; + t = tn + dt; + + if(it == nt) { + std::cout << std::endl; + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ofstream mesh_file("mesh_file.txt"); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/LTS/HeterogeneousERK4_LTS_HHO_FirstOrder.hpp b/apps/wave_propagation/src/prototypes/LTS/HeterogeneousERK4_LTS_HHO_FirstOrder.hpp new file mode 100644 index 00000000..5429e7ac --- /dev/null +++ b/apps/wave_propagation/src/prototypes/LTS/HeterogeneousERK4_LTS_HHO_FirstOrder.hpp @@ -0,0 +1,565 @@ + + +// Created by Romain Mottier +// ../wave_propagation -k 2 -s 0 -r 0 -c 0 -p 0 -l 6 -n 2500 -f 1 -e 0 + +void HeterogeneousERK4_LTS_HHO_FirstOrder(int argc, char **argv); + +void HeterogeneousERK4_LTS_HHO_FirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " EXPLICIT PULSE - COUPLING" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l2_0.4.txt"); // l = 0 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l3_0.21.txt"); // l = 1 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l4_0.096.txt"); // l = 2 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l5_0.0485.txt"); // l = 3 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l6_0.024.txt"); // l = 4 + + // mesh_files.push_back("../../meshes/pulse/poly/poly_l2.txt"); // -l 0 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l3.txt"); // -l 1 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l4.txt"); // -l 2 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l5.txt"); // -l 3 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l6.txt"); // -l 4 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l7.txt"); // -l 5 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 1; + RealType ly = 1; + size_t nx = 2; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-0.5, -0.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 0.25; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + auto water_mat_fun_adi = [](const typename disk::mesh>::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp; + rho = 1.0; + vp = 1.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun_adi = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2.624390244; + vp = 4.0; + vs = 2.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + // acoustic_material_data material = water_mat_fun_adi(bar); + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + // elastic_material_data material = granit_mat_fun_adi(bar); + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + if (bar.y() > 0) { + acoustic_internal_faces.insert(fc_id); + } + else { + elastic_internal_faces.insert(fc_id); + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + auto v_fun_adi_acoustic = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x, y, xc, yc, r, wave, vx, vy, c, lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.125; // 0.1; + fc = 10.0; + c = 10; + vp = std::sqrt(1.0); + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + auto p_fun_ricker = [](const disk::mesh>::point_type& pt) -> double { + double x, y, xc, yc, r, fc, c, vp, lp, p0, pi2; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.15; + fc = 10.0; + c = 10.0; + vp = std::sqrt(1.0); + lp = vp / fc; // longueur caractéristique + p0 = 1.0; + pi2 = M_PI * M_PI; + + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + + double arg = pi2 * r*r / (lp*lp); + + double p = p0 * (1.0 - 2.0 * arg) * std::exp(-arg); + return p; + }; + + + Matrix x_dof; + // Acoustic pulse intialized in pressure + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, p_fun_ricker, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, p_fun_ricker); + // // Acoustic pulse intialized in velocity + // assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, v_fun_adi_acoustic); + // assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + // Elastic pulse intialized in velocity + // assembler.project_over_cells(msh, x_dof, v_fun, null_flux_fun, null_s_fun, null_fun); + // assembler.project_over_faces(msh, x_dof, v_fun, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + assembler.assemble_P(msh, 1); + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "Explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log.flush(); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "A_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(-0.15, 0.1); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + + std::ostringstream filename_int; + filename_int << "I_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_1_log(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-0.15, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "E_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(-0.15, -0.1); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + + bool sensors = false; + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + size_t p = 1; + size_t dtau = dt / p; + auto l0 = x_dof; + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + x_dof_n = x_dof; + size_t n_dof = x_dof.rows(); + + ////////////////////////////////////////////////////////////// COARSE PREDICTOR + std::vector> w, k; + erk_an.compute_wi(x_dof_n, s, assembler.IminusP, w, k); + + for (int m = 0; m < p; ++m) { + + auto w_stage_1 = w[0] + (m*dtau)*w[1] + (0.5*m*m*dtau*dtau)*w[2] + (m*m*m*dtau*dtau*dtau)*w[3]/6.0; + auto w_stage_2_3 = w[0] + ((m+0.5)*dtau)*w[1] + (0.5*(m+0.5)*(m+0.5)*dtau*dtau)*w[2] + ((m+0.5)*(m+0.5)*(m+0.5)*dtau*dtau*dtau)*w[3]/6.0; + auto w_stage_4 = w[0] + ((m+1.0)*dtau)*w[1] + (0.5*(m+1.0)*(m+1.0)*dtau*dtau)*w[2] + ((m+1.0)*(m+1.0)*(m+1.0)*dtau*dtau*dtau)*w[3]/6.0; + + auto y_stage_1 = assembler.P*x_dof; + erk_an.erk_lts_weight(y_stage_1, k[0], w_stage_1); + + auto y_stage_2 = assembler.P*(x_dof + dtau/2.0 * k[0]); + erk_an.erk_lts_weight(y_stage_2, k[1], w_stage_2_3); + + auto y_stage_3 = assembler.P*(x_dof + dtau/2.0 * k[1]); + erk_an.erk_lts_weight(y_stage_3, k[2], w_stage_2_3); + + auto y_stage_4 = assembler.P*(x_dof + dtau * k[2]); + erk_an.erk_lts_weight(y_stage_4, k[3], w_stage_4); + + x_dof_n = x_dof + dtau/6 * (k[0] + 2*k[1] + 2*k[2] + k[3]); + + } + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + if (it == nt) { + std::ostringstream silo; + silo << "Silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_str = silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_str, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/LTS/save.hpp b/apps/wave_propagation/src/prototypes/LTS/save.hpp new file mode 100644 index 00000000..e1670924 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/LTS/save.hpp @@ -0,0 +1,343 @@ + + +// Created by Romain Mottier + +// ../../elastoacoustic -k 1 -s 0 -r 0 -c 1 -p 1 -l 8 -n 1000 -f 0 -e 0 +void ELTSAcousticFirstOrder(int argc, char **argv); + +void ELTSAcousticFirstOrder(int argc, char **argv){ + + // ############################################################################################# + // ############################## Simulation paramaters ######################################## + // ############################################################################################# + + std::cout << std::endl << bold << red << " EXPLICIT ACOUSTIC CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ############################################################################################# + // ############################## Mesh generation ############################################## + // ############################################################################################# + + cpu.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + bool use_poly_mesh = false; + bool use_simp_mesh = false; + if (use_poly_mesh) { + for (int i = 0; i <= 9; ++i) { + mesh_files.push_back( + "../../meshes/conv_test/poly/poly_" + std::to_string(32 * (1 << i)) + ".txt" + ); + } + } + else if (use_simp_mesh) { + std::vector conv_vals = {1.0, 0.35, 0.15, 0.07, 0.035, 0.026, 0.017, 0.0125, 0.0085, 0.005}; + for (int i = 0; i < conv_vals.size(); ++i) { + mesh_files.push_back( + "../../meshes/conv_test/simplices/unstructured/l" + std::to_string(i) + + "_conv_test_" + std::to_string(conv_vals[i]) + ".txt" + ); + } + } + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + + // ############################################################################################# + // ################################ Time controls ############################################## + // ############################################################################################# + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ############################################################################################# + // ############################## Manufactured solution ######################################## + // ############################################################################################# + + scal_vec_analytic_functions functions; + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionCubicInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuarticInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpaceAcoustic); + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ############################################################################################# + // ################################## HHO setting ############################################## + // ############################################################################################# + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ############################################################################################# + // ################################ Material data ############################################## + // ############################################################################################# + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ############################################################################################# + // ############################## Boundary conditions ########################################## + // ############################################################################################# + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ############################################################################################# + // ###################################### Assembly ############################################# + // ############################################################################################# + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ############################################################################################# + // ###################### Projecting initial data ############################################## + // ############################################################################################# + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + // ############################################################################################# + // ###################################### Solving ############################################## + // ############################################################################################# + + Matrix a; + Matrix b; + Matrix c; + + // ERK schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + assembler.assemble(msh, null_fun, s_f_fun, true); + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + std::cout << std::endl << std::endl; + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + // ################################################## + // ################################################## Time marching + // ################################################## + + // DISCRTIZATION INFOS + std::cout << bold << red << " TIME LOOP: " << std::endl; + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + std::cout << bold << cyan << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + + { + // Manufactured solution + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + + assembler.get_e_bc_conditions().updateDirichletFunction(null_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << yellow << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + if(it == nt){ + std::cout << std::endl; + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ofstream mesh_file("mesh_file.txt"); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/acoustic/AcousticIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustic/AcousticIHHOFirstOrder.hpp new file mode 100644 index 00000000..ee7faac6 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustic/AcousticIHHOFirstOrder.hpp @@ -0,0 +1,306 @@ + + +// Created by Romain Mottier + +void AcousticIHHOFirstOrder(int argc, char **argv); + +void AcousticIHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### Simulation paramaters + // ###################################################################### + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit; + + // ###################################################################### Mesh generation + // ###################################################################### + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + Mesh_generation(sim_data, msh); + + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ###################################################################### Assigning Material Data + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ###################################################################### Solving a primal HHO mixed problem + // ###################################################################### + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + + // Stabilization type + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### Projecting initial data + // ###################################################################### + + Matrix x_dof; + // Acoustic pulse intialized in pressure + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, vel_fun, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, vel_fun); + + ////////// Post process of the initial data + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + std::ofstream simulation_log("elasto_acoustic_inhomogeneous_four_fields.txt"); + std::ofstream energy_file("energy_file.txt"); + std::ofstream dissipation_file("dissipation_file.txt"); + + std::ofstream Acoustic_sensor_1_log("Acoustic_s1_four_fields_h.csv"); + std::ofstream Acoustic_sensor_2_log("Acoustic_s2_four_fields_h.csv"); + std::ofstream Acoustic_sensor_3_log("Acoustic_s3_four_fields_h.csv"); + std::ofstream Acoustic_sensor_4_log("Acoustic_s4_four_fields_h.csv"); + bool e_side_Q = true; + bool a_side_Q = false; + typename mesh_type::point_type Acoustic_s1_pt(-0.10, 0.25); + typename mesh_type::point_type Acoustic_s2_pt(-0.10, 0.00); + typename mesh_type::point_type Acoustic_s3_pt(-0.10,-0.25); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + std::pair Acoustic_s2_pt_cell = std::make_pair(Acoustic_s2_pt, -1); + std::pair Acoustic_s3_pt_cell = std::make_pair(Acoustic_s3_pt, -1); + std::cout << bold << cyan << " " << "Acoustic sensor at (-0.1,0.25)" << reset << std::endl; + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + std::cout << bold << cyan << " " << "Acoustic sensor at (-0.1,0.0)" << reset << std::endl; + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + std::cout << bold << cyan << " " << "Acoustic sensor at (-0.1,0.25)" << reset << std::endl; + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s3_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + postprocessor::compute_elasto_acoustic_dissipation_four_field(assembler, t, x_dof, dissipation_file); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << std::endl << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + // dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Time marching + // ################################################## + + std::cout << std::endl << std::endl; + + Matrix x_dof_n; + + for(size_t it = 1; it <= nt; it++) { + + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t + << reset; + + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + // std::cout << std::endl << bold << cyan << " DIRK step completed: " << tc << " seconds" + // << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Acoustic_sensor_1_log); + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Acoustic_sensor_2_log); + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Acoustic_sensor_3_log); + + t += dt; + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, + t, x_dof, energy_file); + postprocessor::compute_elasto_acoustic_dissipation_four_field(assembler, t, x_dof, dissipation_file); + } + + std::cout << std::endl; + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + + } + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of equations: " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_CFL.hpp b/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_CFL.hpp new file mode 100644 index 00000000..2e607b25 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_CFL.hpp @@ -0,0 +1,397 @@ + + +// Created by Romain Mottier + +void EAcoustic_CFL(int argc, char **argv); + +void EAcoustic_CFL(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " ACOUSTIC CFL" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc; + + // ################################################## + // ################################################## Time controls + // ################################################## + + RealType ti = 0.0; + RealType tf = 1.0; + RealType t = ti; + int nt_base = sim_data.m_nt_divs; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Zero source terms, to keep the system energy constant + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Acoustic analytical functions + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Material data + // ################################################## + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Interface detection and faces repartitions + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + RealType eps = 1.0e-10; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + } + + + // Internal faces structure for explicit schemes + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + acoustic_internal_faces.insert(fc_id); + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + // boundary condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ######################s########################### + + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ################################################## + // ################################################## Setting of the time marching scheme + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + bool explicit_scheme = true; + assembler.assemble(msh, null_fun, null_s_fun, explicit_scheme); + size_t elastic_cell_dofs = 0.0; + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = 0.0; + size_t a_face_dofs = assembler.get_a_face_dof(); + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Loop over the ERK schemes + // ################################################## + + for (int s = 2; s < 5; s++) { + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + // nt *= 2; + nt = sim_data.m_nt_divs; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "A_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + // auto block_dimension = assembler.Scc_block_dimension(); + // erk_an.compute_eigenvalues_bis(assembler.LHS_STAB, block_dimension, simulation_log); + // erk_an.compute_eigenvalues(simulation_log); + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + std::cout << bold << red << " ERK(" << s << "):" << reset << std::endl << std::endl; + simulation_log << std::endl << " ERK(" << s << "):" << std::endl; + simulation_log << std::endl; + + // ################################################## + // ################################################## Loop over level of time refinement + // ################################################## + + for (unsigned int i = 0; i < 100; i++) { + + t = ti; + RealType dt = (tf-ti)/nt; + simulation_log << "Step size = " << dt << std::endl; + + // Projecting initial data + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + bool approx_fail_check_Q = false; + RealType energy = energy_0; + + for(size_t it = 1; it <= nt; it++) { + + RealType tn = dt*(it-1)+ti; + + // ERK steps + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + RealType t = tn + c(i,0) * dt; + assembler.assemble_rhs(msh, null_fun, null_s_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + x_dof = x_dof_n; + t = tn + dt; + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + bool unstable_check_Q = (relative_energy > 500e-2) || (relative_energy_0 >= 50e-2); + // bool unstable_check_Q = (relative_energy_0 >= 7.5e-2); + if (unstable_check_Q) { // energy is increasing + approx_fail_check_Q = true; + break; + } + energy = energy_n; + } + + if (approx_fail_check_Q) { + std::cout << bold << red << " Simulation is unstable" << reset << std::endl << std::endl << std::endl; + simulation_log << std::endl; + simulation_log << " Simulation is unstable for:"<< std::endl; + simulation_log << " Number of equations: " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << h << std::endl; + simulation_log << " CFL c(dt/h) = " << dt/h << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + break; + } + else { + simulation_log << " Simulation is stable for:"<< std::endl; + simulation_log << " Number of equations: " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << h << std::endl; + simulation_log << " CFL c(dt/h) = " << dt/h << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + std::cout << " Simulation is stable for: n = " << nt << std::endl; + nt = int(nt - (nt*1/100+1)); + continue; + // break; + } + } + simulation_log << std::endl << " ******************************* " << std::endl; + simulation_log << std::endl << std::endl; + } +} + + diff --git a/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_conv_test.hpp b/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_conv_test.hpp new file mode 100644 index 00000000..925b08f7 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_conv_test.hpp @@ -0,0 +1,392 @@ + + +// Created by Romain Mottier + +// ../../elastoacoustic -k 1 -s 0 -r 0 -c 1 -p 1 -l 8 -n 1000 -f 0 -e 0 +void EAcousticFirstOrder(int argc, char **argv); + +void EAcousticFirstOrder(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " EXPLICIT ACOUSTIC CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + cpu.tic(); + tc.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + { // Simplicial meshes + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // l = 1 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // l = 3 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // l = 5 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // l = 7 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // l = 9 + } + { // Polyhedral meshes + mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); // -l 0 + mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); // -l 2 + mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); // -l 4 + mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); // -l 6 + mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); // -l 8 + mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + } + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionCubicInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuarticInTimeAcoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpaceAcoustic); + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + // for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + // const auto face = *face_it; + // mesh_type::point_type bar = barycenter(msh, face); + // auto fc_id = msh.lookup(face); + // bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + // if (is_member_Q) { + // if (bar.y() > 0) + // acoustic_internal_faces.insert(fc_id); + // else + // elastic_internal_faces.insert(fc_id); + // } + // } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + + // DISCRTIZATION INFOS + std::cout << bold << red << " DISCRETIZATION: "; + std::cout << cyan << "Cell degree = " << hho_di.cell_degree() << std::endl; + std::cout << bold << cyan << " Face degree = " << hho_di.face_degree() << reset << std::endl << std::endl << std::endl; + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK schemes + int s = 3; + erk_butcher_tableau::erk_tables(s, a, b, c); + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, s_f_fun, true); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + std::cout << std::endl << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < i; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + + { + // Manufactured solution + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + + assembler.get_e_bc_conditions().updateDirichletFunction(null_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + if(it == nt){ + std::cout << std::endl; + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + + std::cout << std::endl; + + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ofstream mesh_file("mesh_file.txt"); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_stability.hpp b/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_stability.hpp new file mode 100644 index 00000000..752b4d1a --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustic/EAcoustic_stability.hpp @@ -0,0 +1,379 @@ + +// Created by Romain Mottier + +void EAcoustic_stability(int argc, char **argv); + +void EAcoustic_stability(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " ACOUSTIC STABILITY" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + cpu.tic(); + tc.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + // nt *= 2; + nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + // Acoustic analytical functions + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + // Internal faces structure (for explicit schemes) + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + } + + // boundary conditions + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + + size_t elastic_cell_dofs = 0.0; //assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = 0.0; //assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "A_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + // auto block_dimension = assembler.Scc_block_dimension(); + // erk_an.compute_eigenvalues_bis(assembler.LHS_STAB, block_dimension, simulation_log); + erk_an.compute_eigenvalues(simulation_log); + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + bool approx_fail_check_Q = false; + RealType energy = energy_0; + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << red << " Time step number " << it << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + t = tn + c(i,0) * dt; + { + assembler.assemble_rhs(msh, null_fun, null_s_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset; + x_dof = x_dof_n; + + t = tn + dt; + + // Energy evaluation + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + bool unstable_check_Q = (relative_energy > 1.0e-2) || (relative_energy_0 >= 1.0e-2); + if (unstable_check_Q) { + std::cout << std::endl << std::endl << bold << red << " Simulation is unstable" << reset << std::endl; + break; + } + energy = energy_n; + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << std::endl << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/acoustic/IAcoustic_conv_test.hpp b/apps/wave_propagation/src/prototypes/acoustic/IAcoustic_conv_test.hpp new file mode 100644 index 00000000..ecfc07e7 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustic/IAcoustic_conv_test.hpp @@ -0,0 +1,395 @@ + + +// Created by Romain Mottier + +// ../wave_propagation -s1 -k3 -r1 -c1 -p0 -l4 -n7 -i0 -f1 -e0 + +void IAcoustic_conv_test(int argc, char **argv); + +void IAcoustic_conv_test(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " IMPLICIT ACOUSTIC CONV TEST" << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + cpu.tic(); + tc.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + // nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpaceAcoustic); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::reproduction_acoustic); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionPlaneWaveAcoustic); + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + + // boundary conditions + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_v_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 2; + bool is_sdirk_Q = true; + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, s_f_fun, false); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) { + dirk_an.setIterativeSolver(); + } + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "A_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "A_energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << red << " Time step number " << it << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + + // Manufactured solution + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, null_fun, s_f_fun, false); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " DIRK step completed: " << tc << " seconds" << reset << std::endl << std::endl; + x_dof = x_dof_n; + t = tn + dt; + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, null_fun, null_flux_fun, s_v_fun, s_flux_fun, simulation_log); + std::cout << std::endl; + } + + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ostringstream mesh_file_name; + mesh_file_name << "mesh_quality_l" << sim_data.m_n_divs << ".txt"; + std::string mesh_file_str = mesh_file_name.str(); + std::ofstream mesh_file(mesh_file_str); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/CMakeLists.txt b/apps/wave_propagation/src/prototypes/acoustics_old/CMakeLists.txt new file mode 100644 index 00000000..5e99fa2c --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/CMakeLists.txt @@ -0,0 +1,17 @@ + +set(input_files ${input_files} + ${CMAKE_CURRENT_SOURCE_DIR}/input_files/elliptic_convergence_test.lua + ${CMAKE_CURRENT_SOURCE_DIR}/input_files/acoustics_test.lua + ${CMAKE_CURRENT_SOURCE_DIR}/input_files/acoustics_simulation.lua + ${CMAKE_CURRENT_SOURCE_DIR}/input_files/acoustics_simulation_2d_pulse.lua +) + +file(COPY ${input_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug/input_files/) +file(COPY ${input_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Release/input_files/) + +file(COPY ${input_poly_meshes} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/meshes/) +file(COPY ${input_poly_meshes} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug/meshes/) +file(COPY ${input_poly_meshes} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Release/meshes/) + +add_executable(acoustics acoustics.cpp ${fitted_waves_headers} ${fitted_waves_sources}) +target_link_libraries(acoustics ${LINK_LIBS}) diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/EHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/EHHOFirstOrder.hpp new file mode 100644 index 00000000..b3b45a92 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/EHHOFirstOrder.hpp @@ -0,0 +1,234 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef EHHOFirstOrder_hpp +#define EHHOFirstOrder_hpp + +void EHHOFirstOrder(char **argv){ + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + ///////////////////////////////////////////////////////////////////////// + ////////////////////////// Meshes /////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + if (sim_data.m_polygonal_mesh_Q) { + if (sim_data.m_n_divs > 8) { + sim_data.m_n_divs = 8; + } + } + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/unit_square_polymesh_nel_20.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_40.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_80.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_160.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_320.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_640.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_1280.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_2560.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_5120.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + else { + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////// + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + scal_analytic_functions functions; + switch (sim_data.m_exact_functions) { + case 1: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + break; + case 2: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + break; + default: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionNonPolynomial); + break; + } + + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + assembler.load_material_data(msh); + if (sim_data.m_hdg_stabilization_Q) { + assembler.set_hdg_stabilization(); + } + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "e_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("acoustic_two_fields_explicit.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + int s = 4; + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness and rhs assembly completed: " << tc << " seconds" << reset << std::endl; + size_t n_face_dof = assembler.get_n_face_dof(); + tc.tic(); + erk_hho_scheme erk_an(assembler.LHS,assembler.RHS,assembler.MASS,n_face_dof); + erk_an.Kcc_inverse(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + if(sim_data.m_hdg_stabilization_Q){ + erk_an.Sff_inverse(std::make_pair(assembler.get_n_faces(), assembler.get_face_basis_data())); + }else{ + if (sim_data.m_iterative_solver_Q) { + erk_an.setIterativeSolver(); + } + erk_an.DecomposeFaceTerm(); + } + tc.toc(); + std::cout << bold << cyan << "ERK analysis created: " << tc << " seconds" << reset << std::endl; + + erk_an.refresh_faces_unknowns(x_dof); + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + RealType tn = dt*(it-1)+ti; + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + RealType t = tn + c(i,0) * dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); + assembler.assemble_rhs(msh, rhs_fun); + assembler.apply_bc(msh); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "e_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_two_fields(msh, hho_di, assembler, x_dof, exact_vel_fun, exact_flux_fun,simulation_log); + } + } + + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/IHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/IHHOFirstOrder.hpp new file mode 100644 index 00000000..3c877770 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/IHHOFirstOrder.hpp @@ -0,0 +1,249 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef IHHOFirstOrder_hpp +#define IHHOFirstOrder_hpp + +void IHHOFirstOrder(char **argv){ + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + if (sim_data.m_polygonal_mesh_Q) { + if (sim_data.m_n_divs > 8) { + sim_data.m_n_divs = 8; + } + } + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/unit_square_polymesh_nel_20.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_40.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_80.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_160.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_320.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_640.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_1280.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_2560.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_5120.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + }else{ + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + scal_analytic_functions functions; + switch (sim_data.m_exact_functions) { + case 1: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + break; + case 2: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + break; + default: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionNonPolynomial); + break; + } + + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + // simple material + RealType rho = 1.0; + RealType vp = 1.0; + acoustic_material_data material(rho,vp); + assembler.load_material_data(msh,material); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("acoustic_two_fields.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + // SDIRK case + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); + + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + }else{ + // DIRK case + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + RealType t = tn + c(i,0) * dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); + assembler.assemble_rhs(msh, rhs_fun); + assembler.apply_bc(msh); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_two_fields(msh, hho_di, assembler, x_dof, exact_vel_fun, exact_flux_fun,simulation_log); + } + + } + + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/IHHOSecondOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/IHHOSecondOrder.hpp new file mode 100644 index 00000000..af7d49ef --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Acoustic_Conv_Test/IHHOSecondOrder.hpp @@ -0,0 +1,222 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef IHHOSecondOrder_hpp +#define IHHOSecondOrder_hpp + +void IHHOSecondOrder(char **argv){ + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + if (sim_data.m_polygonal_mesh_Q) { + if (sim_data.m_n_divs > 8) { + sim_data.m_n_divs = 8; + } + } + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/unit_square_polymesh_nel_20.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_40.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_80.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_160.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_320.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_640.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_1280.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_2560.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_5120.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + }else{ + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + scal_analytic_functions functions; + switch (sim_data.m_exact_functions) { + case 1: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + break; + case 2: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + break; + default: + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionNonPolynomial); + break; + } + + + RealType t = ti; + auto exact_scal_fun = functions.Evaluate_u(t); + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_accel_fun = functions.Evaluate_a(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_scal_fun); + tc.tic(); + auto assembler = acoustic_one_field_assembler(msh, hho_di, bnd); + + // simple material + RealType rho = 1.0; + RealType vp = 1.0; + acoustic_material_data material(rho,vp); + assembler.load_material_data(msh,material); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial scalar, velocity and acceleration + Matrix p_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, p_dof_n, exact_scal_fun); + assembler.project_over_cells(msh, v_dof_n, exact_vel_fun); + assembler.project_over_cells(msh, a_dof_n, exact_accel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, p_dof_n, exact_scal_fun, false); + } + + std::ofstream simulation_log("acoustic_one_field.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); + } + + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + linear_solver analysis; + if (sim_data.m_sc_Q) { + analysis.set_Kg(assembler.LHS, assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + }else{ + analysis.set_Kg(assembler.LHS); + } + + if (sim_data.m_iterative_solver_Q) { + analysis.set_iterative_solver(true); + }else{ + analysis.set_direct_solver(true); // symmetric matrix case + } + + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*it+ti; + auto exact_scal_fun = functions.Evaluate_u(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + tc.tic(); + assembler.get_bc_conditions().updateDirichletFunction(exact_scal_fun, 0); + assembler.assemble_rhs(msh, rhs_fun); + + // Compute intermediate state for scalar and rate + p_dof_n = p_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*p_dof_n; + + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update scalar and rate + p_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, p_dof_n, exact_scal_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); + } + + if(it == nt){ + postprocessor::compute_errors_one_field(msh, hho_di, assembler, p_dof_n, exact_scal_fun, exact_flux_fun, simulation_log); + } + + } + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Elliptic_Conv_Test/EllipticOneFieldConvergenceTest.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Elliptic_Conv_Test/EllipticOneFieldConvergenceTest.hpp new file mode 100644 index 00000000..a2989d86 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Elliptic_Conv_Test/EllipticOneFieldConvergenceTest.hpp @@ -0,0 +1,183 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef EllipticOneFieldConvergenceTest_hpp +#define EllipticOneFieldConvergenceTest_hpp + +void EllipticOneFieldConvergenceTest(char **argv){ + + simulation_data sim_data = preprocessor::process_convergence_test_lua_file(argv); + sim_data.print_simulation_data(); + + // Manufactured exact solution + bool quadratic_function_Q = sim_data.m_exact_functions == 1; + auto exact_scal_fun = [quadratic_function_Q](const mesh_type::point_type& pt) -> RealType { + if(quadratic_function_Q){ + return (1.0-pt.x())*pt.x() * (1.0-pt.y())*pt.y(); + }else{ + return std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + } + + }; + + auto exact_flux_fun = [quadratic_function_Q](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + if(quadratic_function_Q){ + flux[0] = (1 - x)*(1 - y)*y - x*(1 - y)*y; + flux[1] = (1 - x)*x*(1 - y) - (1 - x)*x*y; + return flux; + }else{ + flux[0] = M_PI*std::cos(M_PI*pt.x())*std::sin(M_PI*pt.y()); + flux[1] = M_PI*std::sin(M_PI*pt.x())*std::cos(M_PI*pt.y()); + return flux; + } + + }; + + auto rhs_fun = [quadratic_function_Q](const typename mesh_type::point_type& pt) -> RealType { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + return -2.0*((x - 1)*x + (y - 1)*y); + }else{ + return 2.0*M_PI*M_PI*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + } + }; + + if (sim_data.m_polygonal_mesh_Q) { + if (sim_data.m_n_divs > 8) { + sim_data.m_n_divs = 8; + } + } + + // simple material + RealType rho = 1.0; + RealType vp = 1.0; + acoustic_material_data material(rho,vp); + + std::ofstream error_file("steady_scalar_polygon_error.txt"); + + for(size_t k = 0; k <= sim_data.m_k_degree; k++){ + std::cout << bold << cyan << "Running an approximation with k : " << k << reset << std::endl; + error_file << "Approximation with k : " << k << std::endl; + for(size_t l = 0; l < sim_data.m_n_divs; l++){ + + // Reading the polygonal mesh + timecounter tc; + + tc.tic(); + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/unit_square_polymesh_nel_20.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_40.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_80.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_160.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_320.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_640.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_1280.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_2560.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_5120.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + }else{ + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(l); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,k); + + // Solving a scalar primal HHO problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_scal_fun); + tc.tic(); + auto assembler = acoustic_one_field_assembler(msh, hho_di, bnd); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + assembler.load_material_data(msh,material); + assembler.assemble(msh, rhs_fun); + assembler.apply_bc(msh); + tc.toc(); + std::cout << bold << cyan << "Assemble in : " << tc << " seconds" << reset << std::endl; + + // Solving LS + Matrix x_dof; + if (sim_data.m_sc_Q) { + tc.tic(); + linear_solver analysis(assembler.LHS,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + if(sim_data.m_iterative_solver_Q){ + analysis.set_iterative_solver(true); + } + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + error_file << "Number of equations (SC) : " << analysis.n_equations() << std::endl; + }else{ + tc.tic(); + linear_solver analysis(assembler.LHS); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + if(sim_data.m_iterative_solver_Q){ + analysis.set_iterative_solver(true); + } + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + error_file << "Number of equations : " << analysis.n_equations() << std::endl; + } + + // Computing errors + postprocessor::compute_errors_one_field(msh, hho_di, assembler, x_dof, exact_scal_fun, exact_flux_fun,error_file); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "steady_scalar_k" + std::to_string(k) + "_"; + postprocessor::write_silo_one_field(silo_file_name, l, msh, hho_di, x_dof, exact_scal_fun, false); + } + } + error_file << std::endl << std::endl; + } + error_file.close(); +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Elliptic_Conv_Test/EllipticTwoFieldsConvergenceTest.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Elliptic_Conv_Test/EllipticTwoFieldsConvergenceTest.hpp new file mode 100644 index 00000000..f1192b8a --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Elliptic_Conv_Test/EllipticTwoFieldsConvergenceTest.hpp @@ -0,0 +1,189 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef EllipticTwoFieldsConvergenceTest_hpp +#define EllipticTwoFieldsConvergenceTest_hpp + +void EllipticTwoFieldsConvergenceTest(char **argv){ + + simulation_data sim_data = preprocessor::process_convergence_test_lua_file(argv); + sim_data.print_simulation_data(); + + // Manufactured exact solution + bool quadratic_function_Q = sim_data.m_exact_functions == 1; + auto exact_scal_fun = [quadratic_function_Q](const mesh_type::point_type& pt) -> RealType { + if(quadratic_function_Q){ + return (1.0-pt.x())*pt.x() * (1.0-pt.y())*pt.y(); + }else{ + return std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + } + + }; + + auto exact_flux_fun = [quadratic_function_Q](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector flux(2); + if(quadratic_function_Q){ + flux[0] = (1 - x)*(1 - y)*y - x*(1 - y)*y; + flux[1] = (1 - x)*x*(1 - y) - (1 - x)*x*y; + return flux; + }else{ + flux[0] = M_PI*std::cos(M_PI*pt.x())*std::sin(M_PI*pt.y()); + flux[1] = M_PI*std::sin(M_PI*pt.x())*std::cos(M_PI*pt.y()); + return flux; + } + + }; + + auto rhs_fun = [quadratic_function_Q](const typename mesh_type::point_type& pt) -> RealType { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + return -2.0*((x - 1)*x + (y - 1)*y); + }else{ + return 2.0*M_PI*M_PI*std::sin(M_PI*pt.x())*std::sin(M_PI*pt.y()); + } + }; + + if (sim_data.m_polygonal_mesh_Q) { + if (sim_data.m_n_divs > 8) { + sim_data.m_n_divs = 8; + } + } + + // simple material + RealType rho = 1.0; + RealType vp = 1.0; + acoustic_material_data material(rho,vp); + + std::ofstream error_file("steady_scalar_mixed_polygon_error.txt"); + + for(size_t k = 0; k <= sim_data.m_k_degree; k++){ + std::cout << bold << cyan << "Running an approximation with k : " << k << reset << std::endl; + error_file << "Approximation with k : " << k << std::endl; + for(size_t l = 0; l < sim_data.m_n_divs; l++){ + + // Reading the polygonal mesh + timecounter tc; + tc.tic(); + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/unit_square_polymesh_nel_20.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_40.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_80.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_160.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_320.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_640.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_1280.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_2560.txt"); + mesh_files.push_back("meshes/unit_square_polymesh_nel_5120.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + }else{ + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(l); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,k); + + // Solving a scalar primal HHO problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_scal_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + assembler.load_material_data(msh,material); + assembler.assemble(msh, rhs_fun); + assembler.assemble_mass(msh, false); + assembler.apply_bc(msh); + tc.toc(); + std::cout << bold << cyan << "Assemble in : " << tc << " seconds" << reset << std::endl; + + // Solving LS + Matrix x_dof; + if (sim_data.m_sc_Q) { + tc.tic(); + SparseMatrix Kg = assembler.LHS+assembler.MASS; + linear_solver analysis(Kg,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + if(sim_data.m_iterative_solver_Q){ + analysis.set_iterative_solver(); + } + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + error_file << "Number of equations (SC) : " << analysis.n_equations() << std::endl; + }else{ + tc.tic(); + SparseMatrix Kg = assembler.LHS+assembler.MASS; + linear_solver analysis(Kg); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + if(sim_data.m_iterative_solver_Q){ + analysis.set_iterative_solver(); + } + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + error_file << "Number of equations : " << analysis.n_equations() << std::endl; + } + + // Computing errors + postprocessor::compute_errors_two_fields(msh, hho_di, assembler, x_dof, exact_scal_fun, exact_flux_fun, error_file); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "steady_scalar_mixed_k" + std::to_string(k) + "_"; + postprocessor::write_silo_two_fields(silo_file_name, l, msh, hho_di, x_dof, exact_scal_fun, exact_flux_fun, false); + } + } + error_file << std::endl << std::endl; + } + error_file.close(); +} + + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOFirstOrder.hpp new file mode 100644 index 00000000..cf500567 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOFirstOrder.hpp @@ -0,0 +1,254 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousGar6more2DIHHOFirstOrder_hpp +#define HeterogeneousGar6more2DIHHOFirstOrder_hpp + +void HeterogeneousGar6more2DIHHOFirstOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 3.0; + RealType ly = 3.0; + size_t nx = 3; + size_t ny = 3; + + + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.5, -1.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y; + x = pt.x(); + y = pt.y(); + return 0.0; + }; + + auto flux_fun = [](const mesh_type::point_type& pt) -> std::vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 2.0/3.0; + c = 10.0; + lp = std::sqrt(9.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = -wave*(x-xc); + vy = -wave*(y-yc); + std::vector v = {vx,vy}; + return v; + }; + + RealType t = ti; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + rho = 1.0; + if (y < 0.0) { + vp = 1.0*std::sqrt(3.0); + }else{ + vp = 1.0*std::sqrt(9.0); + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + std::string silo_file_props_name = "properties_map"; + postprocessor::write_silo_acoustic_property_map(silo_file_props_name, msh, assembler.get_material_data()); + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, null_fun, flux_fun, false); + } + + std::ofstream simulation_log("inhomogeneous_acoustic_two_fields.txt"); + + std::ofstream sensor_1_log("s1_acoustic_two_fields_h.csv"); + std::ofstream sensor_2_log("s2_acoustic_two_fields_h.csv"); + std::ofstream sensor_3_log("s3_acoustic_two_fields_h.csv"); + typename mesh_type::point_type s1_pt(-1.0/3.0, +1.0/3.0); + typename mesh_type::point_type s2_pt( 0.0, +1.0/3.0); + typename mesh_type::point_type s3_pt(+1.0/3.0, +1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + // postprocessor::record_velocity_data_acoustic_two_fields(0, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + // postprocessor::record_velocity_data_acoustic_two_fields(0, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + // postprocessor::record_velocity_data_acoustic_two_fields(0, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + // SDIRK case + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); + + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + }else{ + // DIRK case + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + assembler.RHS.setZero(); // Optimization: this is a problem with (f = 0) + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, null_fun, flux_fun, false); + } + + // postprocessor::record_velocity_data_acoustic_two_fields(it, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + // postprocessor::record_velocity_data_acoustic_two_fields(it, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + // postprocessor::record_velocity_data_acoustic_two_fields(it, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOSecondOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOSecondOrder.hpp new file mode 100644 index 00000000..90c10b72 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOSecondOrder.hpp @@ -0,0 +1,242 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousGar6more2DIHHOSecondOrder_hpp +#define HeterogeneousGar6more2DIHHOSecondOrder_hpp + +void HeterogeneousGar6more2DIHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 3.0; + RealType ly = 3.0; + size_t nx = 3; + size_t ny = 3; + + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.5, -1.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = tf/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y; + x = pt.x(); + y = pt.y(); + return 0.0; + }; + + auto p_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y,xc,yc,r,wave,vx,vy,v,c,lp,factor; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 2.0/3.0; + c = 10.0; + lp = 1.0*std::sqrt(9.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + factor = (lp*lp/(2.0*M_PI*M_PI)); + return factor*wave; + }; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); // easy because boundary assumes zero every where any time. + tc.tic(); + auto assembler = acoustic_one_field_assembler(msh, hho_di, bnd); + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + rho = 1.0; + if (y < 0.0) { + vp = 1.0*std::sqrt(3.0); + }else{ + vp = 1.0*std::sqrt(9.0); + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial scalar, velocity and acceleration + Matrix p_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, p_dof_n, p_fun); + assembler.project_over_faces(msh, p_dof_n, p_fun); + assembler.project_over_cells(msh, v_dof_n, null_fun); + assembler.project_over_faces(msh, v_dof_n, null_fun); + assembler.project_over_cells(msh, a_dof_n, null_fun); + assembler.project_over_faces(msh, a_dof_n, null_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, p_dof_n, p_fun, false); + } + + std::ofstream simulation_log("inhomogeneous_acoustic_one_field.txt"); + + std::ofstream sensor_1_log("s1_acoustic_one_field_h.csv"); + std::ofstream sensor_2_log("s2_acoustic_one_field_h.csv"); + std::ofstream sensor_3_log("s3_acoustic_one_field_h.csv"); + typename mesh_type::point_type s1_pt(-1.0/3.0, -1.0/3.0); + typename mesh_type::point_type s2_pt( 0.0, -1.0/3.0); + typename mesh_type::point_type s3_pt(+1.0/3.0, -1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_velocity_data_acoustic_one_field(0, s1_pt_cell, msh, hho_di, assembler, p_dof_n, sensor_1_log); + postprocessor::record_velocity_data_acoustic_one_field(0, s2_pt_cell, msh, hho_di, assembler, p_dof_n, sensor_2_log); + postprocessor::record_velocity_data_acoustic_one_field(0, s3_pt_cell, msh, hho_di, assembler, p_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, ti, p_dof_n, v_dof_n, simulation_log); + } + + timecounter simulation_tc; + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.0; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + linear_solver analysis; + if (sim_data.m_sc_Q) { + tc.tic(); + analysis.set_Kg(assembler.LHS,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + +// analysis.set_iterative_solver(true, 1.0e-10); + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + }else{ + tc.tic(); + analysis.set_Kg(assembler.LHS); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + } + + simulation_tc.tic(); + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*it+ti; + + tc.tic(); + // Compute intermediate state for scalar and rate + p_dof_n = p_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*p_dof_n; + + assembler.RHS.setZero(); + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update scalar and rate + p_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, p_dof_n, p_fun, false); + } + + postprocessor::record_velocity_data_acoustic_one_field(it, s1_pt_cell, msh, hho_di, assembler, p_dof_n, sensor_1_log); + postprocessor::record_velocity_data_acoustic_one_field(it, s2_pt_cell, msh, hho_di, assembler, p_dof_n, sensor_2_log); + postprocessor::record_velocity_data_acoustic_one_field(it, s3_pt_cell, msh, hho_di, assembler, p_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); + } + + } + simulation_tc.toc(); + simulation_log << "Simulation time : " << simulation_tc << " seconds" << std::endl; + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousEHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousEHHOFirstOrder.hpp new file mode 100644 index 00000000..0fd14297 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousEHHOFirstOrder.hpp @@ -0,0 +1,210 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousEHHOFirstOrder_hpp +#define HeterogeneousEHHOFirstOrder_hpp + +void HeterogeneousEHHOFirstOrder(char **argv){ + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 0.2; + size_t nx = 10; + size_t ny = 1; + + + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh_x_direction(sim_data.m_n_divs); + mesh_builder.set_translation_data(0.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 0.5 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = (tf-ti)/nt; + + scal_analytic_functions functions; + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionInhomogeneousInSpace); + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + if (x < 0.5) { + vp = 3.0; + }else{ + vp = 1.0; + } + rho = 1.0/(vp*vp); // this is required to make both formulations compatible by keeping kappa = 1 + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "e_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("acoustic_two_fields_explicit.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + int s = 4; + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness and rhs assembly completed: " << tc << " seconds" << reset << std::endl; + size_t n_face_dof = assembler.get_n_face_dof(); + tc.tic(); + erk_hho_scheme erk_an(assembler.LHS,assembler.RHS,assembler.MASS,n_face_dof); + erk_an.Kcc_inverse(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + if(sim_data.m_hdg_stabilization_Q){ + erk_an.Sff_inverse(std::make_pair(assembler.get_n_faces(), assembler.get_face_basis_data())); + }else{ + if (sim_data.m_iterative_solver_Q) { + erk_an.setIterativeSolver(); + } + erk_an.DecomposeFaceTerm(); + } + tc.toc(); + std::cout << bold << cyan << "ERK analysis created: " << tc << " seconds" << reset << std::endl; + + erk_an.refresh_faces_unknowns(x_dof); + Matrix x_dof_n; + timecounter simulation_tc; + simulation_tc.tic(); + + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + RealType tn = dt*(it-1)+ti; + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + RealType t = tn + c(i,0) * dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); + assembler.RHS.setZero(); + assembler.apply_bc(msh); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "e_inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + } + + + + + + simulation_tc.toc(); + simulation_log << "Simulation time : " << simulation_tc << " seconds" << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousIHHOFirstOrder.hpp new file mode 100644 index 00000000..f3b8f851 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousIHHOFirstOrder.hpp @@ -0,0 +1,232 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousIHHOFirstOrder_hpp +#define HeterogeneousIHHOFirstOrder_hpp + + +void HeterogeneousIHHOFirstOrder(char **argv){ + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 0.2; + size_t nx = 10; + size_t ny = 1; + + + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh_x_direction(sim_data.m_n_divs); + mesh_builder.set_translation_data(0.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 0.5 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = (tf-ti)/nt; + + scal_analytic_functions functions; + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionInhomogeneousInSpace); + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + if (x < 0.5) { + vp = 3.0; + }else{ + vp = 1.0; + } + rho = 1.0/(vp*vp); // this is required to make both formulations compatible by keeping kappa = 1 + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + std::string silo_file_props_name = "properties_map"; + postprocessor::write_silo_acoustic_property_map(silo_file_props_name, msh, assembler.get_material_data()); + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("acoustic_two_fields.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + // SDIRK case + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); + + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + }else{ + // DIRK case + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + RealType t = tn + c(i,0) * dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); + assembler.RHS.setZero(); // Optimization: this is a problem with (f = 0) + assembler.apply_bc(msh); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_two_fields(msh, hho_di, assembler, x_dof, exact_vel_fun, exact_flux_fun,simulation_log); + } + + } + + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousIHHOSecondOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousIHHOSecondOrder.hpp new file mode 100644 index 00000000..b8b85030 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous/HeterogeneousIHHOSecondOrder.hpp @@ -0,0 +1,228 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousIHHOSecondOrder_hpp +#define HeterogeneousIHHOSecondOrder_hpp + +void HeterogeneousIHHOSecondOrder(char **argv){ + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + /////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////// Building a cartesian mesh ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////// + + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 0.2; + size_t nx = 10; + size_t ny = 1; + + mesh_type msh; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh_x_direction(sim_data.m_n_divs); + mesh_builder.set_translation_data(0.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////////////// + /////////////////// Time controls : Final time value 0.5 ////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////// + + size_t nt = 10; // Number of temp iterations + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = (tf-ti)/nt; + + + scal_analytic_functions functions; + functions.set_function_type(scal_analytic_functions::EFunctionType::EFunctionInhomogeneousInSpace); + RealType t = ti; + auto exact_scal_fun = functions.Evaluate_u(t); + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_accel_fun = functions.Evaluate_a(t); + auto exact_flux_fun = functions.Evaluate_q(t); + auto rhs_fun = functions.Evaluate_f(t); + + /////////////////////////////////////////////////////////////////////////////////////// + /////// Creating HHO approximation spaces and corresponding linear operator ////// + /////////////////////////////////////////////////////////////////////////////////////// + + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + /////////////////////////////////////////////////////////////////////////////////////// + /////////////////////// Solving a primal HHO mixed problem //////////////////////// + /////////////////////////////////////////////////////////////////////////////////////// + + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_scal_fun); // easy because boundary assumes zero every where any time. + tc.tic(); + auto assembler = acoustic_one_field_assembler(msh, hho_di, bnd); + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + if (x < 0.5) { + vp = 10.0; + }else{ + vp = 1.0; + } + rho = 1.0/(vp*vp); // this is required to make both formulations compatible by keeping kappa = 1 + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////////////// + ///////////// Projecting initial scalar, velocity and acceleration //////////////// + /////////////////////////////////////////////////////////////////////////////////////// + + Matrix p_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, p_dof_n, exact_scal_fun); + assembler.project_over_faces(msh, p_dof_n, exact_scal_fun); + assembler.project_over_cells(msh, v_dof_n, exact_vel_fun); + assembler.project_over_faces(msh, v_dof_n, exact_vel_fun); + assembler.project_over_cells(msh, a_dof_n, exact_accel_fun); + assembler.project_over_faces(msh, a_dof_n, exact_accel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, v_dof_n, exact_vel_fun, false); + } + + std::ofstream simulation_log("acoustic_one_field.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); + } + + linear_solver analysis; + bool standar_Q = true; + + /////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////// Newmark process ///////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////// + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 0.6; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + linear_solver analysis; + if (sim_data.m_sc_Q) { + analysis.set_Kg(assembler.LHS, assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + }else{ + analysis.set_Kg(assembler.LHS); + } + + if (sim_data.m_iterative_solver_Q) { + analysis.set_iterative_solver(true); + }else{ + analysis.set_direct_solver(true); // symmetric matrix case + } + + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////// Temporal Loop /////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////// + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*it+ti; + auto exact_scal_fun = functions.Evaluate_u(t); + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_q(t); + + assembler.get_bc_conditions().updateDirichletFunction(exact_scal_fun, 0); + assembler.RHS.setZero(); // Optimization: this is a problem with (f = 0) + assembler.apply_bc(msh); + + // Compute intermediate state for scalar and rate + p_dof_n = p_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*p_dof_n; + + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update scalar and rate + p_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, v_dof_n, exact_vel_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); + } + + if(it == nt){ + postprocessor::compute_errors_one_field(msh, hho_di, assembler, p_dof_n, exact_scal_fun, exact_flux_fun, simulation_log); + } + + } + + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseEHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseEHHOFirstOrder.hpp new file mode 100644 index 00000000..08c7e30e --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseEHHOFirstOrder.hpp @@ -0,0 +1,270 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousPulseEHHOFirstOrder_hpp +#define HeterogeneousPulseEHHOFirstOrder_hpp + +void HeterogeneousPulseEHHOFirstOrder(char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + + auto validate_l = [](size_t l) -> size_t { + if ((0 < l) && (l < 5) ) { + return l; + }else{ + std::cout << "Warning:: Only five meshes available. Running level 4." << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_4096.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_5120.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_10240.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_16384.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_65536.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + } + + else { + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 0.25 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.25; + RealType dt = tf/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y; + x = pt.x(); + y = pt.y(); + return 0.0; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + return {0,0}; + }; + + auto vel_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y,xc,yc,r,wave; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 0.25; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = 0.1*(-4*std::sqrt(10.0/3.0)*(-1 + 1600.0*r*r))/(std::exp(800*r*r)*std::pow(M_PI,0.25)); + return wave; + }; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + rho = 1.0; + if (y < 0.5) { + vp = 5.0; + }else{ + vp = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + assembler.load_material_data(msh,acoustic_mat_fun); + + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, vel_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, vel_fun); + + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "e_inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, vel_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("inhomogeneous_acoustic_two_fields_explicit.txt"); + + std::ofstream sensor_top_log("top_sensor_e_acoustic_two_fields.csv"); + std::ofstream sensor_bot_log("bot_sensor_e_acoustic_two_fields.csv"); + typename mesh_type::point_type top_pt(0.5, 2.0/3.0); + typename mesh_type::point_type bot_pt(0.5, 1.0/3.0); + std::pair top_pt_cell = std::make_pair(top_pt, -1); + std::pair bot_pt_cell = std::make_pair(bot_pt, -1); + + postprocessor::record_data_acoustic_two_fields(0, top_pt_cell, msh, hho_di, x_dof, sensor_top_log); + postprocessor::record_data_acoustic_two_fields(0, bot_pt_cell, msh, hho_di, x_dof, sensor_bot_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + int s = 4; + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness and rhs assembly completed: " << tc << " seconds" << reset << std::endl; + size_t n_face_dof = assembler.get_n_face_dof(); + tc.tic(); + erk_hho_scheme erk_an(assembler.LHS,assembler.RHS,assembler.MASS,n_face_dof); + erk_an.Kcc_inverse(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + if(sim_data.m_hdg_stabilization_Q){ + erk_an.Sff_inverse(std::make_pair(assembler.get_n_faces(), assembler.get_face_basis_data())); + } + else { + if (sim_data.m_iterative_solver_Q) { + erk_an.setIterativeSolver(); + } + erk_an.DecomposeFaceTerm(); + } + tc.toc(); + std::cout << bold << cyan << "ERK analysis created: " << tc << " seconds" << reset << std::endl; + + erk_an.refresh_faces_unknowns(x_dof); + Matrix x_dof_n; + timecounter simulation_tc; + simulation_tc.tic(); + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + RealType tn = dt*(it-1)+ti; + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { +// RealType t = tn + c(i,0) * dt; +// auto exact_vel_fun = functions.Evaluate_v(t); +// auto rhs_fun = functions.Evaluate_f(t); +// assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); +// assembler.assemble_rhs(msh, rhs_fun); +// assembler.apply_bc(msh); +// erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "e_inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, vel_fun, null_flux_fun, false); + } + + postprocessor::record_data_acoustic_two_fields(it, top_pt_cell, msh, hho_di, x_dof, sensor_top_log); + postprocessor::record_data_acoustic_two_fields(it, bot_pt_cell, msh, hho_di, x_dof, sensor_bot_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + } + simulation_tc.toc(); + simulation_log << "Simulation time : " << simulation_tc << " seconds" << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder.hpp new file mode 100644 index 00000000..8b2ef31a --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder.hpp @@ -0,0 +1,337 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousPulseIHHOFirstOrder_hpp +#define HeterogeneousPulseIHHOFirstOrder_hpp + +void HeterogeneousPulseIHHOFirstOrder(char **argv){ + + /////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// Préprocessing ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + using RealType = double; + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// Meshes ////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + + auto validate_l = [](size_t l) -> size_t { + if ((0 < l) && (l < 5) ) { + return l; + }else{ + std::cout << "Warning:: Only five meshes available. Running level 4." << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_4096.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_5120.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_10240.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_16384.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_65536.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + // A commenter pour la lecture des différents maillages polyhédriques réguliers + /* polygon_2d_mesh_reader mesh_builder; + std::string mesh_file = "meshes/mexican_hat_polymesh_adapted_nel_8512.txt"; + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_file); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh);*/ + + } + + else { + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// Time controls /////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + // Time controls : Final time value 0.50 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = tf/nt; + + /////////////////////////////////////////////////////////////////////////////// + ////////////////////////// Source term ? ////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + auto null_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y; + x = pt.x(); + y = pt.y(); + return 0.0; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + return {0,0}; + }; + + auto vel_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y,xc,yc,r,wave; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 0.5; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = 0.1*(-4*std::sqrt(10.0/3.0)*(-1 + 1600.0*r*r))/(std::exp(800*r*r)*std::pow(M_PI,0.25)); + return wave; + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Creating HHO approximation spaces and corresponding linear operator /// + /////////////////////////////////////////////////////////////////////////////// + + + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + /////////////////////////////////////////////////////////////////////////////// + //////////////////// Solving a primal HHO mixed problem /////////////////// + /////////////////////////////////////////////////////////////////////////////// + + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////// Acoustic properties ///////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + rho = 1.0; + if (y < 0.5) { + vp = 1.0; + }else{ + vp = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////// Projecting initial data ///////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, vel_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, vel_fun); + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Postprocessing ///////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, vel_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("inhomogeneous_acoustic_two_fields.txt"); + + std::ofstream sensor_log1("sensor1.csv"); + std::ofstream sensor_log2("sensor2.csv"); + std::ofstream sensor_log3("sensor3.csv"); + typename mesh_type::point_type pt1(1.0/3, 2.0/3); + typename mesh_type::point_type pt2(1.0/2, 2.0/3); + typename mesh_type::point_type pt3(2.0/3, 2.0/3); + std::pair pt1_cell = std::make_pair(pt1, -1); + std::pair pt2_cell = std::make_pair(pt2, -1); + std::pair pt3_cell = std::make_pair(pt3, -1); + postprocessor::record_data_acoustic_two_fields(0, pt1_cell, msh, hho_di, x_dof, sensor_log1); + postprocessor::record_data_acoustic_two_fields(0, pt2_cell, msh, hho_di, x_dof, sensor_log2); + postprocessor::record_data_acoustic_two_fields(0, pt3_cell, msh, hho_di, x_dof, sensor_log3); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + /////////////////////////////////////////////////////////////////////////////// + /////// Solving a first order equation HDG/HHO propagation problem //////// + /////////////////////////////////////////////////////////////////////////////// + + Matrix a; + Matrix b; + Matrix c; + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////////// DIRK(s) schemes ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + // SDIRK case + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); + + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + }else{ + // DIRK case + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + } + + Matrix x_dof_n; + timecounter simulation_tc; + simulation_tc.tic(); + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Temporal loop //////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Postprocessing ////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////// + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, vel_fun, null_flux_fun, false); + } + + postprocessor::record_data_acoustic_two_fields(it, pt1_cell, msh, hho_di, x_dof, sensor_log1); + postprocessor::record_data_acoustic_two_fields(it, pt2_cell, msh, hho_di, x_dof, sensor_log2); + postprocessor::record_data_acoustic_two_fields(it, pt3_cell, msh, hho_di, x_dof, sensor_log3); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + simulation_tc.toc(); + simulation_log << "Simulation time : " << simulation_tc << " seconds" << std::endl; + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder2.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder2.hpp new file mode 100644 index 00000000..e5b76df7 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder2.hpp @@ -0,0 +1,347 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousPulseIHHOFirstOrder_hpp +#define HeterogeneousPulseIHHOFirstOrder_hpp + +void HeterogeneousPulseIHHOFirstOrder(char **argv){ + + /////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// Préprocessing ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + using RealType = double; + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// Meshes ////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + + auto validate_l = [](size_t l) -> size_t { + if ((0 < l) && (l < 5) ) { + return l; + }else{ + std::cout << "Warning:: Only five meshes available. Running level 4." << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_4096.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_5120.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_10240.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_16384.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_65536.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + // A commenter pour la lecture des différents maillages polyhédriques réguliers + /* polygon_2d_mesh_reader mesh_builder; + std::string mesh_file = "meshes/mexican_hat_polymesh_adapted_nel_8512.txt"; + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_file); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh);*/ + + } + + else { + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// Time controls /////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + // Time controls : Final time value 0.50 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + size_t it = 0; + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = tf/nt; + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////// Initial Condition //////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + auto null_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y; + x = pt.x(); + y = pt.y(); + return 0.0; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + return {0,0}; + }; + + auto vel_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y,xc,yc,r,wave; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 0.5; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = 0.1*(-4*std::sqrt(10.0/3.0)*(-1 + 1600.0*r*r))/(std::exp(800*r*r)*std::pow(M_PI,0.25)); + return wave; + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Creating HHO approximation spaces and corresponding linear operator /// + /////////////////////////////////////////////////////////////////////////////// + + + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + /////////////////////////////////////////////////////////////////////////////// + //////////////////// Solving a primal HHO mixed problem /////////////////// + /////////////////////////////////////////////////////////////////////////////// + + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = acoustic_two_fields_assembler(msh, hho_di, bnd); + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////// Acoustic properties ///////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + rho = 1.0; + if (y < 0.5) { + vp = 1.0; + }else{ + vp = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////// Projecting initial data ///////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, null_fun); + + // // Source Term + typename mesh_type::point_type pt_source(0.5,0.5); + std::pair source_cell = std::make_pair(pt_source, -1); + // source_term::ricker_fluid(it,dt,source_cell,msh,hho_di,x_dof); + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Postprocessing ///////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, null_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("inhomogeneous_acoustic_two_fields.txt"); + + std::ofstream sensor_log1("sensor1.csv"); + std::ofstream sensor_log2("sensor2.csv"); + std::ofstream sensor_log3("sensor3.csv"); + typename mesh_type::point_type pt1(1.0/3, 2.0/3); + typename mesh_type::point_type pt2(1.0/2, 2.0/3); + typename mesh_type::point_type pt3(2.0/3, 2.0/3); + std::pair pt1_cell = std::make_pair(pt1, -1); + std::pair pt2_cell = std::make_pair(pt2, -1); + std::pair pt3_cell = std::make_pair(pt3, -1); + postprocessor::record_data_acoustic_two_fields(0, pt1_cell, msh, hho_di, x_dof, sensor_log1); + postprocessor::record_data_acoustic_two_fields(0, pt2_cell, msh, hho_di, x_dof, sensor_log2); + postprocessor::record_data_acoustic_two_fields(0, pt3_cell, msh, hho_di, x_dof, sensor_log3); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + /////////////////////////////////////////////////////////////////////////////// + /////// Solving a first order equation HDG/HHO propagation problem //////// + /////////////////////////////////////////////////////////////////////////////// + + Matrix a; + Matrix b; + Matrix c; + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////////// DIRK(s) schemes ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + // SDIRK case + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); + + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + }else{ + // DIRK case + if (sim_data.m_iterative_solver_Q) { + dirk_an.setIterativeSolver(); + } + } + + Matrix x_dof_n; + timecounter simulation_tc; + simulation_tc.tic(); + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Temporal loop //////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + { + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + source_term::punctual_source(it,dt,source_cell,msh,hho_di,x_dof_n); + x_dof = x_dof_n; + + + RealType t = tn + dt; + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Postprocessing ////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////// + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_scalar_mixed_"; + postprocessor::write_silo_two_fields(silo_file_name, it, msh, hho_di, x_dof, null_fun, null_flux_fun, false); + } + + postprocessor::record_data_acoustic_two_fields(it, pt1_cell, msh, hho_di, x_dof, sensor_log1); + postprocessor::record_data_acoustic_two_fields(it, pt2_cell, msh, hho_di, x_dof, sensor_log2); + postprocessor::record_data_acoustic_two_fields(it, pt3_cell, msh, hho_di, x_dof, sensor_log3); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + simulation_tc.toc(); + simulation_log << "Simulation time : " << simulation_tc << " seconds" << std::endl; + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOSecondOrder.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOSecondOrder.hpp new file mode 100644 index 00000000..2d64ab5a --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOSecondOrder.hpp @@ -0,0 +1,302 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef HeterogeneousPulseIHHOSecondOrder_hpp +#define HeterogeneousPulseIHHOSecondOrder_hpp + +void HeterogeneousPulseIHHOSecondOrder(char **argv){ + + /////////////////////////////////////////////////////////////////////////////// + ////////////////////////////// Préprocessing ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + + simulation_data sim_data = preprocessor::process_acoustics_lua_file(argv); + sim_data.print_simulation_data(); + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////// Meshes ////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + + auto validate_l = [](size_t l) -> size_t { + if ((0 < l) && (l < 5) ) { + return l; + }else{ + std::cout << "Warning:: Only five meshes available. Running level 4." << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_4096.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_5120.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_10240.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_16384.txt"); + mesh_files.push_back("meshes/mexican_hat_polymesh_nel_65536.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + }else{ + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// Time controls /////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = tf/nt; + + /////////////////////////////////////////////////////////////////////////////// + ////////////////////////// Source term ? ////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + auto null_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y; + x = pt.x(); + y = pt.y(); + return 0.0; + }; + + auto vel_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y,xc,yc,r,wave; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 0.5; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = 0.1*(-4*std::sqrt(10.0/3.0)*(-1 + 1600.0*r*r))/(std::exp(800*r*r)*std::pow(M_PI,0.25)); + return wave; + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Creating HHO approximation spaces and corresponding linear operator /// + /////////////////////////////////////////////////////////////////////////////// + + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + /////////////////////////////////////////////////////////////////////////////// + //////////////////// Solving a primal HHO mixed problem /////////////////// + /////////////////////////////////////////////////////////////////////////////// + + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); // easy because boundary assumes zero every where any time. + tc.tic(); + auto assembler = acoustic_one_field_assembler(msh, hho_di, bnd); + + /////////////////////////////////////////////////////////////////////////////// + ///////////////////////// Acoustic properties ///////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(2); + RealType rho, vp; + rho = 1.0; + if (y < 0.5) { + vp = 1.0; + }else{ + vp = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,acoustic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + /////////////////////////////////////////////////////////////////////////////// + /////////// Projecting initial scalar, velocity and acceleration ////////// + /////////////////////////////////////////////////////////////////////////////// + + Matrix p_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, p_dof_n, null_fun); + assembler.project_over_faces(msh, p_dof_n, null_fun); + assembler.project_over_cells(msh, v_dof_n, vel_fun); + assembler.project_over_faces(msh, v_dof_n, vel_fun); + assembler.project_over_cells(msh, a_dof_n, null_fun); + assembler.project_over_faces(msh, a_dof_n, null_fun); + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Postprocessing ///////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, v_dof_n, vel_fun, false); + } + + std::ofstream simulation_log("inhomogeneous_acoustic_one_field.txt"); + + std::ofstream sensor_log1("sensor1.csv"); + std::ofstream sensor_log2("sensor2.csv"); + std::ofstream sensor_log3("sensor3.csv"); + typename mesh_type::point_type pt1(1.0/3, 2.0/3); + typename mesh_type::point_type pt2(1.0/2, 2.0/3); + typename mesh_type::point_type pt3(2.0/2, 2.0/3); + std::pair pt1_cell = std::make_pair(pt1, -1); + std::pair pt2_cell = std::make_pair(pt2, -1); + std::pair pt3_cell = std::make_pair(pt3, -1); + postprocessor::record_data_acoustic_one_field(0, pt1_cell, msh, hho_di, v_dof_n, sensor_log1); + postprocessor::record_data_acoustic_one_field(0, pt2_cell, msh, hho_di, v_dof_n, sensor_log2); + postprocessor::record_data_acoustic_one_field(0, pt3_cell, msh, hho_di, v_dof_n, sensor_log3); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, ti, p_dof_n, v_dof_n, simulation_log); + } + + timecounter simulation_tc; + bool standar_Q = true; + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Newmark process ////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.0; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + linear_solver analysis; + if (sim_data.m_sc_Q) { + analysis.set_Kg(assembler.LHS, assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + }else{ + analysis.set_Kg(assembler.LHS); + } + + if (sim_data.m_iterative_solver_Q) { + analysis.set_iterative_solver(true); + }else{ + analysis.set_direct_solver(true); // symmetric matrix case + } + + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + simulation_tc.tic(); + + + /////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Temporal loop //////////////////////////////// + /////////////////////////////////////////////////////////////////////////////// + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*it+ti; + + tc.tic(); + // Compute intermediate state for scalar and rate + p_dof_n = p_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*p_dof_n; + + assembler.RHS.setZero(); // Optimization: this is a problem with (f = 0) and (p_D = 0) + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update scalar and rate + p_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + ///////////////////////////////////////////////////////////////////////////////// + //////////////////////////// Postprocessing ////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////// + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_scalar_"; + postprocessor::write_silo_one_field(silo_file_name, it, msh, hho_di, v_dof_n, vel_fun, false); + } + + postprocessor::record_data_acoustic_one_field(it, pt1_cell, msh, hho_di, v_dof_n, sensor_log1); + postprocessor::record_data_acoustic_one_field(it, pt2_cell, msh, hho_di, v_dof_n, sensor_log2); + postprocessor::record_data_acoustic_one_field(it, pt3_cell, msh, hho_di, v_dof_n, sensor_log3); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); + } + + //postprocessor::record_velocity_data_acoustic_one_field(it, top_pt_cell, msh, hho_di, v_dof_n, sensor_top_log); + //postprocessor::record_velocity_data_acoustic_one_field(it, bot_pt_cell, msh, hho_di, v_dof_n, sensor_bot_log); + + ///////////////////////////////////////////////////////////////////////////////// + ////////////////////////// Display Terminal ////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////// + } + simulation_tc.toc(); + simulation_log << "Simulation time : " << simulation_tc << " seconds" << std::endl; + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/prototype_selector.hpp b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/prototype_selector.hpp new file mode 100644 index 00000000..d9cd3f66 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/Prototypes/prototype_selector.hpp @@ -0,0 +1,78 @@ + +// Contributions by Omar Durán and Romain Mottier + +#ifndef prototype_selector_hpp +#define prototype_selector_hpp + +void print_prototype_description(){ +} + +int prototype_selector(char **argv, EAcousticPrototype prototype){ + + switch (prototype) { + + case EAcousticPrototype::OneFieldConvTest: { + EllipticOneFieldConvergenceTest(argv); + } + break; + + case EAcousticPrototype::TwoFieldsConvTest: { + EllipticTwoFieldsConvergenceTest(argv); + } + break; + + case EAcousticPrototype::IOneFieldAcoustic: { + IHHOSecondOrder(argv); + } + break; + + case EAcousticPrototype::ITwoFieldsAcoustic: { + IHHOFirstOrder(argv); + } + break; + + case EAcousticPrototype::ETwoFieldsAcoustic: { + EHHOFirstOrder(argv); + } + break; + + case EAcousticPrototype::Hete1DIOneFieldAcoustic: { + HeterogeneousIHHOSecondOrder(argv); + } + break; + + case EAcousticPrototype::Hete1DITwoFieldsAcoustic: { + HeterogeneousIHHOFirstOrder(argv); + } + break; + + case EAcousticPrototype::Hete1DETwoFieldsAcoustic: { + HeterogeneousEHHOFirstOrder(argv); + } + break; + + case EAcousticPrototype::Hete2DIOneFieldAcoustic: { + HeterogeneousPulseIHHOSecondOrder(argv); + } + break; + + case EAcousticPrototype::Hete2DITwoFieldsAcoustic: { + HeterogeneousPulseIHHOFirstOrder(argv); + } + break; + + case EAcousticPrototype::Hete2DETwoFieldsAcoustic: { + HeterogeneousPulseEHHOFirstOrder(argv); + } + break; + + default: { + throw std::invalid_argument("Prototype not available."); + } + break; + + } + +} + +#endif diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/acoustics.cpp b/apps/wave_propagation/src/prototypes/acoustics_old/acoustics.cpp new file mode 100644 index 00000000..3f21b662 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/acoustics.cpp @@ -0,0 +1,158 @@ + +// Contributions by Omar Durán and Romain Mottier + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +using namespace Eigen; + +#include "timecounter.h" +#include "methods/hho" +#include "geometry/geometry.hpp" +#include "boundary_conditions/boundary_conditions.hpp" +#include "output/silo.hpp" + +// application common sources +#include "../common/display_settings.hpp" +#include "../common/fitted_geometry_builders.hpp" +#include "../common/linear_solver.hpp" +#include "../common/acoustic_material_data.hpp" +#include "../common/scal_analytic_functions.hpp" +#include "../common/preprocessor.hpp" +#include "../common/postprocessor.hpp" + +// implicit RK schemes +#include "../common/dirk_hho_scheme.hpp" +#include "../common/dirk_butcher_tableau.hpp" + +// explicit RK schemes +#include "../common/erk_hho_scheme.hpp" +#include "../common/erk_butcher_tableau.hpp" +#include "../common/ssprk_hho_scheme.hpp" +#include "../common/ssprk_shu_osher_tableau.hpp" + +/// Enumerate defining available function prototypes +enum EAcousticPrototype { + OneFieldConvTest = 0, + TwoFieldsConvTest = 1, + IOneFieldAcoustic = 2, + ITwoFieldsAcoustic = 3, + ETwoFieldsAcoustic = 4, + Hete1DIOneFieldAcoustic = 5, + Hete1DITwoFieldsAcoustic = 6, + Hete1DETwoFieldsAcoustic = 7, + Hete2DIOneFieldAcoustic = 8, + Hete2DITwoFieldsAcoustic = 9, + Hete2DETwoFieldsAcoustic = 10 +}; + +// ----- common data types ------------------------------ +using RealType = double; +typedef disk::mesh> mesh_type; +typedef disk::BoundaryConditions boundary_type; + +//Prototype sources +#include "Prototypes/Elliptic_Conv_Test/EllipticOneFieldConvergenceTest.hpp" +#include "Prototypes/Elliptic_Conv_Test/EllipticTwoFieldsConvergenceTest.hpp" +#include "Prototypes/Acoustic_Conv_Test/IHHOSecondOrder.hpp" +#include "Prototypes/Acoustic_Conv_Test/IHHOFirstOrder.hpp" +#include "Prototypes/Acoustic_Conv_Test/EHHOFirstOrder.hpp" +#include "Prototypes/Heterogeneous/HeterogeneousIHHOSecondOrder.hpp" +#include "Prototypes/Heterogeneous/HeterogeneousIHHOFirstOrder.hpp" +#include "Prototypes/Heterogeneous/HeterogeneousEHHOFirstOrder.hpp" +#include "Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOSecondOrder.hpp" +#include "Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder.hpp" +//#include "Prototypes/Heterogeneous_Pulse/HeterogeneousPulseIHHOFirstOrder2.hpp" +#include "Prototypes/Heterogeneous_Pulse/HeterogeneousPulseEHHOFirstOrder.hpp" +#include "Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOSecondOrder.hpp" +#include "Prototypes/Gar6more_2D/HeterogeneousGar6more2DIHHOFirstOrder.hpp" + +#include "Prototypes/prototype_selector.hpp" + +// ----- function prototypes ------------------------------ + +// Convergece tests for elliptic problem +void EllipticOneFieldConvergenceTest(char **argv); +void EllipticTwoFieldsConvergenceTest(char **argv); + +// Convergece tests for the acoustic wave equation +void IHHOSecondOrder(char **argv); +void IHHOFirstOrder(char **argv); +void EHHOFirstOrder(char **argv); + +// Simulation for a heterogeneous acoustics problem +void HeterogeneousIHHOSecondOrder(char **argv); +void HeterogeneousIHHOFirstOrder(char **argv); +void HeterogeneousEHHOFirstOrder(char **argv); + +// Simulation for a heterogeneous acoustics problem on polygonal meshes +void HeterogeneousPulseIHHOSecondOrder(char **argv); +void HeterogeneousPulseIHHOFirstOrder(char **argv); +void HeterogeneousPulseEHHOFirstOrder(char **argv); + +// Comparison with Gar6more2D +void HeterogeneousGar6more2DIHHOSecondOrder(int argc, char **argv); +void HeterogeneousGar6more2DIHHOFirstOrder(int argc, char **argv); + +int prototype_selector(char **argv, EAcousticPrototype prototype); + +void print_prototype_description(); + +int main(int argc, char **argv) { + + HeterogeneousGar6more2DIHHOFirstOrder(argc,argv); + + //EAcousticPrototype prototype; + //const char* const short_opts = "p:h:"; + //const option long_opts[] = { + // {"prototype", required_argument, nullptr, 'p'}, + // {"help", no_argument, nullptr, 'h'}, + // {nullptr, no_argument, nullptr, 0} + //}; + // + //while (true) { + // const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr); + // + // if (-1 == opt) + // break; + // + // switch (opt) { + // case 'p': + // prototype = EAcousticPrototype(std::stoi(optarg)); + // break; + // case 'h': + // print_prototype_description(); + // break; + // case '?': + // default: + // throw std::invalid_argument("Invalid option."); + // break; + // } + //} + // + //if (argc != 4) { + // throw std::invalid_argument("Please specify and option and a lua configuration file."); + // return 0; + //} + // + //HeterogeneousGar6more2DIHHOFirstOrder(argc,argv); + + //return prototype_selector(argv, prototype); + +} + diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_simulation.lua b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_simulation.lua new file mode 100644 index 00000000..b5f9f820 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_simulation.lua @@ -0,0 +1,13 @@ + +-- The file performs a simulation for a heterogeneous acoustics problem with analytical solution: + +config.fac_k_deg = 3 -- : Face polynomial degree: default 0 +config.num_l_ref = 3 -- : Number of uniform spatial refinements: default 0 +config.num_t_ref = 8 -- : Number of uniform time refinements: default 0 +config.stab_type = 1 -- <0-1>: Stabilization type 0 (HHO), 1 (HDG-like): default 0 +config.stab_scal = 0 -- <0-1>: Stabilization scaling 0 O(1), 1 O(1/h_{f}): default 0 +config.stat_cond = 1 -- <0-1>: Static condensation: default 0 +config.iter_solv = 0 -- <0-1>: Iterative solver : default 0 +config.writ_ener = 1 -- <0-1>: Report energy at each time value : default 0 +config.silo_output = 1 -- <0-1>: Write silo files : default 0 + diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_simulation_2d_pulse.lua b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_simulation_2d_pulse.lua new file mode 100644 index 00000000..42464bb4 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_simulation_2d_pulse.lua @@ -0,0 +1,14 @@ + +-- The file performs a simulation for a heterogeneous acoustics problem with analytical solution: + +config.fac_k_deg = 3 -- : Face polynomial degree: default 0 +config.num_l_ref = 1 -- : Number of uniform spatial refinements: default 0 +config.num_t_ref = 7 -- : Number of uniform time refinements: default 0 +config.stab_type = 1 -- <0-1>: Stabilization type 0 (HHO), 1 (HDG-like): default 0 +config.stab_scal = 0 -- <0-1>: Stabilization scaling 0 O(1), 1 O(1/h_{f}): default 0 +config.stat_cond = 1 -- <0-1>: Static condensation: default 0 +config.iter_solv = 0 -- <0-1>: Iterative solver : default 0 +config.writ_ener = 1 -- <0-1>: Report energy at each time value : default 0 +config.poly_mesh = 1 -- <0-1>: Use of polynoal meshes : default 0 +config.silo_output = 1 -- <0-1>: Write silo files : default 0 + diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_test.lua b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_test.lua new file mode 100644 index 00000000..a15cf649 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/acoustics_test.lua @@ -0,0 +1,19 @@ + +-- The file performs a convergence test for the acoustics problem: +-- Exact function types: +-- 0 -> non-polynomial +-- 1 -> quadratic in space +-- 2 -> quadratic in time + +config.fac_k_deg = 3 -- : Face polynomial degree: default 0 +config.num_l_ref = 3 -- : Number of uniform spatial refinements: default 0 +config.num_t_ref = 7 -- : Number of uniform time refinements: default 0 +config.stab_type = 1 -- <0-1>: Stabilization type 0 (HHO), 1 (HDG-like): default 0 +config.stab_scal = 0 -- <0-1>: Stabilization scaling 0 O(1), 1 O(1/h_{f}): default 0 +config.stat_cond = 1 -- <0-1>: Static condensation: default 0 +config.iter_solv = 0 -- <0-1>: Iterative solver : default 0 +config.poly_mesh = 0 -- <0-1>: Use of polynoal meshes : default 0 +config.exac_func = 0 -- <0-2>: Exact function type {0,1,2} : default 0 +config.writ_ener = 1 -- <0-1>: Report energy at each time value : default 0 +config.silo_output = 1 -- <0-1>: Write silo files : default 0 + diff --git a/apps/wave_propagation/src/prototypes/acoustics_old/input_files/elliptic_convergence_test.lua b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/elliptic_convergence_test.lua new file mode 100644 index 00000000..f6d35b67 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/acoustics_old/input_files/elliptic_convergence_test.lua @@ -0,0 +1,15 @@ + +-- The file performs a convergence test for an elliptic problem: +-- The approximation is constructed with implemented +-- assemblers for the acoustic/elastic wave equation + +config.max_k_deg = 4 -- : Maximum face polynomial degree: default 0 +config.max_l_ref = 4 -- : Maximum number of uniform spatial refinements: default 0 +config.stab_type = 0 -- <0-1>: Stabilization type 0 (HHO), 1 (HDG-like): default 0 +config.stab_scal = 1 -- <0-1>: Stabilization scaling 0 O(1), 1 O(1/h_{f}): default 0 +config.stat_cond = 1 -- <0-1>: Static condensation: default 0 +config.iter_solv = 0 -- <0-1>: Iterative solver : default 0 +config.exac_func = 0 -- <0-1>: Manufactured function type 0 (non-polynomial), 1 (quadratic): default 0 +config.poly_mesh = 0 -- <0-1>: Use of polynoal meshes : default 0 +config.silo_output = 0 -- <0-1>: Write silo files : default 0 + diff --git a/apps/wave_propagation/src/prototypes/coupling/Basin/BassinEHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Basin/BassinEHHOFirstOrder.hpp new file mode 100644 index 00000000..093bb51b --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Basin/BassinEHHOFirstOrder.hpp @@ -0,0 +1,423 @@ + +// Created by Romain Mottier + +void BassinEHHOFirstOrder(int argc, char **argv); + +void BassinEHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " EXPLICIT SEDIMENTARY BASIN" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ###################################################################### + // ###################################################################### Mesh generation + // ###################################################################### + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 1) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/basin.txt"); // l = 0 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_bassin(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + // nt *= 2; + nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto air_mat_fun = []() -> acoustic_material_data { + double rho, vp; + rho = 1.225; + vp = 343.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto basin_elastic_mat_fun = []() -> elastic_material_data { + double rho, vp, vs; + rho = 2570.0; + vp = 5350.0; + vs = 3090.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto basin_sediment_mat_fun = []() -> elastic_material_data { + double rho, vp, vs; + rho = 1200.0; + vp = 3400.0; + vs = 1400.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting -- A debug + // ###################################################################### + + std::map> basin_e_material; + std::map> basin_a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + if (mesh_builder.polygons[cell_ind].m_material == 1) { + elastic_material_data material = basin_elastic_mat_fun(); + basin_e_material.insert(std::make_pair(cell_ind,material)); + } + if (mesh_builder.polygons[cell_ind].m_material == 2) { + elastic_material_data material = basin_sediment_mat_fun(); + basin_e_material.insert(std::make_pair(cell_ind,material)); + } + if (mesh_builder.polygons[cell_ind].m_material == 3) { + acoustic_material_data material = air_mat_fun(); + basin_a_material.insert(std::make_pair(cell_ind,material)); + } + + } + + // Detect interfaces + disk::connectivity>> conn(msh); + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + auto fc_id = msh.lookup(face); + auto connected_cells = conn.connected_cells(face); + std::vector cell_inds; + std::vector materials; + for (const auto& cell : connected_cells) { + auto cell_ind = msh.lookup(cell); + cell_inds.push_back(cell_ind); + materials.push_back(mesh_builder.polygons[cell_ind].m_material); + } + if (materials[0] == 3) { + if (materials[1] == 1 || materials[1] == 2) { + interface_cell_pair_indexes[fc_id].first = cell_inds[1]; + interface_cell_pair_indexes[fc_id].second = cell_inds[0]; + continue; + } + } + if (materials[1] == 3) { + if (materials[0] == 1 || materials[0] == 2) { + interface_cell_pair_indexes[fc_id].first = cell_inds[0]; + interface_cell_pair_indexes[fc_id].second = cell_inds[1]; + continue; + } + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> static_vector { + static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary faces + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, basin_e_material, basin_a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + auto pulse_basin = [](const disk::mesh>::point_type& pt) -> static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 750.0; + fc = 25.0; + c = 10; + vp = 5350.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, pulse_basin, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, pulse_basin, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + + // Solving a first order equation HDG/HHO propagation problem + int s = 3; + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + std::cout << std::endl << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + tc.tic(); + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t face_dofs = assembler.get_n_face_dof(); + + size_t e_cells = assembler.get_elastic_cells(); + size_t a_cells = assembler.get_acoustic_cells(); + size_t n_cells = e_cells + a_cells; + + ////////// Post process of the initial data + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + } + + std::ofstream simulation_log("elasto_acoustic_inhomogeneous_four_fields.txt"); + std::ofstream energy_file("energy_file.txt"); + std::ofstream dissipation_file("dissipation_file.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field_bassin(mesh_builder, msh, hho_di, assembler, t, x_dof, energy_file); + } + + // erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, elastic_cell_dofs, acoustic_cell_dofs, face_dofs); + // erk_an.Kcc_inverse(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + // if (sim_data.m_hdg_stabilization_Q) { + // erk_an.Sff_inverse(std::make_pair(assembler.get_n_faces(), assembler.get_face_basis_data())); + // } + // else { + // if (sim_data.m_iterative_solver_Q) { + // erk_an.setIterativeSolver(); + // } + // erk_an.DecomposeFaceTerm(); + // } + // tc.toc(); + // std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + + // erk_an.refresh_faces_unknowns(x_dof); + + // // ################################################## + // // ################################################## Time marching + // // ################################################## + + // std::cout << std::endl << std::endl; + + // Matrix x_dof_n; + + // for(size_t it = 1; it <= nt; it++) { + + + // tcit.tic(); + // std::cout << bold << red << " Time step number " << it << ": t = " << t + // << reset; + + // RealType tn = dt*(it-1)+ti; + + // // ERK step + // tc.tic(); + // { + // size_t n_dof = x_dof.rows(); + // Matrix k = Matrix::Zero(n_dof, s); + // Matrix Fg, Fg_c,xd; + // xd = Matrix::Zero(n_dof, 1); + + // Matrix yn, ki; + + // x_dof_n = x_dof; + // for (int i = 0; i < s; i++) { + // yn = x_dof; + // for (int j = 0; j < s - 1; j++) { + // yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + // } + // erk_an.erk_weight(yn, ki); + // // Accumulated solution + // x_dof_n += dt*b(i,0)*ki; + // k.block(0, i, n_dof, 1) = ki; + // } + // } + // tc.toc(); + // // std::cout << std::endl << bold << cyan << " DIRK step completed: " << tc << " seconds" + // // << reset << std::endl; + + // x_dof = x_dof_n; + + // // ################################################## + // // ################################################## Last postprocess + // // ################################################## + + // if (sim_data.m_render_silo_files_Q) { + // std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + // postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, bassin_e_material, bassin_a_material, false); + // } + + // t += dt; + + // if (sim_data.m_report_energy_Q) { + // postprocessor::compute_elasto_acoustic_energy_four_field_bassin(mesh_builder, msh, hho_di, assembler, t, x_dof, energy_file); + // postprocessor::compute_elasto_acoustic_dissipation_four_field(assembler, t, x_dof, dissipation_file); + // } + + // std::cout << std::endl; + // tcit.toc(); + // std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + + // } + // sim_data.write_simulation_data(simulation_log); + // simulation_log << "Number of ERK steps = " << s << std::endl; + // simulation_log << "Number of time steps = " << nt << std::endl; + // simulation_log << "Step size = " << dt << std::endl; + // simulation_log.flush(); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/Basin/BassinIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Basin/BassinIHHOFirstOrder.hpp new file mode 100644 index 00000000..e4c25dab --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Basin/BassinIHHOFirstOrder.hpp @@ -0,0 +1,519 @@ + + +// Created by Romain Mottier + + +void BassinIHHOFirstOrder(int argc, char **argv); + +void BassinIHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " IMPLICIT SEDIMENTARY BASIN" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ###################################################################### + // ###################################################################### Mesh generation + // ###################################################################### + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 5) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../meshes/basin.txt"); // l = 0 + mesh_files.push_back("../meshes/essai_tris_non_conformes.txt"); // l = 1 + mesh_files.push_back("../meshes/quad_small.txt"); // l = 2 + mesh_files.push_back("../meshes/tri_small.txt"); // l = 3 + mesh_files.push_back("../meshes/strat.txt"); // l = 4 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_bassin(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + // nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto air_mat_fun = []() -> acoustic_material_data { + double rho, vp; + rho = 1.225; + vp = 343.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto basin_elastic_mat_fun = []() -> elastic_material_data { + double rho, vp, vs; + rho = 2570.0; + vp = 5350.0; + vs = 3090.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto basin_sediment_mat_fun = []() -> elastic_material_data { + double rho, vp, vs; + rho = 1200.0; + vp = 3400.0; + vs = 1400.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> basin_e_material; + std::map> basin_a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + if (mesh_builder.polygons[cell_ind].m_material == 1) { + elastic_material_data material = basin_elastic_mat_fun(); + basin_e_material.insert(std::make_pair(cell_ind,material)); + } + if (mesh_builder.polygons[cell_ind].m_material == 2) { + elastic_material_data material = basin_sediment_mat_fun(); + basin_e_material.insert(std::make_pair(cell_ind,material)); + } + if (mesh_builder.polygons[cell_ind].m_material == 3) { + acoustic_material_data material = air_mat_fun(); + basin_a_material.insert(std::make_pair(cell_ind,material)); + } + + } + + // Detect interfaces + auto conn = disk::connectivity_via_faces(msh); + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + auto fc_id = msh.lookup(face); + auto connected_cells = conn.connected_cells(msh, face); + std::vector cell_inds; + std::vector materials; + for (const auto& cell : connected_cells) { + auto cell_ind = msh.lookup(cell); + cell_inds.push_back(cell_ind); + materials.push_back(mesh_builder.polygons[cell_ind].m_material); + } + + if (materials.size() == 2) { + + if (materials[0] == 3) { + if (materials[1] == 1 || materials[1] == 2) { + interface_cell_pair_indexes[fc_id].first = cell_inds[1]; + interface_cell_pair_indexes[fc_id].second = cell_inds[0]; + // Ajouter la face parcourue a la structure interfaces + continue; + } + } + if (materials[1] == 3) { + if (materials[0] == 1 || materials[0] == 2) { + interface_cell_pair_indexes[fc_id].first = cell_inds[0]; + interface_cell_pair_indexes[fc_id].second = cell_inds[1]; + // Ajouter la face parcourue a la structure interfaces + continue; + } + } + } + + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary faces + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, basin_e_material, basin_a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + auto pulse_basin = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = -50.0;//-450.0; + yc = 450.0;//600.0; + fc = 4.0; + c = 5;//10; + vp = 5350.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + auto v_fun_elastic = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 0.5; + fc = 10.0; + c = 10; + vp = std::sqrt(3.0); + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, pulse_basin, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, pulse_basin, null_s_fun); + // assembler.project_over_cells(msh, x_dof, v_fun_elastic, null_flux_fun, null_s_fun, null_fun); + // assembler.project_over_faces(msh, x_dof, v_fun_elastic, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, false); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) + dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "IBasin_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::ostringstream filename; + filename << "IBasin_silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + } + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + // std::ostringstream filename_acou; + // filename_acou << "A_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + // std::string filename_acou_str = filename_acou.str(); + // std::ofstream Acoustic_sensor_1_log(filename_acou_str); + // typename mesh_type::point_type Acoustic_s1_pt(-450, 1200); + // std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + + // std::ostringstream filename_int; + // filename_int << "I_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + // std::string filename_int_str = filename_int.str(); + // std::ofstream Interface_sensor_1_log(filename_int_str); + // typename mesh_type::point_type Interface_s1_pt(-500, 0.0); + // std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + + // std::ostringstream filename_ela; + // filename_ela << "E_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + // std::string filename_ela_str = filename_ela.str(); + // std::ofstream Elastic_sensor_1_log(filename_ela_str); + // typename mesh_type::point_type Elastic_s1_pt(-500, -250); + // std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + + // bool sensors = true; + // if (sensors) { + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); // No souce term + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i), is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " DIRK step completed: " << tc << " seconds" << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + int silo_mod = static_cast(std::round(nt / 15.0)); // Number of silo files + if ((!sim_data.m_render_silo_files_Q && (it == 1 || it == std::round(nt/2) || it == nt)) || (sim_data.m_render_silo_files_Q && (it%silo_mod == 0))) { + std::ostringstream filename; + filename << "IBasin_silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + std::cout << bold << cyan << " Silo file generated" << reset << std::endl; + } + + // if (sensors) { + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + if (it == nt) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + } + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/Basin/Test.hpp b/apps/wave_propagation/src/prototypes/coupling/Basin/Test.hpp new file mode 100644 index 00000000..dfb00d62 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Basin/Test.hpp @@ -0,0 +1,484 @@ + +// Created by Romain Mottier + +void Test_Laurent(int argc, char **argv); + +void Test_Laurent(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " IMPLICIT SEDIMENTARY BASIN" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ###################################################################### + // ###################################################################### Mesh generation + // ###################################################################### + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 2) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/test_Laurent.txt"); // l = 0 + mesh_files.push_back("../../meshes/square2.txt"); // l = 1 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_bassin(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + // nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.5; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto air_mat_fun = []() -> acoustic_material_data { + double rho, vp; + rho = 1.225; + vp = 330.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto basin_elastic_mat_fun = []() -> elastic_material_data { + double rho, vp, vs; + rho = 2570.0; + vp = 5350.0; + vs = 3009.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> basin_e_material; + std::map> basin_a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + if (mesh_builder.polygons[cell_ind].m_material == 1) { + elastic_material_data material = basin_elastic_mat_fun(); + basin_e_material.insert(std::make_pair(cell_ind,material)); + } + if (mesh_builder.polygons[cell_ind].m_material == 2) { + acoustic_material_data material = air_mat_fun(); + // elastic_material_data material = basin_elastic_mat_fun(); + basin_a_material.insert(std::make_pair(cell_ind,material)); + // basin_e_material.insert(std::make_pair(cell_ind,material)); + } + + } + + // Detect interfaces + disk::connectivity>> conn(msh); + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + auto fc_id = msh.lookup(face); + auto connected_cells = conn.connected_cells(face); + std::vector cell_inds; + std::vector materials; + for (const auto& cell : connected_cells) { + auto cell_ind = msh.lookup(cell); + cell_inds.push_back(cell_ind); + materials.push_back(mesh_builder.polygons[cell_ind].m_material); + } + if (materials[0] == 2) { + if (materials[1] == 1 || materials[1] == 2) { + interface_cell_pair_indexes[fc_id].first = cell_inds[1]; + interface_cell_pair_indexes[fc_id].second = cell_inds[0]; + continue; + } + } + if (materials[1] == 2) { + if (materials[0] == 1 || materials[0] == 2) { + interface_cell_pair_indexes[fc_id].first = cell_inds[0]; + interface_cell_pair_indexes[fc_id].second = cell_inds[1]; + continue; + } + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> static_vector { + static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary faces + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, basin_e_material, basin_a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc.to_double() << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + auto pulse_basin = [](const disk::mesh>::point_type& pt) -> static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = -4000.0; + c = 1; + vp = 5350.0; + lp = 3566; + fc = vp/lp; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, pulse_basin, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, pulse_basin, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + if (is_sdirk_Q) + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + else + dirk_butcher_tableau::dirk_tables(s, a, b, c); + + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, false); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) { + dirk_an.setIterativeSolver(); + } + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "IBasin_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::ostringstream filename; + filename << "IBasin_silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + } + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "A_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(0, 50); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + + std::ostringstream filename_int; + filename_int << "I_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_1_log(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(0.0, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "S1_E_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(0.0, -300.0); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + + std::ostringstream filename_ela2; + filename_ela2 << "S2_E_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str2 = filename_ela2.str(); + std::ofstream Elastic_sensor_2_log(filename_ela_str2); + typename mesh_type::point_type Elastic_s2_pt(3000, -4000); + std::pair Elastic_s2_pt_cell = std::make_pair(Elastic_s2_pt, -1); + + bool sensors = true; + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " DIRK step completed: " << tc << " seconds" << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + } + + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log ); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log ); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log ); + } + + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + if (it == nt) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, basin_e_material, basin_a_material, false); + } + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/CFL/EHHOFirstOrderCFL.hpp b/apps/wave_propagation/src/prototypes/coupling/CFL/EHHOFirstOrderCFL.hpp new file mode 100644 index 00000000..e5bcfc75 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/CFL/EHHOFirstOrderCFL.hpp @@ -0,0 +1,439 @@ + +// Created by Romain Mottier +// ../wave_propagation -k 1 -s 0 -r 0 -c 1 -p 0 -l 2 -n 350 -f 0 -e 0 +// BE CAREFUL ON THE CHOICE OF THE WEIGHTING IN FRONT OF THE STAB: elastoacoustic_four_field.hpp + +void EHHOFirstOrderCFL(int argc, char **argv); + +void EHHOFirstOrderCFL(int argc, char **argv) { + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " COUPLING CFL" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc; + + // ################################################## + // ################################################## Time controls + // ################################################## + + RealType ti = 0.0; + RealType tf = 1.0; + RealType t = ti; + int nt_base = sim_data.m_nt_divs; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Zero source terms, to keep the system energy constant + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Elastic analytical functions + // auto v_fun = null_fun; + // auto flux_fun = null_flux_fun; + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + // Acoustic analytical functions + // auto s_v_fun = null_s_fun; + // auto s_flux_fun = null_fun; + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) + return l; + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter_bis(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Material data + // ################################################## + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Interface detection and faces repartitions + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + RealType eps = 1.0e-10; + + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++){ + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + // Internal faces structure for explicit schemes + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + if (bar.y() > 0) { + acoustic_internal_faces.insert(fc_id); + } + else { + elastic_internal_faces.insert(fc_id); + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ######################s########################### + + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ################################################## + // ################################################## Setting of the time marching scheme + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + bool explicit_scheme = true; + assembler.assemble(msh, null_fun, null_s_fun, explicit_scheme); + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Loop over the ERK schemes + // ################################################## + + for (int s = 2; s < 5; s++) { + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "E_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + std::cout << bold << red << " ERK(" << s << "):" << reset << std::endl << std::endl; + simulation_log << std::endl << " ERK(" << s << "):" << std::endl; + simulation_log << std::endl; + + // ################################################## + // ################################################## Loop over level of time refinement + // ################################################## + + for (unsigned int i = 0; i < 1000; i++) { + + t = ti; + RealType dt = (tf-ti)/nt; + simulation_log << "Step size = " << dt << std::endl; + + energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // Projecting initial data + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, v_fun, s_v_fun); + + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + bool approx_fail_check_Q = false; + RealType energy = energy_0; + + for(size_t it = 1; it <= nt; it++) { + + RealType tn = dt*(it-1)+ti; + + // ERK steps + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + RealType t = tn + c(i,0) * dt; + assembler.assemble_rhs(msh, null_fun, null_s_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + x_dof = x_dof_n; + t = tn + dt; + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + // bool unstable_check_Q = (relative_energy > 5.0e-2) || (relative_energy_0 >= 5.0e-2); + bool unstable_check_Q = (relative_energy > 15e-2) || (relative_energy_0 >= 15e-2); + if (unstable_check_Q) { // energy is increasing + approx_fail_check_Q = true; + break; + } + energy = energy_n; + } + if (approx_fail_check_Q) { + std::cout << bold << red << " Simulation is unstable" << reset << std::endl << std::endl << std::endl; + simulation_log << std::endl; + simulation_log << " Simulation is unstable for:"<< std::endl; + simulation_log << " Number of equations: " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << h << std::endl; + simulation_log << " CFL c(dt/h) = " << std::sqrt(3.0)*dt/h << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + break; + } + else { + simulation_log << " Simulation is stable for:"<< std::endl; + simulation_log << " Number of equations: " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << h << std::endl; + simulation_log << " CFL c(dt/h) = " << std::sqrt(3.0)*dt/h << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + std::cout << " Simulation is stable for: n = " << nt << std::endl; + nt = int(nt - (nt*1/100+1)); + continue; + // break; + + } + } + simulation_log << std::endl << " ******************************* " << std::endl; + simulation_log << std::endl << std::endl; + } + } diff --git a/apps/wave_propagation/src/prototypes/coupling/CFL/HeterogeneousEHHOFirstOrderCFL.hpp b/apps/wave_propagation/src/prototypes/coupling/CFL/HeterogeneousEHHOFirstOrderCFL.hpp new file mode 100644 index 00000000..9a0bac5b --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/CFL/HeterogeneousEHHOFirstOrderCFL.hpp @@ -0,0 +1,470 @@ + + +// Created by Romain Mottier + +void HeterogeneousEHHOFirstOrderCFL(int argc, char **argv); + +void HeterogeneousEHHOFirstOrderCFL(int argc, char **argv){ + + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " EXPLICIT PULSE - CFL" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ###################################################################### Mesh generation + // ###################################################################### + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l2_0.4.txt"); // l = 0 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l3_0.21.txt"); // l = 1 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l4_0.096.txt"); // l = 2 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l5_0.0485.txt"); // l = 3 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l6_0.024.txt"); // l = 4 + + // mesh_files.push_back("../../meshes/pulse/poly/poly_l2.txt"); // -l 0 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l3.txt"); // -l 1 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l4.txt"); // -l 2 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l5.txt"); // -l 3 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l6.txt"); // -l 4 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l7.txt"); // -l 5 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 1; + RealType ly = 1; + size_t nx = 2; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-0.5, -0.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + // nt *= 2; + nt = sim_data.m_nt_divs; + } + RealType ti = 0.0; + RealType tf = 0.25; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // Loop over level of time step option -n + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + + RealType dt = (tf-ti)/nt; + + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ###################################################################### Assigning Material Data + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + // interface_face_pair_indexes[fc_id].second = cp_fc; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + // interface_face_pair_indexes[fc_id].first = cp_fc; + } + } + // cp_fc = cp_fc + 1; + } + + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + if (bar.y() > 0) { + acoustic_internal_faces.insert(fc_id); + // std::cout << fc_id << std::endl; + } + else { + elastic_internal_faces.insert(fc_id); + // std::cout << fc_id << std::endl; + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ###################################################################### Solving a primal HHO mixed problem + // ###################################################################### + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + + // Stabilization type + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### Projecting initial data + // ###################################################################### + + Matrix x_dof; + + // Acoustic pulse intialized in velocity + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, v_fun_adi_acoustic); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + + // Elastic pulse intialized in velocity + // assembler.project_over_cells(msh, x_dof, v_fun_adi, null_flux_fun, null_s_fun, null_fun); + // assembler.project_over_faces(msh, x_dof, v_fun_adi, null_s_fun); + + ////////// Post process of the initial data + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 2; + erk_butcher_tableau::erk_tables(s, a, b, c); + + std::cout << std::endl << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + + + if(sim_data.m_hdg_stabilization_Q) { + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes); + } + else { + erk_an.DecomposeFaceTerm(); + } + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl << std::endl; + + std::cout << bold << red << " CFL (dt/h) = " << dt/(lx/mesh_builder.get_nx()) << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + std::cout << std::endl << std::endl; + + Matrix x_dof_n; + + dt = (tf-ti)/nt; + t = ti; + + bool approx_fail_check_Q = false; + bool fail_check_Q = false; + + std::ofstream energy_file("energy_file.txt"); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + RealType energy = energy_0; + + for(size_t it = 1; it <= nt; it++) { + + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + erk_an.erk_weight(yn, ki); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + + // for (int i = 0; i < elastic_cell_dofs; ++i) { + // for (int j = 0; j < x_dof_n.cols(); ++j) { + // std::cout << std::setw(4) << x_dof_n(i, j) << " "; + // } + // std::cout << std::endl; + // } + // std::cout << std::endl << std::endl << std::endl << std::endl; + + } + } + tc.toc(); + // std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + t += dt; + + bool unstable_check_Q = (relative_energy > 1e-2) || (relative_energy_0 >= 0.5e-2); + // bool dissipation_check_Q = (relative_energy < -15e-2) || (relative_energy_0 <= -15e-2); + + // if (dissipation_check_Q) { // energy is increasing + // fail_check_Q = true; + // break; + // } + + if (unstable_check_Q) { // energy is increasing + approx_fail_check_Q = true; + break; + } + + energy = energy_n; + + } + + // if (fail_check_Q) { + // std::cout << bold << red << " Simulation dissipates too much energy" << reset << std::endl; + // break; + // } + + if (approx_fail_check_Q) { + std::cout << bold << red << " Simulation is unstable" << reset << std::endl << std::endl; + simulation_log << std::endl; + simulation_log << " Simulation is unstable for :"<< std::endl; + simulation_log << " Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << lx/mesh_builder.get_nx() << std::endl; + simulation_log << " CFL (dt/h) = " << dt/(lx/mesh_builder.get_nx()) << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + break; + } + else { + simulation_log << " Simulation is stable for :"<< std::endl; + simulation_log << " Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << lx/mesh_builder.get_nx() << std::endl; + simulation_log << " CFL (dt/h) = " << dt/(lx/mesh_builder.get_nx()) << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + std::cout << bold << red << "Simulation is stable for: " << nt << reset << std::endl << std::endl; + nt -= 10; + std::cout << bold << red << "Number of time steps: " << nt << reset << std::endl << std::endl; + continue; + } + + } + + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/EHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/EHHOFirstOrder.hpp new file mode 100644 index 00000000..f4d9a17f --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/EHHOFirstOrder.hpp @@ -0,0 +1,426 @@ + + +// Created by Romain Mottier + +// ../../elastoacoustic -k 1 -s 0 -r 0 -c 1 -p 1 -l 8 -n 1000 -f 0 -e 0 +void EHHOFirstOrder(int argc, char **argv); + +void EHHOFirstOrder(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " EXPLICIT COUPLING CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + cpu.tic(); + tc.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + size_t l = sim_data.m_n_divs; + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + { // Simplicial meshes + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // l = 1 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // l = 3 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // l = 5 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // l = 7 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + // mesh_files.push_back("../../../../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // l = 9 + } + { // Polyhedral meshes + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_32.txt"); // -l 0 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_128.txt"); // -l 2 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_512.txt"); // -l 4 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_2048.txt"); // -l 6 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_8192.txt"); // -l 8 + mesh_files.push_back("../../../../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + } + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Elastic analytical functions + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto a_fun = functions.Evaluate_a(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++){ + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) + acoustic_internal_faces.insert(fc_id); + else + elastic_internal_faces.insert(fc_id); + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, u_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if(sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + // DISCRTIZATION INFOS + std::cout << bold << red << " DISCRETIZATION: "; + std::cout << cyan << "Cell degree = " << hho_di.cell_degree() << std::endl; + std::cout << bold << cyan << " Face degree = " << hho_di.face_degree() << reset << std::endl << std::endl << std::endl; + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, v_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK schemes + int s = 2; + erk_butcher_tableau::erk_tables(s, a, b, c); + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, f_fun, s_f_fun, true); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + // auto block_dimension = assembler.Scc_block_dimension(); + // erk_an.compute_eigenvalues_bis(assembler.LHS_STAB, block_dimension, simulation_log); + // erk_an.compute_eigenvalues(simulation_log); + simulation_log.flush(); + std::cout << std::endl << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + + { + // Manufactured solution + auto v_fun = functions.Evaluate_v(t); + auto f_fun = functions.Evaluate_f(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + + assembler.get_e_bc_conditions().updateDirichletFunction(v_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, f_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + if(it == nt){ + std::cout << std::endl; + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + + std::cout << std::endl; + + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ofstream mesh_file("mesh_file.txt"); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/EHHOFirstOrder_conv_tests.hpp b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/EHHOFirstOrder_conv_tests.hpp new file mode 100644 index 00000000..f9d4a4c2 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/EHHOFirstOrder_conv_tests.hpp @@ -0,0 +1,373 @@ + + +// Created by Romain Mottier + +// ../../elastoacoustic -k 4 -s 0 -r 0 -c 1 -p 1 -l 9 -n 2000 -f 0 -e 0 + +void EHHOFirstOrder_conv_tests(int argc, char **argv); + +void EHHOFirstOrder_conv_tests(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " EXPLICIT COUPLING CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + for (size_t k = 1; k <= sim_data.m_k_degree; k++) { + + std::cout << std::endl << bold << red << " Polynomial degree k : " << k << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if (sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree, k); + + // ################################################## + // ################################################## Loop over level of space refinement + // ################################################## + + for (size_t l = 0; l <= sim_data.m_n_divs; l++) { + + std::cout << bold << cyan << " Space refinment level -l : " << l << reset << std::endl; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + // Mesh availability + auto validate_l = [](size_t l) -> size_t { + if (!((0 <= l) && (l < 15))) { + std::cout << std::endl << std::endl; + std::cout << bold << red << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + // size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + // Simplicial meshes + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + // Polyhedral meshes + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_32.txt"); // -l 0 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_64.txt"); // -l 1 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_128.txt"); // -l 2 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_256.txt"); // -l 3 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_512.txt"); // -l 4 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_2048.txt"); // -l 6 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_8192.txt"); // -l 8 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_16384.txt"); // -l 9 + mesh_files.push_back("../../meshes/conv_test/poly_bad_quality/poly_32768.txt"); // -l 10 + // Reading the mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + // ################################################## + // ################################################## Time discretization infos + // ################################################## + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ERK schemes + Matrix a; + Matrix b; + Matrix c; + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Elastic analytical functions + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto a_fun = functions.Evaluate_a(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++){ + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (!is_member_Q) { + if (bar.y() > 0) + acoustic_internal_faces.insert(fc_id); + else + elastic_internal_faces.insert(fc_id); + } + } + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, u_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, v_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + assembler.assemble(msh, f_fun, s_f_fun, true); + assembler.LHS += assembler.COUPLING; + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << l << "_n_" << sim_data.m_nt_divs << "_k_" << k << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + RealType tn = dt*(it-1)+ti; + // ERK step + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + {// Manufactured solution + auto v_fun = functions.Evaluate_v(t); + auto f_fun = functions.Evaluate_f(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + assembler.get_e_bc_conditions().updateDirichletFunction(v_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, f_fun, s_f_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + x_dof = x_dof_n; + t = tn + dt; + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + if (it == nt) { + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + } + bool mesh_quality = true; + if (mesh_quality) { + std::ostringstream filename_mesh_quality; + filename_mesh_quality << "mesh_quality_l_" << l << ".txt"; + std::string filename_str = filename_mesh_quality.str(); + std::ofstream mesh_file(filename_str); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + } + } + std::cout << std::endl << std::endl; +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/IHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/IHHOFirstOrder.hpp new file mode 100644 index 00000000..a00f22fa --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/IHHOFirstOrder.hpp @@ -0,0 +1,459 @@ + + +// Created by Romain Mottier + +void IHHOFirstOrder(int argc, char **argv); +void IHHOFirstOrder(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " IMPLICIT COUPLING CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + cpu.tic(); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_32.txt"); // -l 0 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_64.txt"); // -l 1 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_128.txt"); // -l 2 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_256.txt"); // -l 3 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_512.txt"); // -l 4 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_2048.txt"); // -l 6 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_8192.txt"); // -l 8 + mesh_files.push_back("../../meshes/conv_test/poly_bad_bad_quality/poly_16384.txt"); // -l 9 + mesh_files.push_back("../../meshes/essai_CV2.txt"); // -l 10 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << std::endl << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + // nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Elastic analytical functions + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto a_fun = functions.Evaluate_a(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, u_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, v_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 1; + bool is_sdirk_Q = true; + if (is_sdirk_Q) + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + else + dirk_butcher_tableau::dirk_tables(s, a, b, c); + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, f_fun, s_f_fun, false); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + dirk_hho_scheme dirk_an(assembler.LHS, assembler.RHS, assembler.MASS); + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) + dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::ostringstream filename; + filename << "IHHO_silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + std::cout << std::endl; + + bool e_side_Q = true; + bool a_side_Q = false; + bool sensors = true; + std::ostringstream filename_acou; + filename_acou << "A_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(0.5, 0.5); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + } + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << red << " Time step number " << it << reset << std::endl; + + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + // Manufactured solution + auto v_fun = functions.Evaluate_v(t); + auto f_fun = functions.Evaluate_f(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + + assembler.get_e_bc_conditions().updateDirichletFunction(v_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, f_fun, s_f_fun, false); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + int silo_mod = static_cast(std::round(nt / 50.0)); // Number of silo files + if (((it == 1 || it == std::round(nt/2) || it == nt)) || (sim_data.m_render_silo_files_Q && (it%silo_mod == 0))) { + std::ostringstream filename; + filename << "IHHO_silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + tc.toc(); + std::cout << bold << cyan << " DIRK step completed: " << tc << " seconds" << reset << std::endl << std::endl; + x_dof = x_dof_n; + t = tn + dt; + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + } + + if (it == nt){ + // Computing errors + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + std::cout << std::endl; + } + + } + + bool mesh_quality = true; + if (mesh_quality) { + std::ostringstream mesh_file_name; + mesh_file_name << "mesh_quality_l" << sim_data.m_n_divs << ".txt"; + std::string mesh_file_str = mesh_file_name.str(); + std::ofstream mesh_file(mesh_file_str); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/IHHOFirstOrder_conv_tests.hpp b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/IHHOFirstOrder_conv_tests.hpp new file mode 100644 index 00000000..ca9aa0a9 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Conv_Tests/IHHOFirstOrder_conv_tests.hpp @@ -0,0 +1,332 @@ + + +// Created by Romain Mottier + +void IHHOFirstOrder_conv_tests(int argc, char **argv); + +void IHHOFirstOrder_conv_tests(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " IMPLICIT COUPLING CONV TEST" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + for (size_t k = 1; k <= sim_data.m_k_degree; k++) { + + std::cout << std::endl << bold << red << " Polynomial degree k : " << k << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if (sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree, k); + + // ################################################## + // ################################################## Loop over level of space refinement + // ################################################## + + for (size_t l = 0; l <= sim_data.m_n_divs; l++) { + + std::cout << bold << cyan << " Space refinment level -l : " << l << reset << std::endl; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(l); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // DIRK(s) schemes + Matrix a; + Matrix b; + Matrix c; + int s = 3; + bool is_sdirk_Q = true; + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Elastic analytical functions + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto a_fun = functions.Evaluate_a(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // Acoustic analytical functions + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++){ + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, u_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, v_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + assembler.assemble(msh, f_fun, s_f_fun, false); + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) { + dirk_an.setIterativeSolver(); + } + dirk_an.DecomposeMatrix(); + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "implicit_l_" << l << "_n_" << sim_data.m_nt_divs << "_k_" << k << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + RealType tn = dt*(it-1)+ti; + // DIRK step + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + RealType t; + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + {// Manufactured solution + auto v_fun = functions.Evaluate_v(t); + auto f_fun = functions.Evaluate_f(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + assembler.get_e_bc_conditions().updateDirichletFunction(v_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_v_fun, 0); + assembler.assemble_rhs(msh, f_fun, s_f_fun, false); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + } + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + x_dof = x_dof_n; + t = tn + dt; + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + if (it == nt) { + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + postprocessor::compute_errors_four_fields_elastoacoustic_energy_norm(msh, hho_di, assembler, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun, simulation_log); + } + } + bool mesh_quality = true; + if (mesh_quality) { + std::ostringstream mesh_file_name; + mesh_file_name << "mesh_quality_l" << l << ".txt"; + std::string mesh_file_str = mesh_file_name.str(); + std::ofstream mesh_file(mesh_file_str); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + } + } + std::cout << std::endl << std::endl; +} diff --git a/apps/wave_propagation/src/prototypes/coupling/EHHOFirstOrder_stability.hpp b/apps/wave_propagation/src/prototypes/coupling/EHHOFirstOrder_stability.hpp new file mode 100644 index 00000000..cf165690 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/EHHOFirstOrder_stability.hpp @@ -0,0 +1,434 @@ + +// Created by Romain Mottier + +// ../../../../elastoacoustic -k 1 -s 1 -r 0 -c 1 -p 0 -l 0 -n 0 -f 0 -e 0 + +void EHHOFirstOrder_stability(int argc, char **argv); + +void EHHOFirstOrder_stability(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " COUPLING STABILITY" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) + return l; + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); // -l 0 + mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); // -l 2 + mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); // -l 4 + mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); // -l 6 + mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); // -l 8 + mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); // -l 10 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + // mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt = sim_data.m_nt_divs; + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Zero source terms, to keep the system energy constant + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Elastic analytical functions + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // Acoustic analytical functions + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++){ + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (!is_member_Q) { + if (bar.y() > 0) + acoustic_internal_faces.insert(fc_id); + else + elastic_internal_faces.insert(fc_id); + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_coupling_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, s_v_fun, s_flux_fun); + assembler.project_over_faces(msh, x_dof, v_fun, s_v_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + bool explicit_scheme = true; + assembler.assemble(msh, null_fun, null_s_fun, explicit_scheme); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + // erk_an.compute_eigenvalues(simulation_log); + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + if (sim_data.m_render_silo_files_Q) { + std::ostringstream silo; + silo << "Silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_str = silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_str, 0, msh, hho_di, x_dof, e_material, a_material, false); + } + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + bool approx_fail_check_Q = false; + RealType energy = energy_0; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + assembler.assemble_rhs(msh, null_fun, null_s_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset; + x_dof = x_dof_n; + t = tn + dt; + + // Energy evalutation + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + bool unstable_check_Q = (relative_energy > 5.0e-2) || (relative_energy_0 >= 5.0e-2); + if (unstable_check_Q) { // energy is increasing + std::cout << std::endl << std::endl << bold << red << " Simulation is unstable" << std::endl; + break; + } + energy = energy_n; + std::cout << std::endl << std::endl; + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << std::endl << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/HeterogeneousGar6more2DIHHOSecondOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/HeterogeneousGar6more2DIHHOSecondOrder.hpp new file mode 100644 index 00000000..d6648bcf --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/HeterogeneousGar6more2DIHHOSecondOrder.hpp @@ -0,0 +1,314 @@ + + +// Created by Romain Mottier + +void HeterogeneousGar6more2DIHHOSecondOrder(int argc, char **argv); + +void HeterogeneousGar6more2DIHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 3.0; + RealType ly = 3.0; + size_t nx = 3; + size_t ny = 3; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.5, -1.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // fluid mass density + vp = std::sqrt(3.0); // seismic compressional velocity vp + vs = 1.0; // seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // fluid mass density + vp = std::sqrt(9.0); // seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + static_vector f{0,0}; + return f; + }; + auto null_s_fun = [](const mesh_type::point_type& pt) -> RealType { + return 0; + }; + + auto u_s_fun = [](const mesh_type::point_type& pt) -> RealType { + RealType x,y,xc,yc,r,wave,vx,vy,v,c,lp,factor; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 2.0/3.0; + c = 10.0; + lp = std::sqrt(9.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + factor = (lp*lp/(2.0*M_PI*M_PI)); + return factor*wave; + }; + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) + { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + if (bar.y() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + }else{ + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + }else{ + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) + { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + }else{ + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // Solving a primal HHO mixed problem + + + tc.tic(); + auto assembler = elastoacoustic_two_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << "Coupling Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial scalar, velocity and acceleration + Matrix u_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, u_dof_n, null_fun, u_s_fun); + assembler.project_over_faces(msh, u_dof_n, null_fun, u_s_fun); + assembler.project_over_cells(msh, v_dof_n, null_fun, null_s_fun); + assembler.project_over_faces(msh, v_dof_n, null_fun, null_s_fun); + assembler.project_over_cells(msh, a_dof_n, null_fun, null_s_fun); + assembler.project_over_faces(msh, a_dof_n, null_fun, null_s_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_inhomogeneous_two_fields_"; + postprocessor::write_silo_two_fields_elastoacoustic(silo_file_name, it, msh, hho_di, v_dof_n, e_material, a_material, false); + } + + std::ofstream simulation_log("elasto_acoustic_inhomogeneous_two_fields.txt"); + + std::ofstream sensor_1_log("s1_elasto_acoustic_two_fields_h.csv"); + std::ofstream sensor_2_log("s2_elasto_acoustic_two_fields_h.csv"); + std::ofstream sensor_3_log("s3_elasto_acoustic_two_fields_h.csv"); + bool e_side_Q = false; + typename mesh_type::point_type s1_pt(-1.0/3.0, +1.0/3.0); + typename mesh_type::point_type s2_pt( 0.0, +1.0/3.0); + typename mesh_type::point_type s3_pt(+1.0/3.0, +1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_velocity_data_elasto_acoustic_two_fields(0, s1_pt_cell, msh, hho_di, assembler, u_dof_n, v_dof_n, e_side_Q, sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_two_fields(0, s2_pt_cell, msh, hho_di, assembler, u_dof_n, v_dof_n, e_side_Q, sensor_2_log); + postprocessor::record_velocity_data_elasto_acoustic_two_fields(0, s3_pt_cell, msh, hho_di, assembler, u_dof_n, v_dof_n, e_side_Q, sensor_3_log); + +// if (sim_data.m_report_energy_Q) { +// postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); +// } + + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun); + SparseMatrix Kg = assembler.LHS; + SparseMatrix C = assembler.COUPLING; + + assembler.LHS *= beta*(dt*dt); + assembler.LHS += gamma*dt*C; + assembler.LHS += assembler.MASS; + linear_solver analysis; + if (sim_data.m_sc_Q) { + analysis.set_Kg(assembler.LHS, assembler.get_n_face_dof()); + + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + analysis.condense_equations(vec_cell_basis_data); + }else{ + analysis.set_Kg(assembler.LHS); + } +// analysis.set_iterative_solver(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*it+ti; + + tc.tic(); + assembler.RHS.setZero(); + assembler.apply_bc(msh); + + // Compute intermediate state for scalar and rate + u_dof_n = u_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*u_dof_n; + Matrix res_v = C*v_dof_n; + assembler.RHS -= res; + assembler.RHS -= res_v; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update scalar and rate + u_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_two_fields_"; + postprocessor::write_silo_two_fields_elastoacoustic(silo_file_name, it, msh, hho_di, v_dof_n, e_material, a_material, false); + } + + postprocessor::record_velocity_data_elasto_acoustic_two_fields(it, s1_pt_cell, msh, hho_di, assembler, u_dof_n, v_dof_n, e_side_Q, sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_two_fields(it, s2_pt_cell, msh, hho_di, assembler, u_dof_n, v_dof_n, e_side_Q, sensor_2_log); + postprocessor::record_velocity_data_elasto_acoustic_two_fields(it, s3_pt_cell, msh, hho_di, assembler, u_dof_n, v_dof_n, e_side_Q, sensor_3_log); + +// if (sim_data.m_report_energy_Q) { +// postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); +// } + + } + + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + + return 0; + +} diff --git a/apps/wave_propagation/src/prototypes/coupling/IHHOSecondOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/IHHOSecondOrder.hpp new file mode 100644 index 00000000..9bff807b --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/IHHOSecondOrder.hpp @@ -0,0 +1,301 @@ + +// Created by Romain Mottier + +void IHHOSecondOrder(int argc, char **argv); + +void IHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + scal_vec_analytic_functions functions; + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + RealType t = ti; + + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto a_fun = functions.Evaluate_a(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_a_fun = functions.Evaluate_s_a(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // fluid mass density + vp = std::sqrt(3.0); // seismic compressional velocity vp + vs = 1.0; // seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // fluid mass density + vp = 1.0; // seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) + { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.x()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + if (bar.x() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + }else{ + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.x() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + }else{ + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) + { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.x() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + }else{ + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, u_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, s_u_fun); + + // Solving a primal HHO mixed problem + + + tc.tic(); + auto assembler = elastoacoustic_two_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << "Coupling Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial scalar, velocity and acceleration + Matrix u_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, u_dof_n, u_fun, s_u_fun); + assembler.project_over_faces(msh, u_dof_n, u_fun, s_u_fun); + assembler.project_over_cells(msh, v_dof_n, v_fun, s_v_fun); + assembler.project_over_faces(msh, v_dof_n, v_fun, s_v_fun); + assembler.project_over_cells(msh, a_dof_n, a_fun, s_a_fun); + assembler.project_over_faces(msh, a_dof_n, a_fun, s_a_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_two_fields_"; + postprocessor::write_silo_two_fields_elastoacoustic(silo_file_name, it, msh, hho_di, v_dof_n, e_material, a_material, false); + } + + std::ofstream simulation_log("elasto_acoustic_two_fields.txt"); + +// if (sim_data.m_report_energy_Q) { +// postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); +// } + + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, f_fun, s_f_fun); + SparseMatrix Kg = assembler.LHS; + SparseMatrix C = assembler.COUPLING; + + assembler.LHS *= beta*(dt*dt); + assembler.LHS += gamma*dt*C; + assembler.LHS += assembler.MASS; + linear_solver analysis; + if (sim_data.m_sc_Q) { + analysis.set_Kg(assembler.LHS, assembler.get_n_face_dof()); + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + analysis.condense_equations(vec_cell_basis_data); + }else{ + analysis.set_Kg(assembler.LHS); + } +// analysis.set_iterative_solver(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*it+ti; + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + auto s_u_fun = functions.Evaluate_s_u(t); + auto s_v_fun = functions.Evaluate_s_v(t); + auto s_f_fun = functions.Evaluate_s_f(t); + auto s_flux_fun = functions.Evaluate_s_q(t); + + + tc.tic(); + assembler.get_e_bc_conditions().updateDirichletFunction(u_fun, 0); + assembler.get_a_bc_conditions().updateDirichletFunction(s_u_fun, 0); + assembler.assemble_rhs(msh, f_fun, s_f_fun); + + // Compute intermediate state for scalar and rate + u_dof_n = u_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*u_dof_n; + Matrix res_v = C*v_dof_n; + assembler.RHS -= res; + assembler.RHS -= res_v; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update scalar and rate + u_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_two_fields_"; + postprocessor::write_silo_two_fields_elastoacoustic(silo_file_name, it, msh, hho_di, v_dof_n, e_material, a_material, false); + } + +// if (sim_data.m_report_energy_Q) { +// postprocessor::compute_acoustic_energy_one_field(msh, hho_di, assembler, t, p_dof_n, v_dof_n, simulation_log); +// } + + if(it == nt){ + postprocessor::compute_errors_two_fields_elastoacoustic(msh, hho_di, assembler, u_dof_n, u_fun, flux_fun, s_u_fun, s_flux_fun, simulation_log); + } + + } + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + + return 0; + +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/Pulse/ConicWavesEHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Pulse/ConicWavesEHHOFirstOrder.hpp new file mode 100644 index 00000000..6f09fca9 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Pulse/ConicWavesEHHOFirstOrder.hpp @@ -0,0 +1,485 @@ + + +// Created by Romain Mottier + +// source /opt/intel/oneapi/setvars.sh intel64 +// ../../../elastoacoustic -k 3 -s 0 -r 0 -c 0 -p 0 -l 0 -n 1400 -f 0 -e 0 + +void ConicWavesEHHOFirstOrder(int argc, char **argv); + +void ConicWavesEHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " EXPLICIT PULSE - COUPLING - GEOPHYSIC" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + DBSetDeprecateWarnings(0); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l2_0.4.txt"); // l = 0 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l3_0.21.txt"); // l = 1 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l4_0.096.txt"); // l = 2 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l5_0.0485.txt"); // l = 3 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l6_0.024.txt"); // l = 4 + + // mesh_files.push_back("../../meshes/pulse/poly/poly_l2.txt"); // -l 0 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l3.txt"); // -l 1 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l4.txt"); // -l 2 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l5.txt"); // -l 3 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l6.txt"); // -l 4 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l7.txt"); // -l 5 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + // RealType lx = 5000.0; + // RealType ly = 3500.0; + RealType lx = 7500.0; + RealType ly = 5250.0; + // size_t nx = 140; + // size_t ny = 140; + size_t nx = 322/2; // k= 4 -> 224 + size_t ny = 322/2; + cartesian_2d_mesh_builder mesh_builder(lx, ly, nx, ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + // mesh_builder.set_translation_data(-2500.0, -2500.0); + mesh_builder.set_translation_data(-3750.0, -3750.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = sim_data.m_nt_divs; + RealType ti = 0.0; + RealType tf = 0.625; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto water_mat_fun = [](const typename disk::mesh>::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp; + rho = 1025.0; + vp = 1500.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2690.0; + vp = 6000.0; + vs = 3000.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = water_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = granit_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + if (bar.y() > 0) { + acoustic_internal_faces.insert(fc_id); + } + else { + elastic_internal_faces.insert(fc_id); + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary Condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_v = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 100.0; + fc = 10.0; + c = 10.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + Matrix x_dof; + // Acoustic pulse intialized in pressure + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, pulse_geophysic_v); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + std::cout << std::endl << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "Explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "A_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(-2300, 100); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + + std::ostringstream filename_int; + filename_int << "I_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_1_log(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-1300, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "E_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(-2300, -200); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + + bool sensors = true; + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + erk_an.erk_weight(yn, ki); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + int silo_mod = static_cast(std::round(nt / 50.0)); // Number of silo files + if ((!sim_data.m_render_silo_files_Q && (it == 1 || it == std::round(nt/2) || it == nt)) || ((sim_data.m_render_silo_files_Q && (it%silo_mod == 0)) || it == nt)) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + } + + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/Pulse/ConicWavesIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Pulse/ConicWavesIHHOFirstOrder.hpp new file mode 100644 index 00000000..baceec2c --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Pulse/ConicWavesIHHOFirstOrder.hpp @@ -0,0 +1,553 @@ + + +// Created by Romain Mottier + +// source /opt/intel/oneapi/setvars.sh intel64 +// ../../../elastoacoustic -k 3 -s 1 -r 1 -c 1 -p 0 -l 0 -n 8 -f 1 -e 0 + +void ConicWavesIHHOFirstOrder(int argc, char **argv); + +void ConicWavesIHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " IMPLICIT PULSE - COUPLING - GEOPHYSIC" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + DBSetDeprecateWarnings(0); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l2_0.4.txt"); // l = 0 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l3_0.21.txt"); // l = 1 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l4_0.096.txt"); // l = 2 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l5_0.0485.txt"); // l = 3 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l6_0.024.txt"); // l = 4 + + // mesh_files.push_back("../../meshes/pulse/poly/poly_l2.txt"); // -l 0 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l3.txt"); // -l 1 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l4.txt"); // -l 2 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l5.txt"); // -l 3 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l6.txt"); // -l 4 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l7.txt"); // -l 5 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + // RealType lx = 5000.0; + // RealType ly = 3500.0; + RealType lx = 7500.0; + RealType ly = 5250.0; + // size_t nx = 140; + // size_t ny = 140; + size_t nx = 322/4; //250;// 322; // k= 4 -> 224 + size_t ny = 322/4; //175;// 322; + cartesian_2d_mesh_builder mesh_builder(lx, ly, nx, ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + // mesh_builder.set_translation_data(-2500.0, -2500.0); + mesh_builder.set_translation_data(-3750.0, -3750.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = sim_data.m_nt_divs; + nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + + RealType ti = 0.0; + RealType tf = 1.0; //0.625; // 0.425; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto water_mat_fun = [](const typename disk::mesh>::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp; + rho = 1025.0; + vp = 1500.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2690.0; + vp = 6000.0; + vs = 3000.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = water_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = granit_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary Condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_v = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 100.0; // 100.0; + fc = 10.0; + c = 1.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_p = [](const disk::mesh>::point_type& pt) -> double { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 200.0; // 100.0; + fc = 10.0; + c = 1.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + return wave; + }; + + Matrix x_dof; + // Acoustic pulse intialized in pressure + // assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, pulse_geophysic_v); + // assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, pulse_geophysic_p, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, pulse_geophysic_p); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, false); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) + dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations = " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "AP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(-2300.0, 100.0); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + std::ostringstream filename_acou2; + filename_acou2 << "AV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str2 = filename_acou2.str(); + std::ofstream Acoustic_sensor_2_log(filename_acou_str2); + typename mesh_type::point_type Acoustic_s2_pt(-2300.0, 100.0); + std::pair Acoustic_s2_pt_cell = std::make_pair(Acoustic_s2_pt, -1); + + std::ostringstream filename_int; + filename_int << "IP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_pressure.csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_acoustic_pressure(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-1300.0, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + std::ostringstream filename_int2; + filename_int2 << "IAV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_velocity.csv"; + std::string filename_int_str2 = filename_int2.str(); + std::ofstream Interface_sensor_acoustic_velocity(filename_int_str2); + typename mesh_type::point_type Interface_s2_pt(-1300.0, 0.0); + std::pair Interface_s2_pt_cell = std::make_pair(Interface_s2_pt, -1); + std::ostringstream filename_int3; + filename_int3 << "IEV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_velocity.csv"; + std::string filename_int_str3 = filename_int3.str(); + std::ofstream Interface_sensor_elastic_velocity(filename_int_str3); + typename mesh_type::point_type Interface_s3_pt(-1300.0, 0.0); + std::pair Interface_s3_pt_cell = std::make_pair(Interface_s3_pt, -1); + std::ostringstream filename_int4; + filename_int4 << "IS_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_stress.csv"; + std::string filename_int_str4 = filename_int4.str(); + std::ofstream Interface_sensor_elastic_stress(filename_int_str4); + typename mesh_type::point_type Interface_s4_pt(-1300.0, 0.0); + std::pair Interface_s4_pt_cell = std::make_pair(Interface_s4_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "EV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(-2300.0, -200.0); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + std::ostringstream filename_ela2; + filename_ela2 << "ES_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str2 = filename_ela2.str(); + std::ofstream Elastic_sensor_2_log(filename_ela_str2); + typename mesh_type::point_type Elastic_s2_pt(-2300.0, -200.0); + std::pair Elastic_s2_pt_cell = std::make_pair(Elastic_s2_pt, -1); + + bool sensors = true; + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_pressure); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " SDIRK step completed: " << tc << " seconds" << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + int silo_mod = static_cast(std::round(nt / 50.0)); // Number of silo files + if ((it == 1 || it == std::round(nt/2) || it == nt) || (sim_data.m_render_silo_files_Q && (it%silo_mod == 0))) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_pressure); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << reset << std::endl << std::endl; + +} + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/Pulse/HeterogeneousEHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Pulse/HeterogeneousEHHOFirstOrder.hpp new file mode 100644 index 00000000..f1afb308 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Pulse/HeterogeneousEHHOFirstOrder.hpp @@ -0,0 +1,531 @@ + + +// Created by Romain Mottier +// ../wave_propagation -k 2 -s 0 -r 0 -c 0 -p 0 -l 6 -n 2500 -f 1 -e 0 + +void HeterogeneousEHHOFirstOrder(int argc, char **argv); + +void HeterogeneousEHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " EXPLICIT PULSE - COUPLING" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l2_0.4.txt"); // l = 0 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l3_0.21.txt"); // l = 1 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l4_0.096.txt"); // l = 2 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l5_0.0485.txt"); // l = 3 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l6_0.024.txt"); // l = 4 + + // mesh_files.push_back("../../meshes/pulse/poly/poly_l2.txt"); // -l 0 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l3.txt"); // -l 1 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l4.txt"); // -l 2 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l5.txt"); // -l 3 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l6.txt"); // -l 4 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l7.txt"); // -l 5 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 1; + RealType ly = 1; + size_t nx = 2; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-0.5, -0.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 0.25; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + auto water_mat_fun_adi = [](const typename disk::mesh>::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp; + rho = 1.0; + vp = 1.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun_adi = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2.624390244; + vp = 4.0; + vs = 2.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + // acoustic_material_data material = water_mat_fun_adi(bar); + acoustic_material_data material = acoustic_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + // elastic_material_data material = granit_mat_fun_adi(bar); + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + if (bar.y() > 0) { + acoustic_internal_faces.insert(fc_id); + } + else { + elastic_internal_faces.insert(fc_id); + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) { + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + auto v_fun_adi_acoustic = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.125; // 0.1; + fc = 10.0; + c = 10; + vp = std::sqrt(1.0); + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + Matrix x_dof; + // Acoustic pulse intialized in pressure + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, v_fun_adi_acoustic); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + // Elastic pulse intialized in pressure + // assembler.project_over_cells(msh, x_dof, v_fun, null_flux_fun, null_s_fun, null_fun); + // assembler.project_over_faces(msh, x_dof, v_fun, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "Explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log.flush(); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "A_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(-0.15, 0.1); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + + std::ostringstream filename_int; + filename_int << "I_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_1_log(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-0.15, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "E_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(-0.15, -0.1); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + + bool sensors = false; + if (sensors) { + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c; + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + erk_an.erk_weight(yn, ki); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + if (it == nt) { + std::ostringstream silo; + silo << "Silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_str = silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_str, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/Pulse/HeterogeneousIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/coupling/Pulse/HeterogeneousIHHOFirstOrder.hpp new file mode 100644 index 00000000..b7a7662f --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Pulse/HeterogeneousIHHOFirstOrder.hpp @@ -0,0 +1,680 @@ + + +// Created by Romain Mottier + +// source /opt/intel/oneapi/setvars.sh intel64 +// ../wave_propagation -k 2 -s 1 -r 1 -c 1 -p 0 -l 6 -n 7 -f 1 -e 0 + +void HeterogeneousIHHOFirstOrder(int argc, char **argv); + +void HeterogeneousIHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " IMPLICIT PULSE - COUPLING" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l2_0.4.txt"); // l = 0 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l3_0.21.txt"); // l = 1 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l4_0.096.txt"); // l = 2 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l5_0.0485.txt"); // l = 3 + mesh_files.push_back("../../meshes/pulse/simplices/simplex_l6_0.024.txt"); // l = 4 + + // mesh_files.push_back("../../meshes/pulse/poly/poly_l2.txt"); // -l 0 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l3.txt"); // -l 1 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l4.txt"); // -l 2 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l5.txt"); // -l 3 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l6.txt"); // -l 4 + // mesh_files.push_back("../../meshes/pulse/poly/poly_l7.txt"); // -l 5 + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 1; + RealType ly = 1; + size_t nx = 2; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-0.5, -0.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) + nt *= 2; + + RealType ti = 0.0; + RealType tf = 1.0; //0.5; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun_adi_water = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0/2.00; // Fluid mass density + vp = 1.0/2.00; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun_adi_water = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2.6/2.00; + vp = 4.0/2.00; + vs = 2.0/2.00; + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun_adi_air = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0/15; // 2.75; // Fluid mass density + vp = 1.0/15; // 2.75; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun_adi_air = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2200.0/15; // 2.75; + vp = 17.5/15; // 2.75; + vs = 9.0/15; // 2.75; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = acoustic_mat_fun(bar); + // acoustic_material_data material = acoustic_mat_fun_adi_water(bar); + // acoustic_material_data material = acoustic_mat_fun_adi_air(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = elastic_mat_fun(bar); + // elastic_material_data material = granit_mat_fun_adi_water(bar); + // elastic_material_data material = granit_mat_fun_adi_air(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + // No contrast case + auto v_fun_acoustic = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.125; // 0.1; + fc = 10.0; + c = 10; + vp = 1.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + // Contrasted case + auto v_fun_acoustic_water = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.125; // 0.1; + fc = 10.0; + c = 10; + vp = 1.0/2.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + // Contrasted case + auto v_fun_acoustic_air = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.125; // 0.1; + fc = 10.0; + c = 10; + vp = 1.0/15; // 2.75; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + // No contrast case + auto v_fun_elastic = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = -0.125; + fc = 10.0; + c = 10; + vp = std::sqrt(3.0); + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + auto v_fun_elastic_granit_water = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = -0.125; + fc = 10.0; + c = 10; + vp = 4.0/2.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + auto v_fun_elastic_granit_air = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x,y,xc,yc,r,wave,vx,vy,c,lp, fc, vp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = -0.125; + fc = 10.0; + c = 10; + vp = 17.5/15; // 2.75; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + Matrix x_dof; + // // Acoustic pulse intialized in velocity + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, v_fun_acoustic); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + // Elastic pulse intialized in velocity + // assembler.project_over_cells(msh, x_dof, v_fun_elastic_granit_air, null_flux_fun, null_s_fun, null_fun); + // assembler.project_over_faces(msh, x_dof, v_fun_elastic_granit_air, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + if (is_sdirk_Q) + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + else + dirk_butcher_tableau::dirk_tables(s, a, b, c); + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, false); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) + dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "AP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(-0.1, 0.05); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + std::ostringstream filename_acou2; + filename_acou2 << "AV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str2 = filename_acou2.str(); + std::ofstream Acoustic_sensor_2_log(filename_acou_str2); + typename mesh_type::point_type Acoustic_s2_pt(-0.1, 0.05); + std::pair Acoustic_s2_pt_cell = std::make_pair(Acoustic_s2_pt, -1); + + std::ostringstream filename_int; + filename_int << "IP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_pressure.csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_acoustic_pressure(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-0.1, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + std::ostringstream filename_int2; + filename_int2 << "IAV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_velocity.csv"; + std::string filename_int_str2 = filename_int2.str(); + std::ofstream Interface_sensor_acoustic_velocity(filename_int_str2); + typename mesh_type::point_type Interface_s2_pt(-0.1, 0.0); + std::pair Interface_s2_pt_cell = std::make_pair(Interface_s2_pt, -1); + std::ostringstream filename_int3; + filename_int3 << "IEV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_velocity.csv"; + std::string filename_int_str3 = filename_int3.str(); + std::ofstream Interface_sensor_elastic_velocity(filename_int_str3); + typename mesh_type::point_type Interface_s3_pt(-0.1, 0.0); + std::pair Interface_s3_pt_cell = std::make_pair(Interface_s3_pt, -1); + std::ostringstream filename_int4; + filename_int4 << "IS_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_stress.csv"; + std::string filename_int_str4 = filename_int4.str(); + std::ofstream Interface_sensor_elastic_stress(filename_int_str4); + typename mesh_type::point_type Interface_s4_pt(-0.1, 0.0); + std::pair Interface_s4_pt_cell = std::make_pair(Interface_s4_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "EV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(-0.1, -0.05); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + std::ostringstream filename_ela2; + filename_ela2 << "ES_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str2 = filename_ela2.str(); + std::ofstream Elastic_sensor_2_log(filename_ela_str2); + typename mesh_type::point_type Elastic_s2_pt(-0.1, -0.05); + std::pair Elastic_s2_pt_cell = std::make_pair(Elastic_s2_pt, -1); + + bool sensors = true; + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + postprocessor::record_acoustic_pressure_coupling_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, interface_face_indexes, Interface_sensor_acoustic_pressure); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + // DIRK step + tc.tic(); + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i), is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + tc.toc(); + std::cout << bold << cyan << " DIRK step completed: " << tc << " seconds" << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + int silo_mod = static_cast(std::round(nt / 50.0)); // Number of silo files + if (((it == 1 || it == std::round(nt/2) || it == nt)) || (sim_data.m_render_silo_files_Q && (it%silo_mod == 0))) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + postprocessor::record_acoustic_pressure_coupling_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, interface_face_indexes, Interface_sensor_acoustic_pressure); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/coupling/Pulse/IPulseEfficiency.hpp b/apps/wave_propagation/src/prototypes/coupling/Pulse/IPulseEfficiency.hpp new file mode 100644 index 00000000..2903168e --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Pulse/IPulseEfficiency.hpp @@ -0,0 +1,328 @@ + + +// Created by Romain Mottier + + +void IPulseEfficiency(int argc, char **argv); + +void IPulseEfficiency(int argc, char **argv){ + + // ###################################################################### Simulation paramaters + // ###################################################################### + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit; + + // ###################################################################### Mesh generation + // ###################################################################### + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + RealType lx = 5000.0; + RealType ly = 3500.0; + size_t nx = 140; + size_t ny = 140; + cartesian_2d_mesh_builder mesh_builder(lx, ly, nx, ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-2500.0, -2500.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.425; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ###################################################################### Assigning Material Data + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = water_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = granit_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ###################################################################### Solving a primal HHO mixed problem + // ###################################################################### + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + + // Stabilization type + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ###################################################################### Projecting initial data + // ###################################################################### + + Matrix x_dof; + + // Acoustic pulse intialized in pressure + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, pulse_geophysic_v); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + + ////////// Post process of the initial data + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + std::ofstream simulation_log("elasto_acoustic_inhomogeneous_four_fields.txt"); + std::ofstream energy_file("energy_file.txt"); + + bool e_side_Q = true; + bool a_side_Q = false; + std::ofstream Acoustic_sensor_1_log("Acoustic.csv"); + std::ofstream Interface_sensor_1_log("Interface.csv"); + std::ofstream Elastic_sensor_1_log("Elastic.csv"); + typename mesh_type::point_type Acoustic_s1_pt(-500, 250); + typename mesh_type::point_type Interface_s1_pt(-500, 0.0); + typename mesh_type::point_type Elastic_s1_pt(-500, -250); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << std::endl << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, false); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + // dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Time marching + // ################################################## + + std::cout << std::endl << std::endl; + + Matrix x_dof_n; + + for(size_t it = 1; it <= nt; it++) { + + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t + << reset; + + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + // std::cout << std::endl << bold << cyan << " DIRK step completed: " << tc << " seconds" + // << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Acoustic_sensor_1_log); + + t += dt; + + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + + std::cout << std::endl; + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + } + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of equations: " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + diff --git a/apps/wave_propagation/src/prototypes/coupling/Pulse/review_CMAME.hpp b/apps/wave_propagation/src/prototypes/coupling/Pulse/review_CMAME.hpp new file mode 100644 index 00000000..fc223091 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/coupling/Pulse/review_CMAME.hpp @@ -0,0 +1,1007 @@ + + +// Created by Romain Mottier + +// source /opt/intel/oneapi/setvars.sh intel64 +// ../../../elastoacoustic -k 3 -s 1 -r 1 -c 1 -p 0 -l 0 -n 8 -f 1 -e 0 + +void ConicWavesIHHOFirstOrder_review(int argc, char **argv); +void ConicWavesIHHOFirstOrder_review(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " IMPLICIT PULSE - COUPLING - GEOPHYSIC" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + DBSetDeprecateWarnings(0); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + RealType lx = 3800.0; + RealType ly = 2600.0; + size_t nx = 76; + size_t ny = 52; + cartesian_2d_mesh_builder mesh_builder(lx, ly, nx, ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1800.0, -1600.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = sim_data.m_nt_divs; + nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + + RealType ti = 0.0; + RealType tf = 0.5; //0.625; // 0.425; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto water_mat_fun = [](const typename disk::mesh>::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp; + rho = 1025.0; + vp = 1500.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2690.0; + vp = 6000.0; + vs = 3000.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = water_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = granit_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) + interface_cell_pair_indexes[fc_id].second = cell_ind; + else + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary Condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_v = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 100.0; // 100.0; + fc = 10.0; + c = 1.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_p = [](const disk::mesh>::point_type& pt) -> double { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 200.0; // 100.0; + fc = 10.0; + c = 1.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + return wave; + }; + + Matrix x_dof; + // Acoustic pulse intialized in pressure + // assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, pulse_geophysic_v); + // assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, pulse_geophysic_p, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, pulse_geophysic_p); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: source /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) + dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations = " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "AP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(500.0, 200.0); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + std::ostringstream filename_acou2; + filename_acou2 << "AV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str2 = filename_acou2.str(); + std::ofstream Acoustic_sensor_2_log(filename_acou_str2); + typename mesh_type::point_type Acoustic_s2_pt(500.0, 200.0); + std::pair Acoustic_s2_pt_cell = std::make_pair(Acoustic_s2_pt, -1); + + std::ostringstream filename_int; + filename_int << "IP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_pressure.csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_acoustic_pressure(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-400.0, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + std::ostringstream filename_int2; + filename_int2 << "IAV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_velocity.csv"; + std::string filename_int_str2 = filename_int2.str(); + std::ofstream Interface_sensor_acoustic_velocity(filename_int_str2); + typename mesh_type::point_type Interface_s2_pt(-400.0, 0.0); + std::pair Interface_s2_pt_cell = std::make_pair(Interface_s2_pt, -1); + std::ostringstream filename_int3; + filename_int3 << "IEV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_velocity.csv"; + std::string filename_int_str3 = filename_int3.str(); + std::ofstream Interface_sensor_elastic_velocity(filename_int_str3); + typename mesh_type::point_type Interface_s3_pt(-400.0, 0.0); + std::pair Interface_s3_pt_cell = std::make_pair(Interface_s3_pt, -1); + std::ostringstream filename_int4; + filename_int4 << "IS_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_stress.csv"; + std::string filename_int_str4 = filename_int4.str(); + std::ofstream Interface_sensor_elastic_stress(filename_int_str4); + typename mesh_type::point_type Interface_s4_pt(-400.0, 0.0); + std::pair Interface_s4_pt_cell = std::make_pair(Interface_s4_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "EV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(1000.0, -500.0); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + std::ostringstream filename_ela2; + filename_ela2 << "ES_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str2 = filename_ela2.str(); + std::ofstream Elastic_sensor_2_log(filename_ela_str2); + typename mesh_type::point_type Elastic_s2_pt(-1000.0, -500.0); + std::pair Elastic_s2_pt_cell = std::make_pair(Elastic_s2_pt, -1); + + bool sensors = true; + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_pressure); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " SDIRK step completed: " << tc << " seconds" << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + int silo_mod = static_cast(std::round(nt / 50.0)); // Number of silo files + if ((it == 1 || it == std::round(nt/2) || it == nt) || (sim_data.m_render_silo_files_Q && (it%silo_mod == 0))) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_pressure); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << reset << std::endl << std::endl; + +} + + + + +void ConicWavesEHHOFirstOrder_review(int argc, char **argv); +void ConicWavesEHHOFirstOrder_review(int argc, char **argv){ + + // ###################################################################### + // ###################################################################### Simulation paramaters + // ###################################################################### + + std::cout << std::endl << bold << red << " EXPLICIT PULSE - COUPLING - GEOPHYSIC" << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit, cpu; + cpu.tic(); + DBSetDeprecateWarnings(0); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + RealType lx = 3800.0; + RealType ly = 2600.0; + size_t nx = 76; + size_t ny = 52; + cartesian_2d_mesh_builder mesh_builder(lx, ly, nx, ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1800.0, -1600.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) + h = h_l; + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ###################################################################### + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = sim_data.m_nt_divs; + RealType ti = 0.0; + RealType tf = 0.5; //0.625; // 0.425; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) + cell_k_degree++; + disk::hho_degree_info hho_di(cell_k_degree, sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + auto water_mat_fun = [](const typename disk::mesh>::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp; + rho = 1025.0; + vp = 1500.0; + acoustic_material_data material(rho,vp); + return material; + }; + + auto granit_mat_fun = [](const typename disk::mesh>::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + double rho, vp, vs; + rho = 2690.0; + vp = 6000.0; + vs = 3000.0; + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ###################################################################### + // ###################################################################### Structure setting + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + RealType eps = 1.0e-10; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (std::fabs(bar.y()) < eps) { + interface_face_indexes.insert(fc_id); + continue; + } + } + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + + // Assigning the material properties + if (bar.y() > 0) { + acoustic_material_data material = water_mat_fun(bar); + a_material.insert(std::make_pair(cell_ind,material)); + } + else { + elastic_material_data material = granit_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + if (bar.y() > 0) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + else { + interface_cell_pair_indexes[fc_id].first = cell_ind; + } + } + } + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + if (bar.y() > 0) { + acoustic_internal_faces.insert(fc_id); + } + else { + elastic_internal_faces.insert(fc_id); + } + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + if (bar.y() > 0) { + disk::boundary_descriptor bi{bc_acoustic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + acoustic_bc_face_indexes.insert(fc_id); + } + else { + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + } + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Boundary Condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q) + assembler.set_scaled_stabilization(); + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### + // ###################################################################### Projecting initial data + // ###################################################################### + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_v = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 100.0; // 100.0; + fc = 10.0; + c = 1.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + disk::static_vector v{vx,vy}; + return v; + }; + + // Acoustic pulse - Heterogeneous domain - Fluide = Eau + auto pulse_geophysic_p = [](const disk::mesh>::point_type& pt) -> double { + double x, y, xc, yc, r, wave, vp, lp, fc, c, vx, vy; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 200.0; // 100.0; + fc = 10.0; + c = 1.0; + vp = 1500.0; + lp = vp/fc; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + return wave; + }; + + Matrix x_dof; + // Acoustic pulse intialized in pressure + // assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, pulse_geophysic_v); + // assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, pulse_geophysic_p, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, pulse_geophysic_p); + + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + std::cout << std::endl << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = assembler.get_a_n_cells_dof(); + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = assembler.get_a_face_dof(); + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "Explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + size_t it = 0; + std::ostringstream filename_silo; + filename_silo << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename_silo.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Sensors + // ################################################## + + bool e_side_Q = true; + bool a_side_Q = false; + + std::ostringstream filename_acou; + filename_acou << "AP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str = filename_acou.str(); + std::ofstream Acoustic_sensor_1_log(filename_acou_str); + typename mesh_type::point_type Acoustic_s1_pt(500.0, 200.0); + std::pair Acoustic_s1_pt_cell = std::make_pair(Acoustic_s1_pt, -1); + std::ostringstream filename_acou2; + filename_acou2 << "AV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_acou_str2 = filename_acou2.str(); + std::ofstream Acoustic_sensor_2_log(filename_acou_str2); + typename mesh_type::point_type Acoustic_s2_pt(500.0, 200.0); + std::pair Acoustic_s2_pt_cell = std::make_pair(Acoustic_s2_pt, -1); + + std::ostringstream filename_int; + filename_int << "IP_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_pressure.csv"; + std::string filename_int_str = filename_int.str(); + std::ofstream Interface_sensor_acoustic_pressure(filename_int_str); + typename mesh_type::point_type Interface_s1_pt(-400.0, 0.0); + std::pair Interface_s1_pt_cell = std::make_pair(Interface_s1_pt, -1); + std::ostringstream filename_int2; + filename_int2 << "IAV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_acoustic_velocity.csv"; + std::string filename_int_str2 = filename_int2.str(); + std::ofstream Interface_sensor_acoustic_velocity(filename_int_str2); + typename mesh_type::point_type Interface_s2_pt(-400.0, 0.0); + std::pair Interface_s2_pt_cell = std::make_pair(Interface_s2_pt, -1); + std::ostringstream filename_int3; + filename_int3 << "IEV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_velocity.csv"; + std::string filename_int_str3 = filename_int3.str(); + std::ofstream Interface_sensor_elastic_velocity(filename_int_str3); + typename mesh_type::point_type Interface_s3_pt(-400.0, 0.0); + std::pair Interface_s3_pt_cell = std::make_pair(Interface_s3_pt, -1); + std::ostringstream filename_int4; + filename_int4 << "IS_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_elastic_stress.csv"; + std::string filename_int_str4 = filename_int4.str(); + std::ofstream Interface_sensor_elastic_stress(filename_int_str4); + typename mesh_type::point_type Interface_s4_pt(-400.0, 0.0); + std::pair Interface_s4_pt_cell = std::make_pair(Interface_s4_pt, -1); + + std::ostringstream filename_ela; + filename_ela << "EV_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str = filename_ela.str(); + std::ofstream Elastic_sensor_1_log(filename_ela_str); + typename mesh_type::point_type Elastic_s1_pt(1000.0, -500.0); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + std::ostringstream filename_ela2; + filename_ela2 << "ES_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".csv"; + std::string filename_ela_str2 = filename_ela2.str(); + std::ofstream Elastic_sensor_2_log(filename_ela_str2); + typename mesh_type::point_type Elastic_s2_pt(-1000.0, -500.0); + std::pair Elastic_s2_pt_cell = std::make_pair(Elastic_s2_pt, -1); + + bool sensors = true; + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(0, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_pressure); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(0, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++) { + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + erk_an.erk_weight(yn, ki); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + int silo_mod = static_cast(std::round(nt / 50.0)); // Number of silo files + if ((!sim_data.m_render_silo_files_Q && (it == 1 || it == std::round(nt/2) || it == nt)) || ((sim_data.m_render_silo_files_Q && (it%silo_mod == 0)) || it == nt)) { + std::ostringstream filename; + filename << "silo_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_"; + std::string silo_file_name = filename.str(); + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + if (sensors) { + // Acoustic sensor + postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Acoustic_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_1_log); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Acoustic_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Acoustic_sensor_2_log); + // Interface sensor + // postprocessor::record_acoustic_data_elasto_acoustic_four_fields(it, Interface_s1_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_pressure); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_velocity); + // postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Interface_s2_pt_cell, msh, hho_di, assembler, x_dof, a_side_Q, Interface_sensor_acoustic_velocity); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Interface_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Interface_sensor_elastic_stress); + // Elastic sensor + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + // postprocessor::record_elastic_data_elasto_acoustic_four_fields(it, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + } + + if (sim_data.m_report_energy_Q) + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + t += dt; + + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/elastic/EElastic_stability.hpp b/apps/wave_propagation/src/prototypes/elastic/EElastic_stability.hpp new file mode 100644 index 00000000..082fb497 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/elastic/EElastic_stability.hpp @@ -0,0 +1,405 @@ + +// Created by Romain Mottier + +void EElastic_stability(int argc, char **argv); + +void EElastic_stability(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " ELASTICITY STABILITY" << reset << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + cpu.tic(); + tc.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Zero source terms, to keep the system energy constant + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Elastic analytical functions + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + + // Stabilization type + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + auto acoustic_mat_fun = [](const typename mesh_type::point_type& pt) -> acoustic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp; + rho = 1.0; // Fluid mass density + vp = 1.0; // Seismic compressional velocity vp + acoustic_material_data material(rho,vp); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + + // Internal faces structure + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, v_fun, null_s_fun); + + // ################################################## + // ################################################## Setting of the time marching scheme + // ################################################## + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // ERK(s) schemes + int s = 4; + erk_butcher_tableau::erk_tables(s, a, b, c); + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun, true); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = 0.0; + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = 0.0; + + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes);//assembler.get_interfaces()); + + tc.toc(); + std::cout << bold << cyan << " ERK analysis created: " << tc << " seconds" << reset << std::endl; + tc.tic(); + erk_an.refresh_faces_unknowns(x_dof); + tc.toc(); + std::cout << bold << cyan << " Inverse of Sff + Coupling in: " << tc << " seconds" << reset << std::endl; + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material,false); + std::cout << std::endl; + } + + std::ostringstream filename; + filename << "E_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "h size = " << h << std::endl; + simulation_log << "CFL c(dt/h) = " << std::sqrt(3.0)*dt/h << std::endl; + // auto block_dimension = assembler.Scc_block_dimension(); + // erk_an.compute_eigenvalues_bis(assembler.LHS_STAB, block_dimension, simulation_log); + erk_an.compute_eigenvalues(simulation_log); + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + bool approx_fail_check_Q = false; + RealType energy = energy_0; + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << red << " Time step number " << it << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // ERK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c, xd; + xd = Matrix::Zero(n_dof, 1); + + Matrix yn, ki; + x_dof_n = x_dof; + + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + t = tn + c(i,0) * dt; + { + assembler.assemble_rhs(msh, null_fun, null_s_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + } + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " ERK step completed: " << tc << " seconds" << reset; + x_dof = x_dof_n; + t = tn + dt; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + // Energy evaluation + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + bool unstable_check_Q = (relative_energy > 1.0e-2) || (relative_energy_0 >= 1.0e-2); + if (unstable_check_Q) { + std::cout << std::endl << std::endl << bold << red << " Simulation is unstable" << reset << std::endl; + break; + } + energy = energy_n; + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << std::endl << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; +} + diff --git a/apps/wave_propagation/src/prototypes/elastic/EElasticity_CFL.hpp b/apps/wave_propagation/src/prototypes/elastic/EElasticity_CFL.hpp new file mode 100644 index 00000000..49921412 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/elastic/EElasticity_CFL.hpp @@ -0,0 +1,397 @@ + + +// Created by Romain Mottier +// ../wave_propagation -k 1 -s 0 -r 0 -c 1 -p 0 -l 2 -n 350 -f 0 -e 0 + +void EElasticity_CFL(int argc, char **argv); + +void EElasticity_CFL(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " ELASTIC CFL" << std::endl << std::endl; + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc; + + // ################################################## + // ################################################## Time controls + // ################################################## + + RealType ti = 0.0; + RealType tf = 1.0; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + // functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial_paper); + + // Zero source terms, to keep the system energy constant + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + // Elastic analytical functions + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if (sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + tc.tic(); + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl << std::endl; + + // ################################################## + // ################################################## Material data + // ################################################## + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ################################################## + // ################################################## Interface detection and faces repartitions + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + RealType eps = 1.0e-10; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + // Assigning the material properties + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + // Detection of faces on the interfaces + auto cell_faces = faces(msh,cell); + for (auto face :cell_faces) { + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + interface_cell_pair_indexes[fc_id].second = cell_ind; + } + } + } + + // Internal faces structure for explicit schemes + std::set elastic_internal_faces; + std::set acoustic_internal_faces; + for (auto face_it = msh.faces_begin(); face_it != msh.faces_end(); face_it++) { + const auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + bool is_member_Q = interface_face_indexes.find(fc_id) != interface_face_indexes.end(); + if (is_member_Q) { + } + else { + elastic_internal_faces.insert(fc_id); + } + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + + // boundary condition + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ######################s########################### + + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if (sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + assembler.assemble_mass(msh); + assembler.assemble_coupling_terms(msh); + + // ################################################## + // ################################################## Setting of the time marching scheme + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, null_fun, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, null_fun, null_s_fun); + bool explicit_scheme = true; + assembler.assemble(msh, null_fun, null_s_fun, explicit_scheme); + size_t elastic_cell_dofs = assembler.get_e_n_cells_dof(); + size_t acoustic_cell_dofs = 0.0; + size_t e_face_dofs = assembler.get_e_face_dof(); + size_t a_face_dofs = 0.0; + erk_coupling_hho_scheme erk_an(assembler.LHS, assembler.RHS, assembler.MASS, assembler.COUPLING, elastic_cell_dofs, acoustic_cell_dofs, e_face_dofs, a_face_dofs); + erk_an.Mcc_inverse(assembler.get_elastic_cells(), assembler.get_acoustic_cells(), assembler.get_e_cell_basis_data(), assembler.get_a_cell_basis_data()); + erk_an.Sff_inverse(assembler.get_elastic_faces(), assembler.get_acoustic_faces(), assembler.get_e_face_basis_data(), assembler.get_a_face_basis_data(), assembler.get_e_compress(), assembler.get_a_compress(), elastic_internal_faces, acoustic_internal_faces, interface_face_indexes); + erk_an.refresh_faces_unknowns(x_dof); + + // ################################################## + // ################################################## Loop over the ERK schemes + // ################################################## + + for (int s = 2; s < 5; s++) { + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + // nt *= 2; + nt = sim_data.m_nt_divs; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "E_explicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of ERK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + // auto block_dimension = assembler.Scc_block_dimension(); + // erk_an.compute_eigenvalues_bis(assembler.LHS_STAB, block_dimension, simulation_log); + // erk_an.compute_eigenvalues(simulation_log); + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + std::cout << bold << red << " ERK(" << s << "):" << reset << std::endl << std::endl; + simulation_log << std::endl << " ERK(" << s << "):" << std::endl; + simulation_log << std::endl; + + // ################################################## + // ################################################## Loop over level of time refinement + // ################################################## + + for (unsigned int i = 0; i < 100; i++) { + + t = ti; + RealType dt = (tf-ti)/nt; + simulation_log << "Step size = " << dt << std::endl; + + // Projecting initial data + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, v_fun, null_s_fun); + + auto energy_0 = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + erk_butcher_tableau::erk_tables(s, a, b, c); + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + bool approx_fail_check_Q = false; + RealType energy = energy_0; + + for(size_t it = 1; it <= nt; it++) { + + RealType tn = dt*(it-1)+ti; + + // ERK steps + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + Matrix yn, ki; + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + RealType t = tn + c(i,0) * dt; + assembler.assemble_rhs(msh, null_fun, null_s_fun, true); + erk_an.SetFg(assembler.RHS); + erk_an.erk_weight(yn, ki); + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + x_dof = x_dof_n; + t = tn + dt; + RealType energy_n = postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + RealType relative_energy = (energy_n - energy) / energy; + RealType relative_energy_0 = (energy_n - energy_0) / energy_0; + bool unstable_check_Q = (relative_energy > 5.0e-2) || (relative_energy_0 >= 5.0e-2); + if (unstable_check_Q) { // energy is increasing + approx_fail_check_Q = true; + break; + } + energy = energy_n; + } + if (approx_fail_check_Q) { + std::cout << bold << red << " Simulation is unstable" << reset << std::endl << std::endl << std::endl; + simulation_log << std::endl; + simulation_log << " Simulation is unstable for:"<< std::endl; + simulation_log << " Number of equations: " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << h << std::endl; + simulation_log << " CFL c(dt/h) = " << std::sqrt(3.0)*dt/h << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + break; + } + else { + simulation_log << " Simulation is stable for:"<< std::endl; + simulation_log << " Number of equations: " << assembler.RHS.rows() << std::endl; + simulation_log << " Number of ERK steps = " << s << std::endl; + simulation_log << " Number of time steps = " << nt << std::endl; + simulation_log << " dt size = " << dt << std::endl; + simulation_log << " h size = " << h << std::endl; + simulation_log << " CFL c(dt/h) = " << std::sqrt(3.0)*dt/h << std::endl; + simulation_log << std::endl; + simulation_log.flush(); + std::cout << " Simulation is stable for: n = " << nt << std::endl; + nt = int(nt - (nt*1/100+1)); + continue; + // break; + } + } + simulation_log << std::endl << " ******************************* " << std::endl; + simulation_log << std::endl << std::endl; + } + +} + + diff --git a/apps/wave_propagation/src/prototypes/elastic/ElasticIHHOFirstOrder.hpp b/apps/wave_propagation/src/prototypes/elastic/ElasticIHHOFirstOrder.hpp new file mode 100644 index 00000000..ec1fdbf0 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/elastic/ElasticIHHOFirstOrder.hpp @@ -0,0 +1,308 @@ + + +// Created by Romain Mottier + +void ElasticIHHOFirstOrder(int argc, char **argv); + +void ElasticIHHOFirstOrder(int argc, char **argv){ + + // ###################################################################### Simulation paramaters + // ###################################################################### + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, tcit; + + // ###################################################################### Mesh generation + // ###################################################################### + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + Mesh_generation(sim_data, msh); + + // ###################################################################### Time controls + // ###################################################################### + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ###################################################################### HHO setting + // ###################################################################### + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ###################################################################### Assigning Material Data + // ###################################################################### + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++) { + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + + // Detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, null_fun); + a_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_acoustic_id, null_s_fun); + + // ###################################################################### Solving a primal HHO mixed problem + // ###################################################################### + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + + // Stabilization type + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + // ###################################################################### Projecting initial data + // ###################################################################### + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, sin_elastic, null_flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, sin_elastic, null_s_fun); + + ////////// Post process of the initial data + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + std::ofstream simulation_log("elasto_acoustic_inhomogeneous_four_fields.txt"); + std::ofstream energy_file("energy_file.txt"); + std::ofstream dissipation_file("dissipation_file.txt"); + + std::ofstream Elastic_sensor_1_log("Elastic_s1_four_fields_h.csv"); + std::ofstream Elastic_sensor_2_log("Elastic_s2_four_fields_h.csv"); + std::ofstream Elastic_sensor_3_log("Elastic_s3_four_fields_h.csv"); + std::ofstream Elastic_sensor_4_log("Elastic_s4_four_fields_h.csv"); + bool e_side_Q = true; + bool a_side_Q = false; + typename mesh_type::point_type Elastic_s1_pt(-7.5, -2.5); + typename mesh_type::point_type Elastic_s2_pt(-5.0, -2.5); + typename mesh_type::point_type Elastic_s3_pt(-2.5, -2.5); + typename mesh_type::point_type Elastic_s4_pt( 0.0, -2.5); + std::pair Elastic_s1_pt_cell = std::make_pair(Elastic_s1_pt, -1); + std::pair Elastic_s2_pt_cell = std::make_pair(Elastic_s2_pt, -1); + std::pair Elastic_s3_pt_cell = std::make_pair(Elastic_s3_pt, -1); + std::pair Elastic_s4_pt_cell = std::make_pair(Elastic_s4_pt, -1); + std::cout << bold << cyan << " " << "Elastic sensor at (-7.5,-2.5)" << reset << std::endl; + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + std::cout << bold << cyan << " " << "Elastic sensor at (-5.0,-2.5)" << reset << std::endl; + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + std::cout << bold << cyan << " " << "Elastic sensor at (-2.5,-2.5)" << reset << std::endl; + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_3_log); + std::cout << bold << cyan << " " << "Elastic sensor at (0.0,-2.5)" << reset << std::endl; + postprocessor::record_velocity_data_elasto_acoustic_four_fields(0, Elastic_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_4_log); + + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + postprocessor::compute_elasto_acoustic_dissipation_four_field(assembler, t, x_dof, dissipation_file); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << std::endl << std::endl; + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, null_fun, null_s_fun); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + // dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Time marching + // ################################################## + + std::cout << std::endl << std::endl; + + Matrix x_dof_n; + + for(size_t it = 1; it <= nt; it++) { + + + tcit.tic(); + std::cout << bold << red << " Time step number " << it << ": t = " << t + << reset; + + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + // std::cout << std::endl << bold << cyan << " DIRK step completed: " << tc << " seconds" + // << reset << std::endl; + + x_dof = x_dof_n; + + // ################################################## + // ################################################## Last postprocess + // ################################################## + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "elasto_acoustic_inhomogeneous_four_fields_"; + postprocessor::write_silo_four_fields_elastoacoustic(silo_file_name, it, msh, hho_di, x_dof, e_material, a_material, false); + } + + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s1_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_1_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s2_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_2_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s3_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_3_log); + postprocessor::record_velocity_data_elasto_acoustic_four_fields(it, Elastic_s4_pt_cell, msh, hho_di, assembler, x_dof, e_side_Q, Elastic_sensor_4_log); + + t += dt; + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, + t, x_dof, energy_file); + postprocessor::compute_elasto_acoustic_dissipation_four_field(assembler, t, x_dof, dissipation_file); + } + + std::cout << std::endl; + tcit.toc(); + std::cout << bold << cyan << " Iteration completed in " << tcit << " seconds" << reset << std::endl << std::endl; + + + } + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of equations: " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wave_propagation/src/prototypes/elastic/IElastic_conv_test.hpp b/apps/wave_propagation/src/prototypes/elastic/IElastic_conv_test.hpp new file mode 100644 index 00000000..3f7b995d --- /dev/null +++ b/apps/wave_propagation/src/prototypes/elastic/IElastic_conv_test.hpp @@ -0,0 +1,397 @@ + + +// Created by Romain Mottier + +void IElastic_conv_test(int argc, char **argv); + +void IElastic_conv_test(int argc, char **argv){ + + // ################################################## + // ################################################## Simulation paramaters + // ################################################## + + std::cout << std::endl << bold << red << " IMPLICIT ELASTIC CONV TEST" << std::endl; + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + timecounter tc, cpu; + + // ################################################## + // ################################################## Mesh generation + // ################################################## + + cpu.tic(); + tc.tic(); + + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions e_boundary_type; + typedef disk::BoundaryConditions a_boundary_type; + mesh_type msh; + + if (sim_data.m_polygonal_mesh_Q) { + auto validate_l = [](size_t l) -> size_t { + if ((0 <= l) && (l < 15) ) { + return l; + } + else { + std::cout << std::endl << std::endl; + std::cout << "Warning:: Only few polygonal meshes available."; + std::cout << std::endl << std::endl; + return 4; + } + }; + + size_t l = validate_l(sim_data.m_n_divs); + polygon_2d_mesh_reader mesh_builder; + std::vector mesh_files; + + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l0_conv_test_1.0.txt"); // l = 0 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l1_conv_test_0.35.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l2_conv_test_0.15.txt"); // l = 2 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l3_conv_test_0.07.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l4_conv_test_0.035.txt"); // l = 4 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l5_conv_test_0.026.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l6_conv_test_0.017.txt"); // l = 6 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l7_conv_test_0.0125.txt"); // + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l8_conv_test_0.0085.txt"); // l = 8 + mesh_files.push_back("../../meshes/conv_test/simplices/unstructured/l9_conv_test_0.005.txt"); // + + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_64.txt"); // -l 1 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_128.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_256.txt"); // -l 3 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_512.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_1024.txt"); // -l 5 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_2048.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_4096.txt"); // -l 7 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_8192.txt"); + // mesh_files.push_back("../../meshes/conv_test/poly/poly_16384.txt"); // -l 9 + // mesh_files.push_back("../../meshes/conv_test/poly/poly_32768.txt"); + + // Reading the polygonal mesh + mesh_builder.set_poly_mesh_file(mesh_files[l]); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + mesh_builder.remove_duplicate_points(); + } + else { + RealType lx = 2.0; + RealType ly = 1.0; + size_t nx = 4; + size_t ny = 2; + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + } + + RealType h = 10; + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + RealType h_l = diameter(msh, cell); + if (h_l < h) { + h = h_l; + } + } + + tc.toc(); + std::cout << bold << red << " MESH GENERATION : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Time controls + // ################################################## + + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + // nt = sim_data.m_nt_divs; + } + + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + RealType t = ti; + + // ################################################## + // ################################################## Manufactured solution + // ################################################## + + scal_vec_analytic_functions functions; + //functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + //functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInTime); + //functions.set_function_type(scal_vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + functions.set_function_type(scal_vec_analytic_functions::EFunctionType::reproduction_elastic); + + auto null_s_fun = [](const disk::mesh>::point_type& pt) -> double { + return 0.0; + }; + + auto null_fun = [](const disk::mesh>::point_type& pt) -> disk::static_vector { + disk::static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename disk::mesh>::point_type& pt) -> disk::static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + disk::static_matrix sigma = disk::static_matrix::Zero(2,2); + return sigma; + }; + + // Elastic analytical functions + auto u_fun = functions.Evaluate_u(t); + auto v_fun = functions.Evaluate_v(t); + auto a_fun = functions.Evaluate_a(t); + auto f_fun = functions.Evaluate_f(t); + auto flux_fun = functions.Evaluate_sigma(t); + + // ################################################## + // ################################################## HHO setting + // ################################################## + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q) { + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // ################################################## + // ################################################## Material data + // ################################################## + + // Classify cells per material data and bc faces + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt)-> elastic_material_data { + double x,y; + x = pt.x(); + y = pt.y(); + RealType rho, vp, vs; + rho = 1.0; // Solid mass density + vp = std::sqrt(3.0); // Seismic compressional velocity vp + vs = 1.0; // Seismic shear velocity vs + elastic_material_data material(rho,vp,vs); + return material; + }; + + // ################################################## + // ################################################## Structure setting + // ################################################## + + std::map> e_material; + std::map> a_material; + std::set elastic_bc_face_indexes, acoustic_bc_face_indexes, interface_face_indexes; + std::map> interface_cell_pair_indexes; + + for (auto & cell : msh ) { + auto cell_ind = msh.lookup(cell); + mesh_type::point_type bar = barycenter(msh, cell); + elastic_material_data material = elastic_mat_fun(bar); + e_material.insert(std::make_pair(cell_ind,material)); + } + + size_t bc_elastic_id = 0; + size_t bc_acoustic_id = 1; + for (auto face_it = msh.boundary_faces_begin(); face_it != msh.boundary_faces_end(); face_it++){ + auto face = *face_it; + mesh_type::point_type bar = barycenter(msh, face); + auto fc_id = msh.lookup(face); + disk::boundary_descriptor bi{bc_elastic_id, true}; + msh.backend_storage()->boundary_info.at(fc_id) = bi; + elastic_bc_face_indexes.insert(fc_id); + } + + // detect interface elastic - acoustic + e_boundary_type e_bnd(msh); + a_boundary_type a_bnd(msh); + e_bnd.addDirichletBC(disk::DirichletType::DIRICHLET, bc_elastic_id, u_fun); + + // ################################################## + // ################################################## Solving a primal HHO mixed problem + // ################################################## + + tc.tic(); + auto assembler = elastoacoustic_four_fields_assembler(msh, hho_di, e_bnd, a_bnd, e_material, a_material); + assembler.set_interface_cell_indexes(interface_cell_pair_indexes); + assembler.set_hdg_stabilization(); + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + + tc.toc(); + std::cout << bold << red << " ASSEMBLY 1 : " << std::endl; + std::cout << bold << cyan << " Assembler generation : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << " Mass Assembly : "; + std::cout << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_coupling_terms(msh); + tc.toc(); + std::cout << bold << cyan << " Coupling assembly : "; + std::cout << tc << " seconds" << reset << std::endl << std::endl; + + // ################################################## + // ################################################## Projecting initial data + // ################################################## + + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, v_fun, flux_fun, null_s_fun, null_fun); + assembler.project_over_faces(msh, x_dof, v_fun, null_s_fun); + + // ################################################## + // ################################################## Solving a first order equation HDG/HHO propagation problem + // ################################################## + + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 2; + bool is_sdirk_Q = true; + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + } + else { + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + std::cout << bold << red << " ASSEMBLY 2 : " << std::endl; + std::cout << bold << cyan << " First stiffness assembly completed: "; + tc.tic(); + assembler.assemble(msh, v_fun, null_s_fun, false); + tc.toc(); + std::cout << tc << " seconds" << reset << std::endl; + assembler.LHS += assembler.COUPLING; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + std::vector> vec_cell_basis_data(2); + vec_cell_basis_data[0] = std::make_pair(assembler.get_e_material_data().size(), assembler.get_e_cell_basis_data()); + vec_cell_basis_data[1] = std::make_pair(assembler.get_a_material_data().size(), assembler.get_a_cell_basis_data()); + dirk_an.set_static_condensation_data(vec_cell_basis_data, assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + std::cout << bold << cyan << " Matrix decomposed: "; + tc.tic(); + dirk_an.ComposeMatrix(); + bool iteratif_solver = false; // if false load library: /opt/intel/oneapi/setvars.sh intel64 + if (iteratif_solver) { + dirk_an.setIterativeSolver(); + } + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << tc << " seconds" << reset << std::endl; + } + + // ################################################## + // ################################################## Preprocessor + // ################################################## + + std::ostringstream filename; + filename << "E_implicit_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << ".txt"; + std::string filename_str = filename.str(); + std::ofstream simulation_log(filename_str); + sim_data.write_simulation_data(simulation_log); + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Space step = " << h << std::endl; + simulation_log.flush(); + + std::ostringstream filename_e; + filename_e << "E_energy_l_" << sim_data.m_n_divs << "_n_" << sim_data.m_nt_divs << "_k_" << sim_data.m_k_degree << "_s_" << s << "_discret_" << sim_data.m_hdg_stabilization_Q << ".txt"; + std::string filename_e_str = filename_e.str(); + std::ofstream energy_file(filename_e_str); + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elasto_acoustic_energy_four_field(msh, hho_di, assembler, t, x_dof, energy_file); + } + std::cout << std::endl; + + // ################################################## + // ################################################## Time marching + // ################################################## + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << red << " Time step number " << it << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + // Manufactured solution + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + + assembler.get_e_bc_conditions().updateDirichletFunction(v_fun, 0); + assembler.assemble_rhs(msh, f_fun, null_s_fun, false); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + + tc.toc(); + std::cout << bold << cyan << " DIRK step completed: " << tc << " seconds" << reset << std::endl << std::endl; + x_dof = x_dof_n; + t = tn + dt; + auto v_fun = functions.Evaluate_v(t); + auto flux_fun = functions.Evaluate_sigma(t); + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_four_fields_elastoacoustic(msh, hho_di, assembler, x_dof, v_fun, flux_fun, null_s_fun, null_fun, simulation_log); + std::cout << std::endl; + } + + } + + bool mesh_quality = false; + if (mesh_quality) { + std::ostringstream mesh_file_name; + mesh_file_name << "mesh_quality_l" << sim_data.m_n_divs << ".txt"; + std::string mesh_file_str = mesh_file_name.str(); + std::ofstream mesh_file(mesh_file_str); + postprocessor::mesh_quality(msh, assembler, mesh_file); + } + + cpu.toc(); + simulation_log << "TOTAL CPU TIME: " << cpu << std::endl; + std::cout << bold << red << " TOTAL CPU TIME: " << cpu << std::endl << std::endl; + +} + diff --git a/apps/wave_propagation/src/prototypes/elastodynamics_old/CMakeLists.txt b/apps/wave_propagation/src/prototypes/elastodynamics_old/CMakeLists.txt new file mode 100644 index 00000000..ff30940b --- /dev/null +++ b/apps/wave_propagation/src/prototypes/elastodynamics_old/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(elastodynamics elastodynamics.cpp ${fitted_waves_headers} ${fitted_waves_sources}) +target_link_libraries(elastodynamics ${LINK_LIBS}) diff --git a/apps/wave_propagation/src/prototypes/elastodynamics_old/elastodynamics.cpp b/apps/wave_propagation/src/prototypes/elastodynamics_old/elastodynamics.cpp new file mode 100644 index 00000000..f18a6054 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/elastodynamics_old/elastodynamics.cpp @@ -0,0 +1,3122 @@ + +// Created by Omar Durán + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +using namespace Eigen; + +#include "timecounter.h" +#include "methods/hho" +#include "geometry/geometry.hpp" +#include "boundary_conditions/boundary_conditions.hpp" +#include "output/silo.hpp" + +// application common sources +#include "../common/display_settings.hpp" +#include "../common/fitted_geometry_builders.hpp" +#include "../common/linear_solver.hpp" +#include "../common/vec_analytic_functions.hpp" +#include "../common/preprocessor.hpp" +#include "../common/postprocessor.hpp" + +// implicit RK schemes +#include "../common/dirk_hho_scheme.hpp" +#include "../common/dirk_butcher_tableau.hpp" + +// explicit RK schemes +#include "../common/ssprk_hho_scheme.hpp" +#include "../common/ssprk_shu_osher_tableau.hpp" + +void HeterogeneousGar6more2DIHHOSecondOrder(int argc, char **argv); + +void HeterogeneousGar6more2DIHHOFirstOrder(int argc, char **argv); + +void HeterogeneousGar6more2DIHHOFirstOrderTwoFields(int argc, char **argv); + +void Gar6more2DIHHOSecondOrder(int argc, char **argv); + +void Gar6more2DIHHOFirstOrder(int argc, char **argv); + +void HeterogeneousIHHOFirstOrder(int argc, char **argv); + +void HeterogeneousIHHOSecondOrder(int argc, char **argv); + +void EHHOFirstOrder(int argc, char **argv); + +void IHHOFirstOrderTwoFields(int argc, char **argv); + +void IHHOFirstOrder(int argc, char **argv); + +void IHHOSecondOrder(int argc, char **argv); + +void HHOOneFieldConvergenceExample(int argc, char **argv); + +void HHOTwoFieldsConvergenceExample(int argc, char **argv); + +void HHOThreeFieldsConvergenceExample(int argc, char **argv); + +int main(int argc, char **argv) +{ + + HeterogeneousGar6more2DIHHOFirstOrderTwoFields(argc, argv); + +// HeterogeneousGar6more2DIHHOFirstOrder(argc, argv); +// HeterogeneousGar6more2DIHHOSecondOrder(argc, argv); + +// Gar6more2DIHHOFirstOrder(argc, argv); +// Gar6more2DIHHOSecondOrder(argc, argv); + +// HeterogeneousIHHOFirstOrder(argc, argv); +// HeterogeneousIHHOSecondOrder(argc, argv); + +// EHHOFirstOrder(argc, argv); +// IHHOFirstOrderTwoFields(argc, argv); +// IHHOFirstOrder(argc, argv); +// IHHOSecondOrder(argc, argv); + +// // Examples using main app objects for solving a linear elastic problem with optimal convergence rates + // Primal HHO +// HHOOneFieldConvergenceExample(argc, argv); + // Dual HHO +// HHOTwoFieldsConvergenceExample(argc, argv); +// HHOThreeFieldsConvergenceExample(argc, argv); + + return 0; +} + +void HHOOneFieldConvergenceExample(int argc, char **argv){ + + using RealType = double; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + + simulation_data sim_data = preprocessor::process_convergence_test_args(argc, argv); + sim_data.print_simulation_data(); + + // Manufactured exact solution + bool quadratic_function_Q = false; + bool Nonzero_Dirichlet_Q = false; + RealType lambda = 1000.0; + auto exact_vec_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + RealType ux = (1 - x)*x*(1 - y)*y; + RealType uy = (1 - x)*x*(1 - y)*y; + return static_vector{ux, uy}; + }else{ + if (Nonzero_Dirichlet_Q) { + RealType ux = - std::sin(M_PI * pt.x()) * std::cos(M_PI * pt.y()); + RealType uy = + std::cos(M_PI * pt.x()) * std::sin(M_PI * pt.y()); + return static_vector{ux, uy}; + }else{ + RealType ux = std::sin(2.0 * M_PI * pt.x()) * std::sin(2.0 * M_PI * pt.y()); + RealType uy = std::sin(3.0 * M_PI * pt.x()) * std::sin(3.0 * M_PI * pt.y()); + return static_vector{ux, uy}; + } + + } + + }; + + auto exact_flux_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q,lambda](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + static_matrix sigma = static_matrix::Zero(2,2); + RealType sxx = 2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y + (2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y)/2. + (2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y)/2.; + RealType sxy = (1 - x)*x*(1 - y) - (1 - x)*x*y + (1 - x)*(1 - y)*y - x*(1 - y)*y; + RealType syy = 2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y + (2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y)/2. + (2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y)/2.; + sigma(0,0) = sxx; + sigma(0,1) = sxy; + sigma(1,0) = sxy; + sigma(1,1) = syy; + return sigma; + }else{ + static_matrix sigma = static_matrix::Zero(2,2); + if (Nonzero_Dirichlet_Q) { + RealType sxx = - 2.0 * M_PI * std::cos(M_PI * x) * std::cos(M_PI * y); + RealType syy = + 2.0 * M_PI * std::cos(M_PI * x) * std::cos(M_PI * y); + sigma(0,0) = sxx; + sigma(1,1) = syy; + return sigma; + }else{ + RealType sxx = 4*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y) + + lambda*(3*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + 2*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y)); + RealType sxy = 2*M_PI*std::cos(2*M_PI*y)*std::sin(2*M_PI*x) + + 3*M_PI*std::cos(3*M_PI*x)*std::sin(3*M_PI*y); + RealType syy = 6*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + + lambda*(3*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + 2*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y)); + sigma(0,0) = sxx; + sigma(0,1) = sxy; + sigma(1,0) = sxy; + sigma(1,1) = syy; + return sigma; + } + } + + }; + + auto rhs_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q,lambda](const typename mesh_type::point_type& pt) -> static_vector { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + RealType fx = 2*(1 + x*x + y*(-5 + 3*y) + x*(-3 + 4*y)); + RealType fy = 2*(1 + 3*x*x + (-3 + y)*y + x*(-5 + 4*y)); + return static_vector{-fx, -fy}; + }else{ + if (Nonzero_Dirichlet_Q) { + RealType fx = + 2.0 * M_PI * M_PI * ( std::sin(M_PI * x) * std::cos( M_PI * y)); + RealType fy = - 2.0 * M_PI * M_PI * ( std::cos(M_PI * x) * std::sin( M_PI * y)); + return static_vector{-fx, -fy}; + }else{ + RealType fx = M_PI*M_PI*(9*(1 + lambda)*std::cos(3*M_PI*x)*std::cos(3*M_PI*y) - 4*(3 + lambda)*std::sin(2*M_PI*x)*std::sin(2*M_PI*y)); + RealType fy = M_PI*M_PI*(4*(1 + lambda)*std::cos(2*M_PI*x)*std::cos(2*M_PI*y) - 9*(3 + lambda)*std::sin(3*M_PI*x)*std::sin(3*M_PI*y)); + return static_vector{-fx, -fy}; + } + } + }; + + // simple material + RealType rho = 1.0; + RealType vp; + if (Nonzero_Dirichlet_Q || quadratic_function_Q) { + vp = std::sqrt(3.0); + }else{ + vp = std::sqrt(2.0 + lambda); + } + RealType vs = 1.0; + elastic_material_data material(rho,vp,vs); + + std::ofstream error_file("steady_vector_error.txt"); + + for(size_t k = 1; k <= sim_data.m_k_degree; k++){ + std::cout << bold << cyan << "Running an approximation with k : " << k << reset << std::endl; + error_file << "Approximation with k : " << k << std::endl; + for(size_t l = 0; l <= sim_data.m_n_divs; l++){ + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(l); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,k); + + // Solving a scalar primal HHO problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vec_fun); + tc.tic(); + auto assembler = elastodynamic_one_field_assembler(msh, hho_di, bnd); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + assembler.load_material_data(msh,material); + assembler.assemble(msh, rhs_fun); + assembler.apply_bc(msh); + tc.toc(); + std::cout << bold << cyan << "Assemble in : " << tc << " seconds" << reset << std::endl; + + // Solving LS + + Matrix x_dof; + if (sim_data.m_sc_Q) { + tc.tic(); + linear_solver analysis(assembler.LHS,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + std::cout << bold << cyan << "Number of equations (SC) : " << analysis.n_equations() << reset << std::endl; + }else{ + tc.tic(); + linear_solver analysis(assembler.LHS); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + std::cout << bold << cyan << "Number of equations : " << analysis.n_equations() << reset << std::endl; + } + + // Computing errors + postprocessor::compute_errors_one_field_vectorial(msh, hho_di, assembler, x_dof, exact_vec_fun, exact_flux_fun,error_file); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "steady_vector_k" + std::to_string(k) + "_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, l, msh, hho_di, x_dof, exact_vec_fun, false); + } + } + error_file << std::endl << std::endl; + } + error_file.close(); +} + +void HHOTwoFieldsConvergenceExample(int argc, char **argv){ + + using RealType = double; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + + simulation_data sim_data = preprocessor::process_convergence_test_args(argc, argv); + sim_data.print_simulation_data(); + + // Manufactured exact solution + bool quadratic_function_Q = false; + bool Nonzero_Dirichlet_Q = false; + RealType lambda = 1000.0; + auto exact_vec_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + RealType ux = (1 - x)*x*(1 - y)*y; + RealType uy = (1 - x)*x*(1 - y)*y; + return static_vector{ux, uy}; + }else{ + if (Nonzero_Dirichlet_Q) { + RealType ux = - std::sin(M_PI * pt.x()) * std::cos(M_PI * pt.y()); + RealType uy = + std::cos(M_PI * pt.x()) * std::sin(M_PI * pt.y()); + return static_vector{ux, uy}; + }else{ + RealType ux = std::sin(2.0 * M_PI * pt.x()) * std::sin(2.0 * M_PI * pt.y()); + RealType uy = std::sin(3.0 * M_PI * pt.x()) * std::sin(3.0 * M_PI * pt.y()); + return static_vector{ux, uy}; + } + + } + + }; + + auto exact_flux_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q,lambda](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + static_matrix sigma = static_matrix::Zero(2,2); + RealType sxx = 2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y + (2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y)/2. + (2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y)/2.; + RealType sxy = (1 - x)*x*(1 - y) - (1 - x)*x*y + (1 - x)*(1 - y)*y - x*(1 - y)*y; + RealType syy = 2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y + (2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y)/2. + (2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y)/2.; + sigma(0,0) = sxx; + sigma(0,1) = sxy; + sigma(1,0) = sxy; + sigma(1,1) = syy; + return sigma; + }else{ + static_matrix sigma = static_matrix::Zero(2,2); + if (Nonzero_Dirichlet_Q) { + RealType sxx = - 2.0 * M_PI * std::cos(M_PI * x) * std::cos(M_PI * y); + RealType syy = + 2.0 * M_PI * std::cos(M_PI * x) * std::cos(M_PI * y); + sigma(0,0) = sxx; + sigma(1,1) = syy; + return sigma; + }else{ + RealType sxx = 4*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y) + + lambda*(3*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + 2*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y)); + RealType sxy = 2*M_PI*std::cos(2*M_PI*y)*std::sin(2*M_PI*x) + + 3*M_PI*std::cos(3*M_PI*x)*std::sin(3*M_PI*y); + RealType syy = 6*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + + lambda*(3*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + 2*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y)); + sigma(0,0) = sxx; + sigma(0,1) = sxy; + sigma(1,0) = sxy; + sigma(1,1) = syy; + return sigma; + } + } + + }; + + auto rhs_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q,lambda](const typename mesh_type::point_type& pt) -> static_vector { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + RealType fx = 2*(1 + x*x + y*(-5 + 3*y) + x*(-3 + 4*y)); + RealType fy = 2*(1 + 3*x*x + (-3 + y)*y + x*(-5 + 4*y)); + return static_vector{-fx, -fy}; + }else{ + if (Nonzero_Dirichlet_Q) { + RealType fx = + 2.0 * M_PI * M_PI * ( std::sin(M_PI * x) * std::cos( M_PI * y)); + RealType fy = - 2.0 * M_PI * M_PI * ( std::cos(M_PI * x) * std::sin( M_PI * y)); + return static_vector{-fx, -fy}; + }else{ + RealType fx = M_PI*M_PI*(9*(1 + lambda)*std::cos(3*M_PI*x)*std::cos(3*M_PI*y) - 4*(3 + lambda)*std::sin(2*M_PI*x)*std::sin(2*M_PI*y)); + RealType fy = M_PI*M_PI*(4*(1 + lambda)*std::cos(2*M_PI*x)*std::cos(2*M_PI*y) - 9*(3 + lambda)*std::sin(3*M_PI*x)*std::sin(3*M_PI*y)); + return static_vector{-fx, -fy}; + } + } + }; + + // simple material + RealType rho = 1.0; + RealType vp; + if (Nonzero_Dirichlet_Q || quadratic_function_Q) { + vp = std::sqrt(3.0); + }else{ + vp = std::sqrt(2.0 + lambda); + } + RealType vs = 1.0; + elastic_material_data material(rho,vp,vs); + + std::ofstream error_file("steady_vector_mixed_two_fields_error.txt"); + + for(size_t k = 1; k <= sim_data.m_k_degree; k++){ + std::cout << bold << cyan << "Running an approximation with k : " << k << reset << std::endl; + error_file << "Approximation with k : " << k << std::endl; + for(size_t l = 0; l <= sim_data.m_n_divs; l++){ + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(l); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,k); + + // Solving a scalar primal HHO problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vec_fun); + tc.tic(); + auto assembler = elastodynamic_two_fields_assembler(msh, hho_di, bnd); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + assembler.load_material_data(msh,material); + assembler.assemble(msh, rhs_fun); + assembler.assemble_mass(msh, false); + assembler.apply_bc(msh); + tc.toc(); + std::cout << bold << cyan << "Assemble in : " << tc << " seconds" << reset << std::endl; + + // Solving LS + Matrix x_dof; + if (sim_data.m_sc_Q) { + tc.tic(); + SparseMatrix Kg = assembler.LHS+assembler.MASS; + linear_solver analysis(Kg,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + std::cout << bold << cyan << "Number of equations (SC) : " << analysis.n_equations() << reset << std::endl; + }else{ + tc.tic(); + SparseMatrix Kg = assembler.LHS+assembler.MASS; + linear_solver analysis(Kg); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + std::cout << bold << cyan << "Number of equations : " << analysis.n_equations() << reset << std::endl; + } + + // Computing errors + postprocessor::compute_errors_two_fields_vectorial(msh, hho_di, x_dof, exact_vec_fun, exact_flux_fun, error_file); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "steady_vector_mixed_two_fields_k" + std::to_string(k) + "_"; + postprocessor::write_silo_two_fields_vectorial(silo_file_name, l, msh, hho_di, x_dof, exact_vec_fun, exact_flux_fun, false); + } + } + error_file << std::endl << std::endl; + } + error_file.close(); + + +} + +void HHOThreeFieldsConvergenceExample(int argc, char **argv){ + + using RealType = double; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + + simulation_data sim_data = preprocessor::process_convergence_test_args(argc, argv); + sim_data.print_simulation_data(); + + // Manufactured exact solution + bool quadratic_function_Q = false; + bool Nonzero_Dirichlet_Q = false; + RealType lambda = 1000.0; + auto exact_vec_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + RealType ux = (1 - x)*x*(1 - y)*y; + RealType uy = (1 - x)*x*(1 - y)*y; + return static_vector{ux, uy}; + }else{ + if (Nonzero_Dirichlet_Q) { + RealType ux = - std::sin(M_PI * pt.x()) * std::cos(M_PI * pt.y()); + RealType uy = + std::cos(M_PI * pt.x()) * std::sin(M_PI * pt.y()); + return static_vector{ux, uy}; + }else{ + RealType ux = std::sin(2.0 * M_PI * pt.x()) * std::sin(2.0 * M_PI * pt.y()); + RealType uy = std::sin(3.0 * M_PI * pt.x()) * std::sin(3.0 * M_PI * pt.y()); + return static_vector{ux, uy}; + } + + } + + }; + + auto exact_flux_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q,lambda](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + static_matrix sigma = static_matrix::Zero(2,2); + RealType sxx = 2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y + (2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y)/2. + (2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y)/2.; + RealType sxy = (1 - x)*x*(1 - y) - (1 - x)*x*y + (1 - x)*(1 - y)*y - x*(1 - y)*y; + RealType syy = 2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y + (2*(1 - x)*x*(1 - y) - 2*(1 - x)*x*y)/2. + (2*(1 - x)*(1 - y)*y - 2*x*(1 - y)*y)/2.; + sigma(0,0) = sxx; + sigma(0,1) = sxy; + sigma(1,0) = sxy; + sigma(1,1) = syy; + return sigma; + }else{ + static_matrix sigma = static_matrix::Zero(2,2); + if (Nonzero_Dirichlet_Q) { + RealType sxx = - 2.0 * M_PI * std::cos(M_PI * x) * std::cos(M_PI * y); + RealType syy = + 2.0 * M_PI * std::cos(M_PI * x) * std::cos(M_PI * y); + sigma(0,0) = sxx; + sigma(1,1) = syy; + return sigma; + }else{ + RealType sxx = 4*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y) + + lambda*(3*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + 2*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y)); + RealType sxy = 2*M_PI*std::cos(2*M_PI*y)*std::sin(2*M_PI*x) + + 3*M_PI*std::cos(3*M_PI*x)*std::sin(3*M_PI*y); + RealType syy = 6*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + + lambda*(3*M_PI*std::cos(3*M_PI*y)*std::sin(3*M_PI*x) + 2*M_PI*std::cos(2*M_PI*x)*std::sin(2*M_PI*y)); + sigma(0,0) = sxx; + sigma(0,1) = sxy; + sigma(1,0) = sxy; + sigma(1,1) = syy; + return sigma; + } + } + + }; + + auto rhs_fun = [quadratic_function_Q,Nonzero_Dirichlet_Q,lambda](const typename mesh_type::point_type& pt) -> static_vector { + double x,y; + x = pt.x(); + y = pt.y(); + if(quadratic_function_Q){ + RealType fx = 2*(1 + x*x + y*(-5 + 3*y) + x*(-3 + 4*y)); + RealType fy = 2*(1 + 3*x*x + (-3 + y)*y + x*(-5 + 4*y)); + return static_vector{-fx, -fy}; + }else{ + if (Nonzero_Dirichlet_Q) { + RealType fx = + 2.0 * M_PI * M_PI * ( std::sin(M_PI * x) * std::cos( M_PI * y)); + RealType fy = - 2.0 * M_PI * M_PI * ( std::cos(M_PI * x) * std::sin( M_PI * y)); + return static_vector{-fx, -fy}; + }else{ + RealType fx = M_PI*M_PI*(9*(1 + lambda)*std::cos(3*M_PI*x)*std::cos(3*M_PI*y) - 4*(3 + lambda)*std::sin(2*M_PI*x)*std::sin(2*M_PI*y)); + RealType fy = M_PI*M_PI*(4*(1 + lambda)*std::cos(2*M_PI*x)*std::cos(2*M_PI*y) - 9*(3 + lambda)*std::sin(3*M_PI*x)*std::sin(3*M_PI*y)); + return static_vector{-fx, -fy}; + } + } + }; + + // simple material + RealType rho = 1.0; + RealType vp; + if (Nonzero_Dirichlet_Q || quadratic_function_Q) { + vp = std::sqrt(3.0); + }else{ + vp = std::sqrt(2.0 + lambda); + } + RealType vs = 1.0; + elastic_material_data material(rho,vp,vs); + + std::ofstream error_file("steady_vector_mixed_error.txt"); + + for(size_t k = 1; k <= sim_data.m_k_degree; k++){ + std::cout << bold << cyan << "Running an approximation with k : " << k << reset << std::endl; + error_file << "Approximation with k : " << k << std::endl; + for(size_t l = 0; l <= sim_data.m_n_divs; l++){ + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(l); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = k; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,k); + + // Solving a scalar primal HHO problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vec_fun); + tc.tic(); + auto assembler = elastodynamic_three_fields_assembler(msh, hho_di, bnd); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + assembler.load_material_data(msh,material); + assembler.assemble(msh, rhs_fun); + assembler.assemble_mass(msh, false); + assembler.apply_bc(msh); + tc.toc(); + std::cout << bold << cyan << "Assemble in : " << tc << " seconds" << reset << std::endl; + + // Solving LS + Matrix x_dof; + if (sim_data.m_sc_Q) { + tc.tic(); + SparseMatrix Kg = assembler.LHS+assembler.MASS; + linear_solver analysis(Kg,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + std::cout << bold << cyan << "Number of equations (SC) : " << analysis.n_equations() << reset << std::endl; + }else{ + tc.tic(); + SparseMatrix Kg = assembler.LHS+assembler.MASS; + linear_solver analysis(Kg); + tc.toc(); + std::cout << bold << cyan << "Create analysis in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + tc.tic(); + x_dof = analysis.solve(assembler.RHS); + tc.toc(); + std::cout << bold << cyan << "Linear Solve in : " << tc << " seconds" << reset << std::endl; + std::cout << bold << cyan << "Number of equations : " << analysis.n_equations() << reset << std::endl; + } + + // Computing errors + postprocessor::compute_errors_three_fields_vectorial(msh, hho_di, x_dof, exact_vec_fun, exact_flux_fun, error_file); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "steady_vector_mixed_k" + std::to_string(k) + "_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, l, msh, hho_di, x_dof, exact_vec_fun, exact_flux_fun, false); + } + } + error_file << std::endl << std::endl; + } + error_file.close(); + + +} + +void EHHOFirstOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = tf/nt; + + vec_analytic_functions functions; + functions.set_function_type(vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = elastodynamic_three_fields_assembler(msh, hho_di, bnd); + assembler.load_material_data(msh); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_three_fields_explicit.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + int s = 3; + Matrix alpha; + Matrix beta; + ssprk_shu_osher_tableau::ossprk_tables(s, alpha, beta); + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "Stiffness and rhs assembly completed: " << tc << " seconds" << reset << std::endl; + size_t n_face_dof = assembler.get_n_face_dof(); + ssprk_hho_scheme ssprk_an(assembler.LHS,assembler.RHS,assembler.MASS,n_face_dof); + tc.toc(); + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + { // Updating rhs + RealType t = dt*(it)+ti; + auto rhs_fun = functions.Evaluate_f(t); + assembler.assemble_rhs(msh, rhs_fun); + ssprk_an.SetFg(assembler.RHS); + } + RealType tn = dt*(it-1)+ti; + tc.tic(); + { + + size_t n_dof = x_dof.rows(); + Matrix ys = Matrix::Zero(n_dof, s+1); + + Matrix yn, ysi, yj; + ys.block(0, 0, n_dof, 1) = x_dof; + for (int i = 0; i < s; i++) { + + ysi = Matrix::Zero(n_dof, 1); + for (int j = 0; j <= i; j++) { + yn = ys.block(0, j, n_dof, 1); + ssprk_an.ssprk_weight(yn, yj, dt, alpha(i,j), beta(i,j)); + ysi += yj; + } + ys.block(0, i+1, n_dof, 1) = ysi; + } + + x_dof_n = ys.block(0, s, n_dof, 1); + } + tc.toc(); + std::cout << bold << cyan << "SSPRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_three_fields_vectorial(msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun); + } + } + + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of SSPRKSS steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); +} + +void IHHOFirstOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + vec_analytic_functions functions; + functions.set_function_type(vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = elastodynamic_three_fields_assembler(msh, hho_di, bnd); + assembler.load_material_data(msh); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_three_fields.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 1; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "First stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); +// dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + } + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); + assembler.assemble_rhs(msh, rhs_fun); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_three_fields_vectorial(msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, simulation_log); + } + + } + + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +void IHHOFirstOrderTwoFields(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + vec_analytic_functions functions; + functions.set_function_type(vec_analytic_functions::EFunctionType::EFunctionQuadraticInSpace); + RealType t = ti; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + auto rhs_fun = functions.Evaluate_f(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vel_fun); + tc.tic(); + auto assembler = elastodynamic_two_fields_assembler(msh, hho_di, bnd); + assembler.load_material_data(msh); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, exact_vel_fun, exact_flux_fun); + assembler.project_over_faces(msh, x_dof, exact_vel_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "vector_mixed_two_fields"; + postprocessor::write_silo_two_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_two_fields.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + tc.toc(); + std::cout << bold << cyan << "First stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); +// dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + } + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vel_fun, 0); + assembler.assemble_rhs(msh, rhs_fun); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + t = tn + dt; + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "vector_mixed__two_fields"; + postprocessor::write_silo_two_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + if(it == nt){ + // Computing errors + postprocessor::compute_errors_three_fields_vectorial(msh, hho_di, x_dof, exact_vel_fun, exact_flux_fun, simulation_log); + } + + } + + simulation_log << "Number of equations : " << dirk_an.DirkAnalysis().n_equations() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +void IHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.125; + RealType dt = (tf-ti)/nt; + + vec_analytic_functions functions; + functions.set_function_type(vec_analytic_functions::EFunctionType::EFunctionNonPolynomial); + RealType t = ti; + auto exact_vec_fun = functions.Evaluate_u(t); + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_accel_fun = functions.Evaluate_a(t); + auto rhs_fun = functions.Evaluate_f(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(exact_vec_fun); + + tc.tic(); + auto assembler = elastodynamic_one_field_assembler(msh, hho_di, bnd); + assembler.load_material_data(msh); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler created: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial displacement, velocity and acceleration + tc.tic(); + Matrix u_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, u_dof_n, exact_vec_fun); + assembler.project_over_cells(msh, v_dof_n, exact_vel_fun); + assembler.project_over_cells(msh, a_dof_n, exact_accel_fun); + + assembler.project_over_faces(msh, u_dof_n, exact_vec_fun); + assembler.project_over_faces(msh, v_dof_n, exact_vel_fun); + assembler.project_over_faces(msh, a_dof_n, exact_accel_fun); + tc.toc(); + std::cout << bold << cyan << "Initialization completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, u_dof_n, exact_vec_fun, false); + } + + std::ofstream simulation_log("elastodynamic_one_field.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, t, u_dof_n, v_dof_n, simulation_log); + } + + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.275; + RealType gamma = 0.55; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, rhs_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + linear_solver analysis; + if (sim_data.m_sc_Q) { + analysis.set_Kg(assembler.LHS, assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + }else{ + analysis.set_Kg(assembler.LHS); + } + analysis.set_direct_solver(true); +// analysis.set_iterative_solver(true); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + // Manufactured solution + RealType t = dt*(it)+ti; + auto exact_vec_fun = functions.Evaluate_u(t); + auto exact_vel_fun = functions.Evaluate_v(t); + auto exact_accel_fun = functions.Evaluate_a(t); + auto exact_flux_fun = functions.Evaluate_sigma(t); + auto rhs_fun = functions.Evaluate_f(t); + assembler.get_bc_conditions().updateDirichletFunction(exact_vec_fun, 0); + assembler.assemble_rhs(msh, rhs_fun); + + // Compute intermediate state for scalar and rate + u_dof_n = u_dof_n + dt*v_dof_n + 0.5*dt*dt*(1.0-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1.0-gamma)*a_dof_n; + Matrix res = Kg*u_dof_n; + + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update displacement, velocity and acceleration + u_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, u_dof_n, exact_vec_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, t, u_dof_n, v_dof_n, simulation_log); + } + + if(it == nt){ + postprocessor::compute_errors_one_field_vectorial(msh, hho_di, assembler, u_dof_n, exact_vec_fun, exact_flux_fun, simulation_log); + } + + } + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + +} + +void HeterogeneousIHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 3.0; + RealType ly = 2.5; + size_t nx = 3; + size_t ny = 3; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.75; + RealType dt = (tf-ti)/nt; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = (2.0/3.0)+1.25; + c = 10.0; + lp = std::sqrt(3.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + + tc.tic(); + auto assembler = elastodynamic_one_field_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + rho = 1.0; + if (y < 1.25) { + vp = 1.0*std::sqrt(3.0); + vs = 1.0; + }else{ + vp = std::sqrt(3.0); + vs = 1; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler created: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial displacement, velocity and acceleration + tc.tic(); + Matrix u_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, u_dof_n, null_fun); + assembler.project_over_faces(msh, u_dof_n, null_fun); + + assembler.project_over_cells(msh, v_dof_n, vec_fun); + assembler.project_over_faces(msh, v_dof_n, vec_fun); + + assembler.project_over_cells(msh, a_dof_n, null_fun); + assembler.project_over_faces(msh, a_dof_n, null_fun); + tc.toc(); + std::cout << bold << cyan << "Initialization completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, v_dof_n, vec_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_one_field.txt"); + + std::ofstream sensor_1_log("s1_elastodynamic_one_field.csv"); + std::ofstream sensor_2_log("s2_elastodynamic_one_field.csv"); + std::ofstream sensor_3_log("s3_elastodynamic_one_field.csv"); + typename mesh_type::point_type s1_pt(0.5-2.0/3.0, 1.0/3.0); + typename mesh_type::point_type s2_pt(0.5, 1.0/3.0); + typename mesh_type::point_type s3_pt(0.5+2.0/3.0, 1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_data_elastic_one_field(0, s1_pt_cell, msh, hho_di, v_dof_n, sensor_1_log); + postprocessor::record_data_elastic_one_field(0, s2_pt_cell, msh, hho_di, v_dof_n, sensor_2_log); + postprocessor::record_data_elastic_one_field(0, s3_pt_cell, msh, hho_di, v_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, ti, u_dof_n, v_dof_n, simulation_log); + } + + linear_solver analysis; + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_sc_Q) { + tc.tic(); + analysis.set_Kg(assembler.LHS,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Equations condensed in : " << tc << " seconds" << reset << std::endl; + + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + }else{ + analysis.set_Kg(assembler.LHS); + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + } + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + RealType t = dt*it+ti; + tc.tic(); + // Compute intermediate state for scalar and rate + u_dof_n = u_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*u_dof_n; + + assembler.RHS.setZero(); + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update displacement, velocity and acceleration + u_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, v_dof_n, vec_fun, false); + } + + postprocessor::record_data_elastic_one_field(it, s1_pt_cell, msh, hho_di, v_dof_n, sensor_1_log); + postprocessor::record_data_elastic_one_field(it, s2_pt_cell, msh, hho_di, v_dof_n, sensor_2_log); + postprocessor::record_data_elastic_one_field(it, s3_pt_cell, msh, hho_di, v_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, t, u_dof_n, v_dof_n, simulation_log); + } + + } + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + +} + +void HeterogeneousIHHOFirstOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 1.0; + RealType ly = 1.0; + size_t nx = 2; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + return sigma; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 0.75; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (-4*std::sqrt(10.0/3.0)*(-1 + 1600.0*r*r))/(std::exp(800*r*r)*std::pow(M_PI,0.25)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = elastodynamic_three_fields_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + rho = 1.0; + if (y < 0.5) { + vp = 1.0*std::sqrt(3.0); + vs = 1.0; + }else{ + vp = std::sqrt(3.0); + vs = 1; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, vec_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, vec_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_three_fields.txt"); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "First stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); +// dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + assembler.assemble_rhs(msh, null_fun); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "DIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of DIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +void Gar6more2DIHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 2.0; + RealType ly = 1.5; + size_t nx = 3; + size_t ny = 3; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-0.5, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.75; + RealType dt = (tf-ti)/nt; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 2.0/3.0; + c = 10.0; + lp = 1.0*std::sqrt(3.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + + tc.tic(); + auto assembler = elastodynamic_one_field_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + rho = 1.0; + if (y < 0.5) { + vp = 1.0*std::sqrt(3.0); + vs = 1.0; + }else{ + vp = 1.0*std::sqrt(3.0); + vs = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler created: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial displacement, velocity and acceleration + tc.tic(); + Matrix u_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, u_dof_n, null_fun); + assembler.project_over_faces(msh, u_dof_n, null_fun); + + assembler.project_over_cells(msh, v_dof_n, vec_fun); + assembler.project_over_faces(msh, v_dof_n, vec_fun); + + assembler.project_over_cells(msh, a_dof_n, null_fun); + assembler.project_over_faces(msh, a_dof_n, null_fun); + tc.toc(); + std::cout << bold << cyan << "Initialization completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, v_dof_n, vec_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_one_field.txt"); + + std::ofstream sensor_1_log("s1_elastodynamic_one_field.csv"); + std::ofstream sensor_2_log("s2_elastodynamic_one_field.csv"); + std::ofstream sensor_3_log("s3_elastodynamic_one_field.csv"); + typename mesh_type::point_type s1_pt(0.5-2.0/3.0, 1.0/3.0); + typename mesh_type::point_type s2_pt(0.5, 1.0/3.0); + typename mesh_type::point_type s3_pt(0.5+2.0/3.0, 1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_data_elastic_one_field(0, s1_pt_cell, msh, hho_di, v_dof_n, sensor_1_log); + postprocessor::record_data_elastic_one_field(0, s2_pt_cell, msh, hho_di, v_dof_n, sensor_2_log); + postprocessor::record_data_elastic_one_field(0, s3_pt_cell, msh, hho_di, v_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, ti, u_dof_n, v_dof_n, simulation_log); + } + + linear_solver analysis; + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_sc_Q) { + tc.tic(); + analysis.set_Kg(assembler.LHS,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Equations condensed in : " << tc << " seconds" << reset << std::endl; + + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + }else{ + analysis.set_Kg(assembler.LHS); + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + } + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + RealType t = dt*it+ti; + tc.tic(); + // Compute intermediate state for scalar and rate + u_dof_n = u_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*u_dof_n; + + assembler.RHS.setZero(); + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update displacement, velocity and acceleration + u_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, v_dof_n, vec_fun, false); + } + + postprocessor::record_data_elastic_one_field(it, s1_pt_cell, msh, hho_di, v_dof_n, sensor_1_log); + postprocessor::record_data_elastic_one_field(it, s2_pt_cell, msh, hho_di, v_dof_n, sensor_2_log); + postprocessor::record_data_elastic_one_field(it, s3_pt_cell, msh, hho_di, v_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, t, u_dof_n, v_dof_n, simulation_log); + } + + } + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + +} + +void Gar6more2DIHHOFirstOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 2.0; + RealType ly = 1.5; + size_t nx = 3; + size_t ny = 3; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-0.5, 0.0); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.75; + RealType dt = (tf-ti)/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + return sigma; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.5; + yc = 2.0/3.0; + c = 10.0; + lp = 1.0*std::sqrt(3.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = elastodynamic_three_fields_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + rho = 1.0; + if (y < 0.5) { + vp = 1.0*std::sqrt(3.0); + vs = 1.0; + }else{ + vp = 1.0*std::sqrt(3.0); + vs = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, vec_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, vec_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_three_fields.txt"); + + std::ofstream sensor_1_log("s1_elastodynamic_three_fields.csv"); + std::ofstream sensor_2_log("s2_elastodynamic_three_fields.csv"); + std::ofstream sensor_3_log("s3_elastodynamic_three_fields.csv"); + typename mesh_type::point_type s1_pt(0.5-2.0/3.0, 1.0/3.0); + typename mesh_type::point_type s2_pt(0.5, 1.0/3.0); + typename mesh_type::point_type s3_pt(0.5+2.0/3.0, 1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_data_elastic_three_fields(0, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + postprocessor::record_data_elastic_three_fields(0, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + postprocessor::record_data_elastic_three_fields(0, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "First stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); +// dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; +// assembler.assemble_rhs(msh, null_fun); + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "SDIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + postprocessor::record_data_elastic_three_fields(it, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + postprocessor::record_data_elastic_three_fields(it, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + postprocessor::record_data_elastic_three_fields(it, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +void HeterogeneousGar6more2DIHHOSecondOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 3.0; + RealType ly = 3.0; + size_t nx = 3; + size_t ny = 3; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.5, -1.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 2.0/3.0; + c = 10.0; + lp = 2.0*std::sqrt(3.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + + tc.tic(); + auto assembler = elastodynamic_one_field_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + if (y > 0.0) { + vp = 2.0*std::sqrt(3.0); + vs = 2.0; + rho = 1.0; + }else{ + vp = std::sqrt(3.0); + vs = 1.0; + rho = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler created: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial displacement, velocity and acceleration + tc.tic(); + Matrix u_dof_n, v_dof_n, a_dof_n; + assembler.project_over_cells(msh, u_dof_n, null_fun); + assembler.project_over_faces(msh, u_dof_n, null_fun); + + assembler.project_over_cells(msh, v_dof_n, vec_fun); + assembler.project_over_faces(msh, v_dof_n, vec_fun); + + assembler.project_over_cells(msh, a_dof_n, null_fun); + assembler.project_over_faces(msh, a_dof_n, null_fun); + tc.toc(); + std::cout << bold << cyan << "Initialization completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, v_dof_n, vec_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_one_field.txt"); + + std::ofstream sensor_1_log("s1_elastodynamic_one_field_h.csv"); + std::ofstream sensor_2_log("s2_elastodynamic_one_field_h.csv"); + std::ofstream sensor_3_log("s3_elastodynamic_one_field_h.csv"); + typename mesh_type::point_type s1_pt(-1.0/3.0, -1.0/3.0); + typename mesh_type::point_type s2_pt( 0.0, -1.0/3.0); + typename mesh_type::point_type s3_pt(+1.0/3.0, -1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_data_elastic_one_field(0, s1_pt_cell, msh, hho_di, v_dof_n, sensor_1_log); + postprocessor::record_data_elastic_one_field(0, s2_pt_cell, msh, hho_di, v_dof_n, sensor_2_log); + postprocessor::record_data_elastic_one_field(0, s3_pt_cell, msh, hho_di, v_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, ti, u_dof_n, v_dof_n, simulation_log); + } + + linear_solver analysis; + bool standar_Q = true; + // Newmark process + { + Matrix a_dof_np = a_dof_n; + + RealType beta = 0.25; + RealType gamma = 0.5; + if (!standar_Q) { + RealType kappa = 0.25; + gamma = 1.5; + beta = kappa*(gamma+0.5)*(gamma+0.5); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + SparseMatrix Kg = assembler.LHS; + assembler.LHS *= beta*(dt*dt); + assembler.LHS += assembler.MASS; + tc.toc(); + std::cout << bold << cyan << "Stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + + if (sim_data.m_sc_Q) { + tc.tic(); + analysis.set_Kg(assembler.LHS,assembler.get_n_face_dof()); + analysis.condense_equations(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data())); + tc.toc(); + std::cout << bold << cyan << "Equations condensed in : " << tc << " seconds" << reset << std::endl; + + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + }else{ + analysis.set_Kg(assembler.LHS); + analysis.set_direct_solver(true); + + tc.tic(); + analysis.factorize(); + tc.toc(); + std::cout << bold << cyan << "Factorized in : " << tc << " seconds" << reset << std::endl; + + } + + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + + RealType t = dt*it+ti; + tc.tic(); + // Compute intermediate state for scalar and rate + u_dof_n = u_dof_n + dt*v_dof_n + 0.5*dt*dt*(1-2.0*beta)*a_dof_n; + v_dof_n = v_dof_n + dt*(1-gamma)*a_dof_n; + Matrix res = Kg*u_dof_n; + + assembler.RHS.setZero(); + assembler.RHS -= res; + tc.toc(); + std::cout << bold << cyan << "Rhs assembly completed: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + a_dof_np = analysis.solve(assembler.RHS); // new acceleration + tc.toc(); + std::cout << bold << cyan << "Solution completed: " << tc << " seconds" << reset << std::endl; + + // update displacement, velocity and acceleration + u_dof_n += beta*dt*dt*a_dof_np; + v_dof_n += gamma*dt*a_dof_np; + a_dof_n = a_dof_np; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vec_"; + postprocessor::write_silo_one_field_vectorial(silo_file_name, it, msh, hho_di, v_dof_n, vec_fun, false); + } + + postprocessor::record_data_elastic_one_field(it, s1_pt_cell, msh, hho_di, v_dof_n, sensor_1_log); + postprocessor::record_data_elastic_one_field(it, s2_pt_cell, msh, hho_di, v_dof_n, sensor_2_log); + postprocessor::record_data_elastic_one_field(it, s3_pt_cell, msh, hho_di, v_dof_n, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_one_field(msh, hho_di, assembler, t, u_dof_n, v_dof_n, simulation_log); + } + + } + simulation_log << "Number of equations : " << analysis.n_equations() << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + } + +} + +void HeterogeneousGar6more2DIHHOFirstOrder(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 3.0; + RealType ly = 3.0; + size_t nx = 3; + size_t ny = 3; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.5, -1.5); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 1.0; + RealType dt = (tf-ti)/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + return sigma; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 2.0/3.0; + c = 10.0; + lp = 2.0*std::sqrt(3.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = elastodynamic_three_fields_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + if (y > 0.0) { + vp = 2.0*std::sqrt(3.0); + vs = 2.0; + rho = 1.0; + }else{ + vp = std::sqrt(3.0); + vs = 1.0; + rho = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, vec_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, vec_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_three_fields.txt"); + + std::ofstream sensor_1_log("s1_elastodynamic_three_fields_h.csv"); + std::ofstream sensor_2_log("s2_elastodynamic_three_fields_h.csv"); + std::ofstream sensor_3_log("s3_elastodynamic_three_fields_h.csv"); + typename mesh_type::point_type s1_pt(-1.0/3.0, 1.0/3.0); + typename mesh_type::point_type s2_pt( 0.0, 1.0/3.0); + typename mesh_type::point_type s3_pt(+1.0/3.0, 1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_data_elastic_three_fields(0, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + postprocessor::record_data_elastic_three_fields(0, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + postprocessor::record_data_elastic_three_fields(0, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "First stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); +// dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "SDIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vector_mixed_"; + postprocessor::write_silo_three_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + postprocessor::record_data_elastic_three_fields(it, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + postprocessor::record_data_elastic_three_fields(it, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + postprocessor::record_data_elastic_three_fields(it, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_three_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + +void HeterogeneousGar6more2DIHHOFirstOrderTwoFields(int argc, char **argv){ + + using RealType = double; + simulation_data sim_data = preprocessor::process_args(argc, argv); + sim_data.print_simulation_data(); + + // Building a cartesian mesh + timecounter tc; + tc.tic(); + + RealType lx = 2.0; + RealType ly = 2.0; + size_t nx = 2; + size_t ny = 2; + typedef disk::mesh> mesh_type; + typedef disk::BoundaryConditions boundary_type; + mesh_type msh; + + cartesian_2d_mesh_builder mesh_builder(lx,ly,nx,ny); + mesh_builder.refine_mesh(sim_data.m_n_divs); + mesh_builder.set_translation_data(-1.0, -1.25); + mesh_builder.build_mesh(); + mesh_builder.move_to_mesh_storage(msh); + tc.toc(); + std::cout << bold << cyan << "Mesh generation: " << tc << " seconds" << reset << std::endl; + + // Time controls : Final time value 1.0 + size_t nt = 10; + for (unsigned int i = 0; i < sim_data.m_nt_divs; i++) { + nt *= 2; + } + RealType ti = 0.0; + RealType tf = 0.5; + RealType dt = (tf-ti)/nt; + + auto null_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y; + x = pt.x(); + y = pt.y(); + static_vector f{0,0}; + return f; + }; + + auto null_flux_fun = [](const typename mesh_type::point_type& pt) -> static_matrix { + double x,y; + x = pt.x(); + y = pt.y(); + static_matrix sigma = static_matrix::Zero(2,2); + return sigma; + }; + + auto vec_fun = [](const mesh_type::point_type& pt) -> static_vector { + RealType x,y,xc,yc,r,wave,vx,vy,c,lp; + x = pt.x(); + y = pt.y(); + xc = 0.0; + yc = 0.25; + c = 10.0; + lp = 2.0*std::sqrt(3.0)/10.0; + r = std::sqrt((x-xc)*(x-xc)+(y-yc)*(y-yc)); + wave = (c)/(std::exp((1.0/(lp*lp))*r*r*M_PI*M_PI)); + vx = wave*(x-xc); + vy = wave*(y-yc); + static_vector v{vx,vy}; + return v; + }; + + // Creating HHO approximation spaces and corresponding linear operator + size_t cell_k_degree = sim_data.m_k_degree; + if(sim_data.m_hdg_stabilization_Q){ + cell_k_degree++; + } + disk::hho_degree_info hho_di(cell_k_degree,sim_data.m_k_degree); + + // Solving a primal HHO mixed problem + boundary_type bnd(msh); + bnd.addDirichletEverywhere(null_fun); + tc.tic(); + auto assembler = elastodynamic_two_fields_assembler(msh, hho_di, bnd); + + auto elastic_mat_fun = [](const typename mesh_type::point_type& pt) -> std::vector { + double x,y; + x = pt.x(); + y = pt.y(); + std::vector mat_data(3); + RealType rho, vp, vs; + if (y > 0.0) { + vp = std::sqrt(3.0); + vs = 1.0; + rho = 1.0; + }else{ + vp = std::sqrt(3.0); + vs = 1.0; + rho = 1.0; + } + mat_data[0] = rho; // rho + mat_data[1] = vp; // seismic compressional velocity vp + mat_data[2] = vs; // seismic shear velocity vp + return mat_data; + }; + + assembler.load_material_data(msh,elastic_mat_fun); + if(sim_data.m_hdg_stabilization_Q){ + assembler.set_hdg_stabilization(); + } + if(sim_data.m_scaled_stabilization_Q){ + assembler.set_scaled_stabilization(); + } + tc.toc(); + std::cout << bold << cyan << "Assembler generation: " << tc << " seconds" << reset << std::endl; + + tc.tic(); + assembler.assemble_mass(msh); + tc.toc(); + std::cout << bold << cyan << "Mass Assembly completed: " << tc << " seconds" << reset << std::endl; + + // Projecting initial data + Matrix x_dof; + assembler.project_over_cells(msh, x_dof, vec_fun, null_flux_fun); + assembler.project_over_faces(msh, x_dof, vec_fun); + + if (sim_data.m_render_silo_files_Q) { + size_t it = 0; + std::string silo_file_name = "inhomogeneous_vector_mixed_two_fields_"; + postprocessor::write_silo_two_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + std::ofstream simulation_log("elastodynamic_inhomogeneous_two_fields.txt"); + + std::ofstream sensor_1_log("s1_elastodynamic_two_fields_h.csv"); + std::ofstream sensor_2_log("s2_elastodynamic_two_fields_h.csv"); + std::ofstream sensor_3_log("s3_elastodynamic_two_fields_h.csv"); + typename mesh_type::point_type s1_pt(-1.0/3.0, 1.0/3.0); + typename mesh_type::point_type s2_pt( 0.0, 1.0/3.0); + typename mesh_type::point_type s3_pt(+1.0/3.0, 1.0/3.0); + std::pair s1_pt_cell = std::make_pair(s1_pt, -1); + std::pair s2_pt_cell = std::make_pair(s2_pt, -1); + std::pair s3_pt_cell = std::make_pair(s3_pt, -1); + + postprocessor::record_data_elastic_two_fields(0, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + postprocessor::record_data_elastic_two_fields(0, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + postprocessor::record_data_elastic_two_fields(0, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_two_fields(msh, hho_di, assembler, ti, x_dof, simulation_log); + } + + // Solving a first order equation HDG/HHO propagation problem + Matrix a; + Matrix b; + Matrix c; + + // DIRK(s) schemes + int s = 3; + bool is_sdirk_Q = true; + + if (is_sdirk_Q) { + dirk_butcher_tableau::sdirk_tables(s, a, b, c); + }else{ + dirk_butcher_tableau::dirk_tables(s, a, b, c); + } + + tc.tic(); + assembler.assemble(msh, null_fun); + tc.toc(); + std::cout << bold << cyan << "First stiffness assembly completed: " << tc << " seconds" << reset << std::endl; + dirk_hho_scheme dirk_an(assembler.LHS,assembler.RHS,assembler.MASS); + + if (sim_data.m_sc_Q) { + dirk_an.set_static_condensation_data(std::make_pair(msh.cells_size(), assembler.get_cell_basis_data()), assembler.get_n_face_dof()); + } + + if (is_sdirk_Q) { + double scale = a(0,0) * dt; + dirk_an.SetScale(scale); + tc.tic(); + dirk_an.ComposeMatrix(); +// dirk_an.setIterativeSolver(); + dirk_an.DecomposeMatrix(); + tc.toc(); + std::cout << bold << cyan << "Matrix decomposed: " << tc << " seconds" << reset << std::endl; + } + + Matrix x_dof_n; + for(size_t it = 1; it <= nt; it++){ + + std::cout << bold << yellow << "Time step number : " << it << " being executed." << reset << std::endl; + RealType tn = dt*(it-1)+ti; + + // DIRK step + tc.tic(); + { + size_t n_dof = x_dof.rows(); + Matrix k = Matrix::Zero(n_dof, s); + Matrix Fg, Fg_c,xd; + xd = Matrix::Zero(n_dof, 1); + + RealType t; + Matrix yn, ki; + + x_dof_n = x_dof; + for (int i = 0; i < s; i++) { + + yn = x_dof; + for (int j = 0; j < s - 1; j++) { + yn += a(i,j) * dt * k.block(0, j, n_dof, 1); + } + + t = tn + c(i,0) * dt; + assembler.RHS.setZero(); + dirk_an.SetFg(assembler.RHS); + dirk_an.irk_weight(yn, ki, dt, a(i,i),is_sdirk_Q); + + // Accumulated solution + x_dof_n += dt*b(i,0)*ki; + k.block(0, i, n_dof, 1) = ki; + } + } + tc.toc(); + std::cout << bold << cyan << "SDIRK step completed: " << tc << " seconds" << reset << std::endl; + x_dof = x_dof_n; + + RealType t = tn + dt; + + if (sim_data.m_render_silo_files_Q) { + std::string silo_file_name = "inhomogeneous_vector_mixed_two_fields_"; + postprocessor::write_silo_two_fields_vectorial(silo_file_name, it, msh, hho_di, x_dof, vec_fun, null_flux_fun, false); + } + + postprocessor::record_data_elastic_two_fields(it, s1_pt_cell, msh, hho_di, x_dof, sensor_1_log); + postprocessor::record_data_elastic_two_fields(it, s2_pt_cell, msh, hho_di, x_dof, sensor_2_log); + postprocessor::record_data_elastic_two_fields(it, s3_pt_cell, msh, hho_di, x_dof, sensor_3_log); + + if (sim_data.m_report_energy_Q) { + postprocessor::compute_elastic_energy_two_fields(msh, hho_di, assembler, t, x_dof, simulation_log); + } + + } + + simulation_log << "Number of equations : " << assembler.RHS.rows() << std::endl; + simulation_log << "Number of SDIRK steps = " << s << std::endl; + simulation_log << "Number of time steps = " << nt << std::endl; + simulation_log << "Step size = " << dt << std::endl; + simulation_log.flush(); + +} + diff --git a/apps/wave_propagation/src/prototypes/postpro/conv_space_RK4.py b/apps/wave_propagation/src/prototypes/postpro/conv_space_RK4.py new file mode 100755 index 00000000..0d0f9488 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/postpro/conv_space_RK4.py @@ -0,0 +1,79 @@ +import os +import re +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.lines import Line2D + +# --- Répertoire de travail --- +try: + script_dir = os.path.dirname(os.path.abspath(__file__)) + os.chdir(script_dir) +except: + pass + +# --- Paramètres --- +results = {k: {'h': [], 'l2': [], 'dg': []} for k in range(1, 4)} # k = 1,2,3 + +# Parcourir tous les fichiers implicit_l_*.txt +for filename in os.listdir('.'): + if not filename.startswith("implicit_l_") or not filename.endswith(".txt"): + continue + + # Extraire l et k du nom de fichier + m = re.match(r"implicit_l_(\d+)_n_\d+_k_(\d+)_s_\d+\.txt", filename) + if not m: + continue + l_number = int(m.group(1)) + k = int(m.group(2)) + if k not in results: + continue + + h = l2_error = dg_error = None + + with open(filename, 'r') as f: + lines = f.readlines() + for i, line in enumerate(lines): + # h + if "Characteristic h size" in line: + match_h = re.search(r"Characteristic h size = ([0-9.eE+-]+)", line) + if match_h: + h = float(match_h.group(1)) + + # L2 error acoustique + if line.strip() == "Acoustic region :": + if i+1 < len(lines): + match_l2 = re.search(r"L2-norm error = ([0-9.eE+-]+)", lines[i+1]) + if match_l2: + l2_error = float(match_l2.group(1)) + + # dG error acoustique + if line.strip().startswith("L2 errors of dG unknowns:"): + for j in range(i+1, min(i+5, len(lines))): + if lines[j].strip().startswith("Acoustic region :"): + try: + dg_error = float(lines[j].split(":")[1].strip()) + except: + dg_error = None + break + + if h is not None and l2_error is not None and dg_error is not None: + results[k]['h'].append(h) + results[k]['l2'].append(l2_error) + results[k]['dg'].append(dg_error) + else: + print(f"⚠️ Données manquantes dans {filename}") + +# --- Tracé --- +plt.figure(figsize=(8,8)) +styles = {1:{'color':'darkgreen','marker':'^'}, 2:{'color':'orange','marker':'s'}, 3:{'color':'darkred','marker':'o'}} +for k in results: + if results[k]['h']: + h_sorted, l2_sorted, dg_sorted = zip(*sorted(zip(results[k]['h'], results[k]['l2'], results[k]['dg']))) + plt.loglog(h_sorted, l2_sorted, marker=styles[k]['marker'], linestyle='-', color=styles[k]['color'], label=f'k={k} (L2)') + plt.loglog(h_sorted, dg_sorted, marker=styles[k]['marker'], linestyle='--', color=styles[k]['color'], alpha=0.7, label=f'k={k} (dG)') + +plt.xlabel("h") +plt.ylabel("L2 error / dG error") +plt.legend() +plt.grid(True, which='both') +plt.show() diff --git a/apps/wave_propagation/src/prototypes/postpro/parser_bassin.py b/apps/wave_propagation/src/prototypes/postpro/parser_bassin.py new file mode 100644 index 00000000..6186a833 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/postpro/parser_bassin.py @@ -0,0 +1,134 @@ +import os +import vtkmodules.all as vtk +import subprocess + +# Obtenez le chemin absolu du fichier en cours +current_file_path = os.path.abspath(__file__) +# Obtenez le répertoire du fichier en cours +current_directory = os.path.dirname(current_file_path) +# Changez le répertoire de travail actuel pour le répertoire du fichier en cours +os.chdir(current_directory) + +# Lire le fichier VTK +reader = vtk.vtkUnstructuredGridReader() +reader.SetFileName('square2.vtk') +reader.Update() + +# Récupérer les données du maillage +unstructured_grid = reader.GetOutput() + +# Lire le fichier VTK +with open('square2.vtk', "r") as vtk_file: + lines = vtk_file.readlines() + +# Trouver la ligne qui commence par "POINTS" +points_line = None +for line in lines: + if line.startswith("POINTS"): + points_line = line + break + +# Si la ligne "POINTS" est trouvée, extraire les coordonnées des points +if points_line: + num_points = int(points_line.split()[1]) + points_data = [line.split() for line in lines[lines.index(points_line) + 1:lines.index(points_line) + num_points + 1]] + +# Trouver la ligne qui commence par "CELLS" +cells_line = None +for line in lines: + if line.startswith("CELLS"): + cells_line = line + break + +# Si la ligne "CELLS" est trouvée, extraire les informations des cellules +if cells_line: + num_cells, _ = map(int, cells_line.split()[1:]) # Ne pas exclure le premier chiffre (nombre de sommets) + cells_data = [line.split() for line in lines[lines.index(cells_line) + 1:lines.index(cells_line) + num_cells + 1]] + +# Propriétés matérielles +# Trouver la ligne qui commence par "CELL_DATA" +cell_data_line = None +for line in lines: + if line.startswith("CELL_DATA"): + cell_data_line = line + break + +# Si la ligne "CELL_DATA" est trouvée, extraire le nombre de cellules associées aux données +if cell_data_line: + num_cells_data = int(cell_data_line.split()[1]) + + # Chercher la ligne qui commence par "SCALARS CellEntityIds int 1" + cell_entity_ids_line = None + for line in lines: + if line.startswith("LOOKUP_TABLE default"): + cell_entity_ids_line = line + break + + # Si la ligne est trouvée, extraire les valeurs associées à chaque cellule + if cell_entity_ids_line: + cell_entity_ids_data = [int(line) for line in lines[lines.index(cell_entity_ids_line) + 1:lines.index(cell_entity_ids_line) + num_cells_data + 1]] + + +# Ouvrir un fichier de sortie pour les coordonnées des points en écriture +with open("square2.txt", "w") as output_file: + + # Écrire le nombre de points, le nombre de cellules, et "4" sur la première ligne + output_file.write(f"{len(points_data)} {num_cells} 4\n") + + for point_data in points_data: + # Les coordonnées sont dans les trois premières colonnes + x, y, z = map(float, point_data[:3]) + output_file.write(f"{x} {y}\n") + + for cell_data in cells_data: + adjusted_cell_data = [cell_data[0]] + [str(int(idx) + 1) for idx in cell_data[1:]] + # Écrire toutes les données des cellules, y compris le nombre de sommets + output_file.write(" ".join(adjusted_cell_data) + "\n") + + # Extract the points + points = unstructured_grid.GetPoints() + + # Calculate the dimensions of the domain + x_coords = [points.GetPoint(i)[0] for i in range(points.GetNumberOfPoints())] + y_coords = [points.GetPoint(i)[1] for i in range(points.GetNumberOfPoints())] + + min_x, max_x = min(x_coords), max(x_coords) + min_y, max_y = min(y_coords), max(y_coords) + + print(f"Min X: {min_x}, Max X: {max_x}") + print(f"Min Y: {min_y}, Max Y: {max_y}") + + # Define lists to store point indices on each side + indices_left = [] + indices_right = [] + indices_bottom = [] + indices_top = [] + + # Define a threshold to determine which points are on the sides + threshold = 1e-6 + + for i in range(points.GetNumberOfPoints()): + x, y, _ = points.GetPoint(i) + if abs(x - min_x) < threshold: + indices_left.append(i+1) + if abs(x - max_x) < threshold: + indices_right.append(i+1) + if abs(y - min_y) < threshold: + indices_bottom.append(i+1) + if abs(y - max_y) < threshold: + indices_top.append(i+1) + + # # Écrire les numéros des points de la frontière dans un fichier + #with open("square2.txt", "a") as frontiere_file: + output_file.write(" ".join(map(str, indices_left)) + "\n") + output_file.write(" ".join(map(str, indices_right)) + "\n") + output_file.write(" ".join(map(str, indices_bottom)) + "\n") + output_file.write(" ".join(map(str, indices_top)) + "\n") + + for entity_id in cell_entity_ids_data: + output_file.write(f"{entity_id}\n") + +################################################################################## + +print("Les coordonnées des points et les informations des cellules ont été écrites dans le fichier 'output.txt'.") +print("Les numéros des points de la frontière ont été enregistrés dans 'frontiere_points.txt'.") diff --git a/apps/wave_propagation/src/prototypes/postpro/parser_gmsh_diskpp.py b/apps/wave_propagation/src/prototypes/postpro/parser_gmsh_diskpp.py new file mode 100644 index 00000000..9997cb11 --- /dev/null +++ b/apps/wave_propagation/src/prototypes/postpro/parser_gmsh_diskpp.py @@ -0,0 +1,109 @@ +import os +import vtkmodules.all as vtk +import subprocess + +# Obtenez le chemin absolu du fichier en cours +current_file_path = os.path.abspath(__file__) +# Obtenez le répertoire du fichier en cours +current_directory = os.path.dirname(current_file_path) +# Changez le répertoire de travail actuel pour le répertoire du fichier en cours +os.chdir(current_directory) + +# Lire le fichier VTK +reader = vtk.vtkUnstructuredGridReader() +reader.SetFileName('simplex_l7.vtk') +reader.Update() + +# Récupérer les données du maillage +unstructured_grid = reader.GetOutput() + +# Lire le fichier VTK +with open('simplex_l7.vtk', "r") as vtk_file: + lines = vtk_file.readlines() + +# Trouver la ligne qui commence par "POINTS" +points_line = None +for line in lines: + if line.startswith("POINTS"): + points_line = line + break + +# Si la ligne "POINTS" est trouvée, extraire les coordonnées des points +if points_line: + num_points = int(points_line.split()[1]) + points_data = [line.split() for line in lines[lines.index(points_line) + 1:lines.index(points_line) + num_points + 1]] + +# Trouver la ligne qui commence par "CELLS" +cells_line = None +for line in lines: + if line.startswith("CELLS"): + cells_line = line + break + +# Si la ligne "CELLS" est trouvée, extraire les informations des cellules +if cells_line: + num_cells, _ = map(int, cells_line.split()[1:]) # Ne pas exclure le premier chiffre (nombre de sommets) + cells_data = [line.split() for line in lines[lines.index(cells_line) + 1:lines.index(cells_line) + num_cells + 1]] + + + +# Ouvrir un fichier de sortie pour les coordonnées des points en écriture +with open("simplex_l7.txt", "w") as output_file: + + # Écrire le nombre de points, le nombre de cellules, et "4" sur la première ligne + output_file.write(f"{len(points_data)} {num_cells} 4\n") + + for point_data in points_data: + # Les coordonnées sont dans les trois premières colonnes + x, y, z = map(float, point_data[:3]) + output_file.write(f"{x} {y}\n") + + for cell_data in cells_data: + adjusted_cell_data = [cell_data[0]] + [str(int(idx) + 1) for idx in cell_data[1:]] + # Écrire toutes les données des cellules, y compris le nombre de sommets + output_file.write(" ".join(adjusted_cell_data) + "\n") + + # Extract the points + points = unstructured_grid.GetPoints() + + # Calculate the dimensions of the domain + x_coords = [points.GetPoint(i)[0] for i in range(points.GetNumberOfPoints())] + y_coords = [points.GetPoint(i)[1] for i in range(points.GetNumberOfPoints())] + + min_x, max_x = min(x_coords), max(x_coords) + min_y, max_y = min(y_coords), max(y_coords) + + print(f"Min X: {min_x}, Max X: {max_x}") + print(f"Min Y: {min_y}, Max Y: {max_y}") + + # Define lists to store point indices on each side + indices_left = [] + indices_right = [] + indices_bottom = [] + indices_top = [] + + # Define a threshold to determine which points are on the sides + threshold = 1e-6 + + for i in range(points.GetNumberOfPoints()): + x, y, _ = points.GetPoint(i) + if abs(x - min_x) < threshold: + indices_left.append(i+1) + if abs(x - max_x) < threshold: + indices_right.append(i+1) + if abs(y - min_y) < threshold: + indices_bottom.append(i+1) + if abs(y - max_y) < threshold: + indices_top.append(i+1) + + # # Écrire les numéros des points de la frontière dans un fichier + # with open("bassin.txt", "a") as frontiere_file: + output_file.write(" ".join(map(str, indices_left)) + "\n") + output_file.write(" ".join(map(str, indices_right)) + "\n") + output_file.write(" ".join(map(str, indices_bottom)) + "\n") + output_file.write(" ".join(map(str, indices_top)) + "\n") + +################################################################################## + +print("Les coordonnées des points et les informations des cellules ont été écrites dans le fichier 'output.txt'.") +print("Les numéros des points de la frontière ont été enregistrés dans 'frontiere_points.txt'.") diff --git a/apps/wave_propagation/src/prototypes/postpro/parser_gmsh_unstructured_simplices.py b/apps/wave_propagation/src/prototypes/postpro/parser_gmsh_unstructured_simplices.py new file mode 100644 index 00000000..2c95476b --- /dev/null +++ b/apps/wave_propagation/src/prototypes/postpro/parser_gmsh_unstructured_simplices.py @@ -0,0 +1,109 @@ +import os +import vtkmodules.all as vtk +import subprocess + +# Obtenez le chemin absolu du fichier en cours +current_file_path = os.path.abspath(__file__) +# Obtenez le répertoire du fichier en cours +current_directory = os.path.dirname(current_file_path) +# Changez le répertoire de travail actuel pour le répertoire du fichier en cours +os.chdir(current_directory) + +# Lire le fichier VTK +reader = vtk.vtkUnstructuredGridReader() +reader.SetFileName('l9_conv_test_0.005.vtk') +reader.Update() + +# Récupérer les données du maillage +unstructured_grid = reader.GetOutput() + +# Lire le fichier VTK +with open('l9_conv_test_0.005.vtk', "r") as vtk_file: + lines = vtk_file.readlines() + +# Trouver la ligne qui commence par "POINTS" +points_line = None +for line in lines: + if line.startswith("POINTS"): + points_line = line + break + +# Si la ligne "POINTS" est trouvée, extraire les coordonnées des points +if points_line: + num_points = int(points_line.split()[1]) + points_data = [line.split() for line in lines[lines.index(points_line) + 1:lines.index(points_line) + num_points + 1]] + +# Trouver la ligne qui commence par "CELLS" +cells_line = None +for line in lines: + if line.startswith("CELLS"): + cells_line = line + break + +# Si la ligne "CELLS" est trouvée, extraire les informations des cellules +if cells_line: + num_cells, _ = map(int, cells_line.split()[1:]) # Ne pas exclure le premier chiffre (nombre de sommets) + cells_data = [line.split() for line in lines[lines.index(cells_line) + 1:lines.index(cells_line) + num_cells + 1]] + + + +# Ouvrir un fichier de sortie pour les coordonnées des points en écriture +with open("l9_conv_test_0.005.txt", "w") as output_file: + + # Écrire le nombre de points, le nombre de cellules, et "4" sur la première ligne + output_file.write(f"{len(points_data)} {num_cells} 4\n") + + for point_data in points_data: + # Les coordonnées sont dans les trois premières colonnes + x, y, z = map(float, point_data[:3]) + output_file.write(f"{x} {y}\n") + + for cell_data in cells_data: + adjusted_cell_data = [cell_data[0]] + [str(int(idx) + 1) for idx in cell_data[1:]] + # Écrire toutes les données des cellules, y compris le nombre de sommets + output_file.write(" ".join(adjusted_cell_data) + "\n") + + # Extract the points + points = unstructured_grid.GetPoints() + + # Calculate the dimensions of the domain + x_coords = [points.GetPoint(i)[0] for i in range(points.GetNumberOfPoints())] + y_coords = [points.GetPoint(i)[1] for i in range(points.GetNumberOfPoints())] + + min_x, max_x = min(x_coords), max(x_coords) + min_y, max_y = min(y_coords), max(y_coords) + + print(f"Min X: {min_x}, Max X: {max_x}") + print(f"Min Y: {min_y}, Max Y: {max_y}") + + # Define lists to store point indices on each side + indices_left = [] + indices_right = [] + indices_bottom = [] + indices_top = [] + + # Define a threshold to determine which points are on the sides + threshold = 1e-6 + + for i in range(points.GetNumberOfPoints()): + x, y, _ = points.GetPoint(i) + if abs(x - min_x) < threshold: + indices_left.append(i+1) + if abs(x - max_x) < threshold: + indices_right.append(i+1) + if abs(y - min_y) < threshold: + indices_bottom.append(i+1) + if abs(y - max_y) < threshold: + indices_top.append(i+1) + + # # Écrire les numéros des points de la frontière dans un fichier + # with open("bassin.txt", "a") as frontiere_file: + output_file.write(" ".join(map(str, indices_left)) + "\n") + output_file.write(" ".join(map(str, indices_right)) + "\n") + output_file.write(" ".join(map(str, indices_bottom)) + "\n") + output_file.write(" ".join(map(str, indices_top)) + "\n") + +################################################################################## + +print("Les coordonnées des points et les informations des cellules ont été écrites dans le fichier 'output.txt'.") +print("Les numéros des points de la frontière ont été enregistrés dans 'frontiere_points.txt'.") diff --git a/apps/wave_propagation/src/wave_propagation.cpp b/apps/wave_propagation/src/wave_propagation.cpp new file mode 100644 index 00000000..0919a582 --- /dev/null +++ b/apps/wave_propagation/src/wave_propagation.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace Eigen; + +#include "diskpp/common/timecounter.hpp" +#include "diskpp/methods/hho" +#include "diskpp/geometry/geometry.hpp" +#include "diskpp/boundary_conditions/boundary_conditions.hpp" +#include "diskpp/output/silo.hpp" + +// application common sources +#include "common/display_settings.hpp" +#include "common/fitted_geometry_builders.hpp" +#include "common/linear_solver.hpp" +#include "common/acoustic_material_data.hpp" +#include "common/elastic_material_data.hpp" +#include "common/scal_vec_analytic_functions.hpp" +#include "common/preprocessor.hpp" +#include "common/postprocessor.hpp" + +// RK schemes +#include "common/dirk_hho_scheme.hpp" +#include "common/dirk_butcher_tableau.hpp" +#include "common/erk_butcher_tableau.hpp" +#include "common/erk_hho_scheme.hpp" +#include "common/erk_coupling_hho_scheme.hpp" + +// Prototypes: +// Computation of an empirical CFL criteria +#include "prototypes/acoustic/EAcoustic_CFL.hpp" // CFl - Acoustic +#include "prototypes/elastic/EElasticity_CFL.hpp" // CFl - Linear Elasticity +#include "prototypes/coupling/CFL/EHHOFirstOrderCFL.hpp" // CFl - Elasto-Acoustic Coupling +// Stability study & Spectral radius computation: +#include "prototypes/acoustic/EAcoustic_stability.hpp" // Acoustic +#include "prototypes/elastic/EElastic_stability.hpp" // Linear Elasticity +#include "prototypes/coupling/EHHOFirstOrder_stability.hpp" // Elasto-Acoustic Coupling +// Convergence test on sinusoidal analytical solution +#include "prototypes/acoustic/EAcoustic_conv_test.hpp" // Explicit Acoustic +#include "prototypes/acoustic/IAcoustic_conv_test.hpp" // Implicit Acoustic +#include "prototypes/elastic/IElastic_conv_test.hpp" // Implicit Elastic +#include "prototypes/coupling/Conv_Tests/IHHOFirstOrder.hpp" // Implicit Coupling +#include "prototypes/coupling/Conv_Tests/IHHOFirstOrder_conv_tests.hpp" // Explicit Coupling +#include "prototypes/coupling/Conv_Tests/EHHOFirstOrder.hpp" // Explicit Coupling +#include "prototypes/coupling/Conv_Tests/EHHOFirstOrder_conv_tests.hpp" // Explicit Coupling +// Pulses for comparison with Gar6more +#include "prototypes/coupling/Pulse/HeterogeneousIHHOFirstOrder.hpp" // Implicit Pulse (adimensional) +#include "prototypes/coupling/Pulse/HeterogeneousEHHOFirstOrder.hpp" // Explicit Pulse (adimensional) +#include "prototypes/coupling/Pulse/ConicWavesIHHOFirstOrder.hpp" // Implicit Pulse (geophysic) +#include "prototypes/coupling/Pulse/review_CMAME.hpp" // Implicit Pulse (geophysic) +#include "prototypes/coupling/Pulse/ConicWavesEHHOFirstOrder.hpp" // Implicit Pulse (geophysic) +// Sedimentary Basin +#include "prototypes/coupling/Basin/BassinIHHOFirstOrder.hpp" // Implicit Sedimentary Basin +// LTS +#include "prototypes/LTS/ELTSAcoustic_conv_test.hpp" +#include "prototypes/LTS/ERK4_LTS_conv_test.hpp" +#include "prototypes/LTS/HeterogeneousERK4_LTS_HHO_FirstOrder.hpp" + +int main(int argc, char **argv){ + + DBSetDeprecateWarnings(0); + + // REGRESSION TESTS + if (basename(argv[0]) == std::string("name1") ) { + std::cout << "called with name1" << std::endl; + return 0; + } + + if (basename(argv[0]) == std::string("name2") ) { + std::cout << "called with name2" << std::endl; + return 0; + } + +// CFL TABLE: + // EAcoustic_CFL(argc, argv); + // EElasticity_CFL(argc, argv); + // EHHOFirstOrderCFL(argc, argv); + +// STABILITY STUDY & SPECTRAL RADIUS COMPUTATION: + // EAcoustic_stability(argc, argv); + // EElastic_stability(argc, argv); + // EHHOFirstOrder_stability(argc, argv); + +// CV TESTS: + // EAcousticFirstOrder(argc, argv); + // IAcoustic_conv_test(argc, argv); + // IElastic_conv_test(argc, argv); + // IHHOFirstOrder(argc, argv); + // IHHOFirstOrder_conv_tests(argc, argv); + // EHHOFirstOrder(argc, argv); + // EHHOFirstOrder_conv_tests(argc, argv); + +// PULSE: + // HeterogeneousIHHOFirstOrder(argc, argv); + // HeterogeneousEHHOFirstOrder(argc, argv); + // ConicWavesIHHOFirstOrder(argc, argv); + // ConicWavesIHHOFirstOrder_review(argc, argv); + // ConicWavesEHHOFirstOrder(argc, argv); + // ConicWavesEHHOFirstOrder_review(argc, argv); + +// SEDIMENTARY BASIN: + // BassinIHHOFirstOrder(argc, argv); + // Test(argc, argv); + // BassinEHHOFirstOrder(argc, argv); Not working + +// LOCAL TIME STEPPING + // ELTSAcousticFirstOrder(argc, argv); + // ERK4_LTS_conv_test(argc, argv); + HeterogeneousERK4_LTS_HHO_FirstOrder(argc, argv); +} + + + + diff --git a/conv_detected.png b/conv_detected.png new file mode 100644 index 00000000..ec728e17 Binary files /dev/null and b/conv_detected.png differ diff --git a/libdiskpp/contrib/spectra b/libdiskpp/contrib/spectra new file mode 160000 index 00000000..a29f37fe --- /dev/null +++ b/libdiskpp/contrib/spectra @@ -0,0 +1 @@ +Subproject commit a29f37fe3ed1c2895b07b449fcb8f09bc0940e40 diff --git a/libdiskpp/include/diskpp/bases/bases_scalar.hpp b/libdiskpp/include/diskpp/bases/bases_scalar.hpp index be7a5936..c30db597 100644 --- a/libdiskpp/include/diskpp/bases/bases_scalar.hpp +++ b/libdiskpp/include/diskpp/bases/bases_scalar.hpp @@ -65,6 +65,8 @@ struct scaled_monomial_scalar_basis /* Basis 'factory'. */ #ifndef USE_LEGENDRE +#ifndef ORTHO_BASIS + template auto make_scalar_monomial_basis(const MeshType& msh, @@ -74,6 +76,17 @@ make_scalar_monomial_basis(const MeshType& msh, { return scaled_monomial_scalar_basis(msh, elem, degree, use_inertia_axes); } +#else +template +auto +make_scalar_monomial_basis(const MeshType& msh, + const ElementType& elem, + size_t degree, + bool use_inertia_axes = USE_INERTIA_AXES) +{ + return scaled_monomial_scalar_basis_ortho(msh, elem, degree, use_inertia_axes); +} +#endif #endif /***************************************************************************************************/ diff --git a/libdiskpp/include/diskpp/boundary_conditions/boundary_conditions.hpp b/libdiskpp/include/diskpp/boundary_conditions/boundary_conditions.hpp index c2fc2ffd..ca07b678 100644 --- a/libdiskpp/include/diskpp/boundary_conditions/boundary_conditions.hpp +++ b/libdiskpp/include/diskpp/boundary_conditions/boundary_conditions.hpp @@ -311,8 +311,7 @@ class BoundaryConditions template void - addDirichletBC(const size_t& btype, const size_t& b_id, const Function& bcf) - { + addDirichletBC(const size_t& btype, const size_t& b_id, const Function& bcf) { const size_t bcf_id = m_dirichlet_func.size(); m_dirichlet_func.push_back(bcf); @@ -341,6 +340,14 @@ class BoundaryConditions } } + template + void + updateDirichletFunction(const Function& bcf, size_t bcf_index) + { + assert(0 <= bcf_index && bcf_index < m_dirichlet_func.size()); + m_dirichlet_func[bcf_index] = bcf; + } + void multiplyAllFunctionsByAFactor(const scalar_type& factor) { diff --git a/libdiskpp/include/diskpp/geometry/geometry_generic.hpp b/libdiskpp/include/diskpp/geometry/geometry_generic.hpp index 226f7347..38c966c8 100644 --- a/libdiskpp/include/diskpp/geometry/geometry_generic.hpp +++ b/libdiskpp/include/diskpp/geometry/geometry_generic.hpp @@ -248,6 +248,14 @@ barycenter(const generic_mesh& msh, return point(Cx, Cy); } +template +point +barycenter_bis(const Mesh& msh, const Element& elm) +{ + auto pts = points(msh, elm); + auto bar = std::accumulate(std::next(pts.begin()), pts.end(), pts.front()); + return bar / typename Mesh::coordinate_type( pts.size() ); +} /** * \brief Return the length of the specified 2D face diff --git a/libdiskpp/include/diskpp/mesh/cut_mesh.hpp b/libdiskpp/include/diskpp/mesh/cut_mesh.hpp new file mode 100644 index 00000000..73af58a7 --- /dev/null +++ b/libdiskpp/include/diskpp/mesh/cut_mesh.hpp @@ -0,0 +1,6 @@ + +#pragma once + +#include "mesh.hpp" +#include "level_set.hpp" +#include "mesh_storage.hpp" diff --git a/libdiskpp/include/diskpp/mesh/level_set.hpp b/libdiskpp/include/diskpp/mesh/level_set.hpp new file mode 100644 index 00000000..99f2f3f1 --- /dev/null +++ b/libdiskpp/include/diskpp/mesh/level_set.hpp @@ -0,0 +1,204 @@ +/* + * /\ Guillaume Delay 2018,2019 + * /__\ guillaume.delay@enpc.fr + * /_\/_\ École Nationale des Ponts et Chaussées - CERMICS + * /\ /\ + * /__\ /__\ This is ProtoN, a library for fast Prototyping of + * /_\/_\/_\/_\ Numerical methods. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * If you use this code or parts of it for scientific publications, you + * are required to cite it as following: + * + * Implementation of Discontinuous Skeletal methods on arbitrary-dimensional, + * polytopal meshes using generic programming. + * M. Cicuttin, D. A. Di Pietro, A. Ern. + * Journal of Computational and Applied Mathematics. + * DOI: 10.1016/j.cam.2017.09.017 + */ + + +template +struct level_set { + public: + virtual T operator()(const disk::point& pt) const { + } + + virtual Eigen::Matrix gradient(const disk::point& pt) const { + } + + Eigen::Matrix normal(const disk::point& pt) const { + Eigen::Matrix ret; + ret = gradient(pt); + return ret/ret.norm(); + } +}; + +template +struct circle_level_set: public level_set +{ + T radius, alpha, beta; + + circle_level_set(T r, T a, T b) : radius(r), alpha(a), beta(b) { + } + + T operator()(const disk::point& pt) const { + auto x = pt.x(); + auto y = pt.y(); + return (x-alpha)*(x-alpha) + (y-beta)*(y-beta) - radius*radius; + } + + Eigen::Matrix gradient(const disk::point& pt) const { + Eigen::Matrix ret; + ret(0) = 2*pt.x() - 2*alpha; + ret(1) = 2*pt.y() - 2*beta; + return ret; + } +}; + +template +struct line_level_set: public level_set +{ + T cut_y; + + line_level_set(T cy) + : cut_y(cy) + {} + + T operator()(const disk::point& pt) const + { + auto x = pt.x(); + auto y = pt.y(); + + return y - cut_y; + } + + Eigen::Matrix gradient(const disk::point& pt) const { + Eigen::Matrix ret; + ret(0) = 0; + ret(1) = 1; + return ret; + } +}; + + + +template +struct square_level_set: public level_set +{ + public: + T y_top, y_bot, x_left, x_right; + + square_level_set(T yt, T yb, T xl, T xr) + : y_top(yt), y_bot(yb), x_left(xl), x_right(xr) + {} + + T operator()(const disk::point& pt) const + { + auto x = pt.x(); + auto y = pt.y(); + + T in = 1; + if(x > x_left && x < x_right && y > y_bot && y < y_top) + in = 1; + else + in = -1; + + T dist_x = std::min( abs(x-x_left), abs(x-x_right)); + T dist_y = std::min( abs(y-y_bot), abs(y-y_top)); + + + return - in * std::min(dist_x , dist_y); + } + + Eigen::Matrix gradient(const disk::point& pt) const + { + Eigen::Matrix ret; + + + auto x = pt.x(); + auto y = pt.y(); + + T dist = abs(x - x_left); + ret(0) = -1; + ret(1) = 0; + + if(abs(x - x_right) < dist ) + { + dist = abs(x - x_right); + ret(0) = 1; + ret(1) = 0; + } + if(abs(y - y_bot) < dist ) + { + dist = abs(y - y_bot); + ret(0) = 0; + ret(1) = -1; + } + if(abs(y - y_top) < dist) + { + ret(0) = 0; + ret(1) = 1; + } + + return ret; + } +}; + + + +template +struct flower_level_set: public level_set +{ + T radius, alpha, beta, a; + size_t N; + + flower_level_set(T r, T al, T b, size_t N_, T a_) + : radius(r), alpha(al), beta(b), N(N_), a(a_) + {} + + T operator()(const disk::point& pt) const + { + auto x = pt.x(); + auto y = pt.y(); + + T theta; + if(x == alpha && y < beta) + theta = - M_PI / 2.0; + else if(x == alpha && y >= beta) + theta = M_PI / 2.0; + else + theta = atan((y-beta)/(x-alpha)); + + if(x < alpha) + theta = theta + M_PI; + + return (x-alpha)*(x-alpha) + (y-beta)*(y-beta) - radius*radius + - a * std::cos(N*theta); + } + + Eigen::Matrix gradient(const disk::point& pt) const + { + Eigen::Matrix ret; + auto X = pt.x() - alpha; + auto Y = pt.y() - beta; + + T theta; + if(X == 0 && Y < 0) + theta = - M_PI / 2.0; + else if(X == 0 && Y >= 0) + theta = M_PI / 2.0; + else + theta = atan( Y / X ); + + if(pt.x() < alpha) + theta = theta + M_PI; + + ret(0) = 2*X - a * N * std::sin(N * theta) * Y / (X*X + Y*Y); + ret(1) = 2*Y + a * N * std::sin(N * theta) * X / (X*X + Y*Y); + return ret; + } +}; diff --git a/libdiskpp/include/diskpp/mesh/mesh.hpp b/libdiskpp/include/diskpp/mesh/mesh.hpp index 12c880bb..2e78c0d9 100644 --- a/libdiskpp/include/diskpp/mesh/mesh.hpp +++ b/libdiskpp/include/diskpp/mesh/mesh.hpp @@ -761,6 +761,23 @@ class neighbour_connectivity return std::make_pair( *std::next(msh.cells_begin(), fo[1].value()), true); } + + std::set + connected_cells(const Mesh& msh, const face_type& fc) + { + std::set ret; + auto face_id = msh.lookup(fc); + auto fo = face_owners.at( face_id ); + if (fo[0]) { + ret.insert(msh[fo[0].value()]); + } + if (fo[1]) { + ret.insert(msh[fo[1].value()]); + } + + return ret; + } + }; template diff --git a/libdiskpp/include/diskpp/methods/implementation_hho/scalar_stabilization.hpp b/libdiskpp/include/diskpp/methods/implementation_hho/scalar_stabilization.hpp index d647491b..b8b76424 100644 --- a/libdiskpp/include/diskpp/methods/implementation_hho/scalar_stabilization.hpp +++ b/libdiskpp/include/diskpp/methods/implementation_hho/scalar_stabilization.hpp @@ -147,7 +147,8 @@ dynamic_matrix make_scalar_hdg_stabilization(const Mesh& msh, const typename Mesh::cell_type& cl, const CellDegreeInfo& cell_infos, - bool hF = true) + bool hF = true, + bool scaling = true) { using T = typename Mesh::coordinate_type; typedef Matrix matrix_type; @@ -179,7 +180,7 @@ make_scalar_hdg_stabilization(const Mesh& msh, const auto fc = fcs[i]; const auto facdeg = fdi.degree(); - if(hF){ + if (hF) { h = diameter(msh, fc); } @@ -211,7 +212,12 @@ make_scalar_hdg_stabilization(const Mesh& msh, tr.block(0, 0, fbs, cbs) = trace; oper.block(0, 0, fbs, cbs) = mass.ldlt().solve(trace); - data += oper.transpose() * tr * (1. / h); + if (scaling) { + data += oper.transpose() * tr * (1. / h); + } + else { + data += oper.transpose() * tr; + } offset += fbs; } @@ -496,11 +502,12 @@ dynamic_matrix make_scalar_hdg_stabilization(const Mesh& msh, const typename Mesh::cell_type& cl, const hho_degree_info& di, - bool hF = true) + bool hF = true, + bool scaling = true) { const CellDegreeInfo cell_infos(msh, cl, di.cell_degree(), di.face_degree(), di.grad_degree()); - return make_scalar_hdg_stabilization(msh, cl, cell_infos, hF); + return make_scalar_hdg_stabilization(msh, cl, cell_infos, hF, scaling); } /** @@ -519,9 +526,10 @@ dynamic_matrix make_scalar_hdg_stabilization(const Mesh& msh, const typename Mesh::cell_type& cl, const MeshDegreeInfo& msh_infos, - bool hF = true) + bool hF = true, + bool scaling = true) { - return make_scalar_hdg_stabilization(msh, cl, msh_infos.cellDegreeInfo(msh, cl), hF); + return make_scalar_hdg_stabilization(msh, cl, msh_infos.cellDegreeInfo(msh, cl), hF, scaling); } /** diff --git a/libdiskpp/include/diskpp/methods/implementation_hho/vector_stabilization.hpp b/libdiskpp/include/diskpp/methods/implementation_hho/vector_stabilization.hpp index dcfe4d1c..b345ed0d 100644 --- a/libdiskpp/include/diskpp/methods/implementation_hho/vector_stabilization.hpp +++ b/libdiskpp/include/diskpp/methods/implementation_hho/vector_stabilization.hpp @@ -217,9 +217,10 @@ dynamic_matrix make_vector_hdg_stabilization(const Mesh& msh, const typename Mesh::cell_type& cl, const hho_degree_info& di, - const bool hF = true) + bool hF = true, + bool scaling = true) { - const auto hdg_scalar_stab = make_scalar_hdg_stabilization(msh, cl, di, hF); + const auto hdg_scalar_stab = make_scalar_hdg_stabilization(msh, cl, di, hF, scaling); return priv::compute_lhs_vector(msh, cl, di, hdg_scalar_stab); } @@ -240,9 +241,10 @@ dynamic_matrix make_vector_hdg_stabilization(const Mesh& msh, const typename Mesh::cell_type& cl, const MeshDegreeInfo& msh_infos, - const bool hF = true) + const bool hF = true, + bool scaling = true) { - const auto hdg_scalar_stab = make_scalar_hdg_stabilization(msh, cl, msh_infos, hF); + const auto hdg_scalar_stab = make_scalar_hdg_stabilization(msh, cl, msh_infos, hF, scaling); return priv::compute_lhs_vector(msh, cl, msh_infos.cellDegreeInfo(msh, cl), hdg_scalar_stab); }