diff --git a/examples/helmholtz/crossPoints/CMakeLists.txt b/examples/helmholtz/crossPoints/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a2ccf9a85fe35e93aef5ac322cedae2ce9436cc --- /dev/null +++ b/examples/helmholtz/crossPoints/CMakeLists.txt @@ -0,0 +1,231 @@ +cmake_minimum_required(VERSION 3.0 FATAL_ERROR) + +project(demo CXX) + +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag("-std=c++11" HAVE_CXX11) +if(HAVE_CXX11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +else() + message(ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") +endif() + +check_cxx_compiler_flag("-Wall" HAVE_WALL) +if(HAVE_WALL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +endif() + +macro(find_all_libraries VARNAME LISTNAME PATH SUFFIX) + set(${VARNAME}) + list(LENGTH ${LISTNAME} NUM_LIST) + foreach(LIB ${${LISTNAME}}) + if("${PATH}" STREQUAL "") + find_library(FOUND_LIB ${LIB} PATH_SUFFIXES ${SUFFIX}) + else() + find_library(FOUND_LIB ${LIB} PATHS ${PATH} NO_DEFAULT_PATH) + endif() + if(FOUND_LIB) + list(APPEND ${VARNAME} ${FOUND_LIB}) + endif() + unset(FOUND_LIB CACHE) + endforeach() + list(LENGTH ${VARNAME} NUM_FOUND_LIBRARIES) + if(NUM_FOUND_LIBRARIES LESS NUM_LIST) + set(${VARNAME}) + endif() +endmacro() + + +macro(set_config_option STRING VARNAME) + set(${VARNAME} TRUE) + list(APPEND CONFIG_OPTIONS ${STRING}) + message(STATUS "Found " ${STRING}) +endmacro() + +macro(opt OPTION HELP VALUE) + option(ENABLE_${OPTION} ${HELP} ${VALUE}) + set(OPT_TEXI "${OPT_TEXI}\n@item ENABLE_${OPTION}\n${HELP} (default: ${VALUE})") +endmacro() + +opt(MPI "Enable MPI" OFF) + +#### +# Mandatory libs +#### + +# Gmsh (Mandatory) + +find_library(GMSH_LIB gmsh) +if(NOT GMSH_LIB) + message(FATAL_ERROR "Could not find libgmsh") +endif(NOT GMSH_LIB) + +find_path(GMSH_INC gmsh.h) +if(NOT GMSH_INC) + message(FATAL_ERROR "Could not find gmsh.h") +endif(NOT GMSH_INC) + +list(APPEND EXTRA_INCS ${GMSH_INC}) +list(APPEND EXTRA_LIBS ${GMSH_LIB}) + +# GmshFem + +find_library(GMSHFEM_LIB gmshfem) +if(NOT GMSHFEM_LIB) + message(FATAL_ERROR "Could not find libgmshfem") +endif(NOT GMSHFEM_LIB) + +find_path(GMSHFEM_INC gmshfem/GmshFem.h) +if(NOT GMSHFEM_INC) + message(FATAL_ERROR "Could not find 'gmshfem/GmshFem.h'") +endif(NOT GMSHFEM_INC) + +list(APPEND EXTRA_LIBS ${GMSHFEM_LIB}) +list(APPEND EXTRA_INCS ${GMSHFEM_INC}/gmshfem/contrib) +list(APPEND EXTRA_INCS ${GMSHFEM_INC}) + +# GmshDdm + +find_library(GMSHDDM_LIB gmshddm) +if(NOT GMSHDDM_LIB) + message(FATAL_ERROR "Could not find libgmshddm") +endif(NOT GMSHDDM_LIB) + +find_path(GMSHDDM_INC gmshddm/GmshDdm.h) +if(NOT GMSHDDM_INC) + message(FATAL_ERROR "Could not find 'gmshddm/GmshDdm.h'") +endif(NOT GMSHDDM_INC) + +list(APPEND EXTRA_LIBS ${GMSHDDM_LIB}) +list(APPEND EXTRA_INCS ${GMSHDDM_INC}) + +# Eigen + +find_package(Eigen3 REQUIRED) +list(APPEND EXTRA_INCS "${EIGEN3_INCLUDE_DIR}") + +# OpenMP + +find_package(OpenMP) +if(OPENMP_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +endif(OPENMP_FOUND) + +if(APPLE AND EXISTS "/usr/local/opt/libomp") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xpreprocessor -fopenmp -I/usr/local/opt/libomp/include") + list(APPEND EXTRA_LIBS "-L/usr/local/opt/libomp/lib -lomp") +endif() + +# MPI + +if(ENABLE_MPI) + find_package(MPI) + if(MPI_FOUND) + list(APPEND EXTRA_INCS ${MPI_CXX_INCLUDE_PATH}) + list(APPEND EXTRA_LIBS ${MPI_CXX_LIBRARIES}) + set(CMAKE_C_COMPILER ${MPI_C_COMPILER}) + set(CMAKE_CXX_COMPILER ${MPI_CXX_COMPILER}) + set(CMAKE_Fortran_COMPILER ${MPI_Fortran_COMPILER}) + set_config_option("MPI" HAVE_MPI) + endif() +endif() + +# PETSc + +if(PETSC_DIR) +set(ENV_PETSC_DIR ${PETSC_DIR}) +else() + set(ENV_PETSC_DIR $ENV{PETSC_DIR}) +endif() + +if(PETSC_ARCH) + set(ENV_PETSC_ARCH ${PETSC_ARCH}) +else() + set(ENV_PETSC_ARCH $ENV{PETSC_ARCH}) +endif() + +set(PETSC_POSSIBLE_CONF_FILES + ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/conf/petscvariables + ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib/petsc-conf/petscvariables + ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib/petsc/conf/petscvariables) + +foreach(FILE ${PETSC_POSSIBLE_CONF_FILES}) + if(EXISTS ${FILE}) + # old-style PETSc installations (using PETSC_DIR and PETSC_ARCH) + message(STATUS "Using PETSc dir: ${ENV_PETSC_DIR}") + message(STATUS "Using PETSc arch: ${ENV_PETSC_ARCH}") + # find includes by parsing the petscvariables file + file(STRINGS ${FILE} PETSC_VARIABLES NEWLINE_CONSUME) + endif() +endforeach() + +if(PETSC_VARIABLES) + # try to find PETSC_CC_INCLUDES for PETSc >= 3.4 + string(REGEX MATCH "PETSC_CC_INCLUDES = [^\n\r]*" PETSC_PACKAGES_INCLUDES ${PETSC_VARIABLES}) + if(PETSC_PACKAGES_INCLUDES) + string(REPLACE "PETSC_CC_INCLUDES = " "" PETSC_PACKAGES_INCLUDES ${PETSC_PACKAGES_INCLUDES}) + else() + # try to find PETSC_PACKAGES_INCLUDES in older versions + list(APPEND EXTRA_INCS ${ENV_PETSC_DIR}/include) + list(APPEND EXTRA_INCS ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/include) + string(REGEX MATCH "PACKAGES_INCLUDES = [^\n\r]*" PETSC_PACKAGES_INCLUDES ${PETSC_VARIABLES}) + string(REPLACE "PACKAGES_INCLUDES = " "" PETSC_PACKAGES_INCLUDES ${PETSC_PACKAGES_INCLUDES}) + endif() + + if(PETSC_PACKAGES_INCLUDES) + if(PETSC_PACKAGES_INCLUDES) + string(REPLACE "-I" "" PETSC_PACKAGES_INCLUDES ${PETSC_PACKAGES_INCLUDES}) + string(REPLACE " " ";" PETSC_PACKAGES_INCLUDES ${PETSC_PACKAGES_INCLUDES}) + foreach(VAR ${PETSC_PACKAGES_INCLUDES}) + list(APPEND EXTRA_INCS ${VAR}) + endforeach() + endif() + endif() + + # find libraries (<= 3.0) + set(PETSC_LIBS_REQUIRED petscksp petscdm petscmat petscvec petsc) + find_all_libraries(PETSC_LIBS PETSC_LIBS_REQUIRED ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib "") + # petsc 3.1 creates only one library (libpetsc) + if(NOT PETSC_LIBS) + find_library(PETSC_LIBS petsc PATHS ${ENV_PETSC_DIR}/${ENV_PETSC_ARCH}/lib NO_DEFAULT_PATH) + endif() + + list(APPEND EXTRA_LIBS ${PETSC_LIBS}) + + string(REGEX MATCH "PACKAGES_LIBS = [^\n\r]*" PLIBS ${PETSC_VARIABLES}) + if(PLIBS) + string(REPLACE "PACKAGES_LIBS = " "" PLIBS ${PLIBS}) + string(STRIP ${PLIBS} PLIBS) + list(APPEND EXTRA_LIBS "${PLIBS}") + endif() + + string(REGEX MATCH "PETSC_EXTERNAL_LIB_BASIC = [^\n\r]*" PLIBS_BASIC ${PETSC_VARIABLES}) + if(PLIBS_BASIC) + string(REPLACE "PETSC_EXTERNAL_LIB_BASIC = " "" PLIBS_BASIC ${PLIBS_BASIC}) + string(STRIP ${PLIBS_BASIC} PLIBS_BASIC) + list(APPEND EXTRA_LIBS "${PLIBS_BASIC}") + endif() + + string(REGEX MATCH "PCC_LINKER_LIBS = [^\n\r]*" LLIBS ${PETSC_VARIABLES}) + if(LLIBS) + string(REPLACE "PCC_LINKER_LIBS = " "" LLIBS ${LLIBS}) + string(STRIP ${LLIBS} LLIBS) + list(APPEND EXTRA_LIBS "${LLIBS}") + endif() + + set_config_option("PETSc" HAVE_PETSC) + list(APPEND EXTRA_LIBS ${PETSC_LIBS}) +else() + find_library(PETSC_LIBS petsc) + find_path(PETSC_INC "petsc.h" PATH_SUFFIXES include/petsc) + if(PETSC_LIBS AND PETSC_INC) + set_config_option("PETSc" HAVE_PETSC) + list(APPEND EXTRA_LIBS ${PETSC_LIBS}) + list(APPEND EXTRA_INCS ${PETSC_INC}) + endif() +endif() + +include_directories(${EXTRA_INCS}) +add_executable(demo main.cpp mesh.cpp ddm2D.cpp ddm3D.cpp Subproblem2D.cpp Subproblem3D.cpp SubproblemDomains.cpp SubproblemParameters.cpp monoDomain.cpp ${EXTRA_INCS}) +target_link_libraries(demo ${EXTRA_LIBS}) + diff --git a/examples/helmholtz/crossPoints/README.md b/examples/helmholtz/crossPoints/README.md new file mode 100644 index 0000000000000000000000000000000000000000..93a68a746c336ca524b870232485f06730ed36dd --- /dev/null +++ b/examples/helmholtz/crossPoints/README.md @@ -0,0 +1,33 @@ +# Helmholtz cross-points +> Anthony Royer + +Dependency(ies): +* GmshDDM : 1.0.0 +* GmshFEM : 1.0.0 +* ... + +## Project description + +In this work, we present a non-overlapping substructured DDM with PML transmission conditions or HABC +transmission conditionz forvcheckerboard (Cartesian) decompositions that takes cross-points into account. +In such decompositions, each subdomain is surrounded by PMLs associated to edges and corners. + +## Installation + +``` +mkdir build && cd build +cmake .. +make +sudo make install +``` + +## Usage + +Simply run: +``` + ./example [PARAM] +``` + +## References + +A. Royer, C. Geuzaine, E. Béchet and A. Modave, "A non-overlapping domain decomposition method with perfectly matched layer transmission conditions for the Helmholtz equation", in review, 2021 diff --git a/examples/helmholtz/crossPoints/Subproblem2D.cpp b/examples/helmholtz/crossPoints/Subproblem2D.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0cd84471f3ea5fe284d81af232a0b8f94967073b --- /dev/null +++ b/examples/helmholtz/crossPoints/Subproblem2D.cpp @@ -0,0 +1,1317 @@ +#include "Subproblem2D.h" + +using gmshfem::equation::dof; +using gmshfem::equation::tf; +using gmshfem::function::operator-; +using gmshfem::function::operator+; +using gmshfem::function::operator*; + +namespace D2 { + + + // ********************************** + // Boundary + // ********************************** + + Boundary::Boundary(const unsigned int boundary) : _boundary(boundary) + { + } + + Boundary::~Boundary() + { + } + + std::string Boundary::orientation() const + { + switch (_boundary) { + case 0: + return "E"; + break; + case 1: + return "N"; + break; + case 2: + return "W"; + break; + case 3: + return "S"; + break; + default: + break; + } + return "null"; + } + + // ********************************** + // Corner + // ********************************** + + Corner::Corner(const unsigned int corner, Boundary *first, Boundary *second) : _corner(corner), _bnd {first, second} + { + } + + Corner::~Corner() + { + } + + std::string Corner::orientation() const + { + switch (_corner) { + case 0: + return "EN"; + break; + case 1: + return "NW"; + break; + case 2: + return "WS"; + break; + case 3: + return "SE"; + break; + default: + break; + } + return "null"; + } + + // ********************************** + // Subproblem + // ********************************** + + void Subproblem::_parseParameters(std::string &method, std::vector< std::string > ¶meters, const std::string &str) const + { + method.clear(); + parameters.clear(); + std::string *current = &method; + for(unsigned int i = 0; i < str.size(); ++i) { + if(str[i] == '_') { + parameters.push_back(std::string()); + current = ¶meters.back(); + } + else { + (*current) += str[i]; + } + } + } + + Subproblem::Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters, const std::string &E, const std::string &N, const std::string &W, const std::string &S) : _domains(domains), _parameters(parameters), _formulation(formulation), _fieldName(fieldName), _boundary(4, nullptr), _corner(4, nullptr) + { + std::string type[4] = {E, N, W, S}; + std::string method[4]; + std::vector< std::string > bndParameters[4]; + for(unsigned int i = 0; i < 4; ++i) { + _parseParameters(method[i], bndParameters[i], type[i]); + } + + for(unsigned int b = 0; b < 4; ++b) { + if(method[b] == "sommerfeld") { // str: sommerfeld + _boundary[b] = new Sommerfeld(b); + } + else if(method[b] == "habc") { // str: habc_[N]_[theta] + const unsigned int N = std::stoi(bndParameters[b][0]); + const double theta = std::stof(bndParameters[b][1]); + _boundary[b] = new HABC(b, N, theta); + } + else if(method[b] == "pmlContinuous") { // str: pmlContinuous_[N_pml]_[Type] + const double N_pml = std::stof(bndParameters[b][0]); + const std::string type = bndParameters[b][1]; + _boundary[b] = new PmlContinuous(b, N_pml, type); + } + else if(method[b] == "pmlDiscontinuous") { // str: pmlDiscontinuous_[N_pml]_[Type] + const double N_pml = std::stof(bndParameters[b][0]); + const std::string type = bndParameters[b][1]; + _boundary[b] = new PmlDiscontinuous(b, N_pml, type); + } + else if(method[b] == "pmlWithoutMultiplier") { // str: pmlWithoutMultiplier_[N_pml]_[Type] + const double N_pml = std::stof(bndParameters[b][0]); + const std::string type = bndParameters[b][1]; + _boundary[b] = new PmlWithoutMultiplier(b, N_pml, type); + } + else { + gmshfem::msg::error << "Unknown method '" << method[b] << "'" << gmshfem::msg::endl; + } + } + + for(unsigned int c = 0; c < 4; ++c) { + if(method[c] == "sommerfeld" && method[(c+1)%4] == "sommerfeld") { + } + else if(method[c] == "habc" && method[(c+1)%4] == "habc") { + _corner[c] = new HABC_HABC(c, static_cast< HABC * >(_boundary[c]), static_cast< HABC * >(_boundary[(c+1)%4])); + } + else if(method[c] == "habc" && method[(c+1)%4] == "sommerfeld") { + _corner[c] = new HABC_Sommerfeld(c, static_cast< HABC * >(_boundary[c]), static_cast< Sommerfeld * >(_boundary[(c+1)%4])); + } + else if(method[c] == "sommerfeld" && method[(c+1)%4] == "habc") { + _corner[c] = new Sommerfeld_HABC(c, static_cast< Sommerfeld * >(_boundary[c]), static_cast< HABC * >(_boundary[(c+1)%4])); + } + else if(method[c] == "pmlContinuous" && method[(c+1)%4] == "pmlContinuous") { + _corner[c] = new PmlContinuous_PmlContinuous(c, static_cast< PmlContinuous * >(_boundary[c]), static_cast< PmlContinuous * >(_boundary[(c+1)%4])); + } + else if(method[c] == "pmlDiscontinuous" && method[(c+1)%4] == "pmlDiscontinuous") { + _corner[c] = new PmlDiscontinuous_PmlDiscontinuous(c, static_cast< PmlDiscontinuous * >(_boundary[c]), static_cast< PmlDiscontinuous * >(_boundary[(c+1)%4])); + } + else if(method[c] == "pmlWithoutMultiplier" && method[(c+1)%4] == "pmlWithoutMultiplier") { + _corner[c] = new PmlWithoutMultiplier_PmlWithoutMultiplier(c, static_cast< PmlWithoutMultiplier * >(_boundary[c]), static_cast< PmlWithoutMultiplier * >(_boundary[(c+1)%4])); + } + else if(method[c] == "pmlContinuous" && method[(c+1)%4] == "sommerfeld") { + _corner[c] = new PmlContinuous_Sommerfeld(c, static_cast< PmlContinuous * >(_boundary[c]), static_cast< Sommerfeld * >(_boundary[(c+1)%4])); + } + else if(method[c] == "sommerfeld" && method[(c+1)%4] == "pmlContinuous") { + _corner[c] = new Sommerfeld_PmlContinuous(c, static_cast< Sommerfeld * >(_boundary[c]), static_cast< PmlContinuous * >(_boundary[(c+1)%4])); + } + else if(method[c] == "pmlDiscontinuous" && method[(c+1)%4] == "sommerfeld") { + _corner[c] = new PmlDiscontinuous_Sommerfeld(c, static_cast< PmlDiscontinuous * >(_boundary[c]), static_cast< Sommerfeld * >(_boundary[(c+1)%4])); + } + else if(method[c] == "sommerfeld" && method[(c+1)%4] == "pmlDiscontinuous") { + _corner[c] = new Sommerfeld_PmlDiscontinuous(c, static_cast< Sommerfeld * >(_boundary[c]), static_cast< PmlDiscontinuous * >(_boundary[(c+1)%4])); + } + else { + gmshfem::msg::warning << "Any corner treatment between '" << method[c] << "' and '" << method[(c+1)%4] << "'" << gmshfem::msg::endl; + } + } + } + + Subproblem::~Subproblem() + { + for(unsigned int c = 0; c < 4; ++c) { + if(_corner[c] != nullptr) { + delete _corner[c]; + } + } + for(unsigned int b = 0; b < 4; ++b) { + if(_boundary[b] != nullptr) { + delete _boundary[b]; + } + } + } + + void Subproblem::writeFormulation() + { + for(unsigned int b = 0; b < 4; ++b) { + _boundary[b]->writeFormulation(_formulation, _fieldName, _domains, _parameters); + } + + for(unsigned int c = 0; c < 4; ++c) { + if(_corner[c] != nullptr) { + _corner[c]->writeFormulation(_formulation, _domains, _parameters); + } + } + } + + Boundary *Subproblem::getBoundary(const unsigned int b) const + { + return _boundary[b]; + } + + Corner *Subproblem::getCorner(const unsigned int c) const + { + return _corner[c]; + } + + // ********************************** + // Sommerfeld + // ********************************** + + Sommerfeld::Sommerfeld(const unsigned int boundary) : Boundary(boundary) + { + } + + Sommerfeld::~Sommerfeld() + { + delete _v; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* Sommerfeld::getV() const + { + return _v; + } + + void Sommerfeld::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + const std::complex< double > im(0., 1.); + formulation.integral(-dof(*_v), tf(*u), sigma, gauss); + + formulation.integral(dof(*_v), tf(*_v), sigma, gauss); + formulation.integral(im * kappa * dof(*u), tf(*_v), sigma, gauss); + } + + // ********************************** + // HABC + // ********************************** + + HABC::HABC(const unsigned int boundary, const unsigned int N, const double theta) : Boundary(boundary), _N(N), _theta(theta) + { + } + + HABC::~HABC() + { + delete _v; + for(unsigned int m = 0; m < _N; ++m) { + delete _uHABC[m]; + } + } + + unsigned int HABC::getN() const + { + return _N; + } + + double HABC::getTheta() const + { + return _theta; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * HABC::getUHABC(const unsigned int m) const + { + if(m > _N) throw gmshfem::common::Exception("Try to get uHABC field " + std::to_string(m)); + return _uHABC[m]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* HABC::getV() const + { + return _v; + } + + void HABC::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uHABC.resize(_N); + for(unsigned int m = 0; m < _N; ++m) { + _uHABC[m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uHABC_" + orientation() + "_" + std::to_string(m), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + } + + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + const double pi = 3.141592653589793238462643383279; + const std::complex< double > expPTheta(std::cos(_theta), std::sin(_theta)); + const std::complex< double > expMTheta(std::cos(-_theta), std::sin(-_theta)); + const std::complex< double > expPTheta2(std::cos(_theta/2.), std::sin(_theta/2.)); + const double M = 2 * _N + 1; + double cPade[_N]; + for(unsigned int m = 0; m < _N; ++m) { + cPade[m] = std::tan((m+1) * pi / M) * std::tan((m+1) * pi / M); + } + + const std::complex< double > im(0., 1.); + + formulation.integral(-dof(*_v), tf(*u), sigma, gauss); + + formulation.integral( dof(*_v), tf(*_v), sigma, gauss); + formulation.integral( im * kappa * expPTheta2 * dof(*u), tf(*_v), sigma, gauss); + + for(unsigned int m = 0; m < _N; ++m) { + formulation.integral( im * kappa * expPTheta2 * 2./M * cPade[m] * dof(*u), tf(*_v), sigma, gauss); + formulation.integral( im * kappa * expPTheta2 * 2./M * cPade[m] * dof(*_uHABC[m]), tf(*_v), sigma, gauss); + } + + // auxiliary + for(unsigned int m = 0; m < _N; ++m) { + formulation.integral(grad(dof(*_uHABC[m])), grad(tf(*_uHABC[m])), sigma, gauss); + formulation.integral(- kappa * kappa * (expPTheta * cPade[m] + 1.) * dof(*_uHABC[m]), tf(*_uHABC[m]), sigma, gauss); + formulation.integral(- kappa * kappa * expPTheta * (cPade[m] + 1.) * dof(*u), tf(*_uHABC[m]), sigma, gauss); + } + } + + // ********************************** + // PML + // ********************************** + + Pml::Pml(const unsigned int boundary, const double pmlSize, const std::string type) : Boundary(boundary), _size(pmlSize), _type(type) + { + } + + Pml::~Pml() + { + } + + double Pml::getSize() const + { + return _size; + } + + gmshfem::function::ScalarFunction< std::complex< double > > Pml::pmlCoefficients(gmshfem::function::TensorFunction< std::complex< double > > &D, gmshfem::function::ScalarFunction< std::complex< double > > &E, gmshfem::domain::Domain &bnd, const gmshfem::function::ScalarFunction< std::complex< double > > &kappa) const + { + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod; + const std::complex< double > im(0., 1.); + + gmshfem::function::ScalarFunction< std::complex< double > > distSigma; + gmshfem::function::ScalarFunction< std::complex< double > > sigma; + if(orientation() == "E" || orientation() == "W") { + distSigma = abs(gmshfem::function::x< std::complex< double > >() - gmshfem::function::x< std::complex< double > >(bnd)); + if(bnd.maxDim() == 0) { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >(bnd)); + } + else { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(), gmshfem::function::z< double >()); + } + } + else if(orientation() == "N" || orientation() == "S") { + distSigma = abs(gmshfem::function::y< std::complex< double > >() - gmshfem::function::y< std::complex< double > >(bnd)); + if(bnd.maxDim() == 0) { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >(bnd)); + } + else { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >()); + } + } + + if(_type == "hs") { + sigma = 1. / (_size - distSigma) - 1./ _size; + } + else if(_type == "h") { + sigma = 1. / (_size - distSigma); + } + else if(_type == "q") { + const double sigmaStar = 86.435; // N = 6 : 86.435; N = 1 : 186 + sigma = sigmaStar * distSigma * distSigma / (_size * _size); + } + + gmshfem::function::ScalarFunction< std::complex< double > > kMod = 1. + im * sigma / kappaMod; + if(orientation() == "E" || orientation() == "W") { + D = gmshfem::function::tensorDiag< std::complex< double > >(1./kMod, kMod, kMod); + E = kMod; + } + else if(orientation() == "N" || orientation() == "S") { + D = gmshfem::function::tensorDiag< std::complex< double > >(kMod, 1./kMod, kMod); + E = kMod; + } + + return kappaMod; + } + + // ********************************** + // PML continuous + // ********************************** + + PmlContinuous::PmlContinuous(const unsigned int boundary, const double pmlSize, const std::string type) : Pml(boundary, pmlSize, type) + { + } + + PmlContinuous::~PmlContinuous() + { + delete _v; + delete _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlContinuous::getUPml() const + { + return _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlContinuous::getV() const + { + return _v; + } + + void PmlContinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + gmshfem::domain::Domain pml = domains.getPml(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + const double stab = parameters.getStab(); + + _uPml = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPml_" + orientation(), pml, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = pmlCoefficients(D, E, sigma, kappa); + + formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_uPml)), pml, gauss); + formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_uPml), pml, gauss); + + formulation.integral(dof(*_v), tf(*_uPml), sigma, gauss); + formulation.integral(- dof(*_v), tf(*u), sigma, gauss); + + formulation.integral(dof(*_uPml), tf(*_v), sigma, gauss); + formulation.integral(- dof(*u), tf(*_v), sigma, gauss); + + // penalization + formulation.integral(stab * dof(*_v), tf(*_v), sigma, gauss); + } + + // ********************************** + // PML discontinuous + // ********************************** + + PmlDiscontinuous::PmlDiscontinuous(const unsigned int boundary, const double pmlSize, const std::string type) : Pml(boundary, pmlSize, type) + { + } + + PmlDiscontinuous::~PmlDiscontinuous() + { + delete _v; + delete _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlDiscontinuous::getUPml() const + { + return _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * PmlDiscontinuous::getV() const + { + return _v; + } + + void PmlDiscontinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + gmshfem::domain::Domain pml = domains.getPml(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + const double stab = parameters.getStab(); + + _uPml = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPml_" + orientation(), pml, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = pmlCoefficients(D, E, sigma, kappa); + + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + + formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_uPml)), pml, gauss); + formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_uPml), pml, gauss); + + formulation.integral(n * dof(*_v), tf(*_uPml), sigma, gauss); + formulation.integral(- n * dof(*_v), tf(*u), sigma, gauss); + + formulation.integral(dof(*_uPml), n * tf(*_v), sigma, gauss); + formulation.integral(- dof(*u), n * tf(*_v), sigma, gauss); + + // penalization + formulation.integral(stab * dof(*_v), tf(*_v), sigma, gauss); + } + + // ********************************** + // PML without multiplier + // ********************************** + + PmlWithoutMultiplier::PmlWithoutMultiplier(const unsigned int boundary, const double pmlSize, const std::string type) : Pml(boundary, pmlSize, type) + { + } + + PmlWithoutMultiplier::~PmlWithoutMultiplier() + { + delete _v; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlWithoutMultiplier::getUPml() const + { + return _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlWithoutMultiplier::getV() const + { + return _v; + } + + void PmlWithoutMultiplier::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + gmshfem::domain::Domain pml = domains.getPml(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uPml = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + _uPml->domain(_uPml->domain() | pml); + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = pmlCoefficients(D, E, sigma, kappa); + + formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_uPml)), pml, gauss); + formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_uPml), pml, gauss); + + gmshfem::domain::SkinLayer pmlLayer = pml.getSkinLayer(sigma); + formulation.integral(dof(*_v), tf(*_v), sigma, gauss); + formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_v)), pmlLayer, gauss); + formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_v), pmlLayer, gauss); + } + + + // ********************************** + // HABC_HABC + // ********************************** + + HABC_HABC::HABC_HABC(const unsigned int corner, HABC *first, HABC *second) : Corner(corner, first, second) + { + } + + HABC_HABC::~HABC_HABC() + { + const unsigned int N0 = static_cast< HABC * >(_bnd[0])->getN(); + const unsigned int N1 = static_cast< HABC * >(_bnd[1])->getN(); + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + delete _uHABC_C[m][n]; + } + } + for(unsigned int m = 0; m < N0; ++m) { + delete _vC[0][m]; + } + for(unsigned int n = 0; n < N1; ++n) { + delete _vC[1][n]; + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *HABC_HABC::getV(const unsigned int m, const unsigned int i) const + { + return _vC[i][m]; + } + + HABC *HABC_HABC::firstBoundary() const + { + return static_cast< HABC * >(_bnd[0]); + } + + HABC *HABC_HABC::secondBoundary() const + { + return static_cast< HABC * >(_bnd[1]); + } + + void HABC_HABC::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + // TODO: Only work when both HABC are the same + gmshfem::domain::Domain corner = domains.getCorner(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + const unsigned int N0 = static_cast< HABC * >(_bnd[0])->getN(); + const unsigned int N1 = static_cast< HABC * >(_bnd[1])->getN(); + + const double theta0 = static_cast< HABC * >(_bnd[0])->getTheta(); + // const double theta1 = static_cast< HABC * >(_bnd[1])->getTheta(); + + if(N0 != N1) { + throw gmshfem::common::Exception("Corner with HABC having different number of auxilary fields"); + } + + _uHABC_C.resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _uHABC_C[m].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _uHABC_C[m][n] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uHABC_Corner_" + orientation() + "_" + std::to_string(m) + "_" + std::to_string(n), corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + } + } + + _vC[0].resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _vC[0][m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(m) + "_first", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + _vC[1].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _vC[1][n] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(n) + "_second", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + + const double pi = 3.141592653589793238462643383279; + const std::complex< double > expPTheta(std::cos(theta0), std::sin(theta0)); + const std::complex< double > expMTheta(std::cos(-theta0), std::sin(-theta0)); + const std::complex< double > expPTheta2(std::cos(theta0/2.), std::sin(theta0/2.)); + const double M0 = 2 * N0 + 1; + double cPade0[N0]; + for(unsigned int m = 0; m < N0; ++m) { + cPade0[m] = std::tan((m+1) * pi / M0) * std::tan((m+1) * pi / M0); + } + const double M1 = 2 * N1 + 1; + double cPade1[N1]; + for(unsigned int n = 0; n < N1; ++n) { + cPade1[n] = std::tan((n+1) * pi / M1) * std::tan((n+1) * pi / M1); + } + + const std::complex< double > im(0., 1.); + + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > uHABC[2]; + uHABC[0].resize(N0); + uHABC[1].resize(N1); + + for(unsigned int m = 0; m < N0; ++m) { + uHABC[0][m] = static_cast< HABC * >(_bnd[0])->getUHABC(m); + formulation.integral(-dof(*_vC[0][m]), tf(*uHABC[0][m]), corner, gauss); + + formulation.integral( dof(*_vC[0][m]), tf(*_vC[0][m]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[0][m]), tf(*_vC[0][m]), corner, gauss); + + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*uHABC[0][m]), tf(*_vC[0][m]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*_uHABC_C[m][n]), tf(*_vC[0][m]), corner, gauss); + } + } + + for(unsigned int n = 0; n < N1; ++n) { + uHABC[1][n] = static_cast< HABC * >(_bnd[1])->getUHABC(n); + formulation.integral(-dof(*_vC[1][n]), tf(*uHABC[1][n]), corner, gauss); + + formulation.integral( dof(*_vC[1][n]), tf(*_vC[1][n]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[1][n]), tf(*_vC[1][n]), corner, gauss); + + for(unsigned int m = 0; m < N0; ++m) { + formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*uHABC[1][n]), tf(*_vC[1][n]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*_uHABC_C[m][n]), tf(*_vC[1][n]), corner, gauss); + } + } + + // auxiliary + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral( (cPade0[m] + cPade1[n] + expMTheta) * dof(*_uHABC_C[m][n]), tf(*_uHABC_C[m][n]), corner, gauss); + formulation.integral( (cPade1[n] + 1.) * dof(*uHABC[0][m]), tf(*_uHABC_C[m][n]), corner, gauss); + formulation.integral( (cPade0[m] + 1.) * dof(*uHABC[1][n]), tf(*_uHABC_C[m][n]), corner, gauss); + } + } + } + + // ********************************** + // PML continuous _ PML continuous + // ********************************** + + PmlContinuous_PmlContinuous::PmlContinuous_PmlContinuous(const unsigned int corner, PmlContinuous *first, PmlContinuous *second) : Corner(corner, first, second) + { + } + + PmlContinuous_PmlContinuous::~PmlContinuous_PmlContinuous() + { + delete _uPmlCorner; + delete _vC[0]; + delete _vC[1]; + delete _vCorner; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous::getUPml() const + { + return _uPmlCorner; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous::getV(const unsigned int i) const + { + return _vC[i]; + } + + PmlContinuous *PmlContinuous_PmlContinuous::firstBoundary() const + { + return static_cast< PmlContinuous * >(_bnd[0]); + } + + PmlContinuous *PmlContinuous_PmlContinuous::secondBoundary() const + { + return static_cast< PmlContinuous * >(_bnd[1]); + } + + void PmlContinuous_PmlContinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + const double stab = parameters.getStab(); + + _uPmlCorner = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPmlCorner_" + orientation(), pmlCorner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + _vC[0] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_first", pmlBnd.first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + _vC[1] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_second", pmlBnd.second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml[2]; + uPml[0] = static_cast< PmlContinuous * >(_bnd[0])->getUPml(); + uPml[1] = static_cast< PmlContinuous * >(_bnd[1])->getUPml(); + + gmshfem::function::TensorFunction< std::complex< double > > D[2]; + gmshfem::function::ScalarFunction< std::complex< double > > E[2]; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlContinuous * >(_bnd[0])->pmlCoefficients(D[0], E[0], corner, kappa); + static_cast< PmlContinuous * >(_bnd[1])->pmlCoefficients(D[1], E[1], corner, kappa); + + formulation.integral(- D[0] * D[1] * grad(dof(*_uPmlCorner)), grad(tf(*_uPmlCorner)), pmlCorner, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * dof(*_uPmlCorner), tf(*_uPmlCorner), pmlCorner, gauss); + + formulation.integral(dof(*_vC[0]), tf(*_uPmlCorner), pmlBnd.first, gauss); + formulation.integral(- dof(*_vC[0]), tf(*uPml[0]), pmlBnd.first, gauss); + + formulation.integral(dof(*_uPmlCorner), tf(*_vC[0]), pmlBnd.first, gauss); + formulation.integral(- dof(*uPml[0]), tf(*_vC[0]), pmlBnd.first, gauss); + + formulation.integral(dof(*_vC[1]), tf(*_uPmlCorner), pmlBnd.second, gauss); + formulation.integral(- dof(*_vC[1]), tf(*uPml[1]), pmlBnd.second, gauss); + + formulation.integral(dof(*_uPmlCorner), tf(*_vC[1]), pmlBnd.second, gauss); + formulation.integral(- dof(*uPml[1]), tf(*_vC[1]), pmlBnd.second, gauss); + + // corner equation + _vCorner = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vCorner_" + orientation(), corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + +// formulation.integral(dof(*_vC[0]), tf(*_vCorner), corner, gauss); +// formulation.integral(dof(*_vCorner), tf(*_vC[0]), corner, gauss); +// +// formulation.integral(-dof(*_vC[1]), tf(*_vCorner), corner, gauss); +// formulation.integral(-dof(*_vCorner), tf(*_vC[1]), corner, gauss); +// +// formulation.integral(dof(*static_cast< PmlContinuous * >(_bnd[0])->getV()), tf(*_vCorner), corner, gauss); +// formulation.integral(dof(*_vCorner), tf(*static_cast< PmlContinuous * >(_bnd[0])->getV()), corner, gauss); +// +// formulation.integral(-dof(*static_cast< PmlContinuous * >(_bnd[1])->getV()), tf(*_vCorner), corner, gauss); +// formulation.integral(-dof(*_vCorner), tf(*static_cast< PmlContinuous * >(_bnd[1])->getV()), corner, gauss); + + // penalization + formulation.integral(stab * dof(*_vC[0]), tf(*_vC[0]), pmlBnd.first, gauss); + formulation.integral(stab * dof(*_vC[1]), tf(*_vC[1]), pmlBnd.second, gauss); + } + + // ********************************** + // PML discontinuous _ PML discontinuous + // ********************************** + + PmlDiscontinuous_PmlDiscontinuous::PmlDiscontinuous_PmlDiscontinuous(const unsigned int corner, PmlDiscontinuous *first, PmlDiscontinuous *second) : Corner(corner, first, second) + { + } + + PmlDiscontinuous_PmlDiscontinuous::~PmlDiscontinuous_PmlDiscontinuous() + { + delete _uPmlCorner; + delete _vC[0]; + delete _vC[1]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlDiscontinuous_PmlDiscontinuous::getUPml() const + { + return _uPmlCorner; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* PmlDiscontinuous_PmlDiscontinuous::getV(const unsigned int i) const + { + return _vC[i]; + } + + PmlDiscontinuous *PmlDiscontinuous_PmlDiscontinuous::firstBoundary() const + { + return static_cast< PmlDiscontinuous * >(_bnd[0]); + } + + PmlDiscontinuous *PmlDiscontinuous_PmlDiscontinuous::secondBoundary() const + { + return static_cast< PmlDiscontinuous * >(_bnd[1]); + } + + void PmlDiscontinuous_PmlDiscontinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + const double stab = parameters.getStab(); + + _uPmlCorner = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPmlCorner_" + orientation(), pmlCorner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + _vC[0] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >("vC_" + orientation() + "_first", pmlBnd.first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder); + _vC[1] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >("vC_" + orientation() + "_second", pmlBnd.second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml[2]; + uPml[0] = static_cast< PmlDiscontinuous * >(_bnd[0])->getUPml(); + uPml[1] = static_cast< PmlDiscontinuous * >(_bnd[1])->getUPml(); + + gmshfem::function::TensorFunction< std::complex< double > > D[2]; + gmshfem::function::ScalarFunction< std::complex< double > > E[2]; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlDiscontinuous * >(_bnd[0])->pmlCoefficients(D[0], E[0], corner, kappa); + static_cast< PmlDiscontinuous * >(_bnd[1])->pmlCoefficients(D[1], E[1], corner, kappa); + + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + + formulation.integral(- D[0] * D[1] * grad(dof(*_uPmlCorner)), grad(tf(*_uPmlCorner)), pmlCorner, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * dof(*_uPmlCorner), tf(*_uPmlCorner), pmlCorner, gauss); + + formulation.integral(n * dof(*_vC[0]), tf(*_uPmlCorner), pmlBnd.first, gauss); + formulation.integral(- n * dof(*_vC[0]), tf(*uPml[0]), pmlBnd.first, gauss); + + formulation.integral(dof(*_uPmlCorner), n * tf(*_vC[0]), pmlBnd.first, gauss); + formulation.integral(- dof(*uPml[0]), n * tf(*_vC[0]), pmlBnd.first, gauss); + + formulation.integral(n * dof(*_vC[1]), tf(*_uPmlCorner), pmlBnd.second, gauss); + formulation.integral(- n * dof(*_vC[1]), tf(*uPml[1]), pmlBnd.second, gauss); + + formulation.integral(dof(*_uPmlCorner), n * tf(*_vC[1]), pmlBnd.second, gauss); + formulation.integral(- dof(*uPml[1]), n * tf(*_vC[1]), pmlBnd.second, gauss); + + // penalization + formulation.integral(stab * dof(*_vC[0]), tf(*_vC[0]), pmlBnd.first, gauss); + formulation.integral(stab * dof(*_vC[1]), tf(*_vC[1]), pmlBnd.second, gauss); + } + + // ********************************** + // PML without multiplier _ PML without multiplier + // ********************************** + + PmlWithoutMultiplier_PmlWithoutMultiplier::PmlWithoutMultiplier_PmlWithoutMultiplier(const unsigned int corner, PmlWithoutMultiplier *first, PmlWithoutMultiplier *second) : Corner(corner, first, second) + { + } + + PmlWithoutMultiplier_PmlWithoutMultiplier::~PmlWithoutMultiplier_PmlWithoutMultiplier() + { + delete _vC[0]; + delete _vC[1]; + delete _vCorner; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlWithoutMultiplier_PmlWithoutMultiplier::getUPml() const + { + return _uPmlCorner; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlWithoutMultiplier_PmlWithoutMultiplier::getV(const unsigned int i) const + { + return _vC[i]; + } + + PmlWithoutMultiplier *PmlWithoutMultiplier_PmlWithoutMultiplier::firstBoundary() const + { + return static_cast< PmlWithoutMultiplier * >(_bnd[0]); + } + + PmlWithoutMultiplier *PmlWithoutMultiplier_PmlWithoutMultiplier::secondBoundary() const + { + return static_cast< PmlWithoutMultiplier * >(_bnd[1]); + } + + void PmlWithoutMultiplier_PmlWithoutMultiplier::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uPmlCorner = static_cast< PmlWithoutMultiplier * >(_bnd[0])->getUPml(); + _uPmlCorner->domain(_uPmlCorner->domain() | pmlCorner); + + _vC[0] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_first", pmlBnd.first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + _vC[1] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_second", pmlBnd.second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::function::TensorFunction< std::complex< double > > D[2]; + gmshfem::function::ScalarFunction< std::complex< double > > E[2]; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlWithoutMultiplier * >(_bnd[0])->pmlCoefficients(D[0], E[0], corner, kappa); + static_cast< PmlWithoutMultiplier * >(_bnd[1])->pmlCoefficients(D[1], E[1], corner, kappa); + + formulation.integral(- D[0] * D[1] * grad(dof(*_uPmlCorner)), grad(tf(*_uPmlCorner)), pmlCorner, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * dof(*_uPmlCorner), tf(*_uPmlCorner), pmlCorner, gauss); + + gmshfem::domain::SkinLayer layerPmlCornerFirst = pmlCorner.getSkinLayer(pmlBnd.first); + gmshfem::domain::SkinLayer layerPmlCornerSecond = pmlCorner.getSkinLayer(pmlBnd.second); + gmshfem::domain::SkinLayer layerPmlBndFirst = pmlBnd.first.getSkinLayer(corner); + gmshfem::domain::SkinLayer layerPmlBndSecond = pmlBnd.second.getSkinLayer(corner); + + formulation.integral(dof(*_vC[0]), tf(*_vC[0]), pmlBnd.first, gauss); + formulation.integral(- D[0] * D[1] * grad(dof(*_uPmlCorner)), grad(tf(*_vC[0])), layerPmlCornerFirst, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * dof(*_uPmlCorner), tf(*_vC[0]), layerPmlCornerFirst, gauss); + formulation.integral(dof(*_vC[1]), tf(*_vC[0]), layerPmlBndSecond, gauss); + + formulation.integral(dof(*_vC[1]), tf(*_vC[1]), pmlBnd.second, gauss); + formulation.integral(- D[0] * D[1] * grad(dof(*_uPmlCorner)), grad(tf(*_vC[1])), layerPmlCornerSecond, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * dof(*_uPmlCorner), tf(*_vC[1]), layerPmlCornerSecond, gauss); + formulation.integral(dof(*_vC[0]), tf(*_vC[1]), layerPmlBndFirst, gauss); + + // corner equation + _vCorner = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vCorner_" + orientation(), corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + formulation.integral(dof(*_vC[0]), tf(*_vCorner), corner, gauss); + formulation.integral(dof(*_vCorner), tf(*_vC[0]), corner, gauss); + + formulation.integral(-dof(*_vC[1]), tf(*_vCorner), corner, gauss); + formulation.integral(-dof(*_vCorner), tf(*_vC[1]), corner, gauss); + + formulation.integral(dof(*static_cast< PmlWithoutMultiplier * >(_bnd[0])->getV()), tf(*_vCorner), corner, gauss); + formulation.integral(dof(*_vCorner), tf(*static_cast< PmlWithoutMultiplier * >(_bnd[0])->getV()), corner, gauss); + + formulation.integral(-dof(*static_cast< PmlWithoutMultiplier * >(_bnd[1])->getV()), tf(*_vCorner), corner, gauss); + formulation.integral(-dof(*_vCorner), tf(*static_cast< PmlWithoutMultiplier * >(_bnd[1])->getV()), corner, gauss); + + // link with edge neumann traces + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *v[2]; + v[0] = static_cast< PmlWithoutMultiplier * >(_bnd[0])->getV(); + v[1] = static_cast< PmlWithoutMultiplier * >(_bnd[1])->getV(); + + formulation.integral(-dof(*_vC[0]), tf(*v[0]), pmlBnd.first, gauss); + formulation.integral(-dof(*_vC[1]), tf(*v[1]), pmlBnd.second, gauss); + } + + // ********************************** + // PML continuous _ Sommerfeld + // ********************************** + + PmlContinuous_Sommerfeld::PmlContinuous_Sommerfeld(const unsigned int corner, PmlContinuous *first, Sommerfeld *second) : Corner(corner, first, second) + { + } + + PmlContinuous_Sommerfeld::~PmlContinuous_Sommerfeld() + { + delete _vC; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_Sommerfeld::getV() const + { + return _vC; + } + + PmlContinuous *PmlContinuous_Sommerfeld::firstBoundary() const + { + return static_cast< PmlContinuous * >(_bnd[0]); + } + + Sommerfeld *PmlContinuous_Sommerfeld::secondBoundary() const + { + return static_cast< Sommerfeld * >(_bnd[1]); + } + + void PmlContinuous_Sommerfeld::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _vC = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_first", pmlBnd.first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml; + uPml = static_cast< PmlContinuous * >(_bnd[0])->getUPml(); + + // To get kappa at the corner + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlContinuous * >(_bnd[0])->pmlCoefficients(D, E, corner, kappa); + + const std::complex< double > im(0., 1.); + formulation.integral(-dof(*_vC), tf(*uPml), pmlBnd.first, gauss); + + formulation.integral(dof(*_vC), tf(*_vC), pmlBnd.first, gauss); + formulation.integral(im * E * kappaMod * dof(*uPml), tf(*_vC), pmlBnd.first, gauss); + } + + // ********************************** + // Sommerfeld _ PML continuous + // ********************************** + + Sommerfeld_PmlContinuous::Sommerfeld_PmlContinuous(const unsigned int corner, Sommerfeld *first, PmlContinuous *second) : Corner(corner, first, second) + { + } + + Sommerfeld_PmlContinuous::~Sommerfeld_PmlContinuous() + { + delete _vC; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* Sommerfeld_PmlContinuous::getV() const + { + return _vC; + } + + Sommerfeld *Sommerfeld_PmlContinuous::firstBoundary() const + { + return static_cast< Sommerfeld * >(_bnd[0]); + } + + PmlContinuous *Sommerfeld_PmlContinuous::secondBoundary() const + { + return static_cast< PmlContinuous * >(_bnd[1]); + } + + void Sommerfeld_PmlContinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _vC = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_second", pmlBnd.second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml; + uPml = static_cast< PmlContinuous * >(_bnd[1])->getUPml(); + + // To get kappa at the corner + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlContinuous * >(_bnd[1])->pmlCoefficients(D, E, corner, kappa); + + const std::complex< double > im(0., 1.); + formulation.integral(-dof(*_vC), tf(*uPml), pmlBnd.second, gauss); + + formulation.integral(dof(*_vC), tf(*_vC), pmlBnd.second, gauss); + formulation.integral(im * E * kappaMod * dof(*uPml), tf(*_vC), pmlBnd.second, gauss); + } + + // ********************************** + // PML discontinuous _ Sommerfeld + // ********************************** + + PmlDiscontinuous_Sommerfeld::PmlDiscontinuous_Sommerfeld(const unsigned int corner, PmlDiscontinuous *first, Sommerfeld *second) : Corner(corner, first, second) + { + } + + PmlDiscontinuous_Sommerfeld::~PmlDiscontinuous_Sommerfeld() + { + delete _vC; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* PmlDiscontinuous_Sommerfeld::getV() const + { + return _vC; + } + + PmlDiscontinuous *PmlDiscontinuous_Sommerfeld::firstBoundary() const + { + return static_cast< PmlDiscontinuous * >(_bnd[0]); + } + + Sommerfeld *PmlDiscontinuous_Sommerfeld::secondBoundary() const + { + return static_cast< Sommerfeld * >(_bnd[1]); + } + + void PmlDiscontinuous_Sommerfeld::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _vC = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >("vC_" + orientation() + "_first", pmlBnd.first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml; + uPml = static_cast< PmlDiscontinuous * >(_bnd[0])->getUPml(); + + // To get kappa at the corner + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlDiscontinuous * >(_bnd[0])->pmlCoefficients(D, E, corner, kappa); + + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + const std::complex< double > im(0., 1.); + formulation.integral(-n * dof(*_vC), tf(*uPml), pmlBnd.first, gauss); + + formulation.integral(dof(*_vC), tf(*_vC), pmlBnd.first, gauss); + formulation.integral(im * E * kappaMod * dof(*uPml), n * tf(*_vC), pmlBnd.first, gauss); + } + + // ********************************** + // Sommerfeld _ PML discontinuous + // ********************************** + + Sommerfeld_PmlDiscontinuous::Sommerfeld_PmlDiscontinuous(const unsigned int corner, Sommerfeld *first, PmlDiscontinuous *second) : Corner(corner, first, second) + { + } + + Sommerfeld_PmlDiscontinuous::~Sommerfeld_PmlDiscontinuous() + { + delete _vC; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* Sommerfeld_PmlDiscontinuous::getV() const + { + return _vC; + } + + Sommerfeld *Sommerfeld_PmlDiscontinuous::firstBoundary() const + { + return static_cast< Sommerfeld * >(_bnd[0]); + } + + PmlDiscontinuous *Sommerfeld_PmlDiscontinuous::secondBoundary() const + { + return static_cast< PmlDiscontinuous * >(_bnd[1]); + } + + void Sommerfeld_PmlDiscontinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _vC = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >("vC_" + orientation() + "_second", pmlBnd.second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml; + uPml = static_cast< PmlDiscontinuous * >(_bnd[1])->getUPml(); + + // To get kappa at the corner + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlDiscontinuous * >(_bnd[1])->pmlCoefficients(D, E, corner, kappa); + + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + const std::complex< double > im(0., 1.); + formulation.integral(-n * dof(*_vC), tf(*uPml), pmlBnd.second, gauss); + + formulation.integral(dof(*_vC), tf(*_vC), pmlBnd.second, gauss); + formulation.integral(im * E * kappaMod * dof(*uPml), n * tf(*_vC), pmlBnd.second, gauss); + } + + // ********************************** + // HABC_Sommerfeld + // ********************************** + + HABC_Sommerfeld::HABC_Sommerfeld(const unsigned int corner, HABC *first, Sommerfeld *second) : Corner(corner, first, second) + { + } + + HABC_Sommerfeld::~HABC_Sommerfeld() + { + const unsigned int N = static_cast< HABC * >(_bnd[0])->getN(); + for(unsigned int m = 0; m < N; ++m) { + delete _vC[m]; + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *HABC_Sommerfeld::getV(const unsigned int m) const + { + return _vC[m]; + } + + HABC *HABC_Sommerfeld::firstBoundary() const + { + return static_cast< HABC * >(_bnd[0]); + } + + Sommerfeld *HABC_Sommerfeld::secondBoundary() const + { + return static_cast< Sommerfeld * >(_bnd[1]); + } + + void HABC_Sommerfeld::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + const unsigned int N = static_cast< HABC * >(_bnd[0])->getN(); + + _vC.resize(N); + for(unsigned int m = 0; m < N; ++m) { + _vC[m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(m) + "_first", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + + const std::complex< double > im(0., 1.); + + for(unsigned int m = 0; m < N; ++m) { + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * uHABC = static_cast< HABC * >(_bnd[0])->getUHABC(m); + + formulation.integral(dof(*_vC[m]), tf(*uHABC), corner, gauss); + + formulation.integral(dof(*_vC[m]), tf(*_vC[m]), corner, gauss); + formulation.integral(im * kappa * dof(*uHABC), tf(*_vC[m]), corner, gauss); + } + } + + // ********************************** + // Sommerfeld_HABC + // ********************************** + + Sommerfeld_HABC::Sommerfeld_HABC(const unsigned int corner, Sommerfeld *first, HABC *second) : Corner(corner, first, second) + { + } + + Sommerfeld_HABC::~Sommerfeld_HABC() + { + const unsigned int N = static_cast< HABC * >(_bnd[1])->getN(); + for(unsigned int m = 0; m < N; ++m) { + delete _vC[m]; + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *Sommerfeld_HABC::getV(const unsigned int m) const + { + return _vC[m]; + } + + Sommerfeld *Sommerfeld_HABC::firstBoundary() const + { + return static_cast< Sommerfeld * >(_bnd[0]); + } + + HABC *Sommerfeld_HABC::secondBoundary() const + { + return static_cast< HABC * >(_bnd[1]); + } + + void Sommerfeld_HABC::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + const unsigned int N = static_cast< HABC * >(_bnd[1])->getN(); + + _vC.resize(N); + for(unsigned int m = 0; m < N; ++m) { + _vC[m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(m) + "_second", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + + const std::complex< double > im(0., 1.); + + for(unsigned int m = 0; m < N; ++m) { + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * uHABC = static_cast< HABC * >(_bnd[1])->getUHABC(m); + + formulation.integral(dof(*_vC[m]), tf(*uHABC), corner, gauss); + + formulation.integral(dof(*_vC[m]), tf(*_vC[m]), corner, gauss); + formulation.integral(im * kappa * dof(*uHABC), tf(*_vC[m]), corner, gauss); + } + } + +} diff --git a/examples/helmholtz/crossPoints/Subproblem2D.h b/examples/helmholtz/crossPoints/Subproblem2D.h new file mode 100755 index 0000000000000000000000000000000000000000..57bc7692d91547ac638f536e782be927e5c0249d --- /dev/null +++ b/examples/helmholtz/crossPoints/Subproblem2D.h @@ -0,0 +1,349 @@ +#ifndef H_SUBPROBLEM2D +#define H_SUBPROBLEM2D + +#include "SubproblemDomains.h" +#include "SubproblemParameters.h" + +#include <gmshfem/Formulation.h> + +namespace D2 { + + + class Boundary + { + protected: + const unsigned int _boundary; + + public: + Boundary(const unsigned int boundary); + virtual ~Boundary(); + + virtual void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + + std::string orientation() const; + }; + + class Corner + { + protected: + const unsigned int _corner; + Boundary *_bnd[2]; + + public: + Corner(const unsigned int corner, Boundary *first, Boundary *second); + virtual ~Corner(); + + virtual void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + + std::string orientation() const; + }; + + class Subproblem + { + private: + const SubproblemDomains _domains; + const SubproblemParameters _parameters; + gmshfem::problem::Formulation< std::complex< double > > &_formulation; + const std::string _fieldName; + std::vector< Boundary * > _boundary; + std::vector< Corner * > _corner; + + void _parseParameters(std::string &method, std::vector< std::string > ¶meters, const std::string &str) const; + + public: + Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters, const std::string &E, const std::string &N, const std::string &W, const std::string &S); + ~Subproblem(); + + void writeFormulation(); + + Boundary *getBoundary(const unsigned int b) const; + Corner *getCorner(const unsigned int c) const; + }; + + + + + class Sommerfeld : public Boundary + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + Sommerfeld(const unsigned int boundary); + ~Sommerfeld(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class HABC : public Boundary + { + protected: + const unsigned int _N; + const double _theta; + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > _uHABC; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + HABC(const unsigned int boundary, const unsigned int N, const double theta); + ~HABC(); + + unsigned int getN() const; + double getTheta() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUHABC(const unsigned int m) const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class Pml : public Boundary + { + protected: + const double _size; + const std::string _type; + + public: + Pml(const unsigned int boundary, const double pmlSize, const std::string type); + virtual ~Pml(); + + virtual double getSize() const; + virtual gmshfem::function::ScalarFunction< std::complex< double > > pmlCoefficients(gmshfem::function::TensorFunction< std::complex< double > > &D, gmshfem::function::ScalarFunction< std::complex< double > > &E, gmshfem::domain::Domain &bnd, const gmshfem::function::ScalarFunction< std::complex< double > > &kappa) const; + + virtual void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + }; + + class PmlContinuous : public Pml // with Lagrange multiplier + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPml; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + PmlContinuous(const unsigned int boundary, const double pmlSize, const std::string type); + ~PmlContinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlDiscontinuous : public Pml // with Lagrange multiplier + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPml; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * _v; + + public: + PmlDiscontinuous(const unsigned int boundary, const double pmlSize, const std::string type); + ~PmlDiscontinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlWithoutMultiplier : public Pml // without Lagrange multiplier + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPml; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + PmlWithoutMultiplier(const unsigned int boundary, const double pmlSize, const std::string type); + ~PmlWithoutMultiplier(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + + + + class HABC_HABC : public Corner + { + protected: + std::vector< std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > > _uHABC_C; + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > _vC[2]; + + public: + HABC_HABC(const unsigned int corner, HABC *first, HABC *second); + ~HABC_HABC(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getV(const unsigned int m, const unsigned int i) const; + + HABC *firstBoundary() const; + HABC *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlContinuous_PmlContinuous : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPmlCorner; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vC[2]; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vCorner; + + public: + PmlContinuous_PmlContinuous(const unsigned int corner, PmlContinuous *first, PmlContinuous *second); + ~PmlContinuous_PmlContinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV(const unsigned int i) const; + + PmlContinuous *firstBoundary() const; + PmlContinuous *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlDiscontinuous_PmlDiscontinuous : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPmlCorner; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * _vC[2]; + + public: + PmlDiscontinuous_PmlDiscontinuous(const unsigned int corner, PmlDiscontinuous *first, PmlDiscontinuous *second); + ~PmlDiscontinuous_PmlDiscontinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* getV(const unsigned int i) const; + + PmlDiscontinuous *firstBoundary() const; + PmlDiscontinuous *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlWithoutMultiplier_PmlWithoutMultiplier : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPmlCorner; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vC[2]; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vCorner; + + public: + PmlWithoutMultiplier_PmlWithoutMultiplier(const unsigned int corner, PmlWithoutMultiplier *first, PmlWithoutMultiplier *second); + ~PmlWithoutMultiplier_PmlWithoutMultiplier(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV(const unsigned int i) const; + + PmlWithoutMultiplier *firstBoundary() const; + PmlWithoutMultiplier *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlContinuous_Sommerfeld : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vC; + + public: + PmlContinuous_Sommerfeld(const unsigned int corner, PmlContinuous *first, Sommerfeld *second); + ~PmlContinuous_Sommerfeld(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + PmlContinuous *firstBoundary() const; + Sommerfeld *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class Sommerfeld_PmlContinuous : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vC; + + public: + Sommerfeld_PmlContinuous(const unsigned int corner, Sommerfeld *first, PmlContinuous *second); + ~Sommerfeld_PmlContinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + Sommerfeld *firstBoundary() const; + PmlContinuous *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlDiscontinuous_Sommerfeld : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * _vC; + + public: + PmlDiscontinuous_Sommerfeld(const unsigned int corner, PmlDiscontinuous *first, Sommerfeld *second); + ~PmlDiscontinuous_Sommerfeld(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* getV() const; + + PmlDiscontinuous *firstBoundary() const; + Sommerfeld *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class Sommerfeld_PmlDiscontinuous : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * _vC; + + public: + Sommerfeld_PmlDiscontinuous(const unsigned int corner, Sommerfeld *first, PmlDiscontinuous *second); + ~Sommerfeld_PmlDiscontinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* getV() const; + + Sommerfeld *firstBoundary() const; + PmlDiscontinuous *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class HABC_Sommerfeld : public Corner + { + protected: + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > _vC; + + public: + HABC_Sommerfeld(const unsigned int corner, HABC *first, Sommerfeld *second); + ~HABC_Sommerfeld(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getV(const unsigned int m) const; + + HABC *firstBoundary() const; + Sommerfeld *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class Sommerfeld_HABC : public Corner + { + protected: + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > _vC; + + public: + Sommerfeld_HABC(const unsigned int corner, Sommerfeld *first, HABC *second); + ~Sommerfeld_HABC(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getV(const unsigned int m) const; + + Sommerfeld *firstBoundary() const; + HABC *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + +} + +#endif // H_SUBPROBLEM2D diff --git a/examples/helmholtz/crossPoints/Subproblem3D.cpp b/examples/helmholtz/crossPoints/Subproblem3D.cpp new file mode 100755 index 0000000000000000000000000000000000000000..695aaaebd0d68b0e71a32d48d3e885b3f28147b8 --- /dev/null +++ b/examples/helmholtz/crossPoints/Subproblem3D.cpp @@ -0,0 +1,1307 @@ +#include "Subproblem3D.h" + +using gmshfem::equation::dof; +using gmshfem::equation::tf; +using gmshfem::function::operator-; +using gmshfem::function::operator+; +using gmshfem::function::operator*; + +namespace D3 { + + + // ********************************** + // Boundary + // ********************************** + + Boundary::Boundary(const unsigned int boundary) : _boundary(boundary) + { + } + + Boundary::~Boundary() + { + } + + std::string Boundary::orientation() const + { + switch (_boundary) { + case 0: + return "E"; + break; + case 1: + return "N"; + break; + case 2: + return "W"; + break; + case 3: + return "S"; + break; + case 4: + return "D"; + break; + case 5: + return "U"; + break; + default: + break; + } + return "null"; + } + + // ********************************** + // Edge + // ********************************** + + Edge::Edge(const unsigned int edge, Boundary *first, Boundary *second) : _edge(edge), _bnd {first, second} + { + } + + Edge::~Edge() + { + } + + std::string Edge::orientation() const + { + switch (_edge) { + case 0: + return "ED"; + break; + case 1: + return "ND"; + break; + case 2: + return "WD"; + break; + case 3: + return "SD"; + break; + + case 4: + return "EN"; + break; + case 5: + return "NW"; + break; + case 6: + return "WS"; + break; + case 7: + return "SE"; + break; + + case 8: + return "EU"; + break; + case 9: + return "NU"; + break; + case 10: + return "WU"; + break; + case 11: + return "SU"; + break; + default: + break; + } + return "null"; + } + + // ********************************** + // Corner + // ********************************** + + Corner::Corner(const unsigned int corner, Edge *first, Edge *second, Edge *third) : _corner(corner), _bnd {first, second, third} + { + } + + Corner::~Corner() + { + } + + std::string Corner::orientation() const + { + switch (_corner) { + case 0: + return "END"; + break; + case 1: + return "NWD"; + break; + case 2: + return "WSD"; + break; + case 3: + return "SED"; + break; + + case 4: + return "ENU"; + break; + case 5: + return "NWU"; + break; + case 6: + return "WSU"; + break; + case 7: + return "SEU"; + break; + default: + break; + } + return "null"; + } + + // ********************************** + // Subproblem + // ********************************** + + void Subproblem::_parseParameters(std::string &method, std::vector< std::string > ¶meters, const std::string &str) const + { + method.clear(); + parameters.clear(); + std::string *current = &method; + for(unsigned int i = 0; i < str.size(); ++i) { + if(str[i] == '_') { + parameters.push_back(std::string()); + current = ¶meters.back(); + } + else { + (*current) += str[i]; + } + } + } + + Subproblem::Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters, const std::string &E, const std::string &N, const std::string &W, const std::string &S, const std::string &D, const std::string &U) : _domains(domains), _parameters(parameters), _formulation(formulation), _fieldName(fieldName), _boundary(6, nullptr), _edge(12, nullptr), _corner(8, nullptr) + { + std::string type[6] = {E, N, W, S, D, U}; + std::string method[6]; + std::vector< std::string > bndParameters[6]; + for(unsigned int i = 0; i < 6; ++i) { + _parseParameters(method[i], bndParameters[i], type[i]); + } + + for(unsigned int b = 0; b < 6; ++b) { + if(method[b] == "sommerfeld") { // str: sommerfeld + _boundary[b] = new Sommerfeld(b); + } + else if(method[b] == "habc") { // str: habc_[N]_[theta] + const unsigned int N = std::stoi(bndParameters[b][0]); + const double theta = std::stof(bndParameters[b][1]); + _boundary[b] = new HABC(b, N, theta); + } + else if(method[b] == "pmlContinuous") { // str: pmlContinuous_[N_pml]_[Type] + const double N_pml = std::stof(bndParameters[b][0]); + const std::string type = bndParameters[b][1]; + _boundary[b] = new PmlContinuous(b, N_pml, type); + } + // marche pas, il faudrait un vrai H(div) + else if(method[b] == "pmlDiscontinuous") { // str: pmlDiscontinuous_[N_pml]_[Type] + const double N_pml = std::stof(bndParameters[b][0]); + const std::string type = bndParameters[b][1]; + _boundary[b] = new PmlDiscontinuous(b, N_pml, type); + } + else { + gmshfem::msg::error << "Unknown method '" << method[b] << "'" << gmshfem::msg::endl; + } + } + + for(unsigned int e = 0; e < 12; ++e) { + if(e < 4) { + if(method[e%4] == "habc" && method[4] == "habc") { + _edge[e] = new HABC_HABC(e, static_cast< HABC * >(_boundary[e%4]), static_cast< HABC * >(_boundary[4])); + } + else if(method[e%4] == "pmlContinuous" && method[4] == "pmlContinuous") { + _edge[e] = new PmlContinuous_PmlContinuous(e, static_cast< PmlContinuous * >(_boundary[e%4]), static_cast< PmlContinuous * >(_boundary[4])); + } + } + else if(e >= 4 && e < 8) { + if(method[e%4] == "habc" && method[(e+1)%4] == "habc") { + _edge[e] = new HABC_HABC(e, static_cast< HABC * >(_boundary[e%4]), static_cast< HABC * >(_boundary[(e+1)%4])); + } + else if(method[e%4] == "pmlContinuous" && method[(e+1)%4] == "pmlContinuous") { + _edge[e] = new PmlContinuous_PmlContinuous(e, static_cast< PmlContinuous * >(_boundary[e%4]), static_cast< PmlContinuous * >(_boundary[(e+1)%4])); + } + } + else { + if(method[e%4] == "habc" && method[5] == "habc") { + _edge[e] = new HABC_HABC(e, static_cast< HABC * >(_boundary[e%4]), static_cast< HABC * >(_boundary[5])); + } + else if(method[e%4] == "pmlContinuous" && method[5] == "pmlContinuous") { + _edge[e] = new PmlContinuous_PmlContinuous(e, static_cast< PmlContinuous * >(_boundary[e%4]), static_cast< PmlContinuous * >(_boundary[5])); + } + } + } + + for(unsigned int c = 0; c < 8; ++c) { + if(c < 4) { + if(method[c%4] == "habc" && method[(c+1)%4] == "habc" && method[4] == "habc") { + _corner[c] = new HABC_HABC_HABC(c, static_cast< HABC_HABC * >(_edge[c%4]), static_cast< HABC_HABC * >(_edge[(c+1)%4]), static_cast< HABC_HABC * >(_edge[c+4])); + } + else if(method[c%4] == "pmlContinuous" && method[(c+1)%4] == "pmlContinuous" && method[4] == "pmlContinuous") { + _corner[c] = new PmlContinuous_PmlContinuous_PmlContinuous(c, static_cast< PmlContinuous_PmlContinuous * >(_edge[c%4]), static_cast< PmlContinuous_PmlContinuous * >(_edge[(c+1)%4]), static_cast< PmlContinuous_PmlContinuous * >(_edge[c+4])); + } + } + else { + if(method[c%4] == "habc" && method[(c+1)%4] == "habc" && method[5] == "habc") { + _corner[c] = new HABC_HABC_HABC(c, static_cast< HABC_HABC * >(_edge[c%4+8]), static_cast< HABC_HABC * >(_edge[(c+1)%4+8]), static_cast< HABC_HABC * >(_edge[c])); + } + else if(method[c%4] == "pmlContinuous" && method[(c+1)%4] == "pmlContinuous" && method[5] == "pmlContinuous") { + _corner[c] = new PmlContinuous_PmlContinuous_PmlContinuous(c, static_cast< PmlContinuous_PmlContinuous * >(_edge[c%4+8]), static_cast< PmlContinuous_PmlContinuous * >(_edge[(c+1)%4+8]), static_cast< PmlContinuous_PmlContinuous * >(_edge[c])); + } + } + } + } + + Subproblem::~Subproblem() + { + for(unsigned int c = 0; c < 8; ++c) { + if(_corner[c] != nullptr) { + delete _corner[c]; + } + } + for(unsigned int e = 0; e < 12; ++e) { + if(_edge[e] != nullptr) { + delete _edge[e]; + } + } + for(unsigned int b = 0; b < 6; ++b) { + if(_boundary[b] != nullptr) { + delete _boundary[b]; + } + } + } + + void Subproblem::writeFormulation() + { + for(unsigned int b = 0; b < 6; ++b) { + _boundary[b]->writeFormulation(_formulation, _fieldName, _domains, _parameters); + } + + for(unsigned int e = 0; e < 12; ++e) { + if(_edge[e] != nullptr) { + _edge[e]->writeFormulation(_formulation, _domains, _parameters); + } + } + + for(unsigned int c = 0; c < 8; ++c) { + if(_corner[c] != nullptr) { + _corner[c]->writeFormulation(_formulation, _domains, _parameters); + } + } + } + + Boundary *Subproblem::getBoundary(const unsigned int b) const + { + return _boundary[b]; + } + + Edge *Subproblem::getEdge(const unsigned int e) const + { + return _edge[e]; + } + + Corner *Subproblem::getCorner(const unsigned int c) const + { + return _corner[c]; + } + + // ********************************** + // Sommerfeld + // ********************************** + + Sommerfeld::Sommerfeld(const unsigned int boundary) : Boundary(boundary) + { + } + + Sommerfeld::~Sommerfeld() + { + delete _v; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* Sommerfeld::getV() const + { + return _v; + } + + void Sommerfeld::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + const std::complex< double > im(0., 1.); + formulation.integral(-dof(*_v), tf(*u), sigma, gauss); + + formulation.integral(dof(*_v), tf(*_v), sigma, gauss); + formulation.integral(im * kappa * dof(*u), tf(*_v), sigma, gauss); + } + + // ********************************** + // HABC + // ********************************** + + HABC::HABC(const unsigned int boundary, const unsigned int N, const double theta) : Boundary(boundary), _N(N), _theta(theta) + { + } + + HABC::~HABC() + { + delete _v; + for(unsigned int m = 0; m < _N; ++m) { + delete _uHABC[m]; + } + } + + unsigned int HABC::getN() const + { + return _N; + } + + double HABC::getTheta() const + { + return _theta; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * HABC::getUHABC(const unsigned int m) const + { + if(m > _N) throw gmshfem::common::Exception("Try to get uHABC field " + std::to_string(m)); + return _uHABC[m]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* HABC::getV() const + { + return _v; + } + + void HABC::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uHABC.resize(_N); + for(unsigned int m = 0; m < _N; ++m) { + _uHABC[m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uHABC_" + orientation() + "_" + std::to_string(m), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + } + + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + const double pi = 3.141592653589793238462643383279; + const std::complex< double > expPTheta(std::cos(_theta), std::sin(_theta)); + const std::complex< double > expMTheta(std::cos(-_theta), std::sin(-_theta)); + const std::complex< double > expPTheta2(std::cos(_theta/2.), std::sin(_theta/2.)); + const double M = 2 * _N + 1; + double cPade[_N]; + for(unsigned int m = 0; m < _N; ++m) { + cPade[m] = std::tan((m+1) * pi / M) * std::tan((m+1) * pi / M); + } + + const std::complex< double > im(0., 1.); + + formulation.integral(-dof(*_v), tf(*u), sigma, gauss); + + formulation.integral( dof(*_v), tf(*_v), sigma, gauss); + formulation.integral( im * kappa * expPTheta2 * dof(*u), tf(*_v), sigma, gauss); + + for(unsigned int m = 0; m < _N; ++m) { + formulation.integral( im * kappa * expPTheta2 * 2./M * cPade[m] * dof(*u), tf(*_v), sigma, gauss); + formulation.integral( im * kappa * expPTheta2 * 2./M * cPade[m] * dof(*_uHABC[m]), tf(*_v), sigma, gauss); + } + + // auxiliary + for(unsigned int m = 0; m < _N; ++m) { + formulation.integral(grad(dof(*_uHABC[m])), grad(tf(*_uHABC[m])), sigma, gauss); + formulation.integral(- kappa * kappa * (expPTheta * cPade[m] + 1.) * dof(*_uHABC[m]), tf(*_uHABC[m]), sigma, gauss); + formulation.integral(- kappa * kappa * expPTheta * (cPade[m] + 1.) * dof(*u), tf(*_uHABC[m]), sigma, gauss); + } + } + + // ********************************** + // PML + // ********************************** + + Pml::Pml(const unsigned int boundary, const double pmlSize, const std::string type) : Boundary(boundary), _size(pmlSize), _type(type) + { + } + + Pml::~Pml() + { + } + + double Pml::getSize() const + { + return _size; + } + + gmshfem::function::ScalarFunction< std::complex< double > > Pml::pmlCoefficients(gmshfem::function::TensorFunction< std::complex< double > > &D, gmshfem::function::ScalarFunction< std::complex< double > > &E, gmshfem::domain::Domain &bnd, const gmshfem::function::ScalarFunction< std::complex< double > > &kappa) const + { + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod; + const std::complex< double > im(0., 1.); + + gmshfem::function::ScalarFunction< std::complex< double > > distSigma; + gmshfem::function::ScalarFunction< std::complex< double > > sigma; + if(orientation() == "E" || orientation() == "W") { + distSigma = abs(gmshfem::function::x< std::complex< double > >() - gmshfem::function::x< std::complex< double > >(bnd)); + if(bnd.maxDim() == 0) { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >(bnd)); + } + else { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(), gmshfem::function::z< double >()); + } + } + else if(orientation() == "N" || orientation() == "S") { + distSigma = abs(gmshfem::function::y< std::complex< double > >() - gmshfem::function::y< std::complex< double > >(bnd)); + if(bnd.maxDim() == 0) { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >(bnd)); + } + else { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >()); + } + } + else if(orientation() == "D" || orientation() == "U") { + distSigma = abs(gmshfem::function::z< std::complex< double > >() - gmshfem::function::z< std::complex< double > >(bnd)); + if(bnd.maxDim() == 0) { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(bnd), gmshfem::function::y< double >(bnd), gmshfem::function::z< double >(bnd)); + } + else { + kappaMod = changeOfCoordinates(kappa, gmshfem::function::x< double >(), gmshfem::function::y< double >(), gmshfem::function::z< double >(bnd)); + } + } + + if(_type == "hs") { + sigma = 1. / (_size - distSigma) - 1./ _size; + } + else if(_type == "h") { + sigma = 1. / (_size - distSigma); + } + else if(_type == "q") { + const double sigmaStar = 664.55; + sigma = sigmaStar * distSigma * distSigma / (_size * _size); + } + + gmshfem::function::ScalarFunction< std::complex< double > > kMod = 1. + im * sigma / kappaMod; + if(orientation() == "E" || orientation() == "W") { + D = gmshfem::function::tensorDiag< std::complex< double > >(1./kMod, kMod, kMod); + E = kMod; + } + else if(orientation() == "N" || orientation() == "S") { + D = gmshfem::function::tensorDiag< std::complex< double > >(kMod, 1./kMod, kMod); + E = kMod; + } + else if(orientation() == "D" || orientation() == "U") { + D = gmshfem::function::tensorDiag< std::complex< double > >(kMod, kMod, 1./kMod); + E = kMod; + } + + return kappaMod; + } + + // ********************************** + // PML continuous + // ********************************** + + PmlContinuous::PmlContinuous(const unsigned int boundary, const double pmlSize, const std::string type) : Pml(boundary, pmlSize, type) + { + } + + PmlContinuous::~PmlContinuous() + { + delete _v; + delete _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlContinuous::getUPml() const + { + return _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlContinuous::getV() const + { + return _v; + } + + void PmlContinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + gmshfem::domain::Domain pml = domains.getPml(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uPml = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPml_" + orientation(), pml, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = pmlCoefficients(D, E, sigma, kappa); + + formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_uPml)), pml, gauss); + formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_uPml), pml, gauss); + + formulation.integral(dof(*_v), tf(*_uPml), sigma, gauss); + formulation.integral(- dof(*_v), tf(*u), sigma, gauss); + + formulation.integral(dof(*_uPml), tf(*_v), sigma, gauss); + formulation.integral(- dof(*u), tf(*_v), sigma, gauss); + } + + // ********************************** + // PML discontinuous + // ********************************** + + PmlDiscontinuous::PmlDiscontinuous(const unsigned int boundary, const double pmlSize, const std::string type) : Pml(boundary, pmlSize, type) + { + } + + PmlDiscontinuous::~PmlDiscontinuous() + { + delete _v; + delete _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlDiscontinuous::getUPml() const + { + return _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * PmlDiscontinuous::getV() const + { + return _v; + } + + void PmlDiscontinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + // Marche pas, il faudrait du vrai H(div) ... +// gmshfem::domain::Domain sigma = domains.getSigma(_boundary); +// gmshfem::domain::Domain pml = domains.getPml(_boundary); +// +// const unsigned int neumannOrder = parameters.getNeumannOrder(); +// const unsigned int fieldOrder = parameters.getFieldOrder(); +// const std::string gauss = parameters.getGauss(); +// const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); +// +// _uPml = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPml_" + orientation(), pml, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); +// +// _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); +// +// gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); +// +// gmshfem::function::TensorFunction< std::complex< double > > D; +// gmshfem::function::ScalarFunction< std::complex< double > > E; +// gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = pmlCoefficients(D, E, sigma, kappa); +// +// formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_uPml)), pml, gauss); +// formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_uPml), pml, gauss); +// +// formulation.integral(dof(*_v), tf(*_uPml), sigma, gauss); +// formulation.integral(- dof(*_v), tf(*u), sigma, gauss); +// +// formulation.integral(dof(*_uPml), tf(*_v), sigma, gauss); +// formulation.integral(- dof(*u), tf(*_v), sigma, gauss); + } + + // ********************************** + // PML without multiplier + // ********************************** + + PmlWithoutMultiplier::PmlWithoutMultiplier(const unsigned int boundary, const double pmlSize, const std::string type) : Pml(boundary, pmlSize, type) + { + } + + PmlWithoutMultiplier::~PmlWithoutMultiplier() + { + delete _v; + delete _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlWithoutMultiplier::getUPml() const + { + return _uPml; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * PmlWithoutMultiplier::getV() const + { + return _v; + } + + void PmlWithoutMultiplier::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain sigma = domains.getSigma(_boundary); + gmshfem::domain::Domain pml = domains.getPml(_boundary); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uPml = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPml_" + orientation(), pml, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + _v = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("v_" + orientation(), sigma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *u = static_cast< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >(formulation.getField(fieldName)); + + gmshfem::function::TensorFunction< std::complex< double > > D; + gmshfem::function::ScalarFunction< std::complex< double > > E; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = pmlCoefficients(D, E, sigma, kappa); + + formulation.integral(- D * grad(dof(*_uPml)), grad(tf(*_uPml)), pml, gauss); + formulation.integral(kappaMod * kappaMod * E * dof(*_uPml), tf(*_uPml), pml, gauss); + + formulation.integral(dof(*_v), tf(*_uPml), sigma, gauss); + formulation.integral(- dof(*_v), tf(*u), sigma, gauss); + + formulation.integral(dof(*_uPml), tf(*_v), sigma, gauss); + formulation.integral(- dof(*u), tf(*_v), sigma, gauss); + } + + + + + // ********************************** + // HABC_HABC + // ********************************** + + HABC_HABC::HABC_HABC(const unsigned int edge, HABC *first, HABC *second) : Edge(edge, first, second) + { + } + + HABC_HABC::~HABC_HABC() + { + const unsigned int N0 = static_cast< HABC * >(_bnd[0])->getN(); + const unsigned int N1 = static_cast< HABC * >(_bnd[1])->getN(); + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + delete _uHABC_E[m][n]; + } + } + for(unsigned int m = 0; m < N0; ++m) { + delete _vE[0][m]; + } + for(unsigned int n = 0; n < N1; ++n) { + delete _vE[1][n]; + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *HABC_HABC::getUHABC(const unsigned int m, const unsigned int n) const + { + return _uHABC_E[m][n]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *HABC_HABC::getV(const unsigned int m, const unsigned int i) const + { + return _vE[i][m]; + } + + HABC *HABC_HABC::firstBoundary() const + { + return static_cast< HABC * >(_bnd[0]); + } + + HABC *HABC_HABC::secondBoundary() const + { + return static_cast< HABC * >(_bnd[1]); + } + + void HABC_HABC::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain edge = domains.getEdge(_edge); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + const unsigned int N0 = static_cast< HABC * >(_bnd[0])->getN(); + const unsigned int N1 = static_cast< HABC * >(_bnd[1])->getN(); + + const double theta0 = static_cast< HABC * >(_bnd[0])->getTheta(); + // const double theta1 = static_cast< HABC * >(_bnd[1])->getTheta(); + + if(N0 != N1) { + throw gmshfem::common::Exception("Edge with HABC having different number of auxilary fields"); + } + + _uHABC_E.resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _uHABC_E[m].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _uHABC_E[m][n] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uHABC_Edge_" + orientation() + "_" + std::to_string(m) + "_" + std::to_string(n), edge, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + } + } + + _vE[0].resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _vE[0][m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vE_" + orientation() + "_" + std::to_string(m) + "_first", edge, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + _vE[1].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _vE[1][n] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vE_" + orientation() + "_" + std::to_string(n) + "_second", edge, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > uHABC[2]; + for(unsigned int m = 0; m < N0; ++m) { + uHABC[0].push_back(static_cast< HABC * >(_bnd[0])->getUHABC(m)); + } + + for(unsigned int n = 0; n < N1; ++n) { + uHABC[1].push_back(static_cast< HABC * >(_bnd[1])->getUHABC(n)); + } + + const double pi = 3.141592653589793238462643383279; + const std::complex< double > expPTheta(std::cos(theta0), std::sin(theta0)); + const std::complex< double > expMTheta(std::cos(-theta0), std::sin(-theta0)); + const std::complex< double > expPTheta2(std::cos(theta0/2.), std::sin(theta0/2.)); + const double M0 = 2 * N0 + 1; + double cPade0[N0]; + for(unsigned int m = 0; m < N0; ++m) { + cPade0[m] = std::tan((m+1) * pi / M0) * std::tan((m+1) * pi / M0); + } + const double M1 = 2 * N1 + 1; + double cPade1[N1]; + for(unsigned int n = 0; n < N1; ++n) { + cPade1[n] = std::tan((n+1) * pi / M1) * std::tan((n+1) * pi / M1); + } + + const std::complex< double > im(0., 1.); + + for(unsigned int m = 0; m < N0; ++m) { + formulation.integral(-dof(*_vE[0][m]), tf(*uHABC[0][m]), edge, gauss); + + formulation.integral( dof(*_vE[0][m]), tf(*_vE[0][m]), edge, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[0][m]), tf(*_vE[0][m]), edge, gauss); + + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*uHABC[0][m]), tf(*_vE[0][m]), edge, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*_uHABC_E[m][n]), tf(*_vE[0][m]), edge, gauss); + } + } + + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral(-dof(*_vE[1][n]), tf(*uHABC[1][n]), edge, gauss); + + formulation.integral( dof(*_vE[1][n]), tf(*_vE[1][n]), edge, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[1][n]), tf(*_vE[1][n]), edge, gauss); + + for(unsigned int m = 0; m < N0; ++m) { + formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*uHABC[1][n]), tf(*_vE[1][n]), edge, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*_uHABC_E[m][n]), tf(*_vE[1][n]), edge, gauss); + } + } + + // auxiliary + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral(grad(dof(*_uHABC_E[m][n])), grad(tf(*_uHABC_E[m][n])), edge, gauss); + formulation.integral(- kappa * kappa * expPTheta * (cPade0[m] + cPade1[n] + expMTheta) * dof(*_uHABC_E[m][n]), tf(*_uHABC_E[m][n]), edge, gauss); + formulation.integral(- kappa * kappa * expPTheta * (cPade0[m] + 1.) * dof(*uHABC[1][n]), tf(*_uHABC_E[m][n]), edge, gauss); + formulation.integral(- kappa * kappa * expPTheta * (cPade1[n] + 1.) * dof(*uHABC[0][m]), tf(*_uHABC_E[m][n]), edge, gauss); + } + } + } + + // ********************************** + // PML continuous _ PML continuous + // ********************************** + + PmlContinuous_PmlContinuous::PmlContinuous_PmlContinuous(const unsigned int edge, PmlContinuous *first, PmlContinuous *second) : Edge(edge, first, second) + { + } + + PmlContinuous_PmlContinuous::~PmlContinuous_PmlContinuous() + { + delete _uPmlEdge; + delete _vC[0]; + delete _vC[1]; + delete _vEdge; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous::getUPml() const + { + return _uPmlEdge; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous::getV(const unsigned int i) const + { + return _vC[i]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous::getVEdge() const + { + return _vEdge; + } + + PmlContinuous *PmlContinuous_PmlContinuous::firstBoundary() const + { + return static_cast< PmlContinuous * >(_bnd[0]); + } + + PmlContinuous *PmlContinuous_PmlContinuous::secondBoundary() const + { + return static_cast< PmlContinuous * >(_bnd[1]); + } + + void PmlContinuous_PmlContinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain edge = domains.getEdge(_edge); + gmshfem::domain::Domain pmlEdge = domains.getPmlEdge(_edge); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlBnd(_edge); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uPmlEdge = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPmlEdge_" + orientation(), pmlEdge, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + _vC[0] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_first", pmlBnd.first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + _vC[1] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_second", pmlBnd.second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml[2]; + uPml[0] = static_cast< PmlContinuous * >(_bnd[0])->getUPml(); + uPml[1] = static_cast< PmlContinuous * >(_bnd[1])->getUPml(); + + gmshfem::function::TensorFunction< std::complex< double > > D[2]; + gmshfem::function::ScalarFunction< std::complex< double > > E[2]; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = static_cast< PmlContinuous * >(_bnd[0])->pmlCoefficients(D[0], E[0], edge, kappa); + static_cast< PmlContinuous * >(_bnd[1])->pmlCoefficients(D[1], E[1], edge, kappa); + + formulation.integral(- D[0] * D[1] * grad(dof(*_uPmlEdge)), grad(tf(*_uPmlEdge)), pmlEdge, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * dof(*_uPmlEdge), tf(*_uPmlEdge), pmlEdge, gauss); + + formulation.integral(dof(*_vC[0]), tf(*_uPmlEdge), pmlBnd.first, gauss); + formulation.integral(- dof(*_vC[0]), tf(*uPml[0]), pmlBnd.first, gauss); + + formulation.integral(dof(*_uPmlEdge), tf(*_vC[0]), pmlBnd.first, gauss); + formulation.integral(- dof(*uPml[0]), tf(*_vC[0]), pmlBnd.first, gauss); + + formulation.integral(dof(*_vC[1]), tf(*_uPmlEdge), pmlBnd.second, gauss); + formulation.integral(- dof(*_vC[1]), tf(*uPml[1]), pmlBnd.second, gauss); + + formulation.integral(dof(*_uPmlEdge), tf(*_vC[1]), pmlBnd.second, gauss); + formulation.integral(- dof(*uPml[1]), tf(*_vC[1]), pmlBnd.second, gauss); + + // edge equation + _vEdge = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vEdge_" + orientation(), edge, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + formulation.integral(dof(*_vC[0]), tf(*_vEdge), edge, gauss); + formulation.integral(dof(*_vEdge), tf(*_vC[0]), edge, gauss); + + formulation.integral(-dof(*_vC[1]), tf(*_vEdge), edge, gauss); + formulation.integral(-dof(*_vEdge), tf(*_vC[1]), edge, gauss); + + formulation.integral(dof(*static_cast< PmlContinuous * >(_bnd[0])->getV()), tf(*_vEdge), edge, gauss); + formulation.integral(dof(*_vEdge), tf(*static_cast< PmlContinuous * >(_bnd[0])->getV()), edge, gauss); + + formulation.integral(-dof(*static_cast< PmlContinuous * >(_bnd[1])->getV()), tf(*_vEdge), edge, gauss); + formulation.integral(-dof(*_vEdge), tf(*static_cast< PmlContinuous * >(_bnd[1])->getV()), edge, gauss); + } + + + + + // ********************************** + // HABC_HABC_HABC + // ********************************** + + HABC_HABC_HABC::HABC_HABC_HABC(const unsigned int corner, HABC_HABC *first, HABC_HABC *second, HABC_HABC *third) : Corner(corner, first, second, third) + { + } + + HABC_HABC_HABC::~HABC_HABC_HABC() + { + std::vector< HABC * > boundaries(6); + for(unsigned int i = 0; i < 3; ++i) { + boundaries[2 * i] = static_cast< HABC_HABC * >(_bnd[i])->firstBoundary(); + boundaries[2 * i + 1] = static_cast< HABC_HABC * >(_bnd[i])->secondBoundary(); + } + std::sort(boundaries.begin(), boundaries.end()); + + const unsigned int N0 = static_cast< HABC * >(boundaries[0])->getN(); + const unsigned int N1 = static_cast< HABC * >(boundaries[2])->getN(); + const unsigned int N2 = static_cast< HABC * >(boundaries[4])->getN(); + + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + for(unsigned int o = 0; o < N2; ++o) { + delete _uHABC_C[m][n][o]; + } + } + } + + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + delete _vC[0][m][n]; + } + } + for(unsigned int n = 0; n < N1; ++n) { + for(unsigned int o = 0; o < N2; ++o) { + delete _vC[1][n][o]; + } + } + for(unsigned int o = 0; o < N2; ++o) { + for(unsigned int m = 0; m < N0; ++m) { + delete _vC[2][o][m]; + } + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *HABC_HABC_HABC::getUHABC(const unsigned int m, const unsigned int n, const unsigned int o) const + { + return _uHABC_C[m][n][o]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *HABC_HABC_HABC::getV(const unsigned int m, const unsigned int n, const unsigned int i) const + { + return _vC[i][m][n]; + } + + HABC_HABC *HABC_HABC_HABC::firstEdge() const + { + return static_cast< HABC_HABC * >(_bnd[0]); + } + + HABC_HABC *HABC_HABC_HABC::secondEdge() const + { + return static_cast< HABC_HABC * >(_bnd[1]); + } + + HABC_HABC *HABC_HABC_HABC::thirdEdge() const + { + return static_cast< HABC_HABC * >(_bnd[2]); + } + + void HABC_HABC_HABC::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + std::vector< HABC * > boundaries(6); + for(unsigned int i = 0; i < 3; ++i) { + boundaries[2 * i] = static_cast< HABC_HABC * >(_bnd[i])->firstBoundary(); + boundaries[2 * i + 1] = static_cast< HABC_HABC * >(_bnd[i])->secondBoundary(); + } + std::sort(boundaries.begin(), boundaries.end()); + + const unsigned int N0 = static_cast< HABC * >(boundaries[0])->getN(); + const unsigned int N1 = static_cast< HABC * >(boundaries[2])->getN(); + const unsigned int N2 = static_cast< HABC * >(boundaries[4])->getN(); + + const double theta0 = static_cast< HABC * >(boundaries[0])->getTheta(); + // const double theta1 = static_cast< HABC * >(_bnd[1])->getTheta(); + + if(N0 != N1 || N1 != N2 || N0 != N2) { + throw gmshfem::common::Exception("Corner with HABC having different number of auxilary fields"); + } + + _uHABC_C.resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _uHABC_C[m].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _uHABC_C[m][n].resize(N2); + for(unsigned int o = 0; o < N2; ++o) { + _uHABC_C[m][n][o] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uHABC_Corner_" + orientation() + "_" + std::to_string(m) + "_" + std::to_string(n) + "_" + std::to_string(o), corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + } + } + } + + _vC[0].resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _vC[0][m].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _vC[0][m][n] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(m) + "_" + std::to_string(n) + "_first", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + } + _vC[1].resize(N1); + for(unsigned int n = 0; n < N1; ++n) { + _vC[1][n].resize(N2); + for(unsigned int o = 0; o < N2; ++o) { + _vC[1][n][o] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(n) + "_" + std::to_string(o) + "_second", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + } + _vC[2].resize(N2); + for(unsigned int o = 0; o < N2; ++o) { + _vC[2][o].resize(N0); + for(unsigned int m = 0; m < N0; ++m) { + _vC[2][o][m] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_" + std::to_string(o) + "_" + std::to_string(m) + "_third", corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + } + } + + std::vector< std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > > uHABC[3]; + for(unsigned int m = 0; m < N0; ++m) { + uHABC[0].push_back(std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >()); + for(unsigned int n = 0; n < N1; ++n) { + uHABC[0][m].push_back(static_cast< HABC_HABC * >(_bnd[0])->getUHABC(m, n)); + } + } + for(unsigned int n = 0; n < N1; ++n) { + uHABC[1].push_back(std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >()); + for(unsigned int o = 0; o < N2; ++o) { + uHABC[1][n].push_back(static_cast< HABC_HABC * >(_bnd[1])->getUHABC(n, o)); + } + } + for(unsigned int o = 0; o < N2; ++o) { + uHABC[2].push_back(std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * >()); + for(unsigned int m = 0; m < N0; ++m) { + uHABC[2][o].push_back(static_cast< HABC_HABC * >(_bnd[2])->getUHABC(o, m)); + } + } + + const double pi = 3.141592653589793238462643383279; + const std::complex< double > expPTheta(std::cos(theta0), std::sin(theta0)); + const std::complex< double > expMTheta(std::cos(-theta0), std::sin(-theta0)); + const std::complex< double > expPTheta2(std::cos(theta0/2.), std::sin(theta0/2.)); + const double M0 = 2 * N0 + 1; + double cPade0[N0]; + for(unsigned int m = 0; m < N0; ++m) { + cPade0[m] = std::tan((m+1) * pi / M0) * std::tan((m+1) * pi / M0); + } + const double M1 = 2 * N1 + 1; + double cPade1[N1]; + for(unsigned int n = 0; n < N1; ++n) { + cPade1[n] = std::tan((n+1) * pi / M1) * std::tan((n+1) * pi / M1); + } + const double M2 = 2 * N2 + 1; + double cPade2[N2]; + for(unsigned int o = 0; o < N2; ++o) { + cPade2[o] = std::tan((o+1) * pi / M2) * std::tan((o+1) * pi / M2); + } + + const std::complex< double > im(0., 1.); + + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral(-dof(*_vC[0][m][n]), tf(*uHABC[0][m][n]), corner, gauss); + + formulation.integral( dof(*_vC[0][m][n]), tf(*_vC[0][m][n]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[0][m][n]), tf(*_vC[0][m][n]), corner, gauss); + + for(unsigned int o = 0; o < N2; ++o) { + formulation.integral(-im * kappa * expPTheta2 * 2./M2 * cPade2[o] * dof(*uHABC[0][m][n]), tf(*_vC[0][m][n]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M2 * cPade2[o] * dof(*_uHABC_C[m][n][o]), tf(*_vC[0][m][n]), corner, gauss); + } + } + } + + for(unsigned int n = 0; n < N1; ++n) { + for(unsigned int o = 0; o < N2; ++o) { + formulation.integral(-dof(*_vC[1][n][o]), tf(*uHABC[1][n][o]), corner, gauss); + + formulation.integral( dof(*_vC[1][n][o]), tf(*_vC[1][n][o]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[1][n][o]), tf(*_vC[1][n][o]), corner, gauss); + + for(unsigned int m = 0; m < N0; ++m) { + formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*uHABC[1][n][o]), tf(*_vC[1][n][o]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M0 * cPade0[m] * dof(*_uHABC_C[m][n][o]), tf(*_vC[1][n][o]), corner, gauss); + } + } + } + + for(unsigned int o = 0; o < N2; ++o) { + for(unsigned int m = 0; m < N0; ++m) { + formulation.integral(-dof(*_vC[2][o][m]), tf(*uHABC[2][o][m]), corner, gauss); + + formulation.integral( dof(*_vC[2][o][m]), tf(*_vC[2][o][m]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * dof(*uHABC[2][o][m]), tf(*_vC[2][o][m]), corner, gauss); + + for(unsigned int n = 0; n < N1; ++n) { + formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*uHABC[2][o][m]), tf(*_vC[2][o][m]), corner, gauss); + formulation.integral(-im * kappa * expPTheta2 * 2./M1 * cPade1[n] * dof(*_uHABC_C[m][n][o]), tf(*_vC[2][o][m]), corner, gauss); + } + } + } + + // auxiliary + for(unsigned int m = 0; m < N0; ++m) { + for(unsigned int n = 0; n < N1; ++n) { + for(unsigned int o = 0; o < N2; ++o) { + formulation.integral( (cPade0[m] + cPade1[n] + cPade2[o] + expMTheta) * dof(*_uHABC_C[m][n][o]), tf(*_uHABC_C[m][n][o]), corner, gauss); + formulation.integral( (cPade0[m] + 1.) * dof(*uHABC[1][n][o]), tf(*_uHABC_C[m][n][o]), corner, gauss); + formulation.integral( (cPade1[n] + 1.) * dof(*uHABC[2][o][m]), tf(*_uHABC_C[m][n][o]), corner, gauss); + formulation.integral( (cPade2[o] + 1.) * dof(*uHABC[0][m][n]), tf(*_uHABC_C[m][n][o]), corner, gauss); + } + } + } + } + + // ********************************** + // PML continuous _ PML continuous _ PML continuous + // ********************************** + + PmlContinuous_PmlContinuous_PmlContinuous::PmlContinuous_PmlContinuous_PmlContinuous(const unsigned int corner, PmlContinuous_PmlContinuous *first, PmlContinuous_PmlContinuous *second, PmlContinuous_PmlContinuous *third) : Corner(corner, first, second, third) + { + } + + PmlContinuous_PmlContinuous_PmlContinuous::~PmlContinuous_PmlContinuous_PmlContinuous() + { + delete _uPmlCorner; + delete _vC[0]; + delete _vC[1]; + delete _vC[2]; + delete _vEdge[0]; + delete _vEdge[1]; + delete _vEdge[2]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous_PmlContinuous::getUPml() const + { + return _uPmlCorner; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* PmlContinuous_PmlContinuous_PmlContinuous::getV(const unsigned int i) const + { + return _vC[i]; + } + + PmlContinuous_PmlContinuous *PmlContinuous_PmlContinuous_PmlContinuous::firstEdge() const + { + return static_cast< PmlContinuous_PmlContinuous * >(_bnd[0]); + } + + PmlContinuous_PmlContinuous *PmlContinuous_PmlContinuous_PmlContinuous::secondEdge() const + { + return static_cast< PmlContinuous_PmlContinuous * >(_bnd[1]); + } + + PmlContinuous_PmlContinuous *PmlContinuous_PmlContinuous_PmlContinuous::thirdEdge() const + { + return static_cast< PmlContinuous_PmlContinuous * >(_bnd[2]); + } + + void PmlContinuous_PmlContinuous_PmlContinuous::writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) + { + gmshfem::domain::Domain corner = domains.getCorner(_corner); + gmshfem::domain::Domain pmlCorner = domains.getPmlCorner(_corner); + std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > pmlBnd = domains.getPmlEdgeBnd(_corner); + std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > cornerEdge = domains.getCornerEdge(_corner); + + const unsigned int neumannOrder = parameters.getNeumannOrder(); + const unsigned int fieldOrder = parameters.getFieldOrder(); + const std::string gauss = parameters.getGauss(); + const gmshfem::function::ScalarFunction< std::complex< double > > kappa = parameters.getKappa(); + + _uPmlCorner = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("uPmlCorner_" + orientation(), pmlCorner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + _vC[0] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_first", std::get<0>(pmlBnd), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + _vC[1] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_second", std::get<1>(pmlBnd), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + _vC[2] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vC_" + orientation() + "_third", std::get<2>(pmlBnd), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<0>(pmlBnd), "vC_" + orientation() + "_first"); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<1>(pmlBnd), "vC_" + orientation() + "_second"); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<2>(pmlBnd), "vC_" + orientation() + "_third"); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *uPml[3]; + uPml[0] = static_cast< PmlContinuous_PmlContinuous * >(_bnd[0])->getUPml(); + uPml[1] = static_cast< PmlContinuous_PmlContinuous * >(_bnd[1])->getUPml(); + uPml[2] = static_cast< PmlContinuous_PmlContinuous * >(_bnd[2])->getUPml(); + + std::vector< PmlContinuous * > boundaries(6); + for(unsigned int i = 0; i < 3; ++i) { + boundaries[2 * i] = static_cast< PmlContinuous_PmlContinuous * >(_bnd[i])->firstBoundary(); + boundaries[2 * i + 1] = static_cast< PmlContinuous_PmlContinuous * >(_bnd[i])->secondBoundary(); + } + std::sort(boundaries.begin(), boundaries.end()); + gmshfem::function::TensorFunction< std::complex< double > > D[3]; + gmshfem::function::ScalarFunction< std::complex< double > > E[3]; + gmshfem::function::ScalarFunction< std::complex< double > > kappaMod = boundaries[0]->pmlCoefficients(D[0], E[0], corner, kappa); + boundaries[2]->pmlCoefficients(D[1], E[1], corner, kappa); + boundaries[4]->pmlCoefficients(D[2], E[2], corner, kappa); + + formulation.integral(- D[0] * D[1] * D[2] * grad(dof(*_uPmlCorner)), grad(tf(*_uPmlCorner)), pmlCorner, gauss); + formulation.integral(kappaMod * kappaMod * E[0] * E[1] * E[2] * dof(*_uPmlCorner), tf(*_uPmlCorner), pmlCorner, gauss); + + formulation.integral(dof(*_vC[0]), tf(*_uPmlCorner), std::get<0>(pmlBnd), gauss); + formulation.integral(- dof(*_vC[0]), tf(*uPml[0]), std::get<0>(pmlBnd), gauss); + + formulation.integral(dof(*_uPmlCorner), tf(*_vC[0]), std::get<0>(pmlBnd), gauss); + formulation.integral(- dof(*uPml[0]), tf(*_vC[0]), std::get<0>(pmlBnd), gauss); + + formulation.integral(dof(*_vC[1]), tf(*_uPmlCorner), std::get<1>(pmlBnd), gauss); + formulation.integral(- dof(*_vC[1]), tf(*uPml[1]), std::get<1>(pmlBnd), gauss); + + formulation.integral(dof(*_uPmlCorner), tf(*_vC[1]), std::get<1>(pmlBnd), gauss); + formulation.integral(- dof(*uPml[1]), tf(*_vC[1]), std::get<1>(pmlBnd), gauss); + + formulation.integral(dof(*_vC[2]), tf(*_uPmlCorner), std::get<2>(pmlBnd), gauss); + formulation.integral(- dof(*_vC[2]), tf(*uPml[2]), std::get<2>(pmlBnd), gauss); + + formulation.integral(dof(*_uPmlCorner), tf(*_vC[2]), std::get<2>(pmlBnd), gauss); + formulation.integral(- dof(*uPml[2]), tf(*_vC[2]), std::get<2>(pmlBnd), gauss); + + // corner equation + _vEdge[0] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vCornerEdge_" + orientation() + "_first", std::get<0>(cornerEdge), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + formulation.integral(dof(*_vC[0]), tf(*_vEdge[0]), std::get<0>(cornerEdge), gauss); + formulation.integral(dof(*_vEdge[0]), tf(*_vC[0]), std::get<0>(cornerEdge), gauss); + + formulation.integral(-dof(*_vC[2]), tf(*_vEdge[0]), std::get<0>(cornerEdge), gauss); + formulation.integral(-dof(*_vEdge[0]), tf(*_vC[2]), std::get<0>(cornerEdge), gauss); + + formulation.integral(dof(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[0])->getV(0)), tf(*_vEdge[0]), std::get<0>(cornerEdge), gauss); + formulation.integral(dof(*_vEdge[0]), tf(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[0])->getV(0)), std::get<0>(cornerEdge), gauss); + + formulation.integral(-dof(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[2])->getV(0)), tf(*_vEdge[0]), std::get<0>(cornerEdge), gauss); + formulation.integral(-dof(*_vEdge[0]), tf(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[2])->getV(0)), std::get<0>(cornerEdge), gauss); + + _vEdge[1] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vCornerEdge_" + orientation() + "_second", std::get<1>(cornerEdge), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + formulation.integral(dof(*_vC[1]), tf(*_vEdge[1]), std::get<1>(cornerEdge), gauss); + formulation.integral(dof(*_vEdge[1]), tf(*_vC[1]), std::get<1>(cornerEdge), gauss); + + formulation.integral(-dof(*_vC[2]), tf(*_vEdge[1]), std::get<1>(cornerEdge), gauss); + formulation.integral(-dof(*_vEdge[1]), tf(*_vC[2]), std::get<1>(cornerEdge), gauss); + + formulation.integral(dof(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[1])->getV(0)), tf(*_vEdge[1]), std::get<1>(cornerEdge), gauss); + formulation.integral(dof(*_vEdge[1]), tf(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[1])->getV(0)), std::get<1>(cornerEdge), gauss); + + formulation.integral(-dof(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[2])->getV(1)), tf(*_vEdge[1]), std::get<1>(cornerEdge), gauss); + formulation.integral(-dof(*_vEdge[1]), tf(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[2])->getV(1)), std::get<1>(cornerEdge), gauss); + + _vEdge[2] = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vCornerEdge_" + orientation() + "_third", std::get<2>(cornerEdge), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + formulation.integral(dof(*_vC[0]), tf(*_vEdge[2]), std::get<2>(cornerEdge), gauss); + formulation.integral(dof(*_vEdge[2]), tf(*_vC[0]), std::get<2>(cornerEdge), gauss); + + formulation.integral(-dof(*_vC[1]), tf(*_vEdge[2]), std::get<2>(cornerEdge), gauss); + formulation.integral(-dof(*_vEdge[2]), tf(*_vC[1]), std::get<2>(cornerEdge), gauss); + + formulation.integral(dof(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[0])->getV(1)), tf(*_vEdge[2]), std::get<2>(cornerEdge), gauss); + formulation.integral(dof(*_vEdge[2]), tf(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[0])->getV(1)), std::get<2>(cornerEdge), gauss); + + formulation.integral(-dof(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[1])->getV(1)), tf(*_vEdge[2]), std::get<2>(cornerEdge), gauss); + formulation.integral(-dof(*_vEdge[2]), tf(*static_cast< PmlContinuous_PmlContinuous * >(_bnd[1])->getV(1)), std::get<2>(cornerEdge), gauss); + + + _vCorner = new gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >("vCorner_" + orientation(), corner, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder); + + formulation.integral(dof(*_vEdge[0]), tf(*_vCorner), corner, gauss); + formulation.integral(dof(*_vCorner), tf(*_vEdge[0]), corner, gauss); + + formulation.integral(dof(*_vEdge[1]), tf(*_vCorner), corner, gauss); + formulation.integral(dof(*_vCorner), tf(*_vEdge[1]), corner, gauss); + + formulation.integral(dof(*_vEdge[2]), tf(*_vCorner), corner, gauss); + formulation.integral(dof(*_vCorner), tf(*_vEdge[2]), corner, gauss); + } + + +} diff --git a/examples/helmholtz/crossPoints/Subproblem3D.h b/examples/helmholtz/crossPoints/Subproblem3D.h new file mode 100755 index 0000000000000000000000000000000000000000..c1c27170e4f31f3c94593a82cc1cdc25ef70c803 --- /dev/null +++ b/examples/helmholtz/crossPoints/Subproblem3D.h @@ -0,0 +1,272 @@ +#ifndef H_SUBPROBLEM3D +#define H_SUBPROBLEM3D + +#include "SubproblemDomains.h" +#include "SubproblemParameters.h" + +#include <gmshfem/Formulation.h> + +namespace D3 { + + + class Boundary + { + protected: + const unsigned int _boundary; + + public: + Boundary(const unsigned int boundary); + virtual ~Boundary(); + + virtual void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + + std::string orientation() const; + }; + + class Edge + { + protected: + const unsigned int _edge; + Boundary *_bnd[2]; + + public: + Edge(const unsigned int edge, Boundary *first, Boundary *second); + virtual ~Edge(); + + virtual void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + + std::string orientation() const; + }; + + class Corner + { + protected: + const unsigned int _corner; + Edge *_bnd[3]; + + public: + Corner(const unsigned int corner, Edge *first, Edge *second, Edge *third); + virtual ~Corner(); + + virtual void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + + std::string orientation() const; + }; + + class Subproblem + { + private: + const SubproblemDomains _domains; + const SubproblemParameters _parameters; + gmshfem::problem::Formulation< std::complex< double > > &_formulation; + const std::string _fieldName; + std::vector< Boundary * > _boundary; + std::vector< Edge * > _edge; + std::vector< Corner * > _corner; + + void _parseParameters(std::string &method, std::vector< std::string > ¶meters, const std::string &str) const; + + public: + Subproblem(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters, const std::string &E, const std::string &N, const std::string &W, const std::string &S, const std::string &D, const std::string &U); + ~Subproblem(); + + void writeFormulation(); + + Boundary *getBoundary(const unsigned int b) const; + Edge *getEdge(const unsigned int e) const; + Corner *getCorner(const unsigned int c) const; + }; + + + + + class Sommerfeld : public Boundary + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + Sommerfeld(const unsigned int boundary); + ~Sommerfeld(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class HABC : public Boundary + { + protected: + const unsigned int _N; + const double _theta; + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > _uHABC; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + HABC(const unsigned int boundary, const unsigned int N, const double theta); + ~HABC(); + + unsigned int getN() const; + double getTheta() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUHABC(const unsigned int m) const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class Pml : public Boundary + { + protected: + const double _size; + const std::string _type; + + public: + Pml(const unsigned int boundary, const double pmlSize, const std::string type); + virtual ~Pml(); + + double getSize() const; + gmshfem::function::ScalarFunction< std::complex< double > > pmlCoefficients(gmshfem::function::TensorFunction< std::complex< double > > &D, gmshfem::function::ScalarFunction< std::complex< double > > &E, gmshfem::domain::Domain &bnd, const gmshfem::function::ScalarFunction< std::complex< double > > &kappa) const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) = 0; + }; + + class PmlContinuous : public Pml + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPml; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + PmlContinuous(const unsigned int boundary, const double pmlSize, const std::string type); + ~PmlContinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + // Marche pas, il faudrait du vrai H(div) + class PmlDiscontinuous : public Pml + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPml; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 > * _v; + + public: + PmlDiscontinuous(const unsigned int boundary, const double pmlSize, const std::string type); + ~PmlDiscontinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form2 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlWithoutMultiplier : public Pml + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPml; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _v; + + public: + PmlWithoutMultiplier(const unsigned int boundary, const double pmlSize, const std::string type); + ~PmlWithoutMultiplier(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const std::string &fieldName, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + + + + class HABC_HABC : public Edge + { + protected: + std::vector< std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > > _uHABC_E; + std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > _vE[2]; + + public: + HABC_HABC(const unsigned int corner, HABC *first, HABC *second); + ~HABC_HABC(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getUHABC(const unsigned int m, const unsigned int n) const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getV(const unsigned int m, const unsigned int i) const; + + HABC *firstBoundary() const; + HABC *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlContinuous_PmlContinuous : public Edge + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPmlEdge; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vC[2]; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vEdge; + + public: + PmlContinuous_PmlContinuous(const unsigned int edge, PmlContinuous *first, PmlContinuous *second); + ~PmlContinuous_PmlContinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV(const unsigned int i) const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getVEdge() const; + + PmlContinuous *firstBoundary() const; + PmlContinuous *secondBoundary() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + + + + class HABC_HABC_HABC : public Corner + { + protected: + std::vector< std::vector< std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > > > _uHABC_C; + std::vector< std::vector< gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * > > _vC[3]; + + public: + HABC_HABC_HABC(const unsigned int corner, HABC_HABC *first, HABC_HABC *second, HABC_HABC *third); + ~HABC_HABC_HABC(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getUHABC(const unsigned int m, const unsigned int n, const unsigned int o) const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > *getV(const unsigned int m, const unsigned int n, const unsigned int i) const; + + HABC_HABC *firstEdge() const; + HABC_HABC *secondEdge() const; + HABC_HABC *thirdEdge() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + + class PmlContinuous_PmlContinuous_PmlContinuous : public Corner + { + protected: + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _uPmlCorner; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vC[3]; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vEdge[3]; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > * _vCorner; + + public: + PmlContinuous_PmlContinuous_PmlContinuous(const unsigned int corner, PmlContinuous_PmlContinuous *first, PmlContinuous_PmlContinuous *second, PmlContinuous_PmlContinuous *third); + ~PmlContinuous_PmlContinuous_PmlContinuous(); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getUPml() const; + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 >* getV(const unsigned int i) const; + + PmlContinuous_PmlContinuous *firstEdge() const; + PmlContinuous_PmlContinuous *secondEdge() const; + PmlContinuous_PmlContinuous *thirdEdge() const; + + void writeFormulation(gmshfem::problem::Formulation< std::complex< double > > &formulation, const SubproblemDomains &domains, const SubproblemParameters ¶meters) override; + }; + +} + +#endif // H_SUBPROBLEM3D diff --git a/examples/helmholtz/crossPoints/SubproblemDomains.cpp b/examples/helmholtz/crossPoints/SubproblemDomains.cpp new file mode 100755 index 0000000000000000000000000000000000000000..845528bf32be3d0db210ee2267b93ead7bcc7a93 --- /dev/null +++ b/examples/helmholtz/crossPoints/SubproblemDomains.cpp @@ -0,0 +1,235 @@ +#include "SubproblemDomains.h" + +namespace D2 { + + + SubproblemDomains::SubproblemDomains() : _omega(), _sigma(), _pml(), _pmlBnd(), _pmlCorner(), _corner() + { + + } + + SubproblemDomains::~SubproblemDomains() + { + } + + void SubproblemDomains::setOmega(const gmshfem::domain::Domain &omega) + { + _omega = omega; + } + + void SubproblemDomains::setSigma(const std::vector< gmshfem::domain::Domain > &sigma) + { + _sigma = sigma; + } + + gmshfem::domain::Domain SubproblemDomains::getSigma(const unsigned int b) const + { + return _sigma[b]; + } + + void SubproblemDomains::setPml(const std::vector< gmshfem::domain::Domain > &pml) + { + _pml = pml; + } + + gmshfem::domain::Domain SubproblemDomains::getPml(const unsigned int b) const + { + return _pml[b]; + } + + void SubproblemDomains::setPmlBnd(const std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > &pmlBnd) + { + _pmlBnd = pmlBnd; + } + + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > SubproblemDomains::getPmlBnd(const unsigned int c) const + { + return _pmlBnd[c]; + } + + void SubproblemDomains::setPmlCorner(const std::vector< gmshfem::domain::Domain > &pmlCorner) + { + _pmlCorner = pmlCorner; + } + + gmshfem::domain::Domain SubproblemDomains::getPmlCorner(const unsigned int c) const + { + return _pmlCorner[c]; + } + + void SubproblemDomains::setCorner(const std::vector< gmshfem::domain::Domain > &corner) + { + _corner = corner; + } + + gmshfem::domain::Domain SubproblemDomains::getCorner(const unsigned int c) const + { + return _corner[c]; + } + + +} + + +namespace D3 { + + + SubproblemDomains::SubproblemDomains() : _omega(), _sigma(), _pml(), _pmlBnd(), _pmlEdge(), _edge(), _pmlEdgeBnd(), _pmlCorner(), _corner() + { + + } + + SubproblemDomains::~SubproblemDomains() + { + } + + void SubproblemDomains::setOmega(const gmshfem::domain::Domain &omega) + { + _omega = omega; + } + + void SubproblemDomains::setSigma(const std::vector< gmshfem::domain::Domain > &sigma) + { + _sigma = sigma; + } + + gmshfem::domain::Domain SubproblemDomains::getSigma(const unsigned int b) const + { + return _sigma[b]; + } + + void SubproblemDomains::setPml(const std::vector< gmshfem::domain::Domain > &pml) + { + _pml = pml; + } + + gmshfem::domain::Domain SubproblemDomains::getPml(const unsigned int b) const + { + return _pml[b]; + } + + void SubproblemDomains::setPmlBnd(const std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > &pmlBnd) + { + _pmlBnd = pmlBnd; + } + + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > SubproblemDomains::getPmlBnd(const unsigned int e) const + { + return _pmlBnd[e]; + } + + void SubproblemDomains::setPmlEdge(const std::vector< gmshfem::domain::Domain > &pmlEdge) + { + _pmlEdge = pmlEdge; + } + + gmshfem::domain::Domain SubproblemDomains::getPmlEdge(const unsigned int e) const + { + return _pmlEdge[e]; + } + + void SubproblemDomains::setEdge(const std::vector< gmshfem::domain::Domain > &edge) + { + _edge = edge; + } + + gmshfem::domain::Domain SubproblemDomains::getEdge(const unsigned int e) const + { + return _edge[e]; + } + + void SubproblemDomains::setPmlEdgeBnd(const std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > &pmlEdgeBnd) + { + _pmlEdgeBnd = pmlEdgeBnd; + } + + std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > SubproblemDomains::getPmlEdgeBnd(const unsigned int c) const + { + return _pmlEdgeBnd[c]; + } + + void SubproblemDomains::setPmlCorner(const std::vector< gmshfem::domain::Domain > &pmlCorner) + { + _pmlCorner = pmlCorner; + } + + gmshfem::domain::Domain SubproblemDomains::getPmlCorner(const unsigned int c) const + { + return _pmlCorner[c]; + } + + void SubproblemDomains::setCorner(const std::vector< gmshfem::domain::Domain > &corner) + { + _corner = corner; + } + + gmshfem::domain::Domain SubproblemDomains::getCorner(const unsigned int c) const + { + return _corner[c]; + } + + void SubproblemDomains::setCornerEdge(const std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > &cornerEdge) + { + _cornerEdge = cornerEdge; + } + + std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > SubproblemDomains::getCornerEdge(const unsigned int c) const + { + return _cornerEdge[c]; + } + + void SubproblemDomains::saveDebug() const + { + const std::string ori[6] = {"E", "N", "W", "S", "D", "U"}; + + _omega.saveDebug("omega"); + for(unsigned int b = 0; b < 6; ++b) { + _sigma[b].saveDebug("sigma" + ori[b]); + _pml[b].saveDebug("pml" + ori[b]); + } + for(unsigned int e = 0; e < 12; ++e) { + if(e < 4) { + _pmlBnd[e].first.saveDebug("pmlBnd" + ori[e%4] + "D_first"); + _pmlBnd[e].second.saveDebug("pmlBnd" + ori[e%4] + "D_second"); + _pmlEdge[e].saveDebug("pmlEdge" + ori[e%4] + "D"); + _edge[e].saveDebug("edge" + ori[e%4] + "D"); + } + else if(e >= 4 && e < 8) { + _pmlBnd[e].first.saveDebug("pmlBnd" + ori[e%4] + ori[(e+1)%4] + "_first"); + _pmlBnd[e].second.saveDebug("pmlBnd" + ori[e%4] + ori[(e+1)%4] + "_second"); + _pmlEdge[e].saveDebug("pmlEdge" + ori[e%4] + ori[(e+1)%4]); + _edge[e].saveDebug("edge" + ori[e%4] + ori[(e+1)%4]); + } + else { + _pmlBnd[e].first.saveDebug("pmlBnd" + ori[e%4] + "U_first"); + _pmlBnd[e].second.saveDebug("pmlBnd" + ori[e%4] + "U_second"); + _pmlEdge[e].saveDebug("pmlEdge" + ori[e%4] + "U"); + _edge[e].saveDebug("edge" + ori[e%4] + "U"); + } + } + for(unsigned int c = 0; c < 8; ++c) { + if(c < 4) { + std::get<0>(_pmlEdgeBnd[c]).saveDebug("pmlEdgeBnd" + ori[c%4] + ori[(c+1)%4] + "D_first"); + std::get<1>(_pmlEdgeBnd[c]).saveDebug("pmlEdgeBnd" + ori[c%4] + ori[(c+1)%4] + "D_second"); + std::get<2>(_pmlEdgeBnd[c]).saveDebug("pmlEdgeBnd" + ori[c%4] + ori[(c+1)%4] + "D_third"); + _pmlCorner[c].saveDebug("pmlCorner" + ori[c%4] + ori[(c+1)%4] + "D"); + _corner[c].saveDebug("corner" + ori[c%4] + ori[(c+1)%4] + "D"); + std::get<0>(_cornerEdge[c]).saveDebug("cornerEdge" + ori[c%4] + ori[(c+1)%4] + "D_first"); + std::get<1>(_cornerEdge[c]).saveDebug("cornerEdge" + ori[c%4] + ori[(c+1)%4] + "D_second"); + std::get<2>(_cornerEdge[c]).saveDebug("cornerEdge" + ori[c%4] + ori[(c+1)%4] + "D_third"); + } + else { + std::get<0>(_pmlEdgeBnd[c]).saveDebug("pmlEdgeBnd" + ori[c%4] + ori[(c+1)%4] + "U_first"); + std::get<1>(_pmlEdgeBnd[c]).saveDebug("pmlEdgeBnd" + ori[c%4] + ori[(c+1)%4] + "U_second"); + std::get<2>(_pmlEdgeBnd[c]).saveDebug("pmlEdgeBnd" + ori[c%4] + ori[(c+1)%4] + "U_third"); + _pmlCorner[c].saveDebug("pmlCorner" + ori[c%4] + ori[(c+1)%4] + "U"); + _corner[c].saveDebug("corner" + ori[c%4] + ori[(c+1)%4] + "U"); + std::get<0>(_cornerEdge[c]).saveDebug("cornerEdge" + ori[c%4] + ori[(c+1)%4] + "U_first"); + std::get<1>(_cornerEdge[c]).saveDebug("cornerEdge" + ori[c%4] + ori[(c+1)%4] + "U_second"); + std::get<2>(_cornerEdge[c]).saveDebug("cornerEdge" + ori[c%4] + ori[(c+1)%4] + "U_third"); + } + } + } + + +} diff --git a/examples/helmholtz/crossPoints/SubproblemDomains.h b/examples/helmholtz/crossPoints/SubproblemDomains.h new file mode 100755 index 0000000000000000000000000000000000000000..edc598f9226e5eabe5135060f42de493b8b0db73 --- /dev/null +++ b/examples/helmholtz/crossPoints/SubproblemDomains.h @@ -0,0 +1,107 @@ +#ifndef H_SUBPROBLEMDOMAINS +#define H_SUBPROBLEMDOMAINS + +#include <gmshfem/Domain.h> + +#include <tuple> + +namespace D2 { + + + class SubproblemDomains + { + private: + gmshfem::domain::Domain _omega; + // boundary + std::vector< gmshfem::domain::Domain > _sigma; + std::vector< gmshfem::domain::Domain > _pml; + // corner + std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > _pmlBnd; + std::vector< gmshfem::domain::Domain > _pmlCorner; + std::vector< gmshfem::domain::Domain > _corner; + + public: + SubproblemDomains(); + ~SubproblemDomains(); + + void setOmega(const gmshfem::domain::Domain &omega); + + void setSigma(const std::vector< gmshfem::domain::Domain > &sigma); + gmshfem::domain::Domain getSigma(const unsigned int b) const; + + void setPml(const std::vector< gmshfem::domain::Domain > &pml); + gmshfem::domain::Domain getPml(const unsigned int b) const; + + void setPmlBnd(const std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > &pmlBnd); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > getPmlBnd(const unsigned int c) const; + + void setPmlCorner(const std::vector< gmshfem::domain::Domain > &pmlCorner); + gmshfem::domain::Domain getPmlCorner(const unsigned int c) const; + + void setCorner(const std::vector< gmshfem::domain::Domain > &corner); + gmshfem::domain::Domain getCorner(const unsigned int c) const; + }; + + +} + +namespace D3 { + + + class SubproblemDomains + { + private: + gmshfem::domain::Domain _omega; + // boundary + std::vector< gmshfem::domain::Domain > _sigma; + std::vector< gmshfem::domain::Domain > _pml; + // edge + std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > _pmlBnd; + std::vector< gmshfem::domain::Domain > _pmlEdge; + std::vector< gmshfem::domain::Domain > _edge; + // corner + std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > _pmlEdgeBnd; + std::vector< gmshfem::domain::Domain > _pmlCorner; + std::vector< gmshfem::domain::Domain > _corner; + std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > _cornerEdge; + + public: + SubproblemDomains(); + ~SubproblemDomains(); + + void setOmega(const gmshfem::domain::Domain &omega); + + void setSigma(const std::vector< gmshfem::domain::Domain > &sigma); + gmshfem::domain::Domain getSigma(const unsigned int b) const; + + void setPml(const std::vector< gmshfem::domain::Domain > &pml); + gmshfem::domain::Domain getPml(const unsigned int b) const; + + void setPmlBnd(const std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > &pmlBnd); + std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > getPmlBnd(const unsigned int e) const; + + void setPmlEdge(const std::vector< gmshfem::domain::Domain > &pmlEdge); + gmshfem::domain::Domain getPmlEdge(const unsigned int e) const; + + void setEdge(const std::vector< gmshfem::domain::Domain > &edge); + gmshfem::domain::Domain getEdge(const unsigned int e) const; + + void setPmlEdgeBnd(const std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > &pmlEdgeBnd); + std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > getPmlEdgeBnd(const unsigned int c) const; + + void setPmlCorner(const std::vector< gmshfem::domain::Domain > &pmlCorner); + gmshfem::domain::Domain getPmlCorner(const unsigned int c) const; + + void setCorner(const std::vector< gmshfem::domain::Domain > &corner); + gmshfem::domain::Domain getCorner(const unsigned int c) const; + + void setCornerEdge(const std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > &cornerEdge); + std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > getCornerEdge(const unsigned int c) const; + + void saveDebug() const; + }; + + +} + +#endif // H_SUBPROBLEMDOMAINS diff --git a/examples/helmholtz/crossPoints/SubproblemParameters.cpp b/examples/helmholtz/crossPoints/SubproblemParameters.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b8f68c17a1e29a87b6a3d0e33043d0824e860062 --- /dev/null +++ b/examples/helmholtz/crossPoints/SubproblemParameters.cpp @@ -0,0 +1,60 @@ +#include "SubproblemParameters.h" + +SubproblemParameters::SubproblemParameters() +{ + +} + +SubproblemParameters::~SubproblemParameters() +{ +} + +void SubproblemParameters::setGauss(const std::string &gauss) +{ + _gauss = gauss; +} + +std::string SubproblemParameters::getGauss() const +{ + return _gauss; +} + +void SubproblemParameters::setKappa(const gmshfem::function::ScalarFunction< std::complex< double > > &kappa) +{ + _kappa = kappa; +} + +gmshfem::function::ScalarFunction< std::complex< double > > SubproblemParameters::getKappa() const +{ + return _kappa; +} + +void SubproblemParameters::setNeumannOrder(const unsigned int neumannOrder) +{ + _neumannOrder = neumannOrder; +} + +unsigned int SubproblemParameters::getNeumannOrder() const +{ + return _neumannOrder; +} + +void SubproblemParameters::setFieldOrder(const unsigned int fieldOrder) +{ + _fieldOrder = fieldOrder; +} + +unsigned int SubproblemParameters::getFieldOrder() const +{ + return _fieldOrder; +} + +void SubproblemParameters::setStab(const double stab) +{ + _stab = stab; +} + +double SubproblemParameters::getStab() const +{ + return _stab; +} diff --git a/examples/helmholtz/crossPoints/SubproblemParameters.h b/examples/helmholtz/crossPoints/SubproblemParameters.h new file mode 100755 index 0000000000000000000000000000000000000000..63528ae0e8c0fd3c76e2224243183de048c90166 --- /dev/null +++ b/examples/helmholtz/crossPoints/SubproblemParameters.h @@ -0,0 +1,35 @@ +#ifndef H_SUBPROBLEMPARAMETERS +#define H_SUBPROBLEMPARAMETERS + +#include <gmshfem/Function.h> + +class SubproblemParameters +{ + private: + std::string _gauss; + gmshfem::function::ScalarFunction< std::complex< double > > _kappa; + unsigned int _neumannOrder; + unsigned int _fieldOrder; + double _stab; + + public: + SubproblemParameters(); + ~SubproblemParameters(); + + void setGauss(const std::string &gauss); + std::string getGauss() const; + + void setKappa(const gmshfem::function::ScalarFunction< std::complex< double > > &kappa); + gmshfem::function::ScalarFunction< std::complex< double > > getKappa() const; + + void setNeumannOrder(const unsigned int neumannOrder); + unsigned int getNeumannOrder() const; + + void setFieldOrder(const unsigned int fieldOrder); + unsigned int getFieldOrder() const; + + void setStab(const double stab); + double getStab() const; +}; + +#endif // H_SUBPROBLEMPARAMETERS diff --git a/examples/helmholtz/crossPoints/ddm2D.cpp b/examples/helmholtz/crossPoints/ddm2D.cpp new file mode 100755 index 0000000000000000000000000000000000000000..bd94e284649d1d66f48c535b7902c006658f339a --- /dev/null +++ b/examples/helmholtz/crossPoints/ddm2D.cpp @@ -0,0 +1,936 @@ +#include "ddm2D.h" + +#include "mesh.h" +#include "SubproblemDomains.h" +#include "Subproblem2D.h" + +#include <gmshfem/GmshFem.h> +#include <gmshfem/FieldInterface.h> +#include <gmshfem/Formulation.h> +#include <gmshfem/AnalyticalFunction.h> +#include <gmshfem/Post.h> +#include <gmshfem/Function.h> +#include <gmshfem/io.h> + +#include <gmshddm/GmshDdm.h> +#include <gmshddm/Subdomain.h> +#include <gmshddm/Interface.h> +#include <gmshddm/SubdomainField.h> +#include <gmshddm/InterfaceField.h> +#include <gmshddm/Formulation.h> +#include <gmshddm/MPIInterface.h> + +#include <algorithm> +#include <fstream> + +using gmshfem::equation::dof; +using gmshfem::equation::tf; +using gmshfem::function::operator-; +using gmshfem::function::operator*; +using gmshfem::function::abs; + +namespace D2 { + + + void ddm() + { + gmshddm::common::GmshDdm *gmshDdm = gmshddm::common::GmshDdm::currentInstance(); + + // ************************ + // P H Y S I C S + // ************************ + double pi = 3.14159265359; + double k = 4. * pi; + gmshDdm->userDefinedParameter(k, "k"); + double R = 0.5; + gmshDdm->userDefinedParameter(R, "R"); + std::string benchmark = "scattering"; // scattering, marmousi + gmshDdm->userDefinedParameter(benchmark, "benchmark"); + + // ************************ + // M E S H + // ************************ + double lc = 0.03333333333333; // Marmousi = 10; other = 0.03333333333333 + gmshDdm->userDefinedParameter(lc, "lc"); + int meshOrder = 1; + gmshDdm->userDefinedParameter(meshOrder, "meshOrder"); + + // ************************ + // M O D E L I N G + // ************************ + std::string boundary = "sommerfeld"; // sommerfeld, pml, habc + gmshDdm->userDefinedParameter(boundary, "boundary"); + std::string boundaryExt = "sommerfeld"; // sommerfeld, pml, habc + gmshDdm->userDefinedParameter(boundaryExt, "boundaryExt"); + std::string pmlMethod = "continuous"; // continuous, discontinuous, withoutMultiplier + gmshDdm->userDefinedParameter(pmlMethod, "pmlMethod"); + std::string pmlMethodExt = "continuous"; // continuous, discontinuous, withoutMultiplier + gmshDdm->userDefinedParameter(pmlMethodExt, "pmlMethodExt"); + std::string pmlType = "hs"; // hs, h, q + gmshDdm->userDefinedParameter(pmlType, "pmlType"); + std::string pmlTypeExt = "hs"; // hs, h, q + gmshDdm->userDefinedParameter(pmlTypeExt, "pmlTypeExt"); + + + unsigned int nDomX = 2, nDomY = 2; + gmshDdm->userDefinedParameter(nDomX, "nDomX"); + gmshDdm->userDefinedParameter(nDomY, "nDomY"); + unsigned int iterMax = 1000; + gmshDdm->userDefinedParameter(iterMax, "iterMax"); + double res = 1e-6; + gmshDdm->userDefinedParameter(res, "res"); + double sizeX = 2., sizeY = 2.; + gmshDdm->userDefinedParameter(sizeX, "sizeX"); + gmshDdm->userDefinedParameter(sizeY, "sizeY"); + + unsigned int N = 6; + gmshDdm->userDefinedParameter(N, "N"); + double pmlSize = N * lc; + if(pmlSize == 0.) { + pmlSize = 0.3; + } + + unsigned int NExt = N; + gmshDdm->userDefinedParameter(NExt, "NExt"); + double pmlSizeExt = NExt * lc; + if(pmlSizeExt == 0.) { + pmlSizeExt = 0.3; + } + + std::string gauss = "Gauss10"; + gmshDdm->userDefinedParameter(gauss, "gauss"); + int fieldOrder = 1; + gmshDdm->userDefinedParameter(fieldOrder, "fieldOrder"); + int neumannOrder = 1; + gmshDdm->userDefinedParameter(neumannOrder, "neumannOrder"); + double stab = 0.00016666666; + gmshDdm->userDefinedParameter(stab, "stab"); + double thetaPade = 0.; + gmshDdm->userDefinedParameter(thetaPade, "thetaPade"); + thetaPade *= pi; + + // ************************ + // P O S T + // ************************ + bool monoDomainError = false; + gmshDdm->userDefinedParameter(monoDomainError, "monoDomainError"); + bool analyticError = false; + gmshDdm->userDefinedParameter(analyticError, "analyticError"); + std::string fileName = "none"; + gmshDdm->userDefinedParameter(fileName, "file"); + bool saveEMono = false; + gmshDdm->userDefinedParameter(saveEMono, "saveEMono"); + bool saveUMono = false; + gmshDdm->userDefinedParameter(saveUMono, "saveUMono"); + bool saveU = false; + gmshDdm->userDefinedParameter(saveU, "saveU"); + bool saveE = false; + gmshDdm->userDefinedParameter(saveE, "saveE"); + bool wavenumberPlot = false; + gmshDdm->userDefinedParameter(wavenumberPlot, "wavenumber"); + bool meshPlot = false; + gmshDdm->userDefinedParameter(meshPlot, "mesh"); + bool saveMesh = false; + gmshDdm->userDefinedParameter(saveMesh, "saveMesh"); + + if(benchmark == "scattering") { + checkerboard(nDomX, nDomY, sizeX, sizeY, R, lc, (boundary == "pml"), pmlSize, (boundaryExt == "pml"), pmlSizeExt, meshOrder, 0, 0); + } + else if (benchmark == "marmousi") { + checkerboard(nDomX, nDomY, 9192./nDomX, 2904./nDomY, 0., lc, (boundary == "pml"), pmlSize, (boundaryExt == "pml"), pmlSizeExt, meshOrder, -1, -1, true); + sizeX = 9192./nDomX; + sizeY = 2904./nDomY; + } + if(saveMesh) { + gmsh::write("mesh.msh"); + } + + + gmshfem::msg::info << "Running 'ddm2D'" << gmshfem::msg::endl; + gmshfem::msg::info << "Parameters:" << gmshfem::msg::endl; + gmshfem::msg::info << " * physics:" << gmshfem::msg::endl; + if(benchmark == "scattering") { + gmshfem::msg::info << " - k: " << k << " (" << k/pi << "*pi" << ")" << gmshfem::msg::endl; + } + else if (benchmark == "marmousi") { + gmshfem::msg::info << " - k: for Marmousi" << gmshfem::msg::endl; + } + gmshfem::msg::info << " - R: " << R << gmshfem::msg::endl; + gmshfem::msg::info << " * mesh:" << gmshfem::msg::endl; + gmshfem::msg::info << " - lc: " << lc << " (eta_h = " << (2*pi/k)/lc << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - meshOrder: " << meshOrder << gmshfem::msg::endl; + gmshfem::msg::info << " * modeling:" << gmshfem::msg::endl; + gmshfem::msg::info << " - grid: (" << nDomX << ", " << nDomY << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - iterMax: " << iterMax << gmshfem::msg::endl; + gmshfem::msg::info << " - res: " << res << gmshfem::msg::endl; + gmshfem::msg::info << " - subdomain size: (" << sizeX << ", " << sizeY << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - boundary: " << boundary << gmshfem::msg::endl; + gmshfem::msg::info << " - boundaryExt: " << boundaryExt << gmshfem::msg::endl; + if(boundary == "pml") { + gmshfem::msg::info << " - N: " << N << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlSize: " << pmlSize << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlType: " << pmlType << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlMethod: " << pmlMethod << gmshfem::msg::endl; + } + else if(boundary == "habc") { + gmshfem::msg::info << " - N: " << N << gmshfem::msg::endl; + gmshfem::msg::info << " - thetaPade: " << thetaPade << " (" << thetaPade/pi << "*pi" << ")" << gmshfem::msg::endl; + } + if(boundaryExt == "pml") { + gmshfem::msg::info << " - NExt: " << NExt << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlSizeExt: " << pmlSizeExt << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlTypeExt: " << pmlTypeExt << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlMethodExt: " << pmlMethodExt << gmshfem::msg::endl; + } + else if(boundary == "habc") { + gmshfem::msg::info << " - N: " << NExt << gmshfem::msg::endl; + } + gmshfem::msg::info << " - gauss: " << gauss << gmshfem::msg::endl; + gmshfem::msg::info << " - fieldOrder: " << fieldOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - neumannOrder: " << neumannOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - stab: " << stab << " * lc (= " << stab * lc << ")" << gmshfem::msg::endl; + + + // source + gmshfem::analytics::AnalyticalFunction< gmshfem::analytics::helmholtz2D::ScatteringByASoftCylinder< std::complex< double > > > fAnalytic(k, R, 1., 1., 2 * k); + + const unsigned int nDom = nDomX * nDomY; + // Define domain + gmshddm::domain::Subdomain omega(nDom); + gmshfem::domain::Domain gamma; + if(benchmark == "scattering") { + gamma = gmshfem::domain::Domain("gamma"); + } + else if (benchmark == "marmousi") { + gamma = gmshfem::domain::Domain(0, 90101); + } + + std::vector< gmshddm::domain::Subdomain > pml(4, nDom); + std::vector< gmshddm::domain::Subdomain > pmlCorner(4, nDom); + std::vector< gmshddm::domain::Subdomain > sigma(4, nDom); + std::vector< gmshddm::domain::Interface > sigmaInterface(4, nDom); + std::vector< std::pair< gmshddm::domain::Subdomain, gmshddm::domain::Subdomain > > pmlBnd(4, std::make_pair(gmshddm::domain::Subdomain(nDom), gmshddm::domain::Subdomain(nDom)) ); + std::vector< std::pair< gmshddm::domain::Interface, gmshddm::domain::Interface > > pmlBndInterface(4, std::make_pair(gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom))); + + std::vector< gmshddm::domain::Subdomain > corner(4, nDom); + std::vector< std::pair< gmshddm::domain::Interface, gmshddm::domain::Interface > > cornerInterface(4, std::make_pair(gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom))); + // Define topology + std::vector< std::vector< unsigned int > > topology(nDom); + std::vector< std::string > dir {"E", "N", "W", "S"}; + for(unsigned int i = 0; i < static_cast< unsigned int >(nDomX); ++i) { + for(unsigned int j = 0; j < static_cast< unsigned int >(nDomY); ++j) { + unsigned int index = i * nDomY + j; + + const std::string subdomainTag = "_" + std::to_string(i) + "_" + std::to_string(j); + omega(index) = gmshfem::domain::Domain("omega" + subdomainTag); + + for(unsigned int b = 0; b < 4; ++b) { + if(boundary == "pml" || boundaryExt == "pml") { + pml[b](index) = gmshfem::domain::Domain("pml" + dir[b] + subdomainTag); + } + sigma[b](index) = gmshfem::domain::Domain("sigma" + dir[b] + subdomainTag); + } + + for(unsigned int c = 0; c < 4; ++c) { + if(boundary == "pml" || boundaryExt == "pml") { + pmlCorner[c](index) = gmshfem::domain::Domain("pmlCorner" + dir[c] + dir[(c+1)%4] + subdomainTag); + pmlBnd[c].first(index) = gmshfem::domain::Domain("pmlBnd" + dir[c] + "_second" + subdomainTag); + pmlBnd[c].second(index) = gmshfem::domain::Domain("pmlBnd" + dir[(c+1)%4] + "_first" + subdomainTag); + } + corner[c](index) = gmshfem::domain::Domain("corner" + dir[c] + dir[(c+1)%4] + subdomainTag); + } + + if(i != static_cast< unsigned int >(nDomX) - 1) { // E + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[3].first(index, (i+1) * nDomY + j) = pmlBnd[3].first(index); + pmlBndInterface[0].second(index, (i+1) * nDomY + j) = pmlBnd[0].second(index); + } + sigmaInterface[0](index, (i+1) * nDomY + j) = sigma[0](index); + + cornerInterface[3].first(index, (i+1) * nDomY + j) = corner[3](index); + cornerInterface[0].second(index, (i+1) * nDomY + j) = corner[0](index); + + topology[index].push_back((i+1) * nDomY + j); + } + + if(j != static_cast< unsigned int >(nDomY) - 1) { // N + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[0].first(index, i * nDomY + (j+1)) = pmlBnd[0].first(index); + pmlBndInterface[1].second(index, i * nDomY + (j+1)) = pmlBnd[1].second(index); + } + sigmaInterface[1](index, i * nDomY + (j+1)) = sigma[1](index); + + cornerInterface[0].first(index, i * nDomY + (j+1)) = corner[0](index); + cornerInterface[1].second(index, i * nDomY + (j+1)) = corner[1](index); + + topology[index].push_back(i * nDomY + (j+1)); + } + + if(i != 0) { // W + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[1].first(index, (i-1) * nDomY + j) = pmlBnd[1].first(index); + pmlBndInterface[2].second(index, (i-1) * nDomY + j) = pmlBnd[2].second(index); + } + sigmaInterface[2](index, (i-1) * nDomY + j) = sigma[2](index); + + cornerInterface[1].first(index, (i-1) * nDomY + j) = corner[1](index); + cornerInterface[2].second(index, (i-1) * nDomY + j) = corner[2](index); + + topology[index].push_back((i-1) * nDomY + j); + } + + if(j != 0) { // S + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[2].first(index, i * nDomY + (j-1)) = pmlBnd[2].first(index); + pmlBndInterface[3].second(index, i * nDomY + (j-1)) = pmlBnd[3].second(index); + } + sigmaInterface[3](index, i * nDomY + (j-1)) = sigma[3](index); + + cornerInterface[2].first(index, i * nDomY + (j-1)) = corner[2](index); + cornerInterface[3].second(index, i * nDomY + (j-1)) = corner[3](index); + + topology[index].push_back(i * nDomY + (j-1)); + } + } + } + + // Kappa definition + gmshfem::function::ScalarFunction< std::complex< double > > kappa; + if(benchmark == "scattering") { + kappa = k; + } + else if (benchmark == "marmousi") { + // Read the velocity map + std::ifstream file("../marmousi.dat"); + + unsigned int Nx = 0, Ny = 0; + file >> Nx; + file >> Ny; + gmshfem::msg::info << "Reading: Nx = " << Nx << ", Ny = " << Ny << "." << gmshfem::msg::endl; + + std::vector< double > x(Nx), y(Ny); + for(unsigned int i = 0; i < Nx; ++i) { + file >> x[i]; + } + for(unsigned int i = 0; i < Ny; ++i) { + file >> y[i]; + y[i] += 2904.; + } + // Hack to avoid problem at the boundaries + x[0] -= 1e-3; + y[0] -= 1e-3; + x[Nx-1] += 1e-3; + y[Ny-1] += 1e-3; + + std::vector< std::vector< std::complex< double > > > data(Nx, std::vector< std::complex< double > >(Ny)); + for(unsigned int j = 0; j < Ny; ++j) { + for(unsigned int i = 0; i < Nx; ++i) { + double tmp; + file >> tmp; + data[i][j] = tmp; + } + } + file.close(); + + kappa = 2. * pi * 30. / gmshfem::function::bilinearInterpolation< std::complex< double > >(std::move(x), std::move(y), std::move(data)); +// for(unsigned int k = 0; k < nDomX * nDomY; ++k) { +// if(gmshddm::mpi::isItMySubdomain(k)) { +// gmshfem::post::save(kappa, omega(k), "k_" + std::to_string(k), "msh"); +// } +// } + gmshfem::post::save(kappa, omega(37), "k_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(sigma[0](37)), gmshfem::function::y< double >(), gmshfem::function::z< double >()), pml[0](37), "kE_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(), gmshfem::function::y< double >(sigma[1](37)), gmshfem::function::z< double >()), pml[1](37), "kN_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(sigma[2](37)), gmshfem::function::y< double >(), gmshfem::function::z< double >()), pml[2](37), "kS_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(), gmshfem::function::y< double >(sigma[3](37)), gmshfem::function::z< double >()), pml[3](37), "kW_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(corner[0](37)), gmshfem::function::y< double >(corner[0](37)), gmshfem::function::z< double >()), pmlCorner[0](37), "kEN_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(corner[1](37)), gmshfem::function::y< double >(corner[1](37)), gmshfem::function::z< double >()), pmlCorner[1](37), "kNW_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(corner[2](37)), gmshfem::function::y< double >(corner[2](37)), gmshfem::function::z< double >()), pmlCorner[2](37), "kWS_" + std::to_string(37), "msh"); + gmshfem::post::save(changeOfCoordinates(kappa, gmshfem::function::x< double >(corner[3](37)), gmshfem::function::y< double >(corner[3](37)), gmshfem::function::z< double >()), pmlCorner[3](37), "kSE_" + std::to_string(37), "msh"); + } + + // Fields definition + gmshddm::field::SubdomainField< std::complex< double >, gmshfem::field::Form::Form0 > u("u", omega | sigma[0] | sigma[1] | sigma[2] | sigma[3], gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + if(benchmark == "scattering") { + u(0).domain(u(0).domain() | gamma); + } + else if (benchmark == " marmousi") { + u(37).domain(u(37).domain() | gamma); + } + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambda("lambda", gamma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + std::vector< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > gContinuous; + std::vector< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > * > gDiscontinuous; + for(unsigned int f = 0; f < 4; ++f) { + gContinuous.push_back(new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gC_" + dir[f], sigmaInterface[f], gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); + gDiscontinuous.push_back(new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gD_" + dir[f], sigmaInterface[f], gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder)); + } + + std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > gCornerPmlContinuous; + std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > * > > gCornerPmlDiscontinuous; + std::vector< std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > > gCornerHABC; + for(unsigned int f = 0; f < 4; ++f) { + gCornerPmlContinuous.push_back(std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[f] + dir[(f+1)%4] + "_first", pmlBndInterface[f].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[f] + dir[(f+1)%4] + "_second", pmlBndInterface[f].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder))); + gCornerPmlDiscontinuous.push_back(std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[f] + dir[(f+1)%4] + "_first", pmlBndInterface[f].first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[f] + dir[(f+1)%4] + "_second", pmlBndInterface[f].second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder))); + gCornerHABC.push_back(std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N)); + for(unsigned int n = 0; n < N; ++n) { + gCornerHABC[f][n] = std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[f] + dir[(f+1)%4] + "_" + std::to_string(n) + "_first", cornerInterface[f].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[f] + dir[(f+1)%4] + "_" + std::to_string(n) + "_second", cornerInterface[f].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); + } + } + + gmshddm::problem::Formulation< std::complex< double > > formulation("HelmholtzDDMScattering", topology); + + for(unsigned int f = 0; f < 4; ++f) { + formulation.addInterfaceField(*gContinuous[f]); + formulation.addInterfaceField(*gDiscontinuous[f]); + + // Pmls + formulation.addInterfaceField(*gCornerPmlContinuous[f].first); + formulation.addInterfaceField(*gCornerPmlContinuous[f].second); + formulation.addInterfaceField(*gCornerPmlDiscontinuous[f].first); + formulation.addInterfaceField(*gCornerPmlDiscontinuous[f].second); + + // HABC + for(unsigned int n = 0; n < N; ++n) { + formulation.addInterfaceField(*gCornerHABC[f][n].first); + formulation.addInterfaceField(*gCornerHABC[f][n].second); + } + } + + std::vector< std::vector< Subproblem * > > subproblem(nDomX); + for(unsigned int i = 0; i < nDomX; ++i) { + subproblem[i].resize(nDomY); + for(unsigned int j = 0; j < nDomY; ++j) { + unsigned int index = i * nDomY + j; + formulation(index).integral(-grad(dof(u(index))), grad(tf(u(index))), omega(index), gauss); + formulation(index).integral(kappa * kappa * dof(u(index)), tf(u(index)), omega(index), gauss); + + if(benchmark == "scattering") { + if(index == 0) { + formulation(index).integral(dof(lambda), tf(u(index)), gamma, gauss); + formulation(index).integral(dof(u(index)), tf(lambda), gamma, gauss); + formulation(index).integral(formulation.physicalSource(- fAnalytic), tf(lambda), gamma, gauss); + } + } + else if (benchmark == "marmousi") { + if(index == 37) { + formulation(index).integral(dof(lambda), tf(u(index)), gamma, gauss); + formulation(index).integral(dof(u(index)), tf(lambda), gamma, gauss); + formulation(index).integral(formulation.physicalSource(- 1.), tf(lambda), gamma, gauss); + } + } + + SubproblemDomains domains; + domains.setOmega(omega(index)); + domains.setSigma({ sigma[0](index), sigma[1](index), sigma[2](index), sigma[3](index) }); + domains.setPml({ pml[0](index), pml[1](index), pml[2](index), pml[3](index) }); + domains.setPmlBnd({ std::make_pair(pmlBnd[0].first(index), pmlBnd[0].second(index)), std::make_pair(pmlBnd[1].first(index), pmlBnd[1].second(index)), std::make_pair(pmlBnd[2].first(index), pmlBnd[2].second(index)), std::make_pair(pmlBnd[3].first(index), pmlBnd[3].second(index)) }); + domains.setPmlCorner({ pmlCorner[0](index), pmlCorner[1](index), pmlCorner[2](index), pmlCorner[3](index) }); + domains.setCorner({ corner[0](index), corner[1](index), corner[2](index), corner[3](index) }); + + SubproblemParameters parameters; + parameters.setGauss(gauss); + parameters.setKappa(kappa); + parameters.setNeumannOrder(neumannOrder); + parameters.setFieldOrder(fieldOrder); + parameters.setStab(stab * lc * lc); + + std::string bnd = boundary; + if(boundary == "habc") { + bnd += "_" + std::to_string(N) + "_" + std::to_string(thetaPade); + } + else if(boundary == "pml") { + if(pmlMethod == "continuous") { + bnd += "Continuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + else if(pmlMethod == "discontinuous") { + bnd += "Discontinuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + else if(pmlMethod == "withoutMultiplier") { + bnd += "WithoutMultiplier_" + std::to_string(pmlSize) + "_" + pmlType; + } + } + std::string bndExt = boundaryExt; + if(boundaryExt == "habc") { + bndExt += "_" + std::to_string(NExt) + "_" + std::to_string(thetaPade); + } + else if(boundaryExt == "pml") { + if(pmlMethodExt == "continuous") { + bndExt += "Continuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + else if(pmlMethodExt == "discontinuous") { + bndExt += "Discontinuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + else if(pmlMethodExt == "withoutMultiplier") { + bndExt += "WithoutMultiplier_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + } + gmshfem::msg::info << "Subdomain (" << i << ", " << j << ") has boundaries [" << (i == nDomX-1 ? bndExt : bnd) << ", " << (j == nDomY-1 ? bndExt : bnd) << ", " << (i == 0 ? bndExt : bnd) << ", " << (j == 0 ? bndExt : bnd) << "]" << gmshfem::msg::endl; + subproblem[i][j] = new Subproblem(formulation(index), u(index).name(), domains, parameters, (i == nDomX-1 ? bndExt : bnd), (j == nDomY-1 ? bndExt : bnd), (i == 0 ? bndExt : bnd), (j == 0 ? bndExt : bnd)); + subproblem[i][j]->writeFormulation(); + + // coupling + for(unsigned int b = 0; b < 4; ++b) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Boundary *boundary = subproblem[i][j]->getBoundary(b); + if(dynamic_cast< Sommerfeld * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[(b+2)%4])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(dynamic_cast< HABC * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[(b+2)%4])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(dynamic_cast< PmlContinuous * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[(b+2)%4])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(dynamic_cast< PmlDiscontinuous * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - gmshfem::function::normal< std::complex< double > >() * (*gDiscontinuous[(b+2)%4])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(dynamic_cast< PmlWithoutMultiplier * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[(b+2)%4])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + } + } + + for(unsigned int c = 0; c < 4; ++c) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Corner *corner = subproblem[i][j]->getCorner(c); + if(corner == nullptr) { + continue; + } + if(auto cr = dynamic_cast< HABC_HABC * >(corner)) { + if(!cornerInterface[c].first(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf(*cr->firstBoundary()->getUHABC(n)), cornerInterface[c].first(index, jndex), gauss); + } + } + if(!cornerInterface[c].second(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf(*cr->secondBoundary()->getUHABC(n)), cornerInterface[c].second(index, jndex), gauss); + } + } + } + else if(auto cr = dynamic_cast< PmlContinuous_PmlContinuous * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf(*cr->firstBoundary()->getUPml()), pmlBndInterface[c].first(index, jndex), gauss); + } + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf(*cr->secondBoundary()->getUPml()), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlDiscontinuous_PmlDiscontinuous * >(corner)) { + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - n * (*gCornerPmlDiscontinuous[(c-1)%4].second)(jndex, index) ), tf(*cr->firstBoundary()->getUPml()), pmlBndInterface[c].first(index, jndex), gauss); + } + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - n * (*gCornerPmlDiscontinuous[(c+1)%4].first)(jndex, index) ), tf(*cr->secondBoundary()->getUPml()), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlWithoutMultiplier_PmlWithoutMultiplier * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf(*cr->firstBoundary()->getUPml()), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf(*cr->firstBoundary()->getV()), pmlBndInterface[c].first(index, jndex), gauss); + } + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf(*cr->secondBoundary()->getUPml()), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf(*cr->secondBoundary()->getV()), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlContinuous_Sommerfeld * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf(*cr->firstBoundary()->getUPml()), pmlBndInterface[c].first(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< Sommerfeld_PmlContinuous * >(corner)) { + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf(*cr->secondBoundary()->getUPml()), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlDiscontinuous_Sommerfeld * >(corner)) { + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - n * (*gCornerPmlDiscontinuous[(c-1)%4].second)(jndex, index) ), tf(*cr->firstBoundary()->getUPml()), pmlBndInterface[c].first(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< Sommerfeld_PmlDiscontinuous * >(corner)) { + gmshfem::function::VectorFunction< std::complex< double > > n = gmshfem::function::normal< std::complex< double > >(); + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - n * (*gCornerPmlDiscontinuous[(c+1)%4].first)(jndex, index) ), tf(*cr->secondBoundary()->getUPml()), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< HABC_Sommerfeld * >(corner)) { + if(!cornerInterface[c].first(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf(*cr->firstBoundary()->getUHABC(n)), cornerInterface[c].first(index, jndex), gauss); + } + } + } + else if(auto cr = dynamic_cast< Sommerfeld_HABC * >(corner)) { + if(!cornerInterface[c].second(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf(*cr->secondBoundary()->getUHABC(n)), cornerInterface[c].second(index, jndex), gauss); + } + } + } + } + } + + // interface + for(unsigned int b = 0; b < 4; ++b) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Boundary *boundary = subproblem[i][j]->getBoundary(b); + if(auto bnd = dynamic_cast< Sommerfeld * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[(b+2)%4])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(auto bnd = dynamic_cast< HABC * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[(b+2)%4])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(auto bnd = dynamic_cast< PmlContinuous * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[(b+2)%4])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(auto bnd = dynamic_cast< PmlDiscontinuous * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gDiscontinuous[b])(index, jndex)), tf((*gDiscontinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gDiscontinuous[(b+2)%4])(jndex, index) ), tf((*gDiscontinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gDiscontinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(auto bnd = dynamic_cast< PmlWithoutMultiplier * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[(b+2)%4])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + } + } + + for(unsigned int c = 0; c < 4; ++c) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Corner *corner = subproblem[i][j]->getCorner(c); + if(corner == nullptr) { + continue; + } + if(auto cr = dynamic_cast< HABC_HABC * >(corner)) { + if(!cornerInterface[c].first(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gCornerHABC[c][n].first)(index, jndex)), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n, 0), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss); + } + } + if(!cornerInterface[c].second(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gCornerHABC[c][n].second)(index, jndex)), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n, 1), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss); + } + } + } + else if(auto cr = dynamic_cast< PmlContinuous_PmlContinuous * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlContinuous[c].first)(index, jndex)), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(0), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + } + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlContinuous[c].second)(index, jndex)), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(1), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlDiscontinuous_PmlDiscontinuous * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlDiscontinuous[c].first)(index, jndex)), tf((*gCornerPmlDiscontinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlDiscontinuous[(c-1)%4].second)(jndex, index) ), tf((*gCornerPmlDiscontinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(0), tf((*gCornerPmlDiscontinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + } + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlDiscontinuous[c].second)(index, jndex)), tf((*gCornerPmlDiscontinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlDiscontinuous[(c+1)%4].first)(jndex, index) ), tf((*gCornerPmlDiscontinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(1), tf((*gCornerPmlDiscontinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlWithoutMultiplier_PmlWithoutMultiplier * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlContinuous[c].first)(index, jndex)), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(0), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + } + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlContinuous[c].second)(index, jndex)), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(1), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlContinuous_Sommerfeld * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlContinuous[c].first)(index, jndex)), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlContinuous[(c-1)%4].second)(jndex, index) ), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(), tf((*gCornerPmlContinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< Sommerfeld_PmlContinuous * >(corner)) { + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlContinuous[c].second)(index, jndex)), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlContinuous[(c+1)%4].first)(jndex, index) ), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(), tf((*gCornerPmlContinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< PmlDiscontinuous_Sommerfeld * >(corner)) { + if(!pmlBndInterface[c].first(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlDiscontinuous[c].first)(index, jndex)), tf((*gCornerPmlDiscontinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlDiscontinuous[(c-1)%4].second)(jndex, index) ), tf((*gCornerPmlDiscontinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(), tf((*gCornerPmlDiscontinuous[c].first)(index, jndex)), pmlBndInterface[c].first(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< Sommerfeld_PmlDiscontinuous * >(corner)) { + if(!pmlBndInterface[c].second(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gCornerPmlDiscontinuous[c].second)(index, jndex)), tf((*gCornerPmlDiscontinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerPmlDiscontinuous[(c+1)%4].first)(jndex, index) ), tf((*gCornerPmlDiscontinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(), tf((*gCornerPmlDiscontinuous[c].second)(index, jndex)), pmlBndInterface[c].second(index, jndex), gauss); + } + } + else if(auto cr = dynamic_cast< HABC_Sommerfeld * >(corner)) { + if(!cornerInterface[c].first(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gCornerHABC[c][n].first)(index, jndex)), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c-1)%4][n].second)(jndex, index) ), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n), tf((*gCornerHABC[c][n].first)(index, jndex)), cornerInterface[c].first(index, jndex), gauss); + } + } + } + else if(auto cr = dynamic_cast< Sommerfeld_HABC * >(corner)) { + if(!cornerInterface[c].second(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gCornerHABC[c][n].second)(index, jndex)), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gCornerHABC[(c+1)%4][n].first)(jndex, index) ), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n), tf((*gCornerHABC[c][n].second)(index, jndex)), cornerInterface[c].second(index, jndex), gauss); + } + } + } + } + } + } + } + + gmshfem::common::Timer pre = formulation.pre(); + gmshfem::common::Timer solve = formulation.solve("gmres", res, iterMax); + + for(unsigned int i = 0; i < nDomX; ++i) { + for(unsigned int j = 0; j < nDomY; ++j) { + unsigned int index = i * nDomY + j; + if(gmshddm::mpi::isItMySubdomain(index)) { + if(saveU) { + gmshfem::post::save(u(index), omega(index), "u_" + std::to_string(index), "msh"); + } + } + } + } + + if(monoDomainError) { + gmshfem::problem::Formulation< std::complex< double > > formulationMono("HelmholtzMonoDomain"); + + std::vector< gmshfem::domain::Domain > sigmaMono(4); + std::vector< gmshfem::domain::Domain > pmlMono(4); + std::vector< gmshfem::domain::Domain > pmlCornerMono(4); + std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > pmlBndMono(4); + std::vector< gmshfem::domain::Domain > cornerMono(4); + for(unsigned int i = 0; i < nDomX; ++i) { + sigmaMono[1] |= sigma[1](i * nDomY + nDomY - 1); + sigmaMono[3] |= sigma[3](i * nDomY); + + pmlMono[1] |= pml[1](i * nDomY + nDomY - 1); + pmlMono[3] |= pml[3](i * nDomY); + } + + for(unsigned int i = 0; i < nDomY; ++i) { + sigmaMono[0] |= sigma[0](i + (nDomX - 1) * nDomY); + sigmaMono[2] |= sigma[2](i); + + pmlMono[0] |= pml[0](i + (nDomX - 1) * nDomY); + pmlMono[2] |= pml[2](i); + } + + pmlCornerMono[0] = pmlCorner[0](nDomX * nDomY - 1); + pmlCornerMono[1] = pmlCorner[1](nDomY - 1); + pmlCornerMono[2] = pmlCorner[2](0); + pmlCornerMono[3] = pmlCorner[3]((nDomX - 1) * nDomY); + + pmlBndMono[0] = std::make_pair( pmlBnd[0].first(nDomX * nDomY - 1), pmlBnd[0].second(nDomX * nDomY - 1) ); + pmlBndMono[1] = std::make_pair( pmlBnd[1].first(nDomY - 1), pmlBnd[1].second(nDomY - 1) ); + pmlBndMono[2] = std::make_pair( pmlBnd[2].first(0), pmlBnd[2].second(0) ); + pmlBndMono[3] = std::make_pair( pmlBnd[3].first((nDomX - 1) * nDomY), pmlBnd[3].second((nDomX - 1) * nDomY) ); + + cornerMono[0] = corner[0](nDomX * nDomY - 1); + cornerMono[1] = corner[1](nDomY - 1); + cornerMono[2] = corner[2](0); + cornerMono[3] = corner[3]((nDomX - 1) * nDomY); + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > uMono("uMono", omega.getUnion(), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambdaMono("lamdbaMono", gamma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + formulationMono.integral(-grad(dof(uMono)), grad(tf(uMono)), omega.getUnion(), gauss); + formulationMono.integral(kappa * kappa * dof(uMono), tf(uMono), omega.getUnion(), gauss); + + formulationMono.integral(dof(lambda), tf(uMono), gamma, gauss); + formulationMono.integral(dof(uMono), tf(lambda), gamma, gauss); + if(benchmark == "scattering") { + formulationMono.integral(- fAnalytic, tf(lambda), gamma, gauss); + } + else if (benchmark == "marmousi") { + formulationMono.integral(- 1., tf(lambda), gamma, gauss); + } + + SubproblemDomains domains; + domains.setOmega(omega.getUnion()); + domains.setSigma(sigmaMono); + domains.setPml(pmlMono); + domains.setPmlBnd(pmlBndMono); + domains.setPmlCorner(pmlCornerMono); + domains.setCorner(cornerMono); + + SubproblemParameters parameters; + parameters.setGauss(gauss); + parameters.setKappa(kappa); + parameters.setNeumannOrder(neumannOrder); + parameters.setFieldOrder(fieldOrder); + parameters.setStab(stab * lc); + + std::string bndExt = boundaryExt; + if(boundaryExt == "habc") { + bndExt += "_" + std::to_string(NExt) + "_" + std::to_string(thetaPade); + } + else if(boundaryExt == "pml") { + if(pmlMethodExt == "continuous") { + bndExt += "Continuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + else if(pmlMethodExt == "discontinuous") { + bndExt += "Discontinuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + else if(pmlMethodExt == "withoutMultiplier") { + bndExt += "WithoutMultiplier_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + } + gmshfem::msg::info << "Monodomain has boundaries [" << bndExt << ", " << bndExt << ", " << bndExt << ", " << bndExt << "]" << gmshfem::msg::endl; + Subproblem subproblem(formulationMono, uMono.name(), domains, parameters, bndExt, bndExt, bndExt, bndExt); + subproblem.writeFormulation(); + + formulationMono.pre(); + formulationMono.assemble(); + formulationMono.solve(); + + double num = 0.; + double den = 0.; + for(unsigned int i = 0; i < nDomX * nDomY; ++i) { + num += std::real(gmshfem::post::integrate(pow(abs(u(i) - uMono), 2), omega(i), gauss)); + den += std::real(gmshfem::post::integrate(pow(abs(uMono), 2), omega(i), gauss)); + } + + gmshfem::msg::info << "Error mono L2 = " << std::sqrt(num/den) << gmshfem::msg::endl; + + for(unsigned int i = 0; i < nDomX * nDomY; ++i) { + if(gmshddm::mpi::isItMySubdomain(i)) { + if(saveEMono) { + gmshfem::post::save(u(i) - uMono, omega(i), "eMono_" + std::to_string(i)); + } + if(saveUMono) { + gmshfem::post::save(uMono, omega(i), "uMono_" + std::to_string(i)); + } + } + } + + if(fileName != "none") { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << iterMax << formulation.relativeResidual().back() << std::sqrt(num/den) << gmshfem::csv::endl; + file.close(); + } + } + + if(analyticError) { + double num = 0., den = 0.; + for(unsigned int i = 0; i < nDomX * nDomY; ++i) { + if(gmshddm::mpi::isItMySubdomain(i)) { + num += std::real(gmshfem::post::integrate(pow(abs(u(i) - fAnalytic), 2), omega(i), gauss)); + den += std::real(gmshfem::post::integrate(pow(abs(fAnalytic), 2), omega(i), gauss)); + } + if(saveE){ + gmshfem::post::save(u(i) - fAnalytic, omega(i), "e_" + std::to_string(i), "msh"); + } + } + gmshfem::msg::info << "Error L2 = " << std::sqrt(num/den) << gmshfem::msg::endl; + gmshfem::common::CSVio file("results", ';', gmshfem::common::OpeningMode::Append); + file << N << std::sqrt(num/den) << pre+solve << gmshfem::csv::endl; + file.close(); + } + + if(wavenumberPlot) { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << k << formulation.relativeResidual().size()-1 << gmshfem::csv::endl; + file.close(); + } + + if(meshPlot) { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << (2*pi/k)/lc << lc << 1./lc << formulation.relativeResidual().size()-1 << gmshfem::csv::endl; + file.close(); + } + + for(unsigned int i = 0; i < nDomX; ++i) { + for(unsigned int j = 0; j < nDomY; ++j) { + delete subproblem[i][j]; + } + } + + for(unsigned int f = 0; f < 4; ++f) { + delete gContinuous[f]; + delete gDiscontinuous[f]; + delete gCornerPmlContinuous[f].first; + delete gCornerPmlContinuous[f].second; + delete gCornerPmlDiscontinuous[f].first; + delete gCornerPmlDiscontinuous[f].second; + for(unsigned int n = 0; n < N; ++n) { + delete gCornerHABC[f][n].first; + delete gCornerHABC[f][n].second; + } + } + } + + +} diff --git a/examples/helmholtz/crossPoints/ddm2D.h b/examples/helmholtz/crossPoints/ddm2D.h new file mode 100755 index 0000000000000000000000000000000000000000..9abe8f5ebb3aedad8668dea9a9d37cc0125c8893 --- /dev/null +++ b/examples/helmholtz/crossPoints/ddm2D.h @@ -0,0 +1,11 @@ +#ifndef H_DDM2D +#define H_DDM2D + +namespace D2 { + + void ddm(); + +} + + +#endif // H_DDM2D diff --git a/examples/helmholtz/crossPoints/ddm3D.cpp b/examples/helmholtz/crossPoints/ddm3D.cpp new file mode 100755 index 0000000000000000000000000000000000000000..fee4a3f8635091ce5e492346bb4227fb6533b20a --- /dev/null +++ b/examples/helmholtz/crossPoints/ddm3D.cpp @@ -0,0 +1,1412 @@ +#include "ddm3D.h" + +#include "mesh.h" +#include "SubproblemDomains.h" +#include "Subproblem3D.h" + +#include <gmshfem/GmshFem.h> +#include <gmshfem/FieldInterface.h> +#include <gmshfem/Formulation.h> +#include <gmshfem/AnalyticalFunction.h> +#include <gmshfem/Post.h> +#include <gmshfem/Function.h> +#include <gmshfem/io.h> + +#include <gmshddm/GmshDdm.h> +#include <gmshddm/Subdomain.h> +#include <gmshddm/Interface.h> +#include <gmshddm/SubdomainField.h> +#include <gmshddm/InterfaceField.h> +#include <gmshddm/Formulation.h> +#include <gmshddm/MPIInterface.h> + +#include <algorithm> +#include <fstream> +#include <vector> + +using gmshfem::equation::dof; +using gmshfem::equation::tf; +using gmshfem::function::operator-; +using gmshfem::function::operator*; +using gmshfem::function::abs; + +namespace D3 { + + + void ddm() + { + gmshddm::common::GmshDdm *gmshDdm = gmshddm::common::GmshDdm::currentInstance(); + + // ************************ + // P H Y S I C S + // ************************ + double pi = 3.14159265359; + double k = 2. * pi; + gmshDdm->userDefinedParameter(k, "k"); + double R = 0.5; + gmshDdm->userDefinedParameter(R, "R"); + std::string benchmark = "scattering"; // scattering + gmshDdm->userDefinedParameter(benchmark, "benchmark"); + + // ************************ + // M E S H + // ************************ + double lc = 0.1; // other = 0.06666666666666 + gmshDdm->userDefinedParameter(lc, "lc"); + int meshOrder = 1; + gmshDdm->userDefinedParameter(meshOrder, "meshOrder"); + + // ************************ + // M O D E L I N G + // ************************ + std::string boundary = "sommerfeld"; // sommerfeld, pml, habc + gmshDdm->userDefinedParameter(boundary, "boundary"); + std::string boundaryExt = "sommerfeld"; // sommerfeld, pml, habc + gmshDdm->userDefinedParameter(boundaryExt, "boundaryExt"); + std::string pmlMethod = "continuous"; // continuous, discontinuous + gmshDdm->userDefinedParameter(pmlMethod, "pmlMethod"); + std::string pmlMethodExt = "continuous"; // continuous, discontinuous + gmshDdm->userDefinedParameter(pmlMethodExt, "pmlMethodExt"); + std::string pmlType = "hs"; // hs, h, q + gmshDdm->userDefinedParameter(pmlType, "pmlType"); + std::string pmlTypeExt = "hs"; // hs, h, q + gmshDdm->userDefinedParameter(pmlTypeExt, "pmlTypeExt"); + + + unsigned int nDomX = 2, nDomY = 2, nDomZ = 2; + gmshDdm->userDefinedParameter(nDomX, "nDomX"); + gmshDdm->userDefinedParameter(nDomY, "nDomY"); + gmshDdm->userDefinedParameter(nDomZ, "nDomZ"); + unsigned int iterMax = 1000; + gmshDdm->userDefinedParameter(iterMax, "iterMax"); + double res = 1e-6; + gmshDdm->userDefinedParameter(res, "res"); + double sizeX = 2., sizeY = 2., sizeZ = 2.; + gmshDdm->userDefinedParameter(sizeX, "sizeX"); + gmshDdm->userDefinedParameter(sizeY, "sizeY"); + gmshDdm->userDefinedParameter(sizeZ, "sizeZ"); + + unsigned int N = 6; + gmshDdm->userDefinedParameter(N, "N"); + double pmlSize = N * lc; + if(pmlSize == 0.) { + pmlSize = 0.3; + } + + unsigned int NExt = N; + gmshDdm->userDefinedParameter(NExt, "NExt"); + double pmlSizeExt = NExt * lc; + if(pmlSizeExt == 0.) { + pmlSizeExt = 0.3; + } + + std::string gauss = "Gauss10"; + gmshDdm->userDefinedParameter(gauss, "gauss"); + int fieldOrder = 1; + gmshDdm->userDefinedParameter(fieldOrder, "fieldOrder"); + int neumannOrder = 1; + gmshDdm->userDefinedParameter(neumannOrder, "neumannOrder"); + double stab = 0.11; + gmshDdm->userDefinedParameter(stab, "stab"); + double thetaPade = 0.; + gmshDdm->userDefinedParameter(thetaPade, "thetaPade"); + thetaPade *= pi; + + // ************************ + // P O S T + // ************************ + bool onPlane = false; + gmshDdm->userDefinedParameter(onPlane, "onPlane"); + bool monoDomainError = false; + gmshDdm->userDefinedParameter(monoDomainError, "monoDomainError"); + std::string fileName = "none"; + gmshDdm->userDefinedParameter(fileName, "file"); + bool saveEMono = false; + gmshDdm->userDefinedParameter(saveEMono, "saveEMono"); + bool saveUMono = false; + gmshDdm->userDefinedParameter(saveUMono, "saveUMono"); + bool saveU = false; + gmshDdm->userDefinedParameter(saveU, "saveU"); + bool wavenumberPlot = false; + gmshDdm->userDefinedParameter(wavenumberPlot, "wavenumber"); + bool meshPlot = false; + gmshDdm->userDefinedParameter(meshPlot, "mesh"); + bool saveMesh = false; + gmshDdm->userDefinedParameter(saveMesh, "saveMesh"); + + if(benchmark == "scattering") { + checkerboard(nDomX, nDomY, nDomZ, sizeX, sizeY, sizeZ, R, lc, (boundary == "pml"), pmlSize, (boundaryExt == "pml"), pmlSizeExt, meshOrder, 0, 0, 0); + } + if(saveMesh) { + gmsh::write("mesh.msh"); + } + + gmshfem::msg::info << "Running 'ddm3D'" << gmshfem::msg::endl; + gmshfem::msg::info << "Parameters:" << gmshfem::msg::endl; + gmshfem::msg::info << " * physics:" << gmshfem::msg::endl; + gmshfem::msg::info << " - k: " << k << " (" << k/pi << "*pi" << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - R: " << R << gmshfem::msg::endl; + gmshfem::msg::info << " * mesh:" << gmshfem::msg::endl; + gmshfem::msg::info << " - lc: " << lc << " (eta_h = " << (2*pi/k)/lc << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - meshOrder: " << meshOrder << gmshfem::msg::endl; + gmshfem::msg::info << " * modeling:" << gmshfem::msg::endl; + gmshfem::msg::info << " - grid: (" << nDomX << ", " << nDomY << ", " << nDomZ << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - iterMax: " << iterMax << gmshfem::msg::endl; + gmshfem::msg::info << " - res: " << res << gmshfem::msg::endl; + gmshfem::msg::info << " - subdomain size: (" << sizeX << ", " << sizeY << ", " << sizeZ << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - boundary: " << boundary << gmshfem::msg::endl; + gmshfem::msg::info << " - boundaryExt: " << boundaryExt << gmshfem::msg::endl; + if(boundary == "pml") { + gmshfem::msg::info << " - N: " << N << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlSize: " << pmlSize << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlType: " << pmlType << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlMethod: " << pmlMethod << gmshfem::msg::endl; + } + else if(boundary == "habc") { + gmshfem::msg::info << " - N: " << N << gmshfem::msg::endl; + gmshfem::msg::info << " - thetaPade: " << thetaPade << " (" << thetaPade/pi << "*pi" << ")" << gmshfem::msg::endl; + } + if(boundaryExt == "pml") { + gmshfem::msg::info << " - NExt: " << NExt << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlSizeExt: " << pmlSizeExt << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlTypeExt: " << pmlTypeExt << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlMethodExt: " << pmlMethodExt << gmshfem::msg::endl; + } + else if(boundaryExt == "habc") { + gmshfem::msg::info << " - NExt: " << NExt << gmshfem::msg::endl; + } + gmshfem::msg::info << " - gauss: " << gauss << gmshfem::msg::endl; + gmshfem::msg::info << " - fieldOrder: " << fieldOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - neumannOrder: " << neumannOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - stab: " << stab << gmshfem::msg::endl; + + + // source + gmshfem::analytics::AnalyticalFunction< gmshfem::analytics::helmholtz3D::ScatteringByASoftSphere< std::complex< double > > > fAnalytic(k, R, sizeX/2., sizeY/2., sizeZ/2., 2 * k); + + const unsigned int nDom = nDomX * nDomY * nDomZ; + // Define domain + gmshddm::domain::Subdomain omega(nDom); + gmshfem::domain::Domain gamma; + if(benchmark == "scattering") { + gamma = gmshfem::domain::Domain("gamma"); + } + + std::vector< gmshddm::domain::Subdomain > pml(6, nDom); + std::vector< gmshddm::domain::Subdomain > pmlEdge(12, nDom); + std::vector< gmshddm::domain::Subdomain > pmlCorner(8, nDom); + std::vector< gmshddm::domain::Subdomain > sigma(6, nDom); + std::vector< gmshddm::domain::Interface > sigmaInterface(6, nDom); + std::vector< std::pair< gmshddm::domain::Subdomain, gmshddm::domain::Subdomain > > pmlBnd(12, std::make_pair(gmshddm::domain::Subdomain(nDom), gmshddm::domain::Subdomain(nDom)) ); + std::vector< std::pair< gmshddm::domain::Interface, gmshddm::domain::Interface > > pmlBndInterface(12, std::make_pair(gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom)) ); + std::vector< std::tuple< gmshddm::domain::Subdomain, gmshddm::domain::Subdomain, gmshddm::domain::Subdomain > > pmlEdgeBnd(8, std::make_tuple(gmshddm::domain::Subdomain(nDom), gmshddm::domain::Subdomain(nDom), gmshddm::domain::Subdomain(nDom)) ); + std::vector< std::tuple< gmshddm::domain::Interface, gmshddm::domain::Interface, gmshddm::domain::Interface > > pmlEdgeBndInterface(8, std::make_tuple(gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom)) ); + + std::vector< gmshddm::domain::Subdomain > edge(12, nDom); + std::vector< std::pair< gmshddm::domain::Interface, gmshddm::domain::Interface > > edgeInterface(12, std::make_pair(gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom)) ); + std::vector< gmshddm::domain::Subdomain > corner(8, nDom); + std::vector< std::tuple< gmshddm::domain::Interface, gmshddm::domain::Interface, gmshddm::domain::Interface > > cornerInterface(8, std::make_tuple(gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom), gmshddm::domain::Interface(nDom)) ); + std::vector< std::tuple< gmshddm::domain::Subdomain, gmshddm::domain::Subdomain, gmshddm::domain::Subdomain > > cornerEdge(8, std::make_tuple(gmshddm::domain::Subdomain(nDom), gmshddm::domain::Subdomain(nDom), gmshddm::domain::Subdomain(nDom))); + // Define topology + std::vector< std::vector< unsigned int > > topology(nDom); + std::vector< std::string > dir {"E", "N", "W", "S", "D", "U"}; + for(unsigned int i = 0; i < static_cast< unsigned int >(nDomX); ++i) { + for(unsigned int j = 0; j < static_cast< unsigned int >(nDomY); ++j) { + for(unsigned int k = 0; k < static_cast< unsigned int >(nDomZ); ++k) { + unsigned int index = i * nDomZ * nDomY + j * nDomZ + k; + + const std::string subdomainTag = "_" + std::to_string(i) + "_" + std::to_string(j) + "_" + std::to_string(k); + omega(index) = gmshfem::domain::Domain("omega" + subdomainTag); + + for(unsigned int b = 0; b < 6; ++b) { + if(boundary == "pml" || boundaryExt == "pml") { + pml[b](index) = gmshfem::domain::Domain("pml" + dir[b] + subdomainTag); + } + sigma[b](index) = gmshfem::domain::Domain("sigma" + dir[b] + subdomainTag); + } + + for(unsigned int e = 0; e < 12; ++e) { + std::vector< std::string > count {"first", "second", "third", "fourth"}; + if(e < 4) { + if(boundary == "pml" || boundaryExt == "pml") { + pmlEdge[e](index) = gmshfem::domain::Domain("pml" + dir[e%4] + "D" + subdomainTag); + pmlBnd[e].first(index) = gmshfem::domain::Domain("pmlBnd" + dir[e%4] + "_first" + subdomainTag); + pmlBnd[e].second(index) = gmshfem::domain::Domain("pmlBndD_" + count[e%4] + subdomainTag); + } + edge[e](index) = gmshfem::domain::Domain("edge" + dir[e%4] + "D" + subdomainTag); + } + else if(e >= 4 && e < 8) { + if(boundary == "pml" || boundaryExt == "pml") { + pmlEdge[e](index) = gmshfem::domain::Domain("pml" + dir[e%4] + dir[(e+1)%4] + subdomainTag); + pmlBnd[e].first(index) = gmshfem::domain::Domain("pmlBnd" + dir[e%4] + "_second" + subdomainTag); + pmlBnd[e].second(index) = gmshfem::domain::Domain("pmlBnd" + dir[(e+1)%4] + "_fourth" + subdomainTag); + } + edge[e](index) = gmshfem::domain::Domain("edge" + dir[e%4] + dir[(e+1)%4] + subdomainTag); + } + else { + if(boundary == "pml" || boundaryExt == "pml") { + pmlEdge[e](index) = gmshfem::domain::Domain("pml" + dir[e%4] + "U" + subdomainTag); + pmlBnd[e].first(index) = gmshfem::domain::Domain("pmlBnd" + dir[e%4] + "_third" + subdomainTag); + pmlBnd[e].second(index) = gmshfem::domain::Domain("pmlBndU_" + count[e%4] + subdomainTag); + } + edge[e](index) = gmshfem::domain::Domain("edge" + dir[e%4] + "U" + subdomainTag); + } + } + + for(unsigned int c = 0; c < 8; ++c) { + if(c < 4) { + if(boundary == "pml" || boundaryExt == "pml") { + pmlCorner[c](index) = gmshfem::domain::Domain("pml" + dir[c%4] + dir[(c+1)%4] + "D" + subdomainTag); + + std::get<0>(pmlEdgeBnd[c])(index) = gmshfem::domain::Domain("pmlBnd" + dir[c%4] + "D_second" + subdomainTag); + std::get<1>(pmlEdgeBnd[c])(index) = gmshfem::domain::Domain("pmlBnd" + dir[(c+1)%4] + "D_first" + subdomainTag); + std::get<2>(pmlEdgeBnd[c])(index) = gmshfem::domain::Domain("pmlBnd" + dir[c%4] + dir[(c+1)%4] + "_first" + subdomainTag); + + std::get<0>(cornerEdge[c])(index) = gmshfem::domain::Domain("cornerEdge" + dir[c%4] + dir[(c+1)%4] + "D_first" + subdomainTag); + std::get<1>(cornerEdge[c])(index) = gmshfem::domain::Domain("cornerEdge" + dir[c%4] + dir[(c+1)%4] + "D_second" + subdomainTag); + std::get<2>(cornerEdge[c])(index) = gmshfem::domain::Domain("cornerEdge" + dir[c%4] + dir[(c+1)%4] + "D_third" + subdomainTag); + } + corner[c](index) = gmshfem::domain::Domain("corner" + dir[c%4] + dir[(c+1)%4] + "D" + subdomainTag); + } + else { + if(boundary == "pml" || boundaryExt == "pml") { + pmlCorner[c](index) = gmshfem::domain::Domain("pml" + dir[c%4] + dir[(c+1)%4] + "U" + subdomainTag); + + std::get<0>(pmlEdgeBnd[c])(index) = gmshfem::domain::Domain("pmlBnd" + dir[c%4] + "U_second" + subdomainTag); + std::get<1>(pmlEdgeBnd[c])(index) = gmshfem::domain::Domain("pmlBnd" + dir[(c+1)%4] + "U_first" + subdomainTag); + std::get<2>(pmlEdgeBnd[c])(index) = gmshfem::domain::Domain("pmlBnd" + dir[c%4] + dir[(c+1)%4] + "_second" + subdomainTag); + + std::get<0>(cornerEdge[c])(index) = gmshfem::domain::Domain("cornerEdge" + dir[c%4] + dir[(c+1)%4] + "U_first" + subdomainTag); + std::get<1>(cornerEdge[c])(index) = gmshfem::domain::Domain("cornerEdge" + dir[c%4] + dir[(c+1)%4] + "U_second" + subdomainTag); + std::get<2>(cornerEdge[c])(index) = gmshfem::domain::Domain("cornerEdge" + dir[c%4] + dir[(c+1)%4] + "U_third" + subdomainTag); + } + corner[c](index) = gmshfem::domain::Domain("corner" + dir[c%4] + dir[(c+1)%4] + "U" + subdomainTag); + } + } + + if(i != static_cast< unsigned int >(nDomX) - 1) { // E + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[0].second(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[0].second(index); + pmlBndInterface[4].second(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[4].second(index); + pmlBndInterface[8].second(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[8].second(index); + pmlBndInterface[7].first(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[7].first(index); + + std::get<1>(pmlEdgeBndInterface[0])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = std::get<1>(pmlEdgeBnd[0])(index); + std::get<1>(pmlEdgeBndInterface[4])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = std::get<1>(pmlEdgeBnd[4])(index); + std::get<0>(pmlEdgeBndInterface[7])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = std::get<0>(pmlEdgeBnd[7])(index); + std::get<0>(pmlEdgeBndInterface[3])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = std::get<0>(pmlEdgeBnd[3])(index); + + } + sigmaInterface[0](index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = sigma[0](index); + + edgeInterface[0].second(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = edge[0](index); + edgeInterface[4].second(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = edge[4](index); + edgeInterface[8].second(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = edge[8](index); + edgeInterface[7].first(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = edge[7](index); + + std::get<1>(cornerInterface[0])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = corner[0](index); + std::get<1>(cornerInterface[4])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = corner[4](index); + std::get<0>(cornerInterface[7])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = corner[7](index); + std::get<0>(cornerInterface[3])(index, (i+1) * nDomY * nDomZ + j * nDomZ + k) = corner[3](index); + + topology[index].push_back((i+1) * nDomY * nDomZ + j * nDomZ + k); + } + + if(j != static_cast< unsigned int >(nDomY) - 1) { // N + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[1].second(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = pmlBnd[1].second(index); + pmlBndInterface[5].second(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = pmlBnd[5].second(index); + pmlBndInterface[9].second(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = pmlBnd[9].second(index); + pmlBndInterface[4].first(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = pmlBnd[4].first(index); + + std::get<1>(pmlEdgeBndInterface[1])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = std::get<1>(pmlEdgeBnd[1])(index); + std::get<1>(pmlEdgeBndInterface[5])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = std::get<1>(pmlEdgeBnd[5])(index); + std::get<0>(pmlEdgeBndInterface[4])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = std::get<0>(pmlEdgeBnd[4])(index); + std::get<0>(pmlEdgeBndInterface[0])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = std::get<0>(pmlEdgeBnd[0])(index); + } + sigmaInterface[1](index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = sigma[1](index); + + edgeInterface[1].second(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = edge[1](index); + edgeInterface[5].second(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = edge[5](index); + edgeInterface[9].second(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = edge[9](index); + edgeInterface[4].first(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = edge[4](index); + + std::get<1>(cornerInterface[1])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = corner[1](index); + std::get<1>(cornerInterface[5])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = corner[5](index); + std::get<0>(cornerInterface[4])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = corner[4](index); + std::get<0>(cornerInterface[0])(index, i * nDomY * nDomZ + (j+1) * nDomZ + k) = corner[0](index); + + topology[index].push_back(i * nDomY * nDomZ + (j+1) * nDomZ + k); + } + + if(i != 0) { // W + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[2].second(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[2].second(index); + pmlBndInterface[6].second(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[6].second(index); + pmlBndInterface[10].second(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[10].second(index); + pmlBndInterface[5].first(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = pmlBnd[5].first(index); + + std::get<1>(pmlEdgeBndInterface[2])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = std::get<1>(pmlEdgeBnd[2])(index); + std::get<1>(pmlEdgeBndInterface[6])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = std::get<1>(pmlEdgeBnd[6])(index); + std::get<0>(pmlEdgeBndInterface[5])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = std::get<0>(pmlEdgeBnd[5])(index); + std::get<0>(pmlEdgeBndInterface[1])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = std::get<0>(pmlEdgeBnd[1])(index); + } + sigmaInterface[2](index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = sigma[2](index); + + edgeInterface[2].second(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = edge[2](index); + edgeInterface[6].second(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = edge[6](index); + edgeInterface[10].second(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = edge[10](index); + edgeInterface[5].first(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = edge[5](index); + + std::get<1>(cornerInterface[2])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = corner[2](index); + std::get<1>(cornerInterface[6])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = corner[6](index); + std::get<0>(cornerInterface[5])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = corner[5](index); + std::get<0>(cornerInterface[1])(index, (i-1) * nDomY * nDomZ + j * nDomZ + k) = corner[1](index); + + topology[index].push_back((i-1) * nDomY * nDomZ + j * nDomZ + k); + } + + if(j != 0) { // S + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[3].second(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = pmlBnd[3].second(index); + pmlBndInterface[7].second(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = pmlBnd[7].second(index); + pmlBndInterface[11].second(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = pmlBnd[11].second(index); + pmlBndInterface[6].first(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = pmlBnd[6].first(index); + + std::get<1>(pmlEdgeBndInterface[3])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = std::get<1>(pmlEdgeBnd[3])(index); + std::get<1>(pmlEdgeBndInterface[7])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = std::get<1>(pmlEdgeBnd[7])(index); + std::get<0>(pmlEdgeBndInterface[6])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = std::get<0>(pmlEdgeBnd[6])(index); + std::get<0>(pmlEdgeBndInterface[2])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = std::get<0>(pmlEdgeBnd[2])(index); + } + sigmaInterface[3](index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = sigma[3](index); + + edgeInterface[3].second(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = edge[3](index); + edgeInterface[7].second(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = edge[7](index); + edgeInterface[11].second(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = edge[11](index); + edgeInterface[6].first(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = edge[6](index); + + std::get<1>(cornerInterface[3])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = corner[3](index); + std::get<1>(cornerInterface[7])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = corner[7](index); + std::get<0>(cornerInterface[6])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = corner[6](index); + std::get<0>(cornerInterface[2])(index, i * nDomY * nDomZ + (j-1) * nDomZ + k) = corner[2](index); + + topology[index].push_back(i * nDomY * nDomZ + (j-1) * nDomZ + k); + } + + if(k != 0) { // D + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[0].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = pmlBnd[0].first(index); + pmlBndInterface[1].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = pmlBnd[1].first(index); + pmlBndInterface[2].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = pmlBnd[2].first(index); + pmlBndInterface[3].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = pmlBnd[3].first(index); + + std::get<2>(pmlEdgeBndInterface[0])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = std::get<2>(pmlEdgeBnd[0])(index); + std::get<2>(pmlEdgeBndInterface[1])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = std::get<2>(pmlEdgeBnd[1])(index); + std::get<2>(pmlEdgeBndInterface[2])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = std::get<2>(pmlEdgeBnd[2])(index); + std::get<2>(pmlEdgeBndInterface[3])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = std::get<2>(pmlEdgeBnd[3])(index); + } + sigmaInterface[4](index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = sigma[4](index); + + edgeInterface[0].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = edge[0](index); + edgeInterface[1].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = edge[1](index); + edgeInterface[2].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = edge[2](index); + edgeInterface[3].first(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = edge[3](index); + + std::get<2>(cornerInterface[0])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = corner[0](index); + std::get<2>(cornerInterface[1])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = corner[1](index); + std::get<2>(cornerInterface[2])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = corner[2](index); + std::get<2>(cornerInterface[3])(index, i * nDomY * nDomZ + j * nDomZ + (k-1)) = corner[3](index); + + topology[index].push_back(i * nDomY * nDomZ + j * nDomZ + (k-1)); + } + + if(k != static_cast< unsigned int >(nDomZ) - 1) { // U + if(boundary == "pml" || boundaryExt == "pml") { + pmlBndInterface[8].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = pmlBnd[8].first(index); + pmlBndInterface[9].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = pmlBnd[9].first(index); + pmlBndInterface[10].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = pmlBnd[10].first(index); + pmlBndInterface[11].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = pmlBnd[11].first(index); + + std::get<2>(pmlEdgeBndInterface[4])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = std::get<2>(pmlEdgeBnd[4])(index); + std::get<2>(pmlEdgeBndInterface[5])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = std::get<2>(pmlEdgeBnd[5])(index); + std::get<2>(pmlEdgeBndInterface[6])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = std::get<2>(pmlEdgeBnd[6])(index); + std::get<2>(pmlEdgeBndInterface[7])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = std::get<2>(pmlEdgeBnd[7])(index); + } + sigmaInterface[5](index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = sigma[5](index); + + edgeInterface[8].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = edge[8](index); + edgeInterface[9].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = edge[9](index); + edgeInterface[10].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = edge[10](index); + edgeInterface[11].first(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = edge[11](index); + + std::get<2>(cornerInterface[4])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = corner[4](index); + std::get<2>(cornerInterface[5])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = corner[5](index); + std::get<2>(cornerInterface[6])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = corner[6](index); + std::get<2>(cornerInterface[7])(index, i * nDomY * nDomZ + j * nDomZ + (k+1)) = corner[7](index); + + topology[index].push_back(i * nDomY * nDomZ + j * nDomZ + (k+1)); + } + } + } + } + + // Kappa definition + gmshfem::function::ScalarFunction< std::complex< double > > kappa; + if(benchmark == "scattering") { + kappa = k; + } + + // Fields definition + gmshddm::field::SubdomainField< std::complex< double >, gmshfem::field::Form::Form0 > u("u", omega | sigma[0] | sigma[1] | sigma[2] | sigma[3], gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + if(benchmark == "scattering") { + u(0).domain(u(0).domain() | gamma); + } + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambda("lambda", gamma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + std::vector< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > gContinuous; +// std::vector< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > * > gDiscontinuous; + for(unsigned int b = 0; b < 6; ++b) { + gContinuous.push_back(new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gC_" + dir[b], sigmaInterface[b], gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); +// gDiscontinuous.push_back(new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gD_" + dir[b], sigmaInterface[b], gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder)); + } + + std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > gEdgePmlContinuous; +// std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > * > > gEdgePmlDiscontinuous; + std::vector< std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > > gEdgeHABC; + for(unsigned int e = 0; e < 12; ++e) { + if(e < 4) { + gEdgePmlContinuous.push_back(std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgePmlContinuous_" + dir[e%4] + "D_first", pmlBndInterface[e].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgePmlContinuous_" + dir[e%4] + "D_second", pmlBndInterface[e].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder))); +// gEdgePmlDiscontinuous.push_back(std::make_pair( +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gEdgePmlDiscontinuous_" + dir[e%4] + "D_first", pmlBndInterface[e].first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gEdgePmlDiscontinuous_" + dir[e%4] + "D_second", pmlBndInterface[e].second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder))); + gEdgeHABC.push_back(std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N)); + for(unsigned int n = 0; n < N; ++n) { + gEdgeHABC[e][n] = std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgeHABC_" + dir[e%4] + "D_" + std::to_string(n) + "_first", edgeInterface[e].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgeHABC_" + dir[e%4] + "D_" + std::to_string(n) + "_second", edgeInterface[e].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); + } + } + else if(e >= 4 && e < 8) { + gEdgePmlContinuous.push_back(std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgePmlContinuous_" + dir[e%4] + dir[(e+1)%4] + "_first", pmlBndInterface[e].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgePmlContinuous_" + dir[e%4] + dir[(e+1)%4] + "_second", pmlBndInterface[e].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder))); +// gEdgePmlDiscontinuous.push_back(std::make_pair( +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gEdgePmlDiscontinuous_" + dir[e%4] + dir[(e+1)%4] + "_first", pmlBndInterface[e].first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gEdgePmlDiscontinuous_" + dir[e%4] + dir[(e+1)%4] + "_second", pmlBndInterface[e].second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder))); + gEdgeHABC.push_back(std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N)); + for(unsigned int n = 0; n < N; ++n) { + gEdgeHABC[e][n] = std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgeHABC_" + dir[e%4] + dir[(e+1)%4] + "_" + std::to_string(n) + "_first", edgeInterface[e].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgeHABC_" + dir[e%4] + dir[(e+1)%4] + "_" + std::to_string(n) + "_second", edgeInterface[e].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); + } + } + else { + gEdgePmlContinuous.push_back(std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgePmlContinuous_" + dir[e%4] + "U_first", pmlBndInterface[e].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgePmlContinuous_" + dir[e%4] + "U_second", pmlBndInterface[e].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder))); +// gEdgePmlDiscontinuous.push_back(std::make_pair( +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gEdgePmlDiscontinuous_" + dir[e%4] + "U_first", pmlBndInterface[e].first, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gEdgePmlDiscontinuous_" + dir[e%4] + "U_second", pmlBndInterface[e].second, gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder))); + gEdgeHABC.push_back(std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N)); + for(unsigned int n = 0; n < N; ++n) { + gEdgeHABC[e][n] = std::make_pair( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgeHABC_" + dir[e%4] + "U_" + std::to_string(n) + "_first", edgeInterface[e].first, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gEdgeHABC_" + dir[e%4] + "U_" + std::to_string(n) + "_second", edgeInterface[e].second, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); + } + } + } + + std::vector< std::tuple< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > gCornerPmlContinuous; +// std::vector< std::pair< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 > * > > gCornerPmlDiscontinuous; + std::vector< std::vector< std::vector< std::tuple< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > > > gCornerHABC; + for(unsigned int c = 0; c < 8; ++c) { + if(c < 4) { + gCornerPmlContinuous.push_back(std::make_tuple( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[c%4] + dir[(c+1)%4] + "D_first", std::get<0>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[c%4] + dir[(c+1)%4] + "D_second", std::get<1>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[c%4] + dir[(c+1)%4] + "D_third", std::get<2>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder))); +// gCornerPmlDiscontinuous.push_back(std::make_tuple( +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[c%4] + dir[(c+1)%4] + "D_first", std::get<0>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[c%4] + dir[(c+1)%4] + "D_second", std::get<1>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[c%4] + dir[(c+1)%4] + "D_third", std::get<2>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder))); + gCornerHABC.push_back(std::vector< std::vector< std::tuple< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > >(N)); + for(unsigned int n = 0; n < N; ++n) { + gCornerHABC[c][n] = std::vector< std::tuple< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N); + for(unsigned int m = 0; m < N; ++m) { + gCornerHABC[c][n][m] = std::make_tuple( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "D_" + std::to_string(n) + "_" + std::to_string(m) + "_first", std::get<0>(cornerInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "D_" + std::to_string(n) + "_" + std::to_string(m) + "_second", std::get<1>(cornerInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "D_" + std::to_string(n) + "_" + std::to_string(m) + "_third", std::get<2>(cornerInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<0>(cornerInterface[c])(0,1), "gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "D_" + std::to_string(n) + "_" + std::to_string(m) + "_first"); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<1>(cornerInterface[c])(0,1), "gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "D_" + std::to_string(n) + "_" + std::to_string(m) + "_second"); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<2>(cornerInterface[c])(0,1), "gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "D_" + std::to_string(n) + "_" + std::to_string(m) + "_third"); + } + } + } + else { + gCornerPmlContinuous.push_back(std::make_tuple( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[c%4] + dir[(c+1)%4] + "U_first", std::get<0>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[c%4] + dir[(c+1)%4] + "U_second", std::get<1>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerPmlContinuous_" + dir[c%4] + dir[(c+1)%4] + "U_third", std::get<2>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder))); +// gCornerPmlDiscontinuous.push_back(std::make_tuple( +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[c%4] + dir[(c+1)%4] + "U_first", std::get<0>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[c%4] + dir[(c+1)%4] + "U_second", std::get<1>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder), +// new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form2 >("gCornerPmlDiscontinuous_" + dir[c%4] + dir[(c+1)%4] + "U_third", std::get<2>(pmlEdgeBndInterface[c]), gmshfem::field::FunctionSpaceTypeForm2::P_HierarchicalHCurl, neumannOrder))); + gCornerHABC.push_back(std::vector< std::vector< std::tuple< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > > >(N)); + for(unsigned int n = 0; n < N; ++n) { + gCornerHABC[c][n] = std::vector< std::tuple< gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > *, gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 > * > >(N); + for(unsigned int m = 0; m < N; ++m) { + gCornerHABC[c][n][m] = std::make_tuple( + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "U_" + std::to_string(n) + "_" + std::to_string(m) + "_first", std::get<0>(cornerInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "U_" + std::to_string(n) + "_" + std::to_string(m) + "_second", std::get<1>(cornerInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder), + new gmshddm::field::InterfaceField< std::complex< double >, gmshfem::field::Form::Form0 >("gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "U_" + std::to_string(n) + "_" + std::to_string(m) + "_third", std::get<2>(cornerInterface[c]), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, neumannOrder)); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<0>(cornerInterface[c])(0,1), "gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "U_" + std::to_string(n) + "_" + std::to_string(m) + "_first"); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<1>(cornerInterface[c])(0,1), "gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "U_" + std::to_string(n) + "_" + std::to_string(m) + "_second"); +// gmshfem::post::save(gmshfem::function::ScalarFunction< double >(1.), std::get<2>(cornerInterface[c])(0,1), "gCornerHABC_" + dir[c%4] + dir[(c+1)%4] + "U_" + std::to_string(n) + "_" + std::to_string(m) + "_third"); + } + } + } + } + + gmshddm::problem::Formulation< std::complex< double > > formulation("HelmholtzDDMScattering", topology); + + for(unsigned int b = 0; b < 6; ++b) { + formulation.addInterfaceField(*gContinuous[b]); +// formulation.addInterfaceField(*gDiscontinuous[b]); + } + + for(unsigned int e = 0; e < 12; ++e) { + formulation.addInterfaceField(*gEdgePmlContinuous[e].first); + formulation.addInterfaceField(*gEdgePmlContinuous[e].second); + +// formulation.addInterfaceField(*gEdgePmlDiscontinuous[e].first); +// formulation.addInterfaceField(*gEdgePmlDiscontinuous[e].second); + for(unsigned int n = 0; n < N; ++n) { + formulation.addInterfaceField(*gEdgeHABC[e][n].first); + formulation.addInterfaceField(*gEdgeHABC[e][n].second); + } + } + + for(unsigned int c = 0; c < 8; ++c) { + formulation.addInterfaceField(*std::get<0>(gCornerPmlContinuous[c])); + formulation.addInterfaceField(*std::get<1>(gCornerPmlContinuous[c])); + formulation.addInterfaceField(*std::get<2>(gCornerPmlContinuous[c])); + +// formulation.addInterfaceField(*std::get<0>(gCornerPmlDiscontinuous[c])); +// formulation.addInterfaceField(*std::get<1>(gCornerPmlDiscontinuous[c])); +// formulation.addInterfaceField(*std::get<2>(gCornerPmlDiscontinuous[c])); + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation.addInterfaceField(*std::get<0>(gCornerHABC[c][n][m])); + formulation.addInterfaceField(*std::get<1>(gCornerHABC[c][n][m])); + formulation.addInterfaceField(*std::get<2>(gCornerHABC[c][n][m])); + } + } + } + + std::vector< std::vector< std::vector< Subproblem * > > > subproblem(nDomX); + for(unsigned int i = 0; i < nDomX; ++i) { + subproblem[i].resize(nDomY); + for(unsigned int j = 0; j < nDomY; ++j) { + subproblem[i][j].resize(nDomZ); + for(unsigned int k = 0; k < nDomZ; ++k) { + unsigned int index = i * nDomY * nDomZ + j * nDomZ + k; + formulation(index).integral(-grad(dof(u(index))), grad(tf(u(index))), omega(index), gauss); + formulation(index).integral(kappa * kappa * dof(u(index)), tf(u(index)), omega(index), gauss); + + if(benchmark == "scattering") { + if(index == 0) { + formulation(index).integral(dof(lambda), tf(u(index)), gamma, gauss); + formulation(index).integral(dof(u(index)), tf(lambda), gamma, gauss); + formulation(index).integral(formulation.physicalSource(- fAnalytic), tf(lambda), gamma, gauss); + } + } + + SubproblemDomains domains; + domains.setOmega(omega(index)); + domains.setSigma({ sigma[0](index), sigma[1](index), sigma[2](index), sigma[3](index), sigma[4](index), sigma[5](index) }); + domains.setPml({ pml[0](index), pml[1](index), pml[2](index), pml[3](index), pml[4](index), pml[5](index) }); + domains.setPmlBnd({ std::make_pair(pmlBnd[0].first(index), pmlBnd[0].second(index)), std::make_pair(pmlBnd[1].first(index), pmlBnd[1].second(index)), std::make_pair(pmlBnd[2].first(index), pmlBnd[2].second(index)), std::make_pair(pmlBnd[3].first(index), pmlBnd[3].second(index)), std::make_pair(pmlBnd[4].first(index), pmlBnd[4].second(index)), std::make_pair(pmlBnd[5].first(index), pmlBnd[5].second(index)), std::make_pair(pmlBnd[6].first(index), pmlBnd[6].second(index)), std::make_pair(pmlBnd[7].first(index), pmlBnd[7].second(index)), std::make_pair(pmlBnd[8].first(index), pmlBnd[8].second(index)), std::make_pair(pmlBnd[9].first(index), pmlBnd[9].second(index)), std::make_pair(pmlBnd[10].first(index), pmlBnd[10].second(index)), std::make_pair(pmlBnd[11].first(index), pmlBnd[11].second(index)) }); + domains.setPmlEdge({ pmlEdge[0](index), pmlEdge[1](index), pmlEdge[2](index), pmlEdge[3](index), pmlEdge[4](index), pmlEdge[5](index), pmlEdge[6](index), pmlEdge[7](index), pmlEdge[8](index), pmlEdge[9](index), pmlEdge[10](index), pmlEdge[11](index) }); + domains.setEdge({ edge[0](index), edge[1](index), edge[2](index), edge[3](index), edge[4](index), edge[5](index), edge[6](index), edge[7](index), edge[8](index), edge[9](index), edge[10](index), edge[11](index) }); + domains.setPmlEdgeBnd({ std::make_tuple(std::get<0>(pmlEdgeBnd[0])(index), std::get<1>(pmlEdgeBnd[0])(index), std::get<2>(pmlEdgeBnd[0])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[1])(index), std::get<1>(pmlEdgeBnd[1])(index), std::get<2>(pmlEdgeBnd[1])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[2])(index), std::get<1>(pmlEdgeBnd[2])(index), std::get<2>(pmlEdgeBnd[2])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[3])(index), std::get<1>(pmlEdgeBnd[3])(index), std::get<2>(pmlEdgeBnd[3])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[4])(index), std::get<1>(pmlEdgeBnd[4])(index), std::get<2>(pmlEdgeBnd[4])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[5])(index), std::get<1>(pmlEdgeBnd[5])(index), std::get<2>(pmlEdgeBnd[5])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[6])(index), std::get<1>(pmlEdgeBnd[6])(index), std::get<2>(pmlEdgeBnd[6])(index)), std::make_tuple(std::get<0>(pmlEdgeBnd[7])(index), std::get<1>(pmlEdgeBnd[7])(index), std::get<2>(pmlEdgeBnd[7])(index)) }); + domains.setPmlCorner({ pmlCorner[0](index), pmlCorner[1](index), pmlCorner[2](index), pmlCorner[3](index), pmlCorner[4](index), pmlCorner[5](index), pmlCorner[6](index), pmlCorner[7](index) }); + domains.setCorner({ corner[0](index), corner[1](index), corner[2](index), corner[3](index), corner[4](index), corner[5](index), corner[6](index), corner[7](index) }); + domains.setCornerEdge({ std::make_tuple(std::get<0>(cornerEdge[0])(index), std::get<1>(cornerEdge[0])(index), std::get<2>(cornerEdge[0])(index)), std::make_tuple(std::get<0>(cornerEdge[1])(index), std::get<1>(cornerEdge[1])(index), std::get<2>(cornerEdge[1])(index)), std::make_tuple(std::get<0>(cornerEdge[2])(index), std::get<1>(cornerEdge[2])(index), std::get<2>(cornerEdge[2])(index)), std::make_tuple(std::get<0>(cornerEdge[3])(index), std::get<1>(cornerEdge[3])(index), std::get<2>(cornerEdge[3])(index)), std::make_tuple(std::get<0>(cornerEdge[4])(index), std::get<1>(cornerEdge[4])(index), std::get<2>(cornerEdge[4])(index)), std::make_tuple(std::get<0>(cornerEdge[5])(index), std::get<1>(cornerEdge[5])(index), std::get<2>(cornerEdge[5])(index)), std::make_tuple(std::get<0>(cornerEdge[6])(index), std::get<1>(cornerEdge[6])(index), std::get<2>(cornerEdge[6])(index)), std::make_tuple(std::get<0>(cornerEdge[7])(index), std::get<1>(cornerEdge[7])(index), std::get<2>(cornerEdge[7])(index)) }); + + SubproblemParameters parameters; + parameters.setGauss(gauss); + parameters.setKappa(kappa); + parameters.setNeumannOrder(neumannOrder); + parameters.setFieldOrder(fieldOrder); + parameters.setStab(stab); + + std::string bnd = boundary; + if(boundary == "habc") { + bnd += "_" + std::to_string(N) + "_" + std::to_string(thetaPade); + } + else if(boundary == "pml") { + if(pmlMethod == "continuous") { + bnd += "Continuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + else if(pmlMethod == "discontinuous") { + bnd += "Discontinuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + } + std::string bndExt = boundaryExt; + if(boundaryExt == "habc") { + bndExt += "_" + std::to_string(NExt) + "_" + std::to_string(thetaPade); + } + else if(boundaryExt == "pml") { + if(pmlMethodExt == "continuous") { + bndExt += "Continuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + else if(pmlMethodExt == "discontinuous") { + bndExt += "Discontinuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + } + gmshfem::msg::info << "Subdomain (" << i << ", " << j << ", " << k << ") has boundaries [" << (i == nDomX-1 ? bndExt : bnd) << ", " << (j == nDomY-1 ? bndExt : bnd) << ", " << (i == 0 ? bndExt : bnd) << ", " << (j == 0 ? bndExt : bnd) << ", " << (k == 0 ? bndExt : bnd) << ", " << (k == nDomZ-1 ? bndExt : bnd) << "]" << gmshfem::msg::endl; + subproblem[i][j][k] = new Subproblem(formulation(index), u(index).name(), domains, parameters, (i == nDomX-1 ? bndExt : bnd), (j == nDomY-1 ? bndExt : bnd), (i == 0 ? bndExt : bnd), (j == 0 ? bndExt : bnd), (k == 0 ? bndExt : bnd), (k == nDomZ-1 ? bndExt : bnd)); + subproblem[i][j][k]->writeFormulation(); + + // coupling + const int faceNeighbor[6] = { + 2, 3, 0, 1, 5, 4 + }; + for(unsigned int b = 0; b < 6; ++b) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Boundary *boundary = subproblem[i][j][k]->getBoundary(b); + if(dynamic_cast< Sommerfeld * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[faceNeighbor[b]])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(dynamic_cast< HABC * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[faceNeighbor[b]])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(dynamic_cast< PmlContinuous * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*gContinuous[faceNeighbor[b]])(jndex, index)), tf(u(index)), sigmaInterface[b](index, jndex), gauss); + } + } + } + } + + const int edgeNeighbor[12][2] = { + // Down + {8, 2}, + {9, 3}, + {10, 0}, + {11, 1}, + // Rot + {7, 5}, + {4, 6}, + {5, 7}, + {6, 4}, + // Up + {0, 10}, + {1, 11}, + {2, 8}, + {3, 9} + }; + for(unsigned int e = 0; e < 12; ++e) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Edge *edge = subproblem[i][j][k]->getEdge(e); + if(edge == nullptr) { + continue; + } + if(auto eg = dynamic_cast< HABC_HABC * >(edge)) { + if(!edgeInterface[e].first(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gEdgeHABC[edgeNeighbor[e][0]][n].second)(jndex, index) ), tf(*eg->firstBoundary()->getUHABC(n)), edgeInterface[e].first(index, jndex), gauss); + } + } + else { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gEdgeHABC[edgeNeighbor[e][0]][n].first)(jndex, index) ), tf(*eg->firstBoundary()->getUHABC(n)), edgeInterface[e].first(index, jndex), gauss); + } + } + } + if(!edgeInterface[e].second(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gEdgeHABC[edgeNeighbor[e][1]][n].first)(jndex, index) ), tf(*eg->secondBoundary()->getUHABC(n)), edgeInterface[e].second(index, jndex), gauss); + } + } + else { + for(unsigned int n = 0; n < N; ++n) { + formulation(index).integral(formulation.artificialSource( - (*gEdgeHABC[edgeNeighbor[e][1]][n].second)(jndex, index) ), tf(*eg->secondBoundary()->getUHABC(n)), edgeInterface[e].second(index, jndex), gauss); + } + } + } + } + else if(auto eg = dynamic_cast< PmlContinuous_PmlContinuous * >(edge)) { + if(!pmlBndInterface[e].first(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + formulation(index).integral(formulation.artificialSource( - (*gEdgePmlContinuous[edgeNeighbor[e][0]].second)(jndex, index) ), tf(*eg->firstBoundary()->getUPml()), pmlBndInterface[e].first(index, jndex), gauss); + } + else { + formulation(index).integral(formulation.artificialSource( - (*gEdgePmlContinuous[edgeNeighbor[e][0]].first)(jndex, index) ), tf(*eg->firstBoundary()->getUPml()), pmlBndInterface[e].first(index, jndex), gauss); + } + } + if(!pmlBndInterface[e].second(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + formulation(index).integral(formulation.artificialSource( - (*gEdgePmlContinuous[edgeNeighbor[e][1]].first)(jndex, index) ), tf(*eg->secondBoundary()->getUPml()), pmlBndInterface[e].second(index, jndex), gauss); + } + else { + formulation(index).integral(formulation.artificialSource( - (*gEdgePmlContinuous[edgeNeighbor[e][1]].second)(jndex, index) ), tf(*eg->secondBoundary()->getUPml()), pmlBndInterface[e].second(index, jndex), gauss); + } + } + } + } + } + + const int cornerNeighbor[8][3] = { + // Down + {3, 1, 4}, + {0, 2, 5}, + {1, 3, 6}, + {2, 0, 7}, + // Up + {7, 5, 0}, + {4, 6, 1}, + {5, 7, 2}, + {6, 4, 3} + }; + for(unsigned int c = 0; c < 8; ++c) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Corner *corner = subproblem[i][j][k]->getCorner(c); + if(corner == nullptr) { + continue; + } + if(auto cr = dynamic_cast< HABC_HABC_HABC * >(corner)) { + if(!std::get<0>(cornerInterface[c])(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation(index).integral(formulation.artificialSource( - (*std::get<1>(gCornerHABC[cornerNeighbor[c][0]][n][m]))(jndex, index) ), tf(*cr->firstEdge()->getUHABC(n, m)), std::get<0>(cornerInterface[c])(index, jndex), gauss); + } + } + } + if(!std::get<1>(cornerInterface[c])(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation(index).integral(formulation.artificialSource( - (*std::get<0>(gCornerHABC[cornerNeighbor[c][1]][n][m]))(jndex, index) ), tf(*cr->secondEdge()->getUHABC(n, m)), std::get<1>(cornerInterface[c])(index, jndex), gauss); + } + } + } + if(!std::get<2>(cornerInterface[c])(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation(index).integral(formulation.artificialSource( - (*std::get<2>(gCornerHABC[cornerNeighbor[c][2]][n][m]))(jndex, index) ), tf(*cr->thirdEdge()->getUHABC(n, m)), std::get<2>(cornerInterface[c])(index, jndex), gauss); + } + } + } + } + else if(auto cr = dynamic_cast< PmlContinuous_PmlContinuous_PmlContinuous * >(corner)) { + if(!std::get<0>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*std::get<1>(gCornerPmlContinuous[cornerNeighbor[c][0]]))(jndex, index) ), tf(*cr->firstEdge()->getUPml()), std::get<0>(pmlEdgeBndInterface[c])(index, jndex), gauss); + } + if(!std::get<1>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*std::get<0>(gCornerPmlContinuous[cornerNeighbor[c][1]]))(jndex, index) ), tf(*cr->secondEdge()->getUPml()), std::get<1>(pmlEdgeBndInterface[c])(index, jndex), gauss); + } + if(!std::get<2>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { + formulation(index).integral(formulation.artificialSource( - (*std::get<2>(gCornerPmlContinuous[cornerNeighbor[c][2]]))(jndex, index) ), tf(*cr->thirdEdge()->getUPml()), std::get<2>(pmlEdgeBndInterface[c])(index, jndex), gauss); + } + } + } + } + + // interface + for(unsigned int b = 0; b < 6; ++b) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Boundary *boundary = subproblem[i][j][k]->getBoundary(b); + if(auto bnd = dynamic_cast< Sommerfeld * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[faceNeighbor[b]])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(auto bnd = dynamic_cast< HABC * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[faceNeighbor[b]])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + else if(auto bnd = dynamic_cast< PmlContinuous * >(boundary)) { + if(!sigmaInterface[b](index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*gContinuous[b])(index, jndex)), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gContinuous[faceNeighbor[b]])(jndex, index) ), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + formulation(index, jndex).integral(2. * *bnd->getV(), tf((*gContinuous[b])(index, jndex)), sigmaInterface[b](index, jndex), gauss); + } + } + } + } + + for(unsigned int e = 0; e < 12; ++e) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Edge *edge = subproblem[i][j][k]->getEdge(e); + if(edge == nullptr) { + continue; + } + if(auto eg = dynamic_cast< HABC_HABC * >(edge)) { + if(!edgeInterface[e].first(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gEdgeHABC[e][n].first)(index, jndex)), tf((*gEdgeHABC[e][n].first)(index, jndex)), edgeInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgeHABC[edgeNeighbor[e][0]][n].second)(jndex, index) ), tf((*gEdgeHABC[e][n].first)(index, jndex)), edgeInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(n, 0), tf((*gEdgeHABC[e][n].first)(index, jndex)), edgeInterface[e].first(index, jndex), gauss); + } + } + else { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gEdgeHABC[e][n].first)(index, jndex)), tf((*gEdgeHABC[e][n].first)(index, jndex)), edgeInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgeHABC[edgeNeighbor[e][0]][n].first)(jndex, index) ), tf((*gEdgeHABC[e][n].first)(index, jndex)), edgeInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(n, 0), tf((*gEdgeHABC[e][n].first)(index, jndex)), edgeInterface[e].first(index, jndex), gauss); + } + } + } + if(!edgeInterface[e].second(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gEdgeHABC[e][n].second)(index, jndex)), tf((*gEdgeHABC[e][n].second)(index, jndex)), edgeInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgeHABC[edgeNeighbor[e][1]][n].first)(jndex, index) ), tf((*gEdgeHABC[e][n].second)(index, jndex)), edgeInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(n, 1), tf((*gEdgeHABC[e][n].second)(index, jndex)), edgeInterface[e].second(index, jndex), gauss); + } + } + else { + for(unsigned int n = 0; n < N; ++n) { + formulation(index, jndex).integral(dof((*gEdgeHABC[e][n].second)(index, jndex)), tf((*gEdgeHABC[e][n].second)(index, jndex)), edgeInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgeHABC[edgeNeighbor[e][1]][n].second)(jndex, index) ), tf((*gEdgeHABC[e][n].second)(index, jndex)), edgeInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(n, 1), tf((*gEdgeHABC[e][n].second)(index, jndex)), edgeInterface[e].second(index, jndex), gauss); + } + } + } + } + else if(auto eg = dynamic_cast< PmlContinuous_PmlContinuous * >(edge)) { + if(!pmlBndInterface[e].first(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + formulation(index, jndex).integral(dof((*gEdgePmlContinuous[e].first)(index, jndex)), tf((*gEdgePmlContinuous[e].first)(index, jndex)), pmlBndInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgePmlContinuous[edgeNeighbor[e][0]].second)(jndex, index) ), tf((*gEdgePmlContinuous[e].first)(index, jndex)), pmlBndInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(0), tf((*gEdgePmlContinuous[e].first)(index, jndex)), pmlBndInterface[e].first(index, jndex), gauss); + } + else { + formulation(index, jndex).integral(dof((*gEdgePmlContinuous[e].first)(index, jndex)), tf((*gEdgePmlContinuous[e].first)(index, jndex)), pmlBndInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgePmlContinuous[edgeNeighbor[e][0]].first)(jndex, index) ), tf((*gEdgePmlContinuous[e].first)(index, jndex)), pmlBndInterface[e].first(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(0), tf((*gEdgePmlContinuous[e].first)(index, jndex)), pmlBndInterface[e].first(index, jndex), gauss); + } + } + if(!pmlBndInterface[e].second(index, jndex).isEmpty()) { + if(e >= 4 && e < 8) { + formulation(index, jndex).integral(dof((*gEdgePmlContinuous[e].second)(index, jndex)), tf((*gEdgePmlContinuous[e].second)(index, jndex)), pmlBndInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgePmlContinuous[edgeNeighbor[e][1]].first)(jndex, index) ), tf((*gEdgePmlContinuous[e].second)(index, jndex)), pmlBndInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(1), tf((*gEdgePmlContinuous[e].second)(index, jndex)), pmlBndInterface[e].second(index, jndex), gauss); + } + else { + formulation(index, jndex).integral(dof((*gEdgePmlContinuous[e].second)(index, jndex)), tf((*gEdgePmlContinuous[e].second)(index, jndex)), pmlBndInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*gEdgePmlContinuous[edgeNeighbor[e][1]].second)(jndex, index) ), tf((*gEdgePmlContinuous[e].second)(index, jndex)), pmlBndInterface[e].second(index, jndex), gauss); + formulation(index, jndex).integral(2. * *eg->getV(1), tf((*gEdgePmlContinuous[e].second)(index, jndex)), pmlBndInterface[e].second(index, jndex), gauss); + } + } + } + } + } + + for(unsigned int c = 0; c < 8; ++c) { + for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { + const unsigned int jndex = topology[index][jj]; + + Corner *corner = subproblem[i][j][k]->getCorner(c); + if(corner == nullptr) { + continue; + } + if(auto cr = dynamic_cast< HABC_HABC_HABC * >(corner)) { + if(!std::get<0>(cornerInterface[c])(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation(index, jndex).integral(dof((*std::get<0>(gCornerHABC[c][n][m]))(index, jndex)), tf((*std::get<0>(gCornerHABC[c][n][m]))(index, jndex)), std::get<0>(cornerInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*std::get<1>(gCornerHABC[cornerNeighbor[c][0]][n][m]))(jndex, index) ), tf((*std::get<0>(gCornerHABC[c][n][m]))(index, jndex)), std::get<0>(cornerInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n, m, 0), tf((*std::get<0>(gCornerHABC[c][n][m]))(index, jndex)), std::get<0>(cornerInterface[c])(index, jndex), gauss); + } + } + } + if(!std::get<1>(cornerInterface[c])(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation(index, jndex).integral(dof((*std::get<1>(gCornerHABC[c][n][m]))(index, jndex)), tf((*std::get<1>(gCornerHABC[c][n][m]))(index, jndex)), std::get<1>(cornerInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*std::get<0>(gCornerHABC[cornerNeighbor[c][1]][n][m]))(jndex, index) ), tf((*std::get<1>(gCornerHABC[c][n][m]))(index, jndex)), std::get<1>(cornerInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n, m, 1), tf((*std::get<1>(gCornerHABC[c][n][m]))(index, jndex)), std::get<1>(cornerInterface[c])(index, jndex), gauss); + } + } + } + if(!std::get<2>(cornerInterface[c])(index, jndex).isEmpty()) { + for(unsigned int n = 0; n < N; ++n) { + for(unsigned int m = 0; m < N; ++m) { + formulation(index, jndex).integral(dof((*std::get<2>(gCornerHABC[c][n][m]))(index, jndex)), tf((*std::get<2>(gCornerHABC[c][n][m]))(index, jndex)), std::get<2>(cornerInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*std::get<2>(gCornerHABC[cornerNeighbor[c][2]][n][m]))(jndex, index) ), tf((*std::get<2>(gCornerHABC[c][n][m]))(index, jndex)), std::get<2>(cornerInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(n, m, 2), tf((*std::get<2>(gCornerHABC[c][n][m]))(index, jndex)), std::get<2>(cornerInterface[c])(index, jndex), gauss); + } + } + } + } + else if(auto cr = dynamic_cast< PmlContinuous_PmlContinuous_PmlContinuous * >(corner)) { + if(!std::get<0>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*std::get<0>(gCornerPmlContinuous[c]))(index, jndex)), tf((*std::get<0>(gCornerPmlContinuous[c]))(index, jndex)), std::get<0>(pmlEdgeBndInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*std::get<1>(gCornerPmlContinuous[cornerNeighbor[c][0]]))(jndex, index) ), tf((*std::get<0>(gCornerPmlContinuous[c]))(index, jndex)), std::get<0>(pmlEdgeBndInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(0), tf((*std::get<0>(gCornerPmlContinuous[c]))(index, jndex)), std::get<0>(pmlEdgeBndInterface[c])(index, jndex), gauss); + } + if(!std::get<1>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*std::get<1>(gCornerPmlContinuous[c]))(index, jndex)), tf((*std::get<1>(gCornerPmlContinuous[c]))(index, jndex)), std::get<1>(pmlEdgeBndInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*std::get<0>(gCornerPmlContinuous[cornerNeighbor[c][1]]))(jndex, index) ), tf((*std::get<1>(gCornerPmlContinuous[c]))(index, jndex)), std::get<1>(pmlEdgeBndInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(1), tf((*std::get<1>(gCornerPmlContinuous[c]))(index, jndex)), std::get<1>(pmlEdgeBndInterface[c])(index, jndex), gauss); + } + if(!std::get<2>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { + formulation(index, jndex).integral(dof((*std::get<2>(gCornerPmlContinuous[c]))(index, jndex)), tf((*std::get<2>(gCornerPmlContinuous[c]))(index, jndex)), std::get<2>(pmlEdgeBndInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(formulation.artificialSource( (*std::get<2>(gCornerPmlContinuous[cornerNeighbor[c][2]]))(jndex, index) ), tf((*std::get<2>(gCornerPmlContinuous[c]))(index, jndex)), std::get<2>(pmlEdgeBndInterface[c])(index, jndex), gauss); + formulation(index, jndex).integral(2. * *cr->getV(2), tf((*std::get<2>(gCornerPmlContinuous[c]))(index, jndex)), std::get<2>(pmlEdgeBndInterface[c])(index, jndex), gauss); + } + } + } + } + +// for(unsigned int e = 0; e < 12; ++e) { +// for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { +// const unsigned int jndex = topology[index][jj]; +// +// Edge *edge = subproblem[i][j][k]->getEdge(e); +// if(edge == nullptr) { +// continue; +// } +// if(auto eg = dynamic_cast< HABC_HABC * >(edge)) { +// if(!edgeInterface[e].first(index, jndex).isEmpty()) { +// if(e >= 4 && e < 8) { +// for(unsigned int n = 0; n < N; ++n) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[e][n].first)(index, jndex), (*gEdgeHABC[e][n].first)(index, jndex).domain(), (*gEdgeHABC[e][n].first)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1) + (*gEdgeHABC[edgeNeighbor[e][0]][n].second)(jndex, index), (*gEdgeHABC[edgeNeighbor[e][0]][n].second)(jndex, index).domain(), (*gEdgeHABC[edgeNeighbor[e][0]][n].second)(jndex, index).name() + "_pair"); +// } +// } +// else { +// for(unsigned int n = 0; n < N; ++n) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[e][n].first)(index, jndex), (*gEdgeHABC[e][n].first)(index, jndex).domain(), (*gEdgeHABC[e][n].first)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[edgeNeighbor[e][0]][n].first)(jndex, index), (*gEdgeHABC[edgeNeighbor[e][0]][n].first)(jndex, index).domain(), (*gEdgeHABC[edgeNeighbor[e][0]][n].first)(jndex, index).name() + "_pair"); +// } +// } +// } +// if(!edgeInterface[e].second(index, jndex).isEmpty()) { +// if(e >= 4 && e < 8) { +// for(unsigned int n = 0; n < N; ++n) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[e][n].second)(index, jndex), (*gEdgeHABC[e][n].second)(index, jndex).domain(), (*gEdgeHABC[e][n].second)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[edgeNeighbor[e][1]][n].first)(jndex, index), (*gEdgeHABC[edgeNeighbor[e][1]][n].first)(jndex, index).domain(), (*gEdgeHABC[edgeNeighbor[e][1]][n].first)(jndex, index).name() + "_pair"); +// } +// } +// else { +// for(unsigned int n = 0; n < N; ++n) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[e][n].second)(index, jndex), (*gEdgeHABC[e][n].second)(index, jndex).domain(), (*gEdgeHABC[e][n].second)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgeHABC[edgeNeighbor[e][1]][n].second)(jndex, index), (*gEdgeHABC[edgeNeighbor[e][1]][n].second)(jndex, index).domain(), (*gEdgeHABC[edgeNeighbor[e][1]][n].second)(jndex, index).name() + "_pair"); +// } +// } +// } +// } +// else if(auto eg = dynamic_cast< PmlContinuous_PmlContinuous * >(edge)) { +// if(!pmlBndInterface[e].first(index, jndex).isEmpty()) { +// if(e >= 4 && e < 8) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgePmlContinuous[e].first)(index, jndex), (*gEdgePmlContinuous[e].first)(index, jndex).domain(), (*gEdgePmlContinuous[e].first)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1) + (*gEdgePmlContinuous[edgeNeighbor[e][0]].second)(jndex, index), (*gEdgePmlContinuous[edgeNeighbor[e][0]].second)(jndex, index).domain(), (*gEdgePmlContinuous[edgeNeighbor[e][0]].second)(jndex, index).name() + "_pair"); +// } +// else { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgePmlContinuous[e].first)(index, jndex), (*gEdgePmlContinuous[e].first)(index, jndex).domain(), (*gEdgePmlContinuous[e].first)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1) + (*gEdgePmlContinuous[edgeNeighbor[e][0]].first)(jndex, index), (*gEdgePmlContinuous[edgeNeighbor[e][0]].second)(jndex, index).domain(), (*gEdgePmlContinuous[edgeNeighbor[e][0]].first)(jndex, index).name() + "_pair"); +// } +// } +// if(!pmlBndInterface[e].second(index, jndex).isEmpty()) { +// if(e >= 4 && e < 8) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgePmlContinuous[e].second)(index, jndex), (*gEdgePmlContinuous[e].second)(index, jndex).domain(), (*gEdgePmlContinuous[e].second)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1) + (*gEdgePmlContinuous[edgeNeighbor[e][1]].first)(jndex, index), (*gEdgePmlContinuous[edgeNeighbor[e][1]].first)(jndex, index).domain(), (*gEdgePmlContinuous[edgeNeighbor[e][1]].first)(jndex, index).name() + "_pair"); +// } +// else { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*gEdgePmlContinuous[e].second)(index, jndex), (*gEdgePmlContinuous[e].second)(index, jndex).domain(), (*gEdgePmlContinuous[e].second)(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1) + (*gEdgePmlContinuous[edgeNeighbor[e][1]].second)(jndex, index), (*gEdgePmlContinuous[edgeNeighbor[e][1]].second)(jndex, index).domain(), (*gEdgePmlContinuous[edgeNeighbor[e][1]].second)(jndex, index).name() + "_pair"); +// } +// } +// } +// } +// } + +// for(unsigned int c = 0; c < 8; ++c) { +// for(unsigned int jj = 0; jj < topology[index].size(); ++jj) { +// const unsigned int jndex = topology[index][jj]; +// +// Corner *corner = subproblem[i][j][k]->getCorner(c); +// if(corner == nullptr) { +// continue; +// } +// if(auto cr = dynamic_cast< HABC_HABC_HABC * >(corner)) { +// if(!std::get<0>(cornerInterface[c])(index, jndex).isEmpty()) { +// for(unsigned int n = 0; n < N; ++n) { +// for(unsigned int m = 0; m < N; ++m) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<0>(gCornerHABC[c][n][m]))(index, jndex), (*std::get<0>(gCornerHABC[c][n][m]))(index, jndex).domain(), (*std::get<0>(gCornerHABC[c][n][m]))(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<1>(gCornerHABC[cornerNeighbor[c][0]][n][m]))(jndex, index), (*std::get<1>(gCornerHABC[cornerNeighbor[c][0]][n][m]))(jndex, index).domain(), (*std::get<1>(gCornerHABC[cornerNeighbor[c][0]][n][m]))(jndex, index).name() + "_pair"); +// } +// } +// } +// if(!std::get<1>(cornerInterface[c])(index, jndex).isEmpty()) { +// for(unsigned int n = 0; n < N; ++n) { +// for(unsigned int m = 0; m < N; ++m) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<1>(gCornerHABC[c][n][m]))(index, jndex), (*std::get<1>(gCornerHABC[c][n][m]))(index, jndex).domain(), (*std::get<1>(gCornerHABC[c][n][m]))(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<0>(gCornerHABC[cornerNeighbor[c][1]][n][m]))(jndex, index), (*std::get<0>(gCornerHABC[cornerNeighbor[c][1]][n][m]))(jndex, index).domain(), (*std::get<0>(gCornerHABC[cornerNeighbor[c][1]][n][m]))(jndex, index).name() + "_pair"); +// } +// } +// } +// if(!std::get<2>(cornerInterface[c])(index, jndex).isEmpty()) { +// for(unsigned int n = 0; n < N; ++n) { +// for(unsigned int m = 0; m < N; ++m) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<2>(gCornerHABC[c][n][m]))(index, jndex), (*std::get<2>(gCornerHABC[c][n][m]))(index, jndex).domain(), (*std::get<2>(gCornerHABC[c][n][m]))(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<2>(gCornerHABC[cornerNeighbor[c][2]][n][m]))(jndex, index), (*std::get<2>(gCornerHABC[cornerNeighbor[c][2]][n][m]))(jndex, index).domain(), (*std::get<2>(gCornerHABC[cornerNeighbor[c][2]][n][m]))(jndex, index).name() + "_pair"); +// } +// } +// } +// } +// else if(auto cr = dynamic_cast< PmlContinuous_PmlContinuous_PmlContinuous * >(corner)) { +// if(!std::get<0>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<0>(gCornerPmlContinuous[c]))(index, jndex), (*std::get<0>(gCornerPmlContinuous[c]))(index, jndex).domain(), (*std::get<0>(gCornerPmlContinuous[c]))(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<1>(gCornerPmlContinuous[cornerNeighbor[c][0]]))(jndex, index), (*std::get<1>(gCornerPmlContinuous[cornerNeighbor[c][0]]))(jndex, index).domain(), (*std::get<1>(gCornerPmlContinuous[cornerNeighbor[c][0]]))(jndex, index).name() + "_pair"); +// } +// if(!std::get<1>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<1>(gCornerPmlContinuous[c]))(index, jndex), (*std::get<1>(gCornerPmlContinuous[c]))(index, jndex).domain(), (*std::get<1>(gCornerPmlContinuous[c]))(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<0>(gCornerPmlContinuous[cornerNeighbor[c][1]]))(jndex, index), (*std::get<0>(gCornerPmlContinuous[cornerNeighbor[c][1]]))(jndex, index).domain(), (*std::get<0>(gCornerPmlContinuous[cornerNeighbor[c][1]]))(jndex, index).name() + "_pair"); +// } +// if(!std::get<2>(pmlEdgeBndInterface[c])(index, jndex).isEmpty()) { +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<2>(gCornerPmlContinuous[c]))(index, jndex), (*std::get<2>(gCornerPmlContinuous[c]))(index, jndex).domain(), (*std::get<2>(gCornerPmlContinuous[c]))(index, jndex).name()); +// gmshfem::post::save(gmshfem::function::ScalarFunction< std::complex< double > >(1.) + (*std::get<2>(gCornerPmlContinuous[cornerNeighbor[c][2]]))(jndex, index), (*std::get<2>(gCornerPmlContinuous[cornerNeighbor[c][2]]))(jndex, index).domain(), (*std::get<2>(gCornerPmlContinuous[cornerNeighbor[c][2]]))(jndex, index).name() + "_pair"); +// } +// } +// } +// } + +// exit(0); + } + } + } + + formulation.pre(); + formulation.solve("gmres", res, iterMax); + + for(unsigned int i = 0; i < nDomX; ++i) { + for(unsigned int j = 0; j < nDomY; ++j) { + for(unsigned int k = 0; k < nDomZ; ++k) { + unsigned int index = i * nDomY * nDomZ + j * nDomZ + k; + if(gmshddm::mpi::isItMySubdomain(index)) { + if(saveU) { + gmshfem::post::save(u(index), omega(index), "u_" + std::to_string(index), "msh"); + } + } + } + } + } + + if(monoDomainError) { + gmshfem::problem::Formulation< std::complex< double > > formulationMono("HelmholtzMonoDomain"); + + std::vector< gmshfem::domain::Domain > sigmaMono(6); + std::vector< gmshfem::domain::Domain > pmlMono(6); + std::vector< gmshfem::domain::Domain > pmlEdgeMono(12); + std::vector< gmshfem::domain::Domain > pmlCornerMono(8); + std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > pmlBndMono(12); + std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > pmlEdgeBndMono(8); + std::vector< gmshfem::domain::Domain > edgeMono(12); + std::vector< gmshfem::domain::Domain > cornerMono(8); + std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > cornerEdgeMono(8); + + for(unsigned int i = 0; i < nDomX; ++i) { + for(unsigned int j = 0; j < nDomY; ++j) { + for(unsigned int k = 0; k < nDomZ; ++k) { + unsigned int index = i * nDomY * nDomZ + j * nDomZ + k; + if(i == 0) { + sigmaMono[2] |= sigma[2](index); + pmlMono[2] |= pml[2](index); + if(j == 0) { + pmlEdgeMono[6] |= pmlEdge[6](index); + edgeMono[6] |= edge[6](index); + pmlBndMono[6].first |= pmlBnd[6].first(index); + pmlBndMono[6].second |= pmlBnd[6].second(index); + if(k == 0) { + pmlCornerMono[2] |= pmlCorner[2](index); + cornerMono[2] |= corner[2](index); + std::get<0>(pmlEdgeBndMono[2]) |= std::get<0>(pmlEdgeBnd[2])(index); + std::get<1>(pmlEdgeBndMono[2]) |= std::get<1>(pmlEdgeBnd[2])(index); + std::get<2>(pmlEdgeBndMono[2]) |= std::get<2>(pmlEdgeBnd[2])(index); + std::get<0>(cornerEdgeMono[2]) |= std::get<0>(cornerEdge[2])(index); + std::get<1>(cornerEdgeMono[2]) |= std::get<1>(cornerEdge[2])(index); + std::get<2>(cornerEdgeMono[2]) |= std::get<2>(cornerEdge[2])(index); + } + if(k == nDomZ-1) { + pmlCornerMono[6] |= pmlCorner[6](index); + cornerMono[6] |= corner[6](index); + std::get<0>(pmlEdgeBndMono[6]) |= std::get<0>(pmlEdgeBnd[6])(index); + std::get<1>(pmlEdgeBndMono[6]) |= std::get<1>(pmlEdgeBnd[6])(index); + std::get<2>(pmlEdgeBndMono[6]) |= std::get<2>(pmlEdgeBnd[6])(index); + std::get<0>(cornerEdgeMono[6]) |= std::get<0>(cornerEdge[6])(index); + std::get<1>(cornerEdgeMono[6]) |= std::get<1>(cornerEdge[6])(index); + std::get<2>(cornerEdgeMono[6]) |= std::get<2>(cornerEdge[6])(index); + } + } + if(k == 0) { + pmlEdgeMono[2] |= pmlEdge[2](index); + edgeMono[2] |= edge[2](index); + pmlBndMono[2].first |= pmlBnd[2].first(index); + pmlBndMono[2].second |= pmlBnd[2].second(index); + } + if(j == nDomY-1) { + pmlEdgeMono[5] |= pmlEdge[5](index); + edgeMono[5] |= edge[5](index); + pmlBndMono[5].first |= pmlBnd[5].first(index); + pmlBndMono[5].second |= pmlBnd[5].second(index); + if(k == 0) { + pmlCornerMono[1] |= pmlCorner[1](index); + cornerMono[1] |= corner[1](index); + std::get<0>(pmlEdgeBndMono[1]) |= std::get<0>(pmlEdgeBnd[1])(index); + std::get<1>(pmlEdgeBndMono[1]) |= std::get<1>(pmlEdgeBnd[1])(index); + std::get<2>(pmlEdgeBndMono[1]) |= std::get<2>(pmlEdgeBnd[1])(index); + std::get<0>(cornerEdgeMono[1]) |= std::get<0>(cornerEdge[1])(index); + std::get<1>(cornerEdgeMono[1]) |= std::get<1>(cornerEdge[1])(index); + std::get<2>(cornerEdgeMono[1]) |= std::get<2>(cornerEdge[1])(index); + } + if(k == nDomZ-1) { + pmlCornerMono[5] |= pmlCorner[5](index); + cornerMono[5] |= corner[5](index); + std::get<0>(pmlEdgeBndMono[5]) |= std::get<0>(pmlEdgeBnd[5])(index); + std::get<1>(pmlEdgeBndMono[5]) |= std::get<1>(pmlEdgeBnd[5])(index); + std::get<2>(pmlEdgeBndMono[5]) |= std::get<2>(pmlEdgeBnd[5])(index); + std::get<0>(cornerEdgeMono[5]) |= std::get<0>(cornerEdge[5])(index); + std::get<1>(cornerEdgeMono[5]) |= std::get<1>(cornerEdge[5])(index); + std::get<2>(cornerEdgeMono[5]) |= std::get<2>(cornerEdge[5])(index); + } + } + if(k == nDomZ-1) { + pmlEdgeMono[10] |= pmlEdge[10](index); + edgeMono[10] |= edge[10](index); + pmlBndMono[10].first |= pmlBnd[10].first(index); + pmlBndMono[10].second |= pmlBnd[10].second(index); + } + } + if(j == 0) { + sigmaMono[3] |= sigma[3](index); + pmlMono[3] |= pml[3](index); + if(k == 0) { + pmlEdgeMono[3] |= pmlEdge[3](index); + edgeMono[3] |= edge[3](index); + pmlBndMono[3].first |= pmlBnd[3].first(index); + pmlBndMono[3].second |= pmlBnd[3].second(index); + } + if(k == nDomZ-1) { + pmlEdgeMono[11] |= pmlEdge[11](index); + edgeMono[11] |= edge[11](index); + pmlBndMono[11].first |= pmlBnd[11].first(index); + pmlBndMono[11].second |= pmlBnd[11].second(index); + } + } + if(k == 0) { + sigmaMono[4] |= sigma[4](index); + pmlMono[4] |= pml[4](index); + } + if(i == nDomX-1) { + sigmaMono[0] |= sigma[0](index); + pmlMono[0] |= pml[0](index); + if(j == 0) { + pmlEdgeMono[7] |= pmlEdge[7](index); + edgeMono[7] |= edge[7](index); + pmlBndMono[7].first |= pmlBnd[7].first(index); + pmlBndMono[7].second |= pmlBnd[7].second(index); + if(k == 0) { + pmlCornerMono[3] |= pmlCorner[3](index); + cornerMono[3] |= corner[3](index); + std::get<0>(pmlEdgeBndMono[3]) |= std::get<0>(pmlEdgeBnd[3])(index); + std::get<1>(pmlEdgeBndMono[3]) |= std::get<1>(pmlEdgeBnd[3])(index); + std::get<2>(pmlEdgeBndMono[3]) |= std::get<2>(pmlEdgeBnd[3])(index); + std::get<0>(cornerEdgeMono[3]) |= std::get<0>(cornerEdge[3])(index); + std::get<1>(cornerEdgeMono[3]) |= std::get<1>(cornerEdge[3])(index); + std::get<2>(cornerEdgeMono[3]) |= std::get<2>(cornerEdge[3])(index); + } + if(k == nDomZ-1) { + pmlCornerMono[7] |= pmlCorner[7](index); + cornerMono[7] |= corner[7](index); + std::get<0>(pmlEdgeBndMono[7]) |= std::get<0>(pmlEdgeBnd[7])(index); + std::get<1>(pmlEdgeBndMono[7]) |= std::get<1>(pmlEdgeBnd[7])(index); + std::get<2>(pmlEdgeBndMono[7]) |= std::get<2>(pmlEdgeBnd[7])(index); + std::get<0>(cornerEdgeMono[7]) |= std::get<0>(cornerEdge[7])(index); + std::get<1>(cornerEdgeMono[7]) |= std::get<1>(cornerEdge[7])(index); + std::get<2>(cornerEdgeMono[7]) |= std::get<2>(cornerEdge[7])(index); + } + } + if(k == 0) { + pmlEdgeMono[0] |= pmlEdge[0](index); + edgeMono[0] |= edge[0](index); + pmlBndMono[0].first |= pmlBnd[0].first(index); + pmlBndMono[0].second |= pmlBnd[0].second(index); + } + if(j == nDomY-1) { + pmlEdgeMono[4] |= pmlEdge[4](index); + edgeMono[4] |= edge[4](index); + pmlBndMono[4].first |= pmlBnd[4].first(index); + pmlBndMono[4].second |= pmlBnd[4].second(index); + if(k == 0) { + pmlCornerMono[0] |= pmlCorner[0](index); + cornerMono[0] |= corner[0](index); + std::get<0>(pmlEdgeBndMono[0]) |= std::get<0>(pmlEdgeBnd[0])(index); + std::get<1>(pmlEdgeBndMono[0]) |= std::get<1>(pmlEdgeBnd[0])(index); + std::get<2>(pmlEdgeBndMono[0]) |= std::get<2>(pmlEdgeBnd[0])(index); + std::get<0>(cornerEdgeMono[0]) |= std::get<0>(cornerEdge[0])(index); + std::get<1>(cornerEdgeMono[0]) |= std::get<1>(cornerEdge[0])(index); + std::get<2>(cornerEdgeMono[0]) |= std::get<2>(cornerEdge[0])(index); + } + if(k == nDomZ-1) { + pmlCornerMono[4] |= pmlCorner[4](index); + cornerMono[4] |= corner[4](index); + std::get<0>(pmlEdgeBndMono[4]) |= std::get<0>(pmlEdgeBnd[4])(index); + std::get<1>(pmlEdgeBndMono[4]) |= std::get<1>(pmlEdgeBnd[4])(index); + std::get<2>(pmlEdgeBndMono[4]) |= std::get<2>(pmlEdgeBnd[4])(index); + std::get<0>(cornerEdgeMono[4]) |= std::get<0>(cornerEdge[4])(index); + std::get<1>(cornerEdgeMono[4]) |= std::get<1>(cornerEdge[4])(index); + std::get<2>(cornerEdgeMono[4]) |= std::get<2>(cornerEdge[4])(index); + } + } + if(k == nDomZ-1) { + pmlEdgeMono[8] |= pmlEdge[8](index); + edgeMono[8] |= edge[8](index); + pmlBndMono[8].first |= pmlBnd[8].first(index); + pmlBndMono[8].second |= pmlBnd[8].second(index); + } + } + if(j == nDomY-1) { + sigmaMono[1] |= sigma[1](index); + pmlMono[1] |= pml[1](index); + if(k == 0) { + pmlEdgeMono[1] |= pmlEdge[1](index); + edgeMono[1] |= edge[1](index); + pmlBndMono[1].first |= pmlBnd[1].first(index); + pmlBndMono[1].second |= pmlBnd[1].second(index); + } + if(k == nDomZ-1) { + pmlEdgeMono[9] |= pmlEdge[9](index); + edgeMono[9] |= edge[9](index); + pmlBndMono[9].first |= pmlBnd[9].first(index); + pmlBndMono[9].second |= pmlBnd[9].second(index); + } + } + if(k == nDomZ-1) { + sigmaMono[5] |= sigma[5](index); + pmlMono[5] |= pml[5](index); + } + } + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > uMono("uMono", omega.getUnion(), gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > lambdaMono("lamdbaMono", gamma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + + formulationMono.integral(-grad(dof(uMono)), grad(tf(uMono)), omega.getUnion(), gauss); + formulationMono.integral(kappa * kappa * dof(uMono), tf(uMono), omega.getUnion(), gauss); + + formulationMono.integral(dof(lambda), tf(uMono), gamma, gauss); + formulationMono.integral(dof(uMono), tf(lambda), gamma, gauss); + if(benchmark == "scattering") { + formulationMono.integral(- fAnalytic, tf(lambda), gamma, gauss); + } + + SubproblemDomains domains; + domains.setOmega(omega.getUnion()); + domains.setSigma(sigmaMono); + domains.setPml(pmlMono); + domains.setPmlBnd(pmlBndMono); + domains.setPmlEdge(pmlEdgeMono); + domains.setEdge(edgeMono); + domains.setPmlEdgeBnd(pmlEdgeBndMono); + domains.setPmlCorner(pmlCornerMono); + domains.setCorner(cornerMono); + domains.setCornerEdge(cornerEdgeMono); + + SubproblemParameters parameters; + parameters.setGauss(gauss); + parameters.setKappa(kappa); + parameters.setNeumannOrder(neumannOrder); + parameters.setFieldOrder(fieldOrder); + parameters.setStab(stab); + + std::string bndExt = boundaryExt; + if(boundaryExt == "habc") { + bndExt += "_" + std::to_string(NExt) + "_" + std::to_string(thetaPade); + } + else if(boundaryExt == "pml") { + if(pmlMethodExt == "continuous") { + bndExt += "Continuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + else if(pmlMethodExt == "discontinuous") { + bndExt += "Discontinuous_" + std::to_string(pmlSizeExt) + "_" + pmlTypeExt; + } + } + gmshfem::msg::info << "Monodomain has boundaries [" << bndExt << ", " << bndExt << ", " << bndExt << ", " << bndExt << ", " << bndExt << ", " << bndExt << "]" << gmshfem::msg::endl; + Subproblem subproblem(formulationMono, uMono.name(), domains, parameters, bndExt, bndExt, bndExt, bndExt, bndExt, bndExt); + subproblem.writeFormulation(); + + formulationMono.pre(); + formulationMono.assemble(); + formulationMono.solve(); + + double num = 0.; + double den = 0.; + for(unsigned int i = 0; i < nDomX * nDomY * nDomZ; ++i) { + num += std::real(gmshfem::post::integrate(pow(abs(u(i) - uMono), 2), omega(i), gauss)); + den += std::real(gmshfem::post::integrate(pow(abs(uMono), 2), omega(i), gauss)); + } + + gmshfem::msg::info << "Error mono L2 = " << std::sqrt(num/den) << gmshfem::msg::endl; + + for(unsigned int i = 0; i < nDomX * nDomY * nDomZ; ++i) { + if(gmshddm::mpi::isItMySubdomain(i)) { + if(saveEMono) { + gmshfem::post::save(u(i) - uMono, omega(i), "eMono_" + std::to_string(i)); + } + if(saveUMono) { + gmshfem::post::save(uMono, omega(i), "uMono_" + std::to_string(i)); + } + } + } + + if(fileName != "none") { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << iterMax << formulation.relativeResidual().back() << std::sqrt(num/den) << gmshfem::csv::endl; + file.close(); + } + } + + if(wavenumberPlot) { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << k << formulation.relativeResidual().size()-1 << gmshfem::csv::endl; + file.close(); + } + + if(meshPlot) { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << (2*pi/k)/lc << lc << 1./lc << formulation.relativeResidual().size()-1 << gmshfem::csv::endl; + file.close(); + } + } + + +} diff --git a/examples/helmholtz/crossPoints/ddm3D.h b/examples/helmholtz/crossPoints/ddm3D.h new file mode 100755 index 0000000000000000000000000000000000000000..7013c6cc4427b3fee87282774d9620a3a7acf85e --- /dev/null +++ b/examples/helmholtz/crossPoints/ddm3D.h @@ -0,0 +1,11 @@ +#ifndef H_DDM3D +#define H_DDM3D + +namespace D3 { + + void ddm(); + +} + + +#endif // H_DDM3D diff --git a/examples/helmholtz/crossPoints/main.cpp b/examples/helmholtz/crossPoints/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d056e7aa16dce53f8326b9d823ce8421130f37fb --- /dev/null +++ b/examples/helmholtz/crossPoints/main.cpp @@ -0,0 +1,33 @@ +#include "monoDomain.h" +#include "ddm2D.h" +#include "ddm3D.h" + +#include <gmshddm/GmshDdm.h> + +#include <gmshfem/Message.h> + +int main(int argc, char **argv) +{ + gmshddm::common::GmshDdm gmshDdm(argc, argv); + + std::string problem = "monoDomain2D"; // monoDomain, ddm + gmshDdm.userDefinedParameter(problem, "problem"); + + if(problem == "monoDomain2D") { + D2::monoDomain(); + } + else if(problem == "monoDomain3D") { + D3::monoDomain(); + } + else if(problem == "ddm2D") { + D2::ddm(); + } + else if(problem == "ddm3D") { + D3::ddm(); + } + else { + gmshfem::msg::error << "Unknown 'problem = " << problem << "'" << gmshfem::msg::endl; + } + + return 0; +} diff --git a/examples/helmholtz/crossPoints/marmousi.dat b/examples/helmholtz/crossPoints/marmousi.dat new file mode 100644 index 0000000000000000000000000000000000000000..1a104c81efda7f9b4958463aab68ffa6ea0f0eb1 --- /dev/null +++ b/examples/helmholtz/crossPoints/marmousi.dat @@ -0,0 +1,125 @@ +384 122 +0 24 48 72 96 120 144 168 192 216 240 264 288 312 336 360 384 408 432 456 480 504 528 552 576 600 624 648 672 696 720 744 768 792 816 840 864 888 912 936 960 984 1008 1032 1056 1080 1104 1128 1152 1176 1200 1224 1248 1272 1296 1320 1344 1368 1392 1416 1440 1464 1488 1512 1536 1560 1584 1608 1632 1656 1680 1704 1728 1752 1776 1800 1824 1848 1872 1896 1920 1944 1968 1992 2016 2040 2064 2088 2112 2136 2160 2184 2208 2232 2256 2280 2304 2328 2352 2376 2400 2424 2448 2472 2496 2520 2544 2568 2592 2616 2640 2664 2688 2712 2736 2760 2784 2808 2832 2856 2880 2904 2928 2952 2976 3000 3024 3048 3072 3096 3120 3144 3168 3192 3216 3240 3264 3288 3312 3336 3360 3384 3408 3432 3456 3480 3504 3528 3552 3576 3600 3624 3648 3672 3696 3720 3744 3768 3792 3816 3840 3864 3888 3912 3936 3960 3984 4008 4032 4056 4080 4104 4128 4152 4176 4200 4224 4248 4272 4296 4320 4344 4368 4392 4416 4440 4464 4488 4512 4536 4560 4584 4608 4632 4656 4680 4704 4728 4752 4776 4800 4824 4848 4872 4896 4920 4944 4968 4992 5016 5040 5064 5088 5112 5136 5160 5184 5208 5232 5256 5280 5304 5328 5352 5376 5400 5424 5448 5472 5496 5520 5544 5568 5592 5616 5640 5664 5688 5712 5736 5760 5784 5808 5832 5856 5880 5904 5928 5952 5976 6000 6024 6048 6072 6096 6120 6144 6168 6192 6216 6240 6264 6288 6312 6336 6360 6384 6408 6432 6456 6480 6504 6528 6552 6576 6600 6624 6648 6672 6696 6720 6744 6768 6792 6816 6840 6864 6888 6912 6936 6960 6984 7008 7032 7056 7080 7104 7128 7152 7176 7200 7224 7248 7272 7296 7320 7344 7368 7392 7416 7440 7464 7488 7512 7536 7560 7584 7608 7632 7656 7680 7704 7728 7752 7776 7800 7824 7848 7872 7896 7920 7944 7968 7992 8016 8040 8064 8088 8112 8136 8160 8184 8208 8232 8256 8280 8304 8328 8352 8376 8400 8424 8448 8472 8496 8520 8544 8568 8592 8616 8640 8664 8688 8712 8736 8760 8784 8808 8832 8856 8880 8904 8928 8952 8976 9000 9024 9048 9072 9096 9120 9144 9168 9192 +-2904 -2880 -2856 -2832 -2808 -2784 -2760 -2736 -2712 -2688 -2664 -2640 -2616 -2592 -2568 -2544 -2520 -2496 -2472 -2448 -2424 -2400 -2376 -2352 -2328 -2304 -2280 -2256 -2232 -2208 -2184 -2160 -2136 -2112 -2088 -2064 -2040 -2016 -1992 -1968 -1944 -1920 -1896 -1872 -1848 -1824 -1800 -1776 -1752 -1728 -1704 -1680 -1656 -1632 -1608 -1584 -1560 -1536 -1512 -1488 -1464 -1440 -1416 -1392 -1368 -1344 -1320 -1296 -1272 -1248 -1224 -1200 -1176 -1152 -1128 -1104 -1080 -1056 -1032 -1008 -984 -960 -936 -912 -888 -864 -840 -816 -792 -768 -744 -720 -696 -672 -648 -624 -600 -576 -552 -528 -504 -480 -456 -432 -408 -384 -360 -336 -312 -288 -264 -240 -216 -192 -168 -144 -120 -96 -72 -48 -24 0 +3500 3500 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3120 3120 3120 3120 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 3900 4200 4200 4300 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3700 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 4400 4600 4600 4600 4600 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3550 3550 3550 3550 3550 4050 4050 4050 4050 4050 4050 4050 4050 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 4050 4050 4050 4050 4050 4050 4050 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 +3500 3500 3500 3500 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3050 3050 3550 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3700 3700 3700 3700 3700 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3600 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3550 3550 3550 3550 3550 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 3750 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 3550 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 +4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3600 3600 3600 3600 3600 4440 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3550 3550 3550 3550 3550 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 3550 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 +4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3120 3120 3120 3120 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 3900 4200 4200 4300 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3550 3550 3550 3550 3550 3550 3550 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 +4440 4550 4550 4550 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3750 3450 3450 3450 3450 3450 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3600 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3700 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 4050 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 +4440 4440 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3900 3700 3700 3700 3700 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3600 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 +4120 4440 4440 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3120 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3600 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3700 3700 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 +3600 4120 4440 4440 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3120 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3600 3600 3600 3600 3600 4440 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 +3600 3600 4120 4440 4440 4550 4550 4550 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3450 3120 3120 3120 3120 3120 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 +3600 3600 3600 4120 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3450 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3900 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 4400 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 +3600 3600 3600 3600 4120 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3450 3120 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3540 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3300 +5500 5500 5500 5500 5500 4120 4440 4440 4440 4550 4550 4550 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3750 3750 3450 3450 3450 3450 3450 3450 3120 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3600 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3800 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3450 3450 3450 3450 3120 3120 3120 3120 3120 3900 3900 3800 3800 3800 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3800 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 4400 4400 4400 4600 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 3800 3800 3800 3800 3800 3800 3800 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3470 3470 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3800 3540 3540 3540 3540 3380 3380 3380 3380 3380 3380 3380 3400 3400 3400 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3900 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3450 3120 3120 3900 3900 3900 3800 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4600 4600 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3470 3470 3470 3470 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3900 4200 4200 4200 4300 4300 4300 4300 3300 3300 3300 3300 3200 3200 3200 3200 3200 3200 3200 3050 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3600 3350 3350 3350 3350 3200 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3120 3120 3900 3900 3900 3800 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 4400 4400 4400 4600 4600 4600 4600 4600 4600 4600 4600 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4700 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3200 3200 3050 3050 3050 3050 3050 3550 3550 3550 3550 3550 3550 3550 3250 3250 3250 3250 3900 3700 3700 3700 3700 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3200 3200 3600 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3120 3120 3900 3900 3900 3800 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3380 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3800 3800 3800 3800 3800 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 4400 4400 4400 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4600 4400 4400 4400 4400 4400 4400 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 4200 3800 3800 3800 3800 3800 3800 3800 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3580 3580 3580 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3900 3900 3700 3700 3700 3700 3600 3600 3600 3350 3350 3350 3350 3350 3200 3200 3200 3200 3200 3600 3600 3600 3600 4440 4440 4440 4550 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3380 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3200 3200 3600 3600 3600 4120 4440 4440 4440 4550 4550 4550 4550 4550 3500 3500 3500 3500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2700 2700 2700 2700 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 3230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3500 3500 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3380 3200 3200 3200 3750 3750 3750 3750 3750 3750 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4560 4670 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3750 3750 3750 3450 3450 3450 3120 3120 3900 3900 3900 3900 3800 3800 3800 3800 3800 3800 3540 3540 3540 3540 3540 3540 3380 3380 3700 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4560 4560 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2700 2700 2700 2700 2700 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3540 3540 3540 3540 3380 3380 3380 3700 3700 3700 4230 4230 4230 4230 4230 4230 4560 4560 4560 4560 4560 4560 4670 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4560 4560 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 4560 4560 4560 4670 4670 4670 4670 4670 4670 3580 3580 3580 3580 3580 3580 3580 3580 3580 3470 3470 3470 3470 3470 3300 3300 3530 3530 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4560 4560 4560 4560 4560 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3580 3580 3470 3470 3470 3470 3470 3300 3300 3300 3530 3530 3530 3530 3530 3530 3530 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4670 4560 4560 4560 4560 4560 4230 4230 +5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3530 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4670 4560 4560 4560 4560 4560 4230 4230 4230 4230 3380 +2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4670 4560 4560 4560 4560 4560 4560 4230 4230 4230 3380 3380 3380 3380 +2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 4230 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4670 4560 4560 4560 4560 4560 4560 4230 4230 4230 3380 3380 3380 3380 3380 3380 3540 +2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 5500 3200 3200 5500 5500 5500 5500 5500 5500 5500 5500 5500 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3530 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4670 4560 4560 4560 4560 4560 4560 4230 4230 4230 4230 3380 3380 3380 3380 3380 3380 3540 3540 3540 +2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3200 3200 3200 3200 3200 3200 3200 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4670 4560 4560 4560 4560 4560 4230 4230 4230 4230 4230 3380 3380 3380 3380 3380 3380 3540 3540 3540 3540 3540 3540 +4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2440 2440 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3650 3650 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3470 3470 3470 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 3580 4670 4670 4670 4670 4560 4560 4560 4560 4560 4230 4230 4230 4230 3380 3380 3380 3380 3380 3380 3380 3540 3540 3540 3540 3540 3540 3540 3800 3800 +4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3280 3280 3280 3280 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 3280 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2440 2440 2440 2440 2440 2440 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3600 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 4560 4560 4560 4230 3380 3380 3380 3380 3380 3380 3380 3380 3380 3540 3540 3540 3540 3540 3540 3540 3800 3800 3800 3800 3800 +3265 3265 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 3265 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2440 2440 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3600 3600 3600 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 3800 3900 3900 +3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3050 3050 3050 3050 3050 3050 3050 3050 3050 3050 3050 3050 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3050 3050 3050 3050 3050 3050 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 3250 4000 4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2440 2440 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3035 3235 3235 3235 3235 3235 3235 3235 3235 3235 3235 3235 3235 3235 3235 4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 3020 3020 3020 3020 3020 3020 3020 3220 3220 3220 3220 3220 3220 3220 3220 3220 3220 3220 3220 4000 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3600 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3155 3155 3155 3155 3155 3155 3155 3155 3155 3155 3155 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 3005 2935 2935 2935 2935 2935 2935 2935 2935 2935 3005 3005 3005 3005 3005 3205 3205 3205 3205 3205 3205 3205 3205 3205 3205 3205 3205 4000 4000 4000 4000 4000 4000 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3800 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +2990 2990 2990 2990 2990 2990 2990 2990 2990 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 2870 2870 2870 2870 2870 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 3140 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 2870 3140 3140 3140 3140 3140 2990 2990 2990 2990 2990 2990 2990 2990 2920 2920 2920 2920 2920 2990 2990 2990 2990 2990 3190 3190 3190 3190 3190 3190 3190 3190 3190 3190 3190 3190 4000 4000 4000 4000 2500 2500 2500 2500 2650 2650 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2975 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 3125 3125 3125 3125 2975 2975 2975 2905 2905 2905 2905 2905 2975 2975 2975 2975 2975 3175 3175 3175 3175 3175 3175 3175 3175 3175 3175 3175 4000 4000 4000 2500 2500 2500 2500 2650 2440 2440 2440 2440 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2960 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 3110 3110 3110 2960 2960 2890 2890 2890 2890 2890 2890 2960 2960 2960 2960 2960 2960 2960 3160 3160 3160 3160 3160 3160 4000 4000 2500 2500 2500 2500 2650 2440 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3550 3550 3550 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 5500 5500 5500 5500 5500 5500 5500 5500 5500 5500 +2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2945 2825 2825 2825 2825 2825 2825 2825 2825 3095 3095 3095 3095 2945 2875 2875 2875 2875 2875 2875 2945 2945 2945 2945 2945 3145 3145 3145 3145 3145 3145 4000 4000 2500 2500 2500 2500 2650 2440 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3300 3550 3550 3550 3550 3550 3550 3550 3550 3800 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 5500 5500 5500 5500 +2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2930 2930 2930 2930 2930 2930 2930 2930 2930 2930 3650 3350 3350 3350 3350 2930 2930 2930 2930 2930 2930 2930 2930 2930 2810 2810 2810 2810 2810 2810 2810 3080 3080 3080 2930 2860 2860 2860 2860 2860 2930 2930 2930 2930 3130 3130 3130 3130 3130 4000 4000 2500 2500 2500 2500 2500 2650 2440 2440 2440 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3800 3800 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 +2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2915 2915 2915 2915 2915 3500 3500 3500 3350 3350 3350 3350 3350 3350 3350 2915 2915 2915 2915 2915 2915 2795 2795 2795 2795 2795 2795 2795 3065 3065 2915 2845 2845 2845 2845 2915 2915 2915 2915 3115 3115 3115 3115 4000 4000 4000 2500 2500 2500 2500 2650 2650 2440 2440 2440 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3550 3800 3800 3800 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 +2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 3150 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2880 2900 2900 2900 2900 2900 3500 3500 3500 3500 3500 3650 3650 3650 3350 3350 3350 3350 2900 2900 2900 2900 2900 2780 2780 2780 2780 2780 2780 3050 3050 2900 2830 2830 2830 2830 2900 2900 2900 3100 3100 3100 3100 3100 4000 4000 2500 2500 2500 2500 2500 2650 2440 2440 2440 2440 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3550 3550 3550 3550 3550 3550 3550 3550 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 +2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 2865 3135 3135 3135 3135 3135 3135 2865 2865 2865 2865 2865 2865 2865 2865 2865 2885 2885 2885 2885 2885 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 3350 3500 2885 2885 2885 2885 2765 2765 2765 2765 2765 3035 3035 2885 2815 2815 2815 2885 2885 2885 3085 3085 3085 3085 3085 4000 4000 4000 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3800 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4000 4000 4000 4000 +2850 2850 3120 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2850 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2850 2850 2850 2850 2850 2850 2850 3120 3120 3120 3120 3120 3120 3120 2850 2850 2850 2850 2850 2850 2850 2850 2870 2870 2870 2870 2870 2870 3500 3500 3500 3500 3650 3650 3650 3650 3650 3350 3350 3500 2870 2870 2870 2870 2750 2750 2750 2750 2750 3020 2870 2800 2800 2800 2870 2870 2870 3070 3070 3070 3070 3070 4000 4000 4000 2500 2500 2500 2500 2650 2650 2650 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4450 4450 4450 4450 4450 4450 4450 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4450 4450 4450 +2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 3105 3105 3105 3105 3105 3105 3105 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2835 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2835 2835 2835 2835 3105 3105 3105 3105 3105 3105 3105 3105 2835 2835 2835 2835 2835 2835 2835 2835 2835 2855 2855 2855 2855 2855 3500 3500 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2855 2855 2855 2855 2735 2735 2735 2735 2735 2855 2785 2785 2785 2855 2855 2855 3055 3055 3055 3055 3055 4000 4000 4000 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4450 4450 4450 4450 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 3055 4000 4000 4000 4000 4000 4000 4000 4000 +2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 3090 3090 3090 3090 3090 3090 3090 3090 3090 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2820 2790 2790 2790 2790 2790 2790 2790 2820 2820 2820 2820 3090 3090 3090 3090 3090 3090 3090 3090 2820 2820 2820 2820 2820 2820 2820 2820 2820 2840 2840 2840 2840 2840 2840 3500 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2840 2840 2840 2840 2720 2720 2720 2720 2990 2770 2770 2770 2840 2840 2840 3040 3040 3040 3040 3040 4000 4000 4000 4000 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2440 2440 2440 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 4000 4000 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4450 4450 4450 4450 4000 4000 4000 4000 4000 4000 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 3040 4000 4000 +4225 4225 4225 4225 4225 4225 4225 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 4325 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 3075 3075 3075 3075 3075 3075 3075 3075 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2805 2775 2775 2775 2775 2775 2775 2775 2805 2805 2805 3075 3075 3075 3075 3075 3075 3075 3075 3075 2805 2805 2805 2805 2805 2805 2805 2805 2805 2825 2825 2825 2825 2825 2825 2825 3500 3500 3500 3650 3650 3350 3350 3500 3500 2825 2825 2825 2825 2705 2705 2705 2705 2975 2825 2755 2755 2825 2825 2825 2825 3025 3025 3025 3025 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 4000 4000 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 3770 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4000 4000 4000 4000 4000 4000 4000 3025 3025 3025 3025 3025 3025 3025 3025 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3225 3025 3025 3025 3025 3025 3025 3025 +4366 4366 4366 4366 4366 4366 4366 4366 4366 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4186 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 4286 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2810 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 3060 3060 3060 3060 2790 2790 2790 2790 2790 2790 2790 2790 2790 2760 2760 2760 2760 2760 2760 2760 2790 2790 2790 3060 3060 3060 3060 3060 3060 3060 3060 3060 2790 2790 2790 2790 2790 2790 2790 2790 2790 2810 2810 2810 2810 2810 2810 3500 3500 3500 3650 3650 3350 3350 3500 3500 2810 2810 2810 2810 2810 2690 2690 2690 2960 2810 2740 2740 2810 2810 2810 2810 3010 3010 3010 3010 3010 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2650 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 3200 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2500 2500 2500 2500 2500 2500 2500 2500 4450 4000 4000 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3010 3010 3010 3010 3010 3010 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3210 3010 3010 +4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4327 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4147 4247 4247 4247 4247 4247 4247 4247 4247 4247 4247 4247 4247 4247 4247 4247 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2795 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 3045 3045 3045 3045 2775 2775 2775 2775 2775 2745 2745 2745 2745 2745 2745 2745 2775 2775 2775 2775 3045 3045 3045 3045 3045 3045 3045 3045 2775 2775 2775 2775 2775 2775 2775 2775 2775 2775 2795 2795 2795 2795 2795 3500 3500 3500 3650 3650 3350 3350 3500 3500 2795 2795 2795 2795 2795 2675 2675 2675 2945 2795 2725 2725 2795 2795 2795 2795 2995 2995 2995 2995 2995 2995 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 4450 4450 4450 4450 4450 4450 4450 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 2995 3195 3195 3195 3195 3195 3195 3195 3195 3195 3195 3195 3195 3195 3195 +4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4148 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4288 4108 4108 4108 4108 4108 4108 4108 4108 4108 4108 4108 4108 4208 4208 4208 4208 4208 4208 4208 4208 4208 4208 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2680 2680 2680 2680 2680 2680 2680 2680 2680 2680 2680 2680 3030 3030 3030 3030 2760 2760 2760 2760 2730 2730 2730 2730 2730 2730 2760 2760 2760 2760 3030 3030 3030 3030 3030 3030 3030 3030 3030 2760 2760 2760 2760 2760 2760 2760 2760 2760 2780 2780 2780 2780 2780 3500 3500 3500 3650 3650 3350 3350 3350 3500 2780 2780 2780 2780 2780 2660 2660 2660 2930 2710 2710 2710 2710 2780 2780 2780 2980 2980 2980 2980 2980 2980 2980 2980 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 3770 3770 3770 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2980 2980 4000 4000 4000 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2980 2780 2780 2780 2780 2780 2780 2780 2780 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2710 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2780 2980 2980 2980 2980 2980 2980 2980 2980 3180 3180 3180 3180 3180 3180 3180 3180 +2659 2659 2659 2659 2659 2659 2659 2659 2659 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4109 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4249 4069 4069 4069 4069 4069 4069 4069 4069 4069 4169 4169 4169 4169 4169 4169 4169 4169 2765 2765 2765 2765 2765 2765 2765 2765 2765 2765 2765 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 3015 3015 2745 2745 2745 2745 2715 2715 2715 2715 2715 2715 2715 2745 2745 2745 3015 3015 3015 3015 3015 3015 3015 3015 3015 2745 2745 2745 2745 2745 2745 2745 2745 2745 2765 2765 2765 2765 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 2765 2765 2765 2765 2765 2645 2645 2645 2765 2695 2695 2695 2695 2765 2765 2765 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2440 4450 4450 4000 4000 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 3165 3165 2965 2965 2965 2965 4000 4000 4000 4000 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 4450 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2965 2765 2765 2765 2765 2765 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2695 2765 2765 2765 2765 2765 2965 2965 2965 2965 2965 2965 3165 3165 3165 +2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4070 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 4030 4030 4030 4030 4030 4030 4030 4130 4130 4130 4130 4130 4130 4130 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2650 2650 2650 2650 2650 2650 2650 3000 3000 2730 2730 2730 2700 2700 2700 2700 2700 2700 2700 2730 2730 2730 3000 3000 3000 3000 3000 3000 3000 3000 3000 3000 2730 2730 2730 2730 2730 2730 2730 2730 2750 2750 2750 2750 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 2750 2750 2750 2750 2630 2630 2630 2900 2750 2750 2680 2680 2680 2750 2750 2750 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 2950 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2950 4000 4000 4450 4450 4450 4000 4000 3770 3770 3770 3770 4000 4000 4000 4000 4000 4000 4000 4000 4000 3150 3150 3150 3150 3150 3150 2950 2950 2950 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2680 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2680 2680 2680 2680 2680 2680 2680 2680 2680 2680 2680 2680 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2950 2950 2950 2950 2950 2950 2950 2950 2950 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2750 2680 2680 2680 2680 2680 2680 2680 2680 2750 2750 2750 2750 2950 2950 2950 2950 2950 +2701 2701 2701 2701 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 2641 4031 4031 4031 4031 4031 4031 4031 4031 4031 4031 4031 4031 4171 4171 4171 4171 4171 4171 4171 4171 4171 4171 4171 4171 3991 3991 3991 3991 3991 3991 3991 4091 4091 4091 4091 4091 4091 2735 2735 2735 2735 2735 2735 2735 2735 2635 2635 2635 2635 2635 2985 2985 2715 2715 2715 2685 2685 2685 2685 2685 2685 2685 2715 2715 2715 2985 2985 2985 2985 2985 2985 2985 2985 2985 2985 2715 2715 2715 2715 2715 2715 2715 2735 2735 2735 2735 3500 3500 3500 3500 3650 3650 3650 3350 3350 3350 3500 2735 2735 2735 2735 2615 2615 2615 2885 2735 2665 2665 2665 2665 2735 2735 2735 2735 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 2440 3135 3135 3135 2935 2935 4000 4000 4450 4450 4450 4000 4000 4000 3770 3770 3770 3770 3770 3770 3770 4000 4000 2935 2935 2935 3135 3135 3135 3135 3135 3135 3135 2935 2935 2935 2935 2935 2935 2935 2935 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 4000 2735 2735 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2735 2735 2735 2735 2735 2735 2735 2735 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2935 2735 2735 2735 2735 2735 2735 2735 2665 2665 2665 2665 2665 2735 2735 2735 2735 +2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2692 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 2632 3992 3992 3992 3992 3992 3992 3992 3992 4132 4132 4132 4132 4132 4132 4132 4132 4132 4132 4132 4132 3952 3952 3952 3952 3952 3952 3952 4052 4052 4052 4052 2720 2720 2720 2720 2720 2720 2720 2720 2620 2620 2620 2970 2970 2700 2700 2700 2700 2670 2670 2670 2670 2670 2670 2700 2700 2700 2970 2970 2970 2970 2970 2970 2970 2970 2970 2970 2700 2700 2700 2700 2700 2700 2700 2720 2720 2720 2720 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 3500 2720 2720 2720 2720 2600 2600 2870 2870 2720 2650 2650 2650 2650 2650 2720 2720 2720 2920 2920 2920 2920 2920 2920 2920 3120 3120 2920 2920 2920 2920 2920 2920 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2920 3120 3120 3120 3120 3120 3120 2920 2920 2920 4000 4000 4450 4450 4450 4000 4000 4000 3770 3770 3770 3770 3770 4000 2720 2720 2920 2920 2920 2920 3120 3120 3120 3120 3120 3120 3120 3120 3120 3120 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2720 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2920 2720 2720 2720 2720 2720 2650 2650 2650 2650 2650 +2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2683 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 2623 3953 3953 3953 3953 3953 3953 3953 3953 4093 4093 4093 4093 4093 4093 4093 4093 4093 4093 4093 3913 3913 3913 3913 3913 4013 4013 4013 4013 2705 2705 2705 2705 2705 2705 2605 2605 2605 2955 2955 2685 2685 2685 2685 2655 2655 2655 2655 2655 2655 2685 2685 2685 2955 2955 2955 2955 2955 2955 2955 2955 2955 2685 2685 2685 2685 2685 2685 2685 2705 2705 2705 2705 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 3500 2705 2705 2705 2585 2585 2585 2855 2855 2705 2635 2635 2635 2635 2635 2635 2705 2705 2705 2905 2905 2905 2905 2905 2905 2905 3105 3105 3105 2905 2905 2905 2905 2905 4000 4000 4000 4000 4000 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2650 2705 2905 2905 2905 3105 3105 3105 3105 3105 3105 2905 2905 2905 2905 4000 4000 4450 4450 4450 4450 4000 4000 4000 4000 2635 2635 2635 2635 2705 2705 2905 2905 2905 2905 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 3105 2905 2905 2905 2905 2905 2905 2905 2855 2855 2855 2855 2855 2705 2705 2705 2705 2705 2905 2905 2905 2905 2905 2905 2905 2905 2905 2905 2705 2705 2705 2705 2705 2705 2705 2705 2705 2705 2705 2705 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2855 2705 2705 2705 2705 2705 2705 2705 2705 2705 2705 2905 2905 2905 2905 2905 2905 2905 2905 2905 2905 2905 2905 2705 2705 2705 2705 2705 2635 +2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2674 2614 2614 2614 2614 2614 2614 2614 2614 2614 2614 2614 2614 2614 2614 3914 3914 3914 3914 3914 3914 3914 3914 4054 4054 4054 4054 4054 4054 4054 4054 4054 4054 3874 3874 3874 3874 3874 3974 3974 2690 2690 2690 2690 2690 2690 2590 2590 2590 2940 2940 2670 2670 2670 2670 2640 2640 2640 2640 2640 2670 2670 2670 2940 2940 2940 2940 2940 2940 2940 2940 2940 2940 2670 2670 2670 2670 2670 2670 2670 2690 2690 2690 2690 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 3500 3500 2690 2690 2690 2570 2570 2570 2840 2840 2690 2690 2620 2620 2620 2620 2620 2620 2690 2690 2690 2890 2890 2890 2890 2890 2890 2890 3090 3090 3090 2890 2890 2890 2890 2890 4000 4000 4000 4000 4450 4450 4450 4450 4450 4000 4000 4000 3770 2500 2500 2500 2500 2500 2500 2500 2500 2650 2650 2650 2650 2690 2620 2620 2690 2890 2890 2890 3090 3090 3090 3090 3090 3090 3090 2890 2890 2890 4000 4000 4000 4000 4450 4450 4450 3090 2690 2620 2620 2620 2620 2620 2620 2690 2690 2890 2890 2890 2890 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 3090 2570 2570 2570 2570 2840 2840 2840 2840 2840 2840 2840 2840 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2690 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2840 2690 2690 2690 2690 2690 2690 2690 2890 2890 2890 2890 2890 2890 2890 2890 2890 2890 2690 2690 2690 +2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2665 2605 2605 2605 2605 2605 2605 2605 2605 2605 2605 2605 3875 3875 3875 3875 3875 3875 3875 4015 4015 4015 4015 4015 4015 4015 4015 4015 4015 3835 3835 3835 3935 3935 3935 2675 2675 2675 2675 2675 2575 2575 2575 2925 2925 2655 2655 2655 2655 2625 2625 2625 2625 2625 2655 2655 2655 2925 2925 2925 2925 2925 2925 2925 2925 2925 2925 2655 2655 2655 2655 2655 2655 2675 2675 2675 2675 3500 3500 3500 3500 3650 3650 3650 3350 3350 3350 3500 3500 2675 2675 2675 2555 2555 2555 2555 2825 2825 2675 2675 2675 2605 2605 2605 2605 2605 2675 2675 2675 2675 2875 2875 2875 2875 2875 2875 3075 3075 3075 3075 2875 2875 2875 2875 4000 4000 4000 4450 4450 4450 4450 4000 4000 4000 3770 3770 3770 3770 3770 2500 2500 2500 2500 2500 2875 2675 2675 2675 2605 2605 2675 2875 2875 2875 3075 3075 3075 3075 3075 3075 3075 3075 2875 2875 2875 2875 4000 4000 4000 2675 2675 2675 2675 2605 2605 2605 2605 2605 2605 2605 2675 2675 2875 2875 2875 2875 3075 3075 3075 3075 3075 3075 3075 3075 3075 3075 3075 3075 3075 3075 3075 2675 2675 2675 2555 2555 2555 2555 2555 2555 2555 2555 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2825 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2555 2825 2825 2825 2825 2825 2825 2825 2825 2825 2675 2675 2675 2675 2675 2675 2675 2875 2875 2875 2875 2875 2875 2875 2875 +2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2536 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2656 2596 2596 2596 2596 2596 2596 2596 2596 2596 3836 3836 3836 3836 3836 3836 3836 3836 3976 3976 3976 3976 3976 3976 3976 3976 3796 3796 3796 3896 3896 3896 2660 2660 2660 2660 2660 2560 2560 2560 2910 2910 2640 2640 2640 2640 2610 2610 2610 2610 2640 2640 2640 2910 2910 2910 2910 2910 2910 2910 2910 2910 2910 2640 2640 2640 2640 2640 2640 2660 2660 2660 2660 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 3500 2660 2660 2660 2540 2540 2540 2540 2810 2810 2810 2810 2660 2660 2590 2590 2590 2590 2590 2660 2660 2660 2860 2860 2860 2860 2860 2860 3060 3060 3060 3060 3060 2860 2860 2860 4000 4000 4000 4450 4450 4450 4000 4000 4000 3770 3770 3770 3770 3770 4000 4000 2500 2860 2860 2860 2660 2660 2660 2590 2590 2660 2860 2860 2860 3060 3060 3060 3060 3060 3060 3060 3060 2860 2860 2860 2860 2860 2860 2860 2660 2660 2660 2660 2660 2590 2590 2590 2590 2590 2590 2590 2660 2660 2860 2860 2860 2860 2860 3060 3060 3060 3060 3060 3060 3060 3060 3060 3060 2660 2660 2660 2660 2660 2660 2660 2660 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2660 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2810 2810 2810 2810 2810 2810 2810 2660 2660 2660 2660 2660 2660 2860 2860 2860 2860 +2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2527 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2647 2587 2587 2587 2587 2587 2587 2587 2587 2587 3797 3797 3797 3797 3797 3797 3797 3797 3937 3937 3937 3937 3937 3937 3757 3757 3757 3857 3857 3857 2645 2645 2645 2645 2545 2545 2545 2545 2895 2895 2625 2625 2625 2595 2595 2595 2595 2595 2625 2625 2895 2895 2895 2895 2895 2895 2895 2895 2895 2895 2625 2625 2625 2625 2625 2625 2645 2645 2645 2645 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 3500 2645 2645 2645 2645 2525 2525 2525 2525 2795 2795 2795 2645 2645 2645 2575 2575 2575 2575 2575 2645 2645 2645 2845 2845 2845 2845 2845 2845 3045 3045 3045 3045 2845 2845 2845 4000 4000 4450 4450 4450 4450 4000 4000 4000 3770 3770 3770 3770 2645 2645 2845 2845 2845 2845 2645 2645 2575 2575 2575 2645 2845 2845 2845 3045 3045 3045 3045 3045 3045 3045 3045 3045 3045 2845 2845 2845 2845 2845 2845 2645 2645 2645 2645 2645 2575 2575 2575 2575 2575 2575 2575 2645 2645 2845 2845 2845 2845 2845 3045 3045 3045 3045 3045 3045 3045 3500 3500 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2645 2525 2525 2525 2525 2525 2525 2525 2525 2795 2795 2795 2795 2795 2795 2645 2645 2645 2645 2645 2845 +2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2558 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2518 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2638 2578 2578 2578 2578 2578 2578 2578 2578 2578 3758 3758 3758 3758 3758 3758 3758 3898 3898 3898 3898 3898 3898 3718 3718 3718 3818 3818 2630 2630 2630 2630 2630 2530 2530 2530 2530 2880 2880 2610 2610 2580 2580 2580 2580 2580 2610 2610 2610 2880 2880 2880 2880 2880 2880 2880 2880 2880 2610 2610 2610 2610 2610 2610 2630 2630 2630 2630 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 3500 2630 2630 2630 2630 2510 2510 2510 2510 2780 2780 2780 2630 2630 2630 2630 2560 2560 2560 2560 2560 2630 2630 2830 2830 2830 2830 2830 2830 3030 3030 3030 3030 2830 2830 2830 4000 4000 4450 4450 4450 4000 4000 4000 3770 4000 2630 2630 2630 2630 2830 2830 2830 2630 2630 2630 2560 2560 2560 2630 2830 2830 2830 3030 3030 3030 3030 3030 3030 3030 2630 2630 2830 2830 2830 2830 2830 2830 2830 2830 2830 2630 2630 2630 2630 2560 2560 2560 2560 2560 2560 2560 2630 2630 2630 2830 2830 2830 2830 2830 2830 2830 2830 3500 3500 3500 3500 3500 3500 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 3500 3500 3500 3500 3500 3500 3500 3500 3500 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2510 2510 2510 2510 2510 2510 2780 2780 2780 2780 2780 2630 2630 2630 +2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2639 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2549 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2509 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2629 2569 2569 2569 2569 2569 2569 2569 2569 3719 3719 3719 3719 3719 3719 3719 3859 3859 3859 3859 3859 3679 3679 3679 3779 3779 2615 2615 2615 2615 2515 2515 2515 2515 2515 2865 2595 2595 2595 2565 2565 2565 2565 2595 2595 2595 2865 2865 2865 2865 2865 2865 2865 2865 2865 2595 2595 2595 2595 2595 2595 2615 2615 2615 2615 3500 3500 3500 3500 3650 3650 3650 3350 3350 3350 3500 3500 2615 2615 2615 2615 2495 2495 2495 2495 2765 2765 2765 2615 2815 2615 2615 2545 2545 2545 2545 2545 2615 2615 2815 2815 2815 2815 2815 2815 3015 3015 3015 3015 2815 2815 4000 4000 4000 4450 4450 4000 4000 2495 2495 2495 2765 2615 2615 2615 2815 2815 2815 2615 2615 2615 2545 2545 2545 2615 2815 2815 2815 3015 3015 3015 3015 3015 2765 2765 2615 2615 2615 2815 2815 2815 2815 2815 2815 2815 2815 2815 2815 2615 2615 2615 2545 2545 2545 2545 2545 2545 2545 2545 2615 2615 2615 2815 2815 2815 2815 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2615 2615 2615 2615 2615 2615 2615 2615 2615 2615 2495 2495 2495 2495 2495 2765 2765 2765 2765 2765 +2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2630 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2540 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2500 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2620 2560 2560 2560 2560 2560 2560 2560 3680 3680 3680 3680 3680 3680 3680 3820 3820 3820 3820 3820 3640 3640 3740 3740 2600 2600 2600 2600 2500 2500 2500 2500 2500 2850 2580 2580 2580 2550 2550 2550 2550 2580 2580 2580 2850 2850 2850 2850 2850 2850 2850 2850 2850 2580 2580 2580 2580 2580 2580 2600 2600 2600 2600 3500 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2600 2600 2600 2600 2480 2480 2480 2480 2480 2750 2750 2600 2600 2800 2600 2600 2530 2530 2530 2530 2530 2600 2600 2800 2800 2800 2800 2800 3000 3000 3000 3000 2800 2800 2800 4000 4000 4450 2600 2600 2480 2480 2480 2480 2750 2600 2600 2600 2800 2800 2800 2600 2600 2530 2530 2530 2600 2800 2800 2800 2800 3000 3000 2480 2480 2480 2480 2750 2750 2600 2600 2600 2800 2800 2800 2800 2800 2800 2800 2800 2800 2800 2800 2600 2600 2600 2530 2530 2530 2530 2530 2530 2530 2530 2600 2600 2600 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2600 2600 2600 2600 2600 2600 2600 2600 2600 2600 2600 2600 2600 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2600 2600 2600 2600 2600 2600 2600 2600 2480 2480 2480 2480 2480 2750 +2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2511 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2621 2531 2531 2531 2531 2531 2531 2531 2531 2531 2491 2491 2491 2491 2491 2491 2491 2491 2491 2491 2491 2491 2491 2491 2491 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2611 2551 2551 2551 2551 2551 2551 2551 2551 3641 3641 3641 3641 3641 3781 3781 3781 3781 3781 3601 3601 3601 3701 3701 2585 2585 2585 2585 2485 2485 2485 2485 2835 2565 2565 2565 2535 2535 2535 2535 2565 2565 2565 2835 2835 2835 2835 2835 2835 2835 2835 2835 2565 2565 2565 2565 2565 2565 2585 2585 2585 2585 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 3500 2585 2585 2585 2585 2465 2465 2465 2465 2735 2735 2585 2585 2785 2785 2585 2585 2515 2515 2515 2515 2515 2585 2585 2785 2785 2785 2785 2785 2985 2985 2985 2985 2785 2785 3500 2585 2585 2585 2585 2465 2465 2465 2735 2735 2585 2585 2585 2785 2785 2585 2585 2585 2515 2515 2515 2585 2785 2785 2785 2585 2585 2585 2585 2465 2465 2465 2465 2735 2735 2585 2585 2785 2785 2785 2785 2785 2785 2785 2785 2785 2785 2785 2785 2785 2585 2585 2585 2515 2515 2515 2515 2515 2515 2515 3650 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2585 2585 2585 2585 2585 2585 2585 2465 2465 2465 +2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2552 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2502 2612 2612 2612 2612 2612 2612 2612 2612 2612 2612 2612 2612 2612 2522 2522 2522 2522 2522 2482 2482 2482 2482 2482 2482 2482 2482 2482 2482 2482 2482 2482 2482 2482 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2602 2542 2542 2542 2542 2542 2542 2542 3602 3602 3602 3602 3602 3742 3742 3742 3742 3742 3562 3562 3662 3662 2570 2570 2570 2570 2470 2470 2470 2470 2820 2550 2550 2550 2520 2520 2520 2520 2550 2550 2550 2820 2820 2820 2820 2820 2820 2820 2820 2820 2550 2550 2550 2550 2550 2550 2570 2570 2570 2570 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 2570 2570 2570 2570 2570 2450 2450 2450 2720 2720 2570 2570 2770 2770 2770 2570 2570 2500 2500 2500 2500 2570 2570 2770 2770 2770 2770 2770 2970 2970 2970 2970 3500 3500 3500 2570 2570 2570 2570 2450 2450 2450 2720 2720 2570 2570 2770 2770 2770 2570 2570 2500 2500 2500 2500 2570 3500 2570 2570 2570 2570 2570 2570 2570 2450 2450 2450 2720 2720 2570 2570 2570 2770 2770 2770 2770 2770 2770 2770 2770 2770 2770 2770 2770 2770 2770 2570 2570 2570 2500 2500 2500 3500 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2570 2570 2570 2570 2570 2570 +2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2543 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2493 2603 2603 2603 2603 2603 2603 2603 2603 2603 2513 2513 2513 2513 2513 2513 2513 2473 2473 2473 2473 2473 2473 2473 2473 2473 2473 2473 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2593 2533 2533 2533 2533 2533 2533 2533 3563 3563 3563 3563 3703 3703 3703 3703 3703 3523 3523 3623 3623 2555 2555 2555 2555 2455 2455 2455 2455 2805 2535 2535 2535 2505 2505 2505 2505 2535 2535 2535 2805 2805 2805 2805 2805 2805 2805 2805 2805 2535 2535 2535 2535 2535 2535 2555 2555 2555 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 3500 2555 2555 2555 2555 2435 2435 2435 2435 2705 2555 2555 2755 2755 2755 2555 2555 2555 2485 2485 2485 2485 2555 2555 2755 2755 2755 2755 2755 3350 3350 3500 3500 3500 3500 3500 2555 2555 2555 2435 2435 2435 2705 2555 2555 2555 2755 2755 2755 2555 2555 2485 2485 2485 3500 3500 3500 3500 2555 2555 2555 2555 2555 2555 2435 2435 2435 2435 2705 2555 2555 2555 2555 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2755 2555 2555 2555 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3350 3350 3350 3350 3350 3350 3350 3350 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2555 2555 2555 +2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2534 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2484 2594 2594 2594 2594 2594 2594 2594 2594 2594 2594 2504 2504 2504 2504 2504 2464 2464 2464 2464 2464 2464 2464 2464 2464 2464 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2584 2524 2524 2524 2524 2524 2524 3524 3524 3524 3524 3524 3664 3664 3664 3664 3484 3484 3584 3584 2540 2540 2540 2540 2440 2440 2440 2440 2790 2520 2520 2520 2490 2490 2490 2490 2520 2520 2520 2790 2790 2790 2790 2790 2790 2790 2790 2790 2520 2520 2520 2520 2520 2520 2540 2540 3500 3500 3500 3500 3650 3650 3650 3350 3350 3350 3500 2540 2540 2540 2540 2420 2420 2420 2420 2690 2540 2540 2740 2740 2740 2740 2540 2540 2470 2470 2470 2470 2540 2540 2740 2740 2740 3650 3650 3350 3350 3500 3500 3500 3500 3500 2540 2540 2540 2420 2420 2420 2690 2540 2540 2540 2740 2740 2540 2540 2540 3350 3350 3350 3500 3500 3500 3500 3500 2540 2540 2540 2540 2540 2420 2420 2420 2420 2690 2690 2540 2540 2540 2540 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2740 2520 2540 2540 2540 2540 3500 3500 3500 3650 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 +2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2525 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2585 2585 2585 2585 2585 2585 2585 2585 2495 2495 2495 2495 2455 2455 2455 2455 2455 2455 2455 2455 2455 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2575 2515 2515 2515 2515 2515 2515 3485 3485 3485 3485 3625 3625 3625 3625 3445 3445 3545 3545 2525 2525 2525 2525 2425 2425 2425 2425 2775 2505 2505 2475 2475 2475 2475 2475 2505 2505 2505 2775 2775 2775 2775 2775 2775 2775 2775 2775 2505 2505 2505 2505 2505 2525 2525 2525 3500 3500 3500 3650 3650 3650 3350 3350 3350 3500 2525 2525 2525 2525 2405 2405 2405 2405 2675 2675 2525 2725 2725 2725 2725 2525 2525 2525 2455 2455 2455 2455 2525 2525 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 2525 2525 2405 2405 2405 2405 2675 2525 2525 2725 2725 2725 3500 3650 3650 3350 3350 3350 3500 3500 3500 3500 3500 2525 2525 2525 2525 2525 2405 2405 2405 2405 2675 2675 2525 2525 2525 2525 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2725 2505 2505 2505 2505 2525 2525 2525 2525 3500 3500 3500 3500 3500 3650 3650 3650 3650 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3350 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2525 2525 2525 2525 2525 2525 2525 2525 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3650 3650 3650 3650 3350 3350 3350 3350 3350 3350 3500 3500 3500 3500 3500 3500 3500 +2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2486 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2516 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2466 2576 2576 2576 2576 2576 2576 2576 2576 2486 2486 2486 2446 2446 2446 2446 2446 2446 2446 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2566 2506 2506 2506 2506 2506 3446 3446 3446 3446 3586 3586 3586 3586 3406 3406 3406 3506 3506 2510 2510 2510 2410 2410 2410 2410 2760 2490 2490 2460 2460 2460 2460 2460 2490 2490 2490 2760 2760 2760 2760 2760 2760 2760 2760 2760 2490 2490 2490 2490 2490 2510 2510 3500 3500 3500 3650 3650 3650 3650 3350 3350 3500 3500 2510 2510 2510 2390 2390 2390 2390 2660 2510 2510 2710 2710 2710 2710 2510 2510 2510 2440 2440 2440 2490 2510 2510 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 2510 2510 2510 2390 2390 2390 2390 2660 2510 2510 2710 3500 3500 3500 3500 3650 3650 3350 3350 3350 3500 3500 3500 3500 2510 2510 2510 2510 2510 2510 2390 2390 2390 2390 2660 2510 2510 2510 2510 2510 2710 2710 2710 2710 2710 2710 2710 2710 2710 2490 2490 2490 2490 2490 2490 2490 2510 2510 2510 2510 2510 2510 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3650 3500 3500 3500 3500 3500 3500 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 2510 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3650 3650 3650 3350 3350 3350 3350 3350 3500 3500 3500 3500 +1858 1858 1858 1858 1858 1858 1918 1918 1918 1918 1918 1918 1918 1918 1918 1918 1918 1918 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2477 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2507 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2457 2567 2567 2567 2567 2567 2567 2567 2477 2477 2477 2437 2437 2437 2437 2437 2437 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2557 2497 2497 2497 2497 3407 3407 3407 3407 3547 3547 3547 3547 3367 3367 3367 3467 3467 2495 2495 2495 2395 2395 2395 2745 2745 2475 2475 2445 2445 2445 2445 2445 2475 2475 2745 2745 2745 2745 2745 2745 2745 2745 2745 2745 2475 2475 2475 2475 2495 2495 2495 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2495 2495 2495 2375 2375 2375 2375 2645 2495 2495 2695 2695 2695 2695 2695 2495 2495 2475 2475 2475 2475 2475 2495 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 2495 2495 2495 2495 2375 2375 2375 2645 2495 2495 2495 2495 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 3500 3500 2495 2495 2495 2495 2495 2495 2375 2375 2375 2375 2645 2645 2495 2495 2495 2495 2695 2695 2695 2695 2695 2695 2695 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2495 2495 2495 2495 2495 2495 2495 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 3500 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 2495 3500 3500 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 3350 3350 3500 +1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1912 1912 1912 1912 1912 1912 1912 1912 1912 1912 1912 1912 1912 1912 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2468 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2498 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2448 2558 2558 2558 2558 2558 2558 2468 2468 2468 2468 2428 2428 2428 2428 2428 2548 2548 2548 2548 2548 2548 2548 2548 2548 2548 2548 2548 2548 2548 2548 2488 2488 2488 2488 3368 3368 3368 3368 3368 3508 3508 3508 3328 3328 3328 3428 3428 2480 2480 2480 2380 2380 2380 2730 2460 2460 2460 2430 2430 2430 2430 2430 2460 2460 2730 2730 2730 2730 2730 2730 2730 2730 2730 2730 2460 2460 2460 2480 2480 2480 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2480 2480 2480 2360 2360 2360 2360 2630 2480 2480 2680 2680 2680 2680 2680 2730 2460 2460 2460 2460 2460 2460 2480 3500 3500 3650 3350 3350 3500 3500 3500 3500 3500 2480 2480 2480 2480 2360 2360 2460 2460 2460 2460 2480 2480 2480 3500 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 2480 2480 2480 2480 2480 2360 2360 2360 2360 2360 2630 2630 2480 2480 2480 2480 2680 2680 2680 2680 2680 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2480 2480 2480 2480 2480 2480 2480 2480 2480 3500 3500 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 +2026 2026 2026 2026 1896 1896 1896 1896 1896 1896 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1906 1906 1906 1906 1906 1906 1906 1906 1906 1906 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2459 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2489 2439 2439 2439 2439 2439 2439 2439 2439 2439 2439 2439 2439 2439 2439 2439 2549 2549 2549 2549 2549 2459 2459 2459 2459 2419 2419 2419 2419 2539 2539 2539 2539 2539 2539 2539 2539 2539 2539 2539 2539 2539 2539 2539 2479 2479 2479 3329 3329 3329 3329 3329 3469 3469 3469 3289 3289 3389 3389 2465 2465 2465 2365 2365 2365 2365 2715 2445 2445 2445 2415 2415 2415 2415 2415 2445 2445 2715 2715 2715 2715 2715 2715 2715 2715 2715 2445 2445 2445 2445 2465 2465 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2465 2465 2465 2345 2345 2345 2345 2615 2465 2465 2665 2665 2465 2715 2715 2715 2715 2445 2445 2445 2445 2465 2465 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 2465 2465 2465 2465 2445 2445 2445 2445 2445 2445 2465 2465 2465 3500 3500 3500 3650 3650 3350 3350 3350 3500 3500 3500 3500 2465 2465 2465 2465 2465 2465 2345 2345 2345 2345 2615 2615 2615 2465 2465 2465 2665 2665 2665 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2465 2465 2465 2465 2465 2465 2465 2465 2465 2465 2465 2465 2465 2465 2465 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2465 2465 2465 2465 2465 2465 2465 2465 3500 3500 3500 3500 3500 3650 3650 3650 3650 +2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1890 1840 1840 1840 1840 1840 1900 1900 1900 1900 1900 1900 1900 1900 1900 1900 1900 1900 1900 1900 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2450 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2480 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2540 2540 2540 2540 2540 2450 2450 2450 2410 2410 2410 2410 2530 2530 2530 2530 2530 2530 2530 2530 2530 2530 2530 2530 2530 2530 2470 2470 2470 3290 3290 3290 3290 3290 3430 3430 3430 3250 3250 3350 3350 2450 2450 2450 2350 2350 2350 2700 2700 2430 2430 2430 2400 2400 2400 2400 2430 2430 2700 2700 2700 2700 2700 2700 2700 2700 2700 2430 2430 2430 2430 2450 2450 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2450 2450 2450 2330 2330 2330 2330 2600 2450 2450 2700 2700 2700 2700 2700 2700 2700 2430 2430 2430 2430 2450 2450 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 3500 2450 2700 2700 2430 2430 2430 2430 2430 2430 2430 2450 2450 2450 3500 3500 3650 3650 3650 3350 3350 3500 3500 3500 3500 2450 2450 2450 2450 2450 2450 2330 2330 2330 2330 2330 2600 2600 2450 2450 2450 2650 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2700 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2450 2450 2450 2450 2450 2450 2450 3500 3500 3500 3500 3650 +1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 1884 1884 1884 1884 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 1894 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2441 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2471 2421 2421 2421 2421 2421 2421 2421 2421 2421 2421 2421 2421 2531 2531 2531 2531 2531 2441 2441 2401 2401 2401 2401 2521 2521 2521 2521 2521 2521 2521 2521 2521 2521 2521 2521 2521 2461 2461 2461 3251 3251 3251 3251 3251 3391 3391 3391 3211 3211 3311 3311 2435 2435 2435 2335 2335 2335 2685 2685 2415 2415 2415 2385 2385 2385 2385 2415 2415 2685 2685 2685 2685 2685 2685 2685 2685 2685 2415 2415 2415 2435 2435 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 2435 2435 2435 2315 2315 2315 2585 2585 2685 2685 2685 2685 2685 2685 2685 2685 2685 2415 2415 2415 2415 2435 2435 3500 3650 3650 3350 3350 3500 3500 3500 3500 2685 2685 2685 2685 2685 2685 2415 2415 2415 2415 2415 2415 2435 2435 2435 3500 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 2435 2435 2435 2435 2435 2435 2315 2315 2315 2315 2315 2585 2585 2585 2435 2385 2385 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2685 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2435 2435 2435 2435 2435 2435 2435 3500 +1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 1888 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 2008 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1888 1888 1888 1888 1888 1888 1888 1888 1888 2432 2432 2432 2432 2432 2432 2432 2432 2432 2432 2432 2432 2432 2432 2432 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2462 2412 2412 2412 2412 2412 2412 2412 2412 2412 2412 2412 2522 2522 2522 2522 2522 2432 2432 2392 2392 2392 2392 2512 2512 2512 2512 2512 2512 2512 2512 2512 2512 2512 2512 2452 2452 2452 3212 3212 3212 3212 3212 3352 3352 3352 3172 3172 3272 2420 2420 2420 2320 2320 2320 2320 2670 2400 2400 2400 2370 2370 2370 2370 2400 2400 2670 2670 2670 2670 2670 2670 2670 2670 2670 2400 2400 2400 2420 2420 3500 3500 3500 3500 3650 3650 3350 3350 3500 3500 2420 2420 2420 2300 2300 2370 2400 2400 2670 2670 2670 2670 2670 2670 2670 2670 2670 2400 2400 2400 2420 2420 2420 3500 3650 3650 3350 3350 3350 3500 2670 2670 2670 2670 2670 2670 2670 2670 2670 2400 2400 2400 2400 2400 2420 2420 2420 3500 3500 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 2420 2420 2420 2420 2420 2420 2420 2300 2300 2300 2300 2300 2370 2370 2370 2370 2370 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2670 2400 2400 2400 2400 2400 2400 2400 2400 2400 2420 2420 2420 2420 2420 +1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 1882 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 2002 1872 1872 1872 1872 1872 1872 1872 1822 1822 1822 1822 1822 1822 1822 1822 1822 1882 1882 1882 1882 1882 1882 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2423 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2453 2403 2403 2403 2403 2403 2403 2403 2403 2403 2403 2513 2513 2513 2513 2423 2423 2383 2383 2383 2383 2503 2503 2503 2503 2503 2503 2503 2503 2503 2503 2503 2503 2443 2443 3173 3173 3173 3173 3313 3313 3313 3313 3133 3133 3233 2405 2405 2405 2305 2305 2305 2655 2655 2385 2385 2385 2355 2355 2355 2355 2385 2385 2655 2655 2655 2655 2655 2655 2655 2655 2385 2385 2385 2405 2405 2405 3500 3500 3500 3650 3650 3350 3350 3500 3500 2405 2405 2405 2385 2355 2355 2355 2385 2385 2655 2655 2655 2655 2655 2655 2655 2655 2385 2385 2385 2385 2405 2405 3500 3500 3650 3650 3350 2385 2655 2655 2655 2655 2655 2655 2655 2655 2655 2655 2655 2385 2385 2385 2385 2385 2405 2405 2405 3500 3500 3500 3650 3650 3350 3350 3350 3500 3500 3500 3500 3500 2405 2405 2405 2405 2405 2405 2405 2285 2285 2385 2385 2385 2355 2355 2355 2355 2355 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2385 2655 2655 2655 2655 2655 2655 2655 2655 2655 2655 2655 2655 2655 2385 2385 2385 2385 2385 2385 2385 2385 2405 2405 2405 +1806 1806 1806 1806 1806 1806 1806 1806 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1876 1996 1996 1996 1996 1996 1996 1996 1996 1996 1996 1996 1996 1996 1866 1866 1866 1866 1866 1866 1866 1866 1816 1816 1816 1816 1816 1816 1816 1876 1876 1876 1876 1876 2414 2414 2414 2414 2414 2414 2414 2414 2414 2414 2414 2414 2414 2414 2414 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2444 2394 2394 2394 2394 2394 2394 2394 2394 2394 2394 2504 2504 2504 2504 2414 2414 2374 2374 2374 2374 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2434 2434 3134 3134 3134 3134 3274 3274 3274 3094 3094 3194 3194 2390 2390 2390 2290 2290 2290 2640 2370 2370 2370 2370 2340 2340 2340 2370 2370 2640 2640 2640 2640 2640 2640 2640 2640 2370 2370 2370 2390 2390 2390 3500 3500 3650 3650 3650 3350 3350 3500 3500 2390 2370 2370 2340 2340 2340 2340 2370 2370 2640 2640 2640 2640 2640 2640 2640 2640 2370 2370 2370 2370 2390 2390 2390 3500 3500 2370 2370 2370 2370 2640 2640 2640 2640 2640 2640 2640 2640 2640 2640 2370 2370 2370 2370 2370 2390 2390 2390 3500 3500 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 3500 2390 2390 2390 2390 2390 2390 2640 2640 2640 2370 2370 2370 2340 2340 2340 2340 2340 2340 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2370 2640 2640 2640 2640 2640 2640 2640 2640 2640 2640 2640 2370 2370 2370 2370 2370 2370 2370 2370 +1870 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1870 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1860 1860 1860 1860 1860 1860 1860 1810 1810 1810 1810 1810 1810 1870 1870 1870 1870 1870 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2405 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2435 2385 2385 2385 2385 2385 2385 2385 2385 2385 2495 2495 2495 2495 2405 2405 2365 2365 2365 2365 2485 2485 2485 2485 2485 2485 2485 2485 2485 2485 2425 2425 3095 3095 3095 3095 3235 3235 3235 3055 3055 3155 2375 2375 2375 2275 2275 2275 2275 2625 2355 2355 2355 2325 2325 2325 2355 2355 2625 2625 2625 2625 2625 2625 2625 2625 2355 2355 2355 2375 2375 2375 3500 3500 3650 3650 3650 3350 3350 2275 2275 2625 2355 2355 2355 2325 2325 2325 2325 2355 2355 2625 2625 2625 2625 2625 2625 2625 2355 2355 2355 2355 2355 2355 2325 2325 2355 2355 2355 2355 2355 2355 2625 2625 2625 2625 2625 2625 2625 2625 2625 2355 2355 2355 2355 2355 2375 2375 2375 3500 3500 3500 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 3500 2375 2375 2375 2625 2625 2625 2625 2625 2355 2355 2355 2355 2325 2325 2325 2325 2325 2325 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2355 2625 2625 2625 2625 2625 2625 2625 2625 2355 2355 2355 2355 2355 2355 +1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1864 1984 1984 1984 1984 1984 1984 1984 1984 1984 1984 1854 1854 1854 1854 1854 1854 1804 1804 1804 1804 1804 1804 1864 1864 1864 1864 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2396 2426 2426 2426 2426 2426 2426 2426 2426 2426 2426 2426 2426 2426 2426 2376 2376 2376 2376 2376 2376 2376 2376 2486 2486 2486 2486 2486 2396 2396 2356 2356 2356 2356 2476 2476 2476 2476 2476 2476 2476 2476 2476 2416 2416 3056 3056 3056 3056 3196 3196 3196 3016 3016 3116 2360 2360 2360 2260 2260 2260 2610 2340 2340 2340 2310 2310 2310 2310 2340 2340 2610 2610 2610 2610 2610 2610 2610 2340 2340 2340 2360 2360 2360 3500 3500 3650 3650 3650 2360 2360 2360 2260 2610 2610 2340 2340 2340 2310 2310 2310 2340 2340 2610 2610 2610 2610 2610 2610 2610 2340 2340 2340 2340 2340 2340 2310 2310 2310 2340 2340 2340 2340 2340 2610 2610 2610 2610 2610 2610 2610 2610 2610 2340 2340 2340 2340 2340 2360 2360 2360 2360 3500 3500 3500 3500 3500 3650 3650 3350 3350 3500 3500 3500 3500 3500 3500 3500 2610 2610 2610 2610 2610 2610 2610 2340 2340 2340 2340 2310 2310 2310 2310 2310 2310 2310 2310 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2340 2610 2610 2610 2610 2610 2340 2340 2340 2340 +1928 1928 1928 1928 1928 1928 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1858 1978 1978 1978 1978 1978 1978 1978 1978 1978 1978 1978 1848 1848 1848 1798 1798 1798 1798 1798 1858 1858 1858 1858 1858 2387 2387 2387 2387 2387 2387 2387 2387 2387 2387 2387 2387 2387 2387 2387 2417 2417 2417 2417 2417 2417 2417 2417 2417 2417 2417 2417 2417 2417 2367 2367 2367 2367 2367 2367 2367 2477 2477 2477 2477 2387 2387 2387 2347 2347 2347 2467 2467 2467 2467 2467 2467 2467 2467 2467 2407 2407 3017 3017 3017 3157 3157 3157 3157 2977 3077 2345 2345 2345 2245 2245 2245 2245 2595 2325 2325 2295 2295 2295 2295 2325 2325 2595 2595 2595 2595 2595 2595 2595 2325 2325 2325 2345 2345 2345 3500 3500 2977 2977 3077 3077 2345 2345 2245 2245 2595 2325 2325 2325 2295 2295 2295 2325 2325 2595 2595 2595 2595 2595 2595 2595 2595 2245 2595 2595 2595 2325 2295 2295 2295 2295 2325 2325 2325 2325 2325 2595 2595 2595 2595 2595 2595 2595 2595 2325 2325 2325 2325 2325 2345 2345 2345 2345 2345 3500 3500 3500 3500 3650 3650 3650 3350 3350 3500 3500 3500 3500 2595 2595 2595 2595 2595 2595 2595 2595 2595 2595 2325 2325 2325 2325 2325 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2325 2595 2595 2595 2325 2325 +1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1922 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1852 1972 1972 1972 1972 1972 1972 1972 1972 1972 1972 1972 1842 1792 1792 1792 1792 1792 1852 1852 1852 1852 2378 2378 2378 2378 2378 2378 2378 2378 2378 2378 2378 2378 2378 2378 2378 2408 2408 2408 2408 2408 2408 2408 2408 2408 2408 2408 2408 2408 2358 2358 2358 2358 2358 2358 2358 2468 2468 2468 2468 2378 2378 2338 2338 2338 2458 2458 2458 2458 2458 2458 2458 2458 2458 2398 2398 2978 2978 2978 3118 3118 3118 2938 2938 3038 2330 2330 2330 2230 2230 2230 2580 2310 2310 2280 2280 2280 2280 2310 2310 2580 2580 2580 2580 2580 2580 2580 2310 2310 2310 2330 2330 2978 3118 3118 3118 2938 2938 3038 2330 2330 2230 2230 2580 2580 2310 2310 2280 2280 2280 2310 2310 2580 2580 2580 2580 2580 2580 2330 2330 2230 2230 2580 2580 2310 2310 2280 2280 2280 2310 2310 2310 2310 2310 2580 2580 2580 2580 2580 2580 2580 2580 2310 2310 2310 2310 2310 2330 2330 2330 2330 2330 2330 3500 3500 3500 3500 3650 3650 3650 3650 3350 3350 3350 2230 2580 2580 2580 2580 2580 2580 2580 2580 2580 2580 2580 2580 2310 2310 2310 2310 2310 2310 2310 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2310 2580 +1806 1806 1806 1806 1806 1806 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1916 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1846 1966 1966 1966 1966 1966 1966 1966 1966 1966 1836 1836 1786 1786 1786 1786 1786 1846 1846 1846 1846 2369 2369 2369 2369 2369 2369 2369 2369 2369 2369 2369 2369 2369 2369 2399 2399 2399 2399 2399 2399 2399 2399 2399 2399 2399 2399 2349 2349 2349 2349 2349 2349 2459 2459 2459 2459 2369 2369 2329 2329 2329 2449 2449 2449 2449 2449 2449 2449 2449 2449 2389 2939 2939 2939 2939 3079 3079 3079 2899 2999 2315 2315 2315 2215 2215 2215 2215 2565 2295 2295 2265 2265 2265 2295 2295 2565 2565 2565 2565 2565 2565 2565 2295 2295 2295 2389 2939 2939 2939 3079 3079 2899 2899 2999 2315 2315 2215 2215 2565 2295 2295 2295 2265 2265 2265 2295 2565 2565 2565 2565 2899 2899 2999 2315 2315 2215 2215 2565 2565 2565 2295 2295 2265 2265 2265 2295 2295 2295 2295 2295 2565 2565 2565 2565 2565 2565 2565 2295 2295 2295 2295 2295 2295 2315 2315 2315 2315 2315 2315 3500 3500 3500 3500 3650 3650 3650 3650 2215 2215 2215 2215 2565 2565 2565 2565 2565 2565 2565 2565 2565 2565 2565 2565 2565 2295 2295 2295 2295 2295 2295 2295 2295 2295 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2265 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 2295 +1960 1830 1830 1830 1830 1830 1830 1830 1830 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1910 1840 1840 1840 1840 1840 1840 1840 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1840 1960 1960 1960 1960 1960 1960 1960 1960 1830 1830 1780 1780 1780 1780 1780 1840 1840 1840 1840 2360 2360 2360 2360 2360 2360 2360 2360 2360 2360 2360 2360 2360 2390 2390 2390 2390 2390 2390 2390 2390 2390 2390 2390 2390 2340 2340 2340 2340 2340 2340 2450 2450 2450 2360 2360 2320 2320 2320 2440 2440 2440 2440 2440 2440 2440 2440 2380 2380 2900 2900 2900 3040 3040 3040 3040 2860 2960 2300 2300 2200 2200 2200 2200 2550 2280 2280 2250 2250 2250 2280 2280 2550 2550 2550 2550 2550 2550 2550 2280 2380 2380 2380 2380 2900 2900 3040 3040 2860 2860 2960 2300 2300 2200 2200 2550 2280 2280 2280 2250 2250 2250 2280 2550 2550 2900 3040 2860 2860 2960 2300 2300 2300 2200 2200 2550 2550 2280 2280 2250 2250 2250 2280 2280 2280 2280 2280 2550 2550 2550 2550 2550 2550 2550 2550 2280 2280 2280 2280 2280 2300 2300 2300 2300 2300 2300 2300 3500 3500 3500 3500 3650 2300 2200 2200 2200 2200 2200 2200 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2550 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2250 2250 2250 2250 2250 2250 2250 2250 2250 2250 2250 2250 2250 2250 2250 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 2280 +1954 1954 1954 1954 1954 1954 1954 1954 1954 1954 1954 1824 1824 1824 1824 1824 1824 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1904 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1904 1904 1904 1904 1904 1904 1904 1904 1904 1834 1834 1834 1834 1834 1834 1834 1834 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1834 1954 1954 1954 1954 1954 1954 1824 1824 1824 1774 1774 1774 1774 1774 1834 1834 1834 1834 2351 2351 2351 2351 2351 2351 2351 2351 2351 2351 2351 2351 2351 2381 2381 2381 2381 2381 2381 2381 2381 2381 2381 2381 2331 2331 2331 2331 2331 2441 2441 2441 2351 2351 2311 2311 2311 2431 2431 2431 2431 2431 2431 2431 2431 2371 2371 2861 2861 2861 3001 3001 3001 2821 2921 2285 2285 2285 2185 2185 2185 2535 2265 2265 2235 2235 2235 2265 2265 2535 2535 2535 2535 2535 2535 2431 2431 2371 2371 2371 2371 2861 2861 3001 3001 2821 2821 2921 2285 2285 2185 2185 2535 2265 2265 2265 2235 2235 2235 2265 2861 2861 2861 3001 3001 2821 2921 2285 2285 2285 2185 2185 2535 2535 2535 2265 2235 2235 2235 2265 2265 2265 2265 2265 2265 2535 2535 2535 2535 2535 2535 2535 2265 2265 2265 2265 2265 2265 2285 2285 2285 2285 2285 2285 2285 3500 3500 3500 2285 2185 2185 2185 2185 2185 2185 2185 2185 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2535 2265 2265 2265 2265 2265 2265 2265 2265 2265 2235 2235 2235 2235 2235 2235 2235 2235 2235 2235 2235 2235 2235 2235 2265 2265 2265 2265 2265 2265 2265 +1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1948 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1788 1788 1788 1788 1788 1788 1898 1898 1898 1898 1898 1898 1898 1898 1828 1828 1828 1828 1828 1828 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1828 1948 1948 1948 1948 1948 1818 1818 1818 1768 1768 1768 1768 1828 1828 1828 1828 1828 2342 2342 2342 2342 2342 2342 2342 2342 2342 2342 2342 2342 2372 2372 2372 2372 2372 2372 2372 2372 2372 2372 2372 2322 2322 2322 2322 2322 2432 2432 2342 2342 2302 2302 2302 2422 2422 2422 2422 2422 2422 2422 2422 2362 2362 2822 2822 2962 2962 2962 2782 2782 2882 2270 2270 2170 2170 2170 2520 2250 2250 2220 2220 2220 2250 2250 2520 2520 2520 2520 2422 2422 2422 2422 2422 2362 2362 2362 2362 2822 2962 2962 2782 2782 2882 2270 2270 2170 2170 2520 2250 2250 2250 2220 2220 2362 2362 2362 2822 2822 2962 2962 2782 2882 2882 2270 2270 2170 2170 2520 2520 2520 2250 2220 2220 2220 2250 2250 2250 2250 2250 2250 2520 2520 2520 2520 2520 2520 2520 2250 2250 2250 2250 2250 2250 2270 2270 2270 2270 2270 2270 2270 2270 2270 2270 2270 2270 2170 2170 2170 2170 2170 2170 2170 2170 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2520 2250 2250 2250 2250 2250 2250 2250 2220 2220 2220 2220 2220 2220 2220 2220 2220 2220 2220 2220 2220 2250 2250 2250 +1872 1872 1872 1872 1872 1872 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1942 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1782 1782 1892 1892 1892 1892 1892 1892 1892 1892 1822 1822 1822 1822 1822 1822 1822 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1822 1822 1822 1822 1822 1822 1822 1822 1822 1822 1822 1822 1822 1822 1942 1942 1942 1942 1942 1812 1812 1812 1762 1762 1762 1762 1822 1822 1822 1822 2333 2333 2333 2333 2333 2333 2333 2333 2333 2333 2333 2333 2363 2363 2363 2363 2363 2363 2363 2363 2363 2363 2313 2313 2313 2313 2313 2423 2423 2333 2333 2293 2293 2293 2413 2413 2413 2413 2413 2413 2413 2413 2353 2783 2783 2783 2923 2923 2923 2743 2843 2255 2255 2155 2155 2155 2505 2235 2235 2205 2205 2205 2235 2235 2505 2505 2413 2413 2413 2413 2413 2413 2413 2353 2353 2353 2353 2783 2923 2923 2743 2743 2843 2255 2255 2155 2155 2505 2505 2235 2205 2353 2353 2353 2353 2353 2783 2783 2923 2923 2743 2843 2843 2255 2255 2155 2155 2155 2505 2505 2235 2235 2205 2205 2205 2235 2235 2235 2235 2235 2505 2505 2505 2505 2505 2505 2505 2235 2235 2235 2235 2235 2235 2235 2255 2255 2255 2255 2255 2255 2255 2255 2255 2255 2255 2255 2155 2155 2155 2155 2155 2155 2155 2155 2155 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2505 2235 2235 2235 2235 2235 2235 2235 2235 2205 2205 2205 2205 2205 2205 2205 2205 2205 2205 2205 +1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1866 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1936 1806 1806 1806 1806 1806 1806 1806 1776 1776 1776 1886 1886 1886 1886 1886 1886 1886 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1816 1816 1816 1816 1816 1816 1816 1816 1816 1816 1936 1936 1936 1936 1936 1936 1806 1806 1806 1756 1756 1756 1756 1816 1816 1816 1816 2324 2324 2324 2324 2324 2324 2324 2324 2324 2324 2324 2324 2354 2354 2354 2354 2354 2354 2354 2354 2304 2304 2304 2304 2304 2414 2414 2324 2284 2284 2284 2284 2404 2404 2404 2404 2404 2404 2404 2344 2344 2744 2744 2884 2884 2884 2704 2804 2240 2240 2140 2140 2140 2490 2220 2220 2190 2190 2190 2220 2284 2284 2284 2404 2404 2404 2404 2404 2404 2404 2344 2344 2344 2344 2744 2744 2884 2704 2704 2804 2240 2240 2140 2140 2490 2490 2404 2404 2344 2344 2344 2344 2344 2744 2744 2884 2884 2704 2804 2804 2240 2240 2140 2140 2140 2490 2490 2220 2220 2190 2190 2190 2220 2220 2220 2220 2220 2220 2490 2490 2490 2490 2490 2490 2490 2220 2220 2220 2220 2220 2220 2220 2220 2240 2240 2240 2240 2240 2240 2240 2240 2240 2240 2240 2140 2140 2140 2140 2140 2140 2140 2140 2140 2140 2140 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2490 2220 2220 2220 2220 2220 2220 2190 2190 2190 2190 2190 2190 2190 2190 +1910 1910 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1860 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1930 1800 1800 1800 1800 1800 1770 1770 1770 1880 1880 1880 1880 1880 1880 1880 1880 1880 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1930 1930 1930 1930 1930 1800 1800 1750 1750 1750 1750 1810 1810 1810 1810 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2345 2345 2345 2345 2345 2345 2345 2295 2295 2295 2295 2295 2405 2405 2315 2275 2275 2275 2395 2395 2395 2395 2395 2395 2395 2395 2335 2705 2705 2845 2845 2845 2665 2765 2765 2225 2225 2125 2125 2475 2205 2205 2175 2175 2275 2275 2275 2275 2275 2275 2395 2395 2395 2395 2395 2395 2395 2335 2335 2335 2705 2705 2845 2845 2665 2665 2765 2225 2225 2125 2395 2395 2395 2395 2335 2335 2335 2335 2335 2705 2705 2845 2845 2665 2665 2765 2225 2225 2125 2125 2125 2475 2475 2475 2205 2175 2175 2175 2175 2205 2205 2205 2205 2205 2205 2205 2475 2475 2475 2475 2475 2205 2205 2205 2205 2205 2205 2205 2205 2205 2665 2765 2225 2225 2225 2225 2225 2225 2225 2225 2225 2225 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2125 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2475 2205 2205 2205 2205 2205 2175 2175 2175 2175 +1764 1764 1764 1904 1904 1904 1904 1904 1904 1904 1904 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1854 1924 1924 1924 1924 1924 1924 1924 1924 1924 1924 1924 1924 1924 1794 1794 1794 1794 1764 1764 1764 1764 1874 1874 1874 1874 1874 1874 1874 1874 1874 1874 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1804 1804 1804 1804 1804 1804 1804 1804 1804 1924 1924 1924 1924 1794 1794 1744 1744 1744 1744 1744 1804 1804 1804 2306 2306 2306 2306 2306 2306 2306 2306 2306 2306 2306 2336 2336 2336 2336 2336 2336 2336 2286 2286 2286 2286 2396 2396 2306 2306 2266 2266 2266 2386 2386 2386 2386 2386 2386 2386 2326 2326 2666 2666 2806 2806 2626 2726 2726 2210 2210 2110 2110 2460 2190 2190 2306 2306 2266 2266 2266 2266 2266 2266 2266 2386 2386 2386 2386 2386 2326 2326 2326 2326 2666 2666 2806 2806 2626 2626 2726 2626 2386 2386 2386 2386 2386 2386 2326 2326 2326 2326 2326 2666 2666 2806 2806 2626 2626 2726 2210 2210 2110 2110 2110 2460 2460 2460 2190 2190 2160 2160 2160 2160 2190 2190 2190 2190 2190 2190 2190 2460 2460 2460 2460 2460 2190 2190 2190 2190 2190 2190 2806 2626 2626 2726 2726 2210 2210 2210 2210 2210 2210 2210 2210 2210 2210 2210 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2110 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2460 2190 2190 2190 2190 2190 2160 +1728 1728 1728 1728 1758 1758 1758 1758 1758 1758 1898 1898 1898 1898 1898 1898 1898 1898 1898 1898 1898 1898 1898 1898 1898 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1848 1918 1918 1918 1918 1918 1918 1918 1918 1918 1918 1918 1788 1788 1788 1788 1758 1758 1758 1758 1758 1868 1868 1868 1868 1868 1868 1868 1868 1868 1868 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1798 1798 1798 1798 1798 1798 1798 1798 1798 1918 1918 1918 1918 1918 1788 1738 1738 1738 1738 1798 1798 1798 1798 2297 2297 2297 2297 2297 2297 2297 2297 2297 2297 2327 2327 2327 2327 2327 2327 2277 2277 2277 2277 2387 2387 2297 2257 2257 2257 2257 2377 2377 2377 2377 2377 2377 2317 2317 2627 2627 2767 2767 2587 2587 2687 2195 2195 2095 2095 2387 2387 2297 2297 2297 2297 2257 2257 2257 2257 2257 2257 2377 2377 2377 2377 2377 2317 2317 2317 2317 2627 2627 2767 2767 2587 2587 2377 2377 2377 2377 2377 2377 2377 2377 2317 2317 2317 2317 2317 2627 2627 2767 2767 2587 2587 2687 2195 2195 2095 2095 2095 2445 2445 2445 2175 2175 2145 2145 2145 2145 2145 2175 2175 2175 2175 2175 2175 2175 2175 2445 2445 2445 2445 2175 2175 2175 2175 2767 2767 2587 2587 2587 2687 2687 2195 2195 2195 2195 2195 2195 2195 2195 2195 2195 2195 2195 2195 2195 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2095 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2445 2175 2175 2175 +1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1892 1842 1842 1842 1842 1842 1842 1842 1842 1842 1842 1842 1842 1842 1912 1912 1912 1912 1912 1912 1912 1912 1782 1782 1782 1782 1782 1782 1752 1752 1752 1752 1862 1862 1862 1862 1862 1862 1862 1862 1862 1862 1862 1792 1792 1792 1792 1792 1792 1792 1792 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1792 1792 1792 1792 1792 1792 1792 1792 1912 1912 1912 1912 1912 1912 1732 1732 1732 1732 1792 1792 1792 1792 2288 2288 2288 2288 2288 2288 2288 2288 2288 2318 2318 2318 2318 2318 2318 2268 2268 2268 2268 2378 2378 2288 2248 2248 2248 2368 2368 2368 2368 2368 2368 2368 2308 2588 2588 2728 2728 2548 2548 2648 2180 2180 2268 2378 2378 2378 2378 2288 2288 2288 2248 2248 2248 2248 2248 2248 2368 2368 2368 2368 2368 2308 2308 2308 2308 2588 2588 2588 2728 2248 2248 2248 2368 2368 2368 2368 2368 2368 2368 2308 2308 2308 2308 2308 2588 2588 2588 2728 2548 2548 2648 2180 2180 2180 2080 2080 2430 2430 2430 2430 2160 2160 2130 2130 2130 2130 2130 2160 2160 2160 2160 2160 2160 2160 2160 2160 2160 2430 2430 2430 2588 2588 2588 2728 2728 2548 2548 2548 2548 2648 2648 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2080 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2430 2160 +1756 1756 1756 1756 1756 1756 1756 1756 1756 1756 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1716 1716 1716 1716 1716 1716 1716 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1886 1886 1886 1886 1886 1886 1886 1886 1886 1886 1886 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1906 1906 1906 1906 1906 1906 1906 1776 1776 1776 1776 1776 1776 1776 1746 1746 1746 1856 1856 1856 1856 1856 1856 1856 1856 1856 1856 1786 1786 1786 1786 1786 1786 1786 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1786 1786 1786 1786 1786 1786 1786 1786 1906 1906 1906 1906 1776 1726 1726 1726 1726 1786 1786 1786 2279 2279 2279 2279 2279 2279 2279 2279 2279 2309 2309 2309 2309 2309 2259 2259 2259 2259 2369 2369 2279 2279 2239 2239 2239 2359 2359 2359 2359 2359 2359 2299 2299 2549 2549 2689 2509 2509 2609 2259 2259 2259 2369 2369 2369 2369 2279 2279 2279 2239 2239 2239 2239 2239 2239 2239 2359 2359 2359 2359 2299 2299 2299 2299 2299 2549 2239 2239 2239 2239 2239 2359 2359 2359 2359 2359 2359 2359 2299 2299 2299 2299 2299 2549 2549 2549 2689 2509 2509 2609 2165 2165 2165 2065 2065 2065 2415 2415 2415 2415 2145 2145 2115 2115 2115 2115 2115 2115 2145 2145 2145 2145 2145 2145 2145 2145 2145 2359 2299 2299 2549 2549 2549 2689 2689 2689 2509 2509 2509 2509 2609 2609 2609 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2165 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2065 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 2415 +1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1740 1740 1740 1740 1740 1740 1740 1880 1880 1880 1880 1880 1880 1880 1880 1880 1880 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1900 1900 1900 1900 1900 1900 1900 1900 1770 1770 1770 1770 1770 1740 1740 1850 1850 1850 1850 1850 1850 1850 1850 1850 1850 1780 1780 1780 1780 1780 1780 1780 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1780 1780 1780 1780 1780 1780 1780 1780 1900 1900 1900 1900 1770 1720 1720 1720 1720 1780 1780 1780 2270 2270 2270 2270 2270 2270 2270 2270 2300 2300 2300 2300 2300 2250 2250 2250 2250 2360 2360 2270 2230 2230 2230 2350 2350 2350 2350 2350 2350 2290 2290 2510 2510 2650 2650 2300 2300 2300 2250 2250 2250 2360 2360 2360 2360 2270 2270 2230 2230 2230 2230 2230 2230 2230 2350 2350 2350 2350 2290 2290 2290 2290 2230 2230 2230 2230 2230 2230 2230 2350 2350 2350 2350 2350 2350 2350 2290 2290 2290 2290 2290 2510 2510 2510 2650 2470 2470 2570 2570 2150 2150 2050 2050 2050 2400 2400 2400 2400 2130 2130 2130 2130 2100 2100 2100 2100 2100 2100 2130 2130 2130 2130 2130 2130 2230 2350 2350 2290 2290 2290 2510 2510 2510 2650 2650 2650 2470 2470 2470 2470 2470 2570 2570 2570 2570 2570 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2150 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2050 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 2400 +1824 1824 1824 1824 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1704 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1744 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1734 1734 1734 1734 1734 1874 1874 1874 1874 1874 1874 1874 1874 1874 1874 1874 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1894 1894 1894 1894 1894 1894 1894 1894 1894 1764 1764 1764 1764 1734 1844 1844 1844 1844 1844 1844 1844 1844 1844 1774 1774 1774 1774 1774 1774 1774 1774 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1774 1774 1774 1774 1774 1774 1774 1894 1894 1894 1894 1764 1764 1764 1714 1714 1714 1774 1774 1774 2261 2261 2261 2261 2261 2261 2261 2291 2291 2291 2291 2241 2241 2241 2241 2241 2351 2261 2261 2221 2221 2221 2341 2341 2341 2341 2341 2281 2281 2471 2471 2291 2291 2291 2291 2291 2291 2241 2241 2241 2351 2351 2351 2261 2261 2261 2221 2221 2221 2221 2221 2341 2341 2341 2341 2341 2341 2281 2261 2261 2221 2221 2221 2221 2221 2221 2221 2341 2341 2341 2341 2341 2341 2341 2341 2281 2281 2281 2281 2471 2471 2471 2611 2611 2431 2531 2531 2135 2135 2035 2035 2035 2385 2385 2385 2385 2385 2115 2115 2115 2115 2085 2085 2085 2085 2085 2085 2085 2115 2115 2115 2221 2221 2221 2341 2341 2341 2281 2281 2281 2471 2471 2471 2611 2611 2611 2431 2431 2431 2431 2431 2431 2431 2431 2531 2531 2531 2531 2531 2531 2531 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2135 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2035 2385 2385 2385 2385 2385 2385 2385 2385 +1698 1698 1698 1698 1748 1748 1748 1748 1748 1748 1818 1818 1818 1818 1818 1818 1818 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1698 1698 1698 1698 1698 1698 1698 1698 1728 1728 1728 1728 1868 1868 1868 1868 1868 1868 1868 1868 1868 1868 1868 1868 1868 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1888 1888 1888 1888 1888 1888 1888 1888 1758 1758 1758 1758 1758 1838 1838 1838 1838 1838 1838 1838 1838 1768 1768 1768 1768 1768 1768 1768 1768 1768 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1768 1768 1768 1768 1768 1768 1768 1888 1888 1888 1758 1758 1758 1708 1708 1708 1708 1768 1768 2252 2252 2252 2252 2252 2252 2282 2282 2282 2282 2282 2232 2232 2232 2232 2342 2342 2252 2212 2212 2212 2332 2332 2332 2332 2332 2272 2272 2252 2252 2282 2282 2282 2282 2282 2282 2232 2232 2232 2342 2342 2342 2342 2252 2252 2212 2212 2212 2212 2212 2332 2332 2332 2332 2332 2342 2252 2252 2252 2252 2212 2212 2212 2212 2212 2212 2332 2332 2332 2332 2332 2332 2332 2332 2272 2272 2272 2272 2272 2432 2432 2572 2572 2392 2392 2492 2120 2120 2020 2020 2020 2020 2370 2370 2370 2370 2370 2100 2100 2100 2100 2100 2070 2070 2070 2070 2070 2070 2252 2252 2212 2212 2212 2212 2332 2332 2332 2332 2272 2272 2272 2432 2432 2432 2432 2572 2572 2572 2572 2572 2572 2572 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2392 2492 2492 2492 2492 2492 2492 2492 2492 2492 2492 2492 2492 2492 2492 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2120 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2020 2370 2370 2370 2370 2370 +1842 1842 1842 1762 1762 1762 1762 1762 1692 1692 1692 1692 1692 1692 1742 1742 1742 1742 1742 1742 1742 1742 1742 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1742 1742 1742 1742 1742 1742 1742 1742 1742 1742 1812 1812 1812 1812 1812 1812 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1692 1692 1692 1692 1692 1722 1722 1722 1722 1862 1862 1862 1862 1862 1862 1862 1862 1862 1862 1862 1862 1862 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1882 1882 1882 1882 1882 1882 1882 1752 1752 1752 1752 1752 1832 1832 1832 1832 1832 1832 1832 1832 1762 1762 1762 1762 1762 1762 1762 1762 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1762 1762 1762 1762 1762 1762 1762 1882 1882 1882 1752 1752 1752 1702 1702 1702 1702 1762 1762 2243 2243 2243 2243 2243 2273 2273 2273 2273 2223 2223 2223 2223 2333 2333 2243 2243 2203 2203 2323 2323 2323 2323 2323 2243 2243 2243 2243 2273 2273 2273 2273 2273 2273 2273 2223 2223 2223 2333 2333 2333 2243 2203 2203 2203 2203 2203 2203 2323 2323 2323 2333 2333 2333 2333 2243 2243 2243 2203 2203 2203 2203 2203 2203 2323 2323 2323 2323 2323 2323 2323 2323 2263 2263 2263 2263 2263 2393 2393 2533 2533 2353 2353 2453 2105 2105 2105 2005 2005 2005 2005 2355 2355 2355 2355 2355 2085 2085 2085 2085 2085 2055 2055 2055 2055 2223 2223 2333 2243 2203 2203 2203 2203 2203 2323 2323 2323 2323 2323 2263 2263 2263 2263 2263 2393 2393 2393 2393 2393 2393 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2533 2353 2353 2353 2353 2353 2353 2353 2353 2353 2353 2353 2453 2453 2453 2453 2453 2453 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2105 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2005 2355 2355 +1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1836 1756 1756 1756 1756 1756 1756 1756 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1736 1736 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1736 1736 1736 1736 1736 1806 1806 1806 1806 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1686 1686 1686 1686 1716 1716 1716 1716 1856 1856 1856 1856 1856 1856 1856 1856 1856 1856 1856 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1876 1876 1876 1876 1876 1876 1746 1746 1746 1746 1716 1716 1716 1826 1826 1826 1826 1826 1826 1826 1756 1756 1756 1756 1756 1756 1756 1686 1686 1686 1686 1686 1686 1686 1686 1686 1756 1756 1756 1756 1756 1756 1756 1876 1876 1876 1746 1746 1746 1696 1696 1696 1756 1756 2234 2234 2234 2234 2264 2264 2264 2264 2264 2214 2214 2214 2214 2324 2324 2234 2194 2194 2314 2314 2314 1756 2234 2234 2234 2234 2234 2264 2264 2264 2264 2264 2264 2264 2214 2214 2214 2324 2324 2324 2234 2194 2194 2194 2194 2194 2194 2194 2214 2214 2214 2324 2324 2324 2234 2234 2234 2234 2194 2194 2194 2194 2194 2314 2314 2314 2314 2314 2314 2314 2314 2254 2254 2254 2254 2254 2354 2354 2354 2494 2314 2314 2414 2414 2090 2090 1990 1990 1990 1990 1990 2340 2340 2340 2340 2340 2070 2070 2070 2070 2070 2070 2070 2264 2264 2214 2214 2324 2324 2234 2234 2194 2194 2194 2194 2314 2314 2314 2314 2314 2314 2314 2314 2314 2314 2254 2254 2254 2254 2254 2254 2254 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2354 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2494 2314 2314 2314 2314 2314 2314 2314 2414 2414 2414 2414 2414 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 2090 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 +1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1830 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1750 1830 1830 1830 1830 1830 1830 1830 1830 1830 1750 1750 1750 1750 1750 1750 1680 1680 1680 1680 1680 1730 1730 1730 1800 1800 1800 1800 1720 1720 1720 1720 1720 1720 1720 1720 1720 1720 1720 1720 1680 1680 1680 1710 1710 1710 1710 1850 1850 1850 1850 1850 1850 1850 1850 1850 1850 1850 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1870 1870 1870 1870 1870 1740 1740 1740 1740 1710 1710 1710 1820 1820 1820 1820 1820 1820 1820 1820 1750 1750 1750 1750 1750 1680 1680 1680 1680 1680 1680 1680 1680 1750 1750 1750 1750 1750 1750 1750 1870 1870 1870 1870 1740 1740 1690 1690 1690 1750 1750 2225 2225 2225 2225 2255 2255 2255 2255 2205 2205 2205 2205 2315 2315 2225 2185 2185 2185 1690 1690 1750 2225 2225 2225 2225 2225 2225 2255 2255 2255 2255 2255 2255 2205 2205 2205 2315 2315 2225 2225 2185 2185 2185 2185 2185 2185 2205 2205 2205 2205 2315 2315 2315 2225 2225 2225 2225 2185 2185 2185 2185 2185 2305 2305 2305 2305 2305 2305 2305 2305 2245 2245 2245 2245 2245 2315 2315 2315 2455 2455 2275 2275 2375 2075 2075 2075 1975 1975 1975 1975 2325 2325 2325 2325 2325 2325 2055 2055 2055 2055 2225 2225 2255 2255 2205 2205 2205 2205 2315 2315 2225 2225 2185 2185 2185 2185 2185 2185 2305 2305 2305 2305 2305 2305 2305 2305 2305 2305 2305 2305 2305 2305 2245 2245 2245 2245 2245 2245 2245 2245 2245 2245 2245 2245 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2315 2455 2455 2455 2455 2455 2455 2455 2275 2275 2275 2275 2275 2375 2375 2375 2375 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 2075 1975 1975 1975 1975 1975 1975 1975 1975 1975 1975 1975 1975 +1744 1744 1744 1744 1744 1744 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824 1744 1744 1744 1744 1674 1674 1674 1674 1724 1724 1724 1794 1794 1794 1714 1714 1714 1714 1714 1714 1714 1714 1714 1714 1714 1714 1674 1704 1704 1704 1704 1704 1704 1704 1844 1844 1844 1844 1844 1844 1844 1844 1844 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1864 1864 1864 1864 1864 1734 1734 1734 1734 1704 1704 1704 1814 1814 1814 1814 1814 1814 1814 1814 1744 1744 1744 1744 1674 1674 1674 1674 1674 1674 1674 1674 1744 1744 1744 1744 1744 1744 1744 1864 1864 1864 1864 1734 1684 1684 1684 1744 1744 2216 2216 2216 2246 2246 2246 2246 2246 2196 2196 2196 2306 2306 2216 2176 1864 1864 1684 1684 1744 2216 2216 2216 2216 2216 2216 2246 2246 2246 2246 2246 2246 2196 2196 2196 2306 2306 2216 2216 2176 2176 2176 2246 2246 2196 2196 2196 2196 2196 2196 2306 2306 2216 2216 2216 2216 2216 2176 2176 2176 2176 2296 2296 2296 2296 2296 2296 2296 2296 2236 2236 2236 2236 2236 2236 2276 2276 2416 2416 2236 2236 2336 2336 2060 2060 2060 1960 1960 1960 1960 2310 2310 2310 2310 2310 2310 2310 2040 2216 2216 2216 2216 2246 2246 2246 2196 2196 2196 2196 2196 2306 2306 2216 2216 2216 2216 2176 2176 2176 2176 2176 2176 2176 2176 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2296 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2236 2276 2276 2276 2276 2276 2276 2276 2276 2416 2416 2416 2416 2416 2416 2416 2236 2236 2236 2336 2336 2336 2336 2060 2060 2060 2060 2060 2060 2060 2060 2060 2060 2060 2060 2060 2060 2060 1960 1960 1960 1960 1960 1960 1960 1960 1960 1960 +1788 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1818 1738 1738 1738 1738 1668 1668 1668 1718 1718 1718 1718 1788 1788 1788 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1668 1668 1668 1698 1698 1698 1698 1698 1698 1698 1698 1838 1838 1838 1838 1838 1838 1838 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1858 1858 1858 1858 1858 1728 1728 1728 1728 1698 1698 1808 1808 1808 1808 1808 1808 1808 1808 1808 1738 1738 1668 1668 1668 1668 1668 1668 1668 1668 1738 1738 1738 1738 1738 1738 1738 1858 1858 1858 1858 1858 1678 1678 1738 1738 2207 2207 2207 2207 2237 2237 2237 2237 2187 2187 2187 2297 2297 1738 1738 1738 1858 1858 1678 1738 2207 2207 2207 2207 2207 2207 2237 2237 2237 2237 2237 2237 2187 2187 2187 2297 2297 2207 2207 2167 2167 2237 2237 2237 2237 2187 2187 2187 2187 2187 2297 2297 2297 2207 2207 2207 2207 2167 2167 2167 2167 2287 2287 2287 2287 2287 2287 2287 2287 2227 2227 2227 2227 2227 2227 2237 2237 2237 2377 2377 2197 2197 2297 2045 2045 2045 2045 1945 1945 1945 1945 1945 2295 2295 2295 2295 2237 1738 1738 2207 2207 2207 2207 2207 2237 2237 2237 2237 2187 2187 2187 2187 2187 2297 2297 2297 2297 2297 2207 2207 2207 2207 2207 2207 2167 2167 2167 2167 2167 2167 2167 2167 2167 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2287 2227 2227 2227 2227 2227 2227 2227 2227 2237 2237 2237 2237 2237 2237 2377 2377 2377 2377 2377 2197 2197 2197 2297 2297 2297 2045 2045 2045 2045 2045 2045 2045 2045 2045 2045 2045 2045 2045 2045 2045 1945 1945 1945 1945 1945 1945 1945 +1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1652 1652 1652 1652 1652 1652 1652 1652 1652 1652 1652 1652 1652 1652 1652 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1812 1732 1732 1732 1732 1662 1662 1712 1712 1712 1712 1782 1782 1782 1782 1702 1702 1702 1702 1702 1702 1702 1702 1662 1662 1662 1662 1662 1662 1662 1692 1692 1692 1692 1692 1832 1832 1832 1832 1832 1832 1832 1782 1782 1782 1782 1782 1782 1782 1782 1852 1852 1852 1852 1852 1722 1722 1722 1722 1722 1692 1692 1802 1802 1802 1802 1802 1802 1802 1802 1732 1732 1662 1662 1662 1662 1662 1662 1662 1732 1732 1732 1732 1732 1732 1732 1852 1852 1852 1852 1852 1672 1672 1732 1732 2198 2198 2198 2228 2228 2228 2228 2178 2178 2178 1732 1732 1732 1732 1732 1852 1852 1672 1732 1732 2198 2198 2198 2198 2198 2228 2228 2228 2228 2228 2228 2178 2178 2178 2288 2288 2198 2198 2228 2228 2228 2228 2228 2228 2228 2178 2178 2178 2178 2178 2288 2288 2198 2198 2198 2198 2158 2158 2158 2158 2278 2278 2278 2278 2278 2278 2278 2278 2218 2218 2218 2218 2218 2218 2218 2198 2198 2338 2338 2158 2158 2158 2258 2030 2030 2030 1930 1930 1930 1930 1930 1930 2280 2280 1722 1672 1672 1732 1732 1732 2198 2198 2198 2198 2198 2228 2228 2228 2228 2228 2178 2178 2178 2178 2178 2178 2178 2178 2178 2288 2288 2288 2288 2288 2288 2198 2198 2198 2198 2198 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2158 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2278 2218 2218 2218 2218 2218 2198 2198 2198 2198 2198 2198 2338 2338 2338 2338 2158 2158 2158 2258 2258 2030 2030 2030 2030 2030 2030 2030 2030 2030 2030 2030 2030 2030 2030 1930 1930 1930 1930 1930 +1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1646 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1726 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1806 1726 1726 1726 1726 1656 1656 1656 1656 1706 1706 1706 1776 1776 1776 1776 1696 1696 1696 1696 1696 1696 1696 1656 1656 1656 1656 1656 1656 1686 1686 1686 1686 1686 1686 1826 1826 1826 1826 1826 1826 1776 1776 1776 1776 1776 1776 1776 1776 1846 1846 1846 1846 1716 1716 1716 1716 1716 1716 1716 1716 1796 1796 1796 1796 1796 1796 1726 1726 1726 1656 1656 1656 1656 1656 1656 1656 1726 1726 1726 1726 1726 1726 1726 1846 1846 1846 1716 1666 1726 1726 2189 2189 2189 2219 2219 2219 2219 2219 1656 1656 1726 1726 1726 1726 1726 1846 1846 1666 1726 1726 2189 2189 2189 2189 2189 2219 2219 2219 2219 2219 2219 2169 2169 2169 2169 2279 2189 2189 2189 2219 2219 2219 2219 2219 2219 2219 2169 2169 2169 2169 2279 2279 2189 2189 2189 2189 2189 2149 2149 2149 2269 2269 2269 2269 2269 2269 2269 2269 2269 2209 2209 2209 2209 2209 2209 2209 2159 2159 2299 2299 2119 2119 2219 2219 2015 2015 2015 2015 1915 1915 1915 1915 1915 1846 1716 1716 1666 1666 1666 1726 1726 1726 2189 2189 2189 2189 2189 2189 2219 2219 2219 2219 2219 2219 2219 2219 2219 2219 2219 2219 2169 2169 2169 2169 2169 2169 2279 2279 2279 2279 2279 2279 2279 2189 2189 2189 2189 2189 2189 2189 2189 2189 2189 2189 2189 2189 2149 2149 2149 2149 2149 2149 2149 2149 2149 2149 2149 2149 2149 2269 2269 2269 2269 2269 2269 2269 2269 2269 2269 2269 2269 2269 2269 2209 2209 2209 2159 2159 2159 2159 2159 2159 2299 2299 2299 2119 2119 2119 2219 2219 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 1915 1915 1915 +1720 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1640 1640 1640 1640 1640 1640 1640 1640 1640 1640 1770 1770 1770 1770 1770 1770 1770 1640 1640 1640 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1640 1640 1640 1640 1640 1640 1640 1640 1640 1720 1720 1720 1720 1720 1720 1720 1720 1720 1720 1720 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1800 1720 1720 1720 1720 1650 1650 1650 1650 1700 1700 1700 1770 1770 1770 1690 1690 1690 1690 1690 1690 1690 1690 1650 1650 1650 1650 1680 1680 1680 1680 1680 1680 1820 1820 1820 1820 1820 1820 1770 1770 1770 1770 1770 1770 1770 1840 1840 1840 1840 1840 1710 1710 1710 1710 1710 1710 1710 1790 1790 1790 1790 1790 1790 1720 1720 1650 1650 1650 1650 1650 1650 1650 1720 1720 1720 1720 1720 1720 1720 1840 1840 1840 1660 1660 1720 1720 2180 2180 2210 2210 2210 1650 1650 1650 1650 1720 1720 1720 1720 1720 1840 1840 1660 1720 1720 2180 2180 2180 2180 2180 2210 2210 2210 2210 2210 2210 2210 2160 2160 2160 2180 2180 2180 2180 2210 2210 2210 2210 2210 2210 2210 2160 2160 2160 2160 2160 2270 2180 2180 2180 2180 2180 2140 2140 2140 2140 2260 2260 2260 2260 2260 2260 2260 2260 2260 2200 2200 2200 2200 2200 2200 2120 2120 2260 2260 2260 2080 2080 2180 2000 2000 2000 2000 2000 2000 1900 1840 1840 1840 1840 1710 1710 1710 1660 1660 1660 1720 1720 1720 1720 1720 2180 2180 2180 2180 2180 2180 2180 2180 2210 2210 2210 2210 2210 2210 2210 2210 2210 2210 2210 2210 2210 2160 2160 2160 2160 2160 2160 2160 2160 2270 2270 2270 2270 2270 2270 2270 2270 2270 2270 2270 2270 2180 2180 2180 2180 2180 2180 2180 2180 2180 2180 2140 2140 2140 2140 2140 2140 2140 2140 2140 2140 2260 2260 2260 2260 2260 2260 2260 2260 2260 2200 2200 2200 2120 2120 2120 2120 2120 2260 2260 2260 2080 2080 2080 2180 2180 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 1900 +1714 1714 1714 1714 1714 1714 1714 1714 1714 1714 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1634 1634 1634 1634 1634 1634 1714 1714 1714 1714 1714 1714 1714 1714 1714 1714 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1794 1714 1714 1714 1714 1644 1644 1644 1694 1694 1694 1764 1764 1764 1684 1684 1684 1684 1684 1684 1684 1684 1644 1644 1644 1644 1674 1674 1674 1674 1814 1814 1814 1814 1814 1814 1814 1764 1764 1764 1764 1764 1764 1834 1834 1834 1834 1834 1834 1834 1834 1704 1704 1704 1704 1784 1784 1784 1784 1784 1714 1714 1644 1644 1644 1644 1644 1644 1644 1714 1714 1714 1714 1714 1714 1714 1834 1834 1654 1654 1714 1714 2171 2171 1714 1714 1714 1714 1644 1644 1644 1714 1714 1714 1714 1714 1834 1834 1654 1654 1714 2171 2171 2171 2171 2171 2171 2201 2201 2201 2201 2201 2201 1714 1714 1714 2171 2171 2171 2171 2171 2201 2201 2201 2201 2201 2201 2201 2151 2151 2151 2151 2261 2171 2171 2171 2171 2171 2131 2131 2131 2131 2251 2251 2251 2251 2251 2251 2251 2251 2251 2191 2191 2191 2191 2191 2191 2191 2081 2081 2221 2221 2041 2041 2041 2141 2141 1985 1985 1985 1985 1714 1714 1714 1714 1834 1834 1834 1834 1704 1704 1654 1654 1654 1654 1654 1714 1714 1714 1714 1714 1714 2171 2171 2171 2171 2171 2171 2171 2171 2171 2171 2171 2171 2171 2171 2201 2201 2201 2201 2201 2201 2201 2201 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2151 2261 2261 2261 2261 2261 2261 2261 2261 2171 2171 2171 2171 2171 2131 2131 2131 2131 2131 2131 2131 2251 2251 2251 2251 2251 2251 2251 2191 2191 2191 2081 2081 2081 2081 2221 2221 2221 2041 2041 2141 2141 2141 1985 1985 1985 1985 1985 1985 1985 1985 1985 1985 +1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1708 1708 1708 1708 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1628 1628 1628 1628 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1788 1708 1708 1708 1708 1638 1638 1638 1688 1688 1688 1758 1758 1678 1678 1678 1678 1678 1678 1678 1678 1638 1638 1638 1638 1638 1668 1668 1808 1808 1808 1808 1808 1808 1808 1758 1758 1758 1758 1758 1758 1828 1828 1828 1828 1828 1828 1828 1828 1698 1698 1698 1698 1778 1778 1778 1708 1708 1708 1708 1638 1638 1638 1638 1638 1638 1708 1708 1708 1708 1708 1708 1828 1828 1698 1648 1708 1708 1698 1778 1778 1708 1708 1708 1638 1638 1638 1638 1708 1708 1708 1708 1828 1828 1648 1648 1708 2162 2162 2162 2162 2162 2162 2192 2192 2192 2192 2192 1648 1648 1708 1708 1708 2162 2162 2162 2162 2192 2192 2192 2192 2192 2192 2192 2142 2142 2142 2142 2252 2252 2162 2162 2162 2162 2122 2122 2122 2122 2242 2242 2242 2242 2242 2242 2242 2242 2242 2242 2182 2182 2182 2182 2182 2182 2042 2042 2042 2182 2182 2002 2002 2002 2102 2102 1970 1708 1708 1708 1708 1708 1708 1708 1828 1828 1828 1828 1828 1698 1698 1648 1648 1648 1648 1648 1648 1648 1648 1648 1708 1708 1708 1708 1708 1708 1708 1708 1708 1708 2162 2162 2162 2162 2162 2162 2162 2162 2162 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2192 2142 2142 2142 2142 2142 2142 2142 2142 2142 2252 2252 2252 2252 2252 2162 2162 2162 2162 2122 2122 2122 2122 2122 2242 2242 2242 2242 2242 2242 2242 2182 2182 2042 2042 2042 2182 2182 2182 2182 2002 2002 2102 2102 1970 1970 1970 1970 1970 1970 1970 1970 +1662 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1622 1622 1622 1622 1622 1622 1622 1622 1622 1622 1622 1702 1702 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1782 1702 1702 1702 1702 1632 1632 1632 1682 1682 1682 1752 1752 1672 1672 1672 1672 1672 1672 1672 1632 1632 1632 1632 1662 1662 1802 1802 1802 1802 1802 1802 1802 1752 1752 1752 1752 1752 1752 1752 1822 1822 1822 1822 1822 1822 1692 1692 1692 1692 1772 1772 1772 1702 1702 1702 1702 1632 1632 1632 1632 1632 1632 1702 1702 1702 1702 1702 1702 1822 1822 1642 1822 1692 1692 1772 1772 1702 1702 1702 1632 1632 1632 1632 1702 1702 1702 1702 1822 1822 1642 1642 1702 1702 2153 2153 2153 2153 2153 2183 2183 2183 1692 1692 1692 1642 1642 1702 1702 2153 2153 2153 2153 2153 2183 2183 2183 2183 2183 2183 2133 2133 2133 2133 2243 2243 2153 2153 2153 2153 2113 2113 2113 2113 2233 2233 2233 2233 2233 2233 2233 2233 2233 2233 2233 2173 2173 2173 2173 2173 2173 2003 2003 2003 2143 2143 1963 1963 1963 1963 1702 1702 1702 1702 1702 1702 1702 1702 1702 1822 1822 1822 1822 1822 1822 1822 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 1702 2153 2153 2153 2153 2153 2153 2153 2153 2153 2153 2153 2153 2153 2153 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2183 2133 2133 2133 2133 2133 2133 2243 2243 2243 2243 2153 2153 2113 2113 2113 2113 2113 2113 2233 2233 2233 2233 2233 2233 2173 2003 2003 2003 2003 2143 2143 2143 1963 1963 2063 2063 1955 1955 1955 1955 1955 1955 +1656 1656 1656 1656 1656 1656 1656 1656 1656 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1616 1616 1616 1616 1616 1616 1616 1616 1616 1616 1696 1696 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1776 1696 1696 1696 1626 1626 1626 1676 1676 1676 1746 1746 1666 1666 1666 1666 1666 1666 1626 1626 1626 1626 1656 1656 1796 1796 1796 1796 1796 1796 1796 1746 1746 1746 1746 1746 1746 1746 1816 1816 1816 1816 1816 1686 1686 1686 1686 1686 1766 1766 1766 1766 1696 1696 1626 1626 1626 1626 1626 1626 1696 1696 1696 1696 1696 1696 1746 1816 1816 1816 1686 1766 1766 1766 1696 1696 1626 1626 1626 1626 1696 1696 1696 1696 1696 1816 1636 1636 1696 1696 2144 2144 2144 2144 2144 2174 1696 1696 1816 1686 1686 1686 1636 1696 1696 2144 2144 2144 2144 2144 2174 2174 2174 2174 2174 2174 2174 2124 2124 2124 2124 2234 2144 2144 2144 2144 2104 2104 2104 2104 2224 2224 2224 2224 2224 2224 2224 2224 2224 2224 2224 2224 2164 2164 2164 2164 2164 2164 1964 1964 1964 1964 2104 2104 1924 1626 1626 1626 1626 1696 1696 1696 1696 1696 1696 1696 1696 1696 1816 1816 1816 1816 1816 1816 1816 1816 1686 1686 1686 1686 1686 1686 1686 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 1696 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2144 2174 2174 2174 2174 2174 2174 2174 2174 2124 2124 2124 2124 2124 2234 2234 2234 2144 2144 2104 2104 2104 2104 2104 2224 2224 2224 2224 2224 2164 2164 1964 1964 1964 2104 2104 2104 1924 1924 1924 2024 1940 1940 1940 1940 +1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1650 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1610 1610 1610 1610 1610 1610 1610 1610 1610 1690 1690 1690 1690 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1770 1690 1690 1620 1620 1620 1670 1670 1670 1740 1740 1660 1660 1660 1660 1660 1660 1620 1620 1620 1650 1650 1790 1790 1790 1790 1790 1790 1790 1740 1740 1740 1740 1740 1740 1740 1810 1810 1810 1810 1810 1680 1680 1680 1680 1760 1760 1760 1760 1760 1690 1690 1620 1620 1620 1620 1620 1690 1690 1690 1740 1740 1740 1810 1810 1810 1680 1680 1760 1760 1760 1690 1620 1620 1620 1620 1690 1690 1690 1690 1690 1810 1630 1630 1690 1690 2135 2135 2135 2135 2135 1690 1690 1690 1810 1680 1680 1680 1630 1690 1690 2135 2135 2135 2135 2135 2165 2165 2165 2165 2165 2165 2165 2115 2115 2115 2115 2225 2225 2135 2135 2135 2095 2095 2095 2095 2095 2215 2215 2215 2215 2215 2215 2215 2215 2215 2215 2215 2215 2155 2155 2155 2155 2155 2155 2155 1925 1925 1925 1620 1620 1620 1620 1620 1620 1620 1620 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 1690 2135 2135 2135 2135 2135 2135 2135 2135 2135 2165 2165 2165 2165 2165 2165 2165 2115 2115 2115 2115 2225 2225 2225 2135 2135 2095 2095 2095 2095 2095 2215 2215 2215 2215 2155 1925 1925 1925 1925 2065 2065 1885 1885 1885 1985 1925 1925 +1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1644 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1604 1604 1604 1604 1604 1604 1604 1604 1684 1684 1684 1684 1684 1684 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1764 1684 1684 1614 1614 1614 1614 1664 1664 1734 1734 1654 1654 1654 1654 1654 1614 1614 1614 1644 1644 1784 1784 1784 1784 1784 1784 1784 1734 1734 1734 1734 1734 1734 1734 1804 1804 1804 1804 1674 1674 1674 1674 1754 1754 1754 1754 1754 1684 1684 1614 1614 1614 1614 1614 1784 1734 1734 1734 1734 1734 1804 1804 1804 1674 1754 1754 1754 1684 1614 1614 1614 1614 1684 1684 1684 1684 1684 1804 1674 1624 1684 1684 2126 2126 2126 1684 1684 1684 1684 1684 1804 1804 1674 1674 1624 1624 1684 1684 2126 2126 2126 2126 2126 2156 2156 2156 2156 2156 2156 2106 2106 2106 2106 2216 2216 2126 2126 2126 2086 2086 2086 2086 2086 2206 2206 2206 2206 2206 2206 2206 2206 2206 2206 2206 2206 2206 2146 2146 2146 2146 2146 2146 2146 2146 1684 1684 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1684 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1804 1674 1674 1674 1674 1674 1674 1674 1624 1624 1624 1624 1624 1624 1624 1624 1624 1624 1624 1624 1624 1624 1684 1684 1684 1684 1684 1684 1684 1684 2126 2126 2126 2126 2126 2126 2126 2156 2156 2156 2156 2156 2156 2156 2106 2106 2106 2106 2216 2216 2126 2126 2086 2086 2086 2086 2206 2206 2206 2206 2146 2146 1886 1886 1886 2026 2026 1846 1846 1946 1946 +1778 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1638 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1728 1728 1728 1728 1728 1728 1728 1728 1728 1728 1598 1598 1598 1598 1598 1598 1678 1678 1678 1678 1678 1678 1678 1678 1678 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1758 1678 1678 1608 1608 1608 1608 1658 1658 1728 1728 1648 1648 1648 1648 1648 1608 1608 1638 1638 1778 1778 1778 1778 1778 1778 1728 1728 1728 1728 1728 1728 1728 1728 1798 1798 1798 1798 1668 1668 1668 1748 1748 1748 1748 1748 1678 1678 1678 1608 1638 1778 1778 1778 1728 1728 1728 1728 1798 1798 1798 1668 1668 1748 1748 1678 1678 1608 1608 1608 1678 1678 1678 1678 1678 1798 1668 1618 1618 1678 1678 1608 1608 1678 1678 1678 1678 1678 1678 1798 1798 1668 1618 1618 1678 1678 2117 2117 2117 2117 2117 2147 2147 2147 2147 2147 2147 2097 2097 2097 2097 2097 2207 2117 2117 2117 2077 2077 2077 2077 2077 2077 2197 2197 2197 2197 2197 2197 2197 2197 2197 2197 2197 2197 2197 2197 2137 2137 2137 2137 1748 1748 1678 1678 1678 1678 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1678 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1618 1618 1618 1618 1618 1618 1618 1678 1678 1678 1678 1678 1678 2117 2117 2117 2117 2117 2117 2147 2147 2147 2147 2147 2147 2147 2097 2097 2097 2207 2207 2117 2117 2077 2077 2077 2197 2197 2197 2197 2137 2137 1847 1847 1847 1987 1987 1807 1807 +1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1772 1632 1632 1632 1632 1632 1632 1632 1632 1632 1632 1632 1632 1632 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1722 1592 1592 1592 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1752 1672 1672 1602 1602 1602 1652 1652 1652 1722 1642 1642 1642 1642 1642 1602 1602 1632 1632 1772 1772 1772 1772 1772 1772 1722 1722 1722 1722 1722 1722 1722 1722 1792 1792 1792 1792 1662 1662 1742 1742 1742 1742 1742 1742 1602 1632 1632 1772 1772 1772 1722 1722 1722 1722 1792 1792 1792 1662 1662 1742 1742 1672 1672 1602 1602 1602 1602 1672 1672 1672 1672 1792 1662 1662 1612 1612 1602 1602 1602 1602 1672 1672 1672 1672 1672 1792 1792 1662 1612 1612 1672 1672 2108 2108 2108 2108 2108 2108 2138 2138 2138 2138 2138 2088 2088 2088 2088 2088 2198 2198 2108 2108 2108 2068 2068 2068 2068 2068 2068 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 2188 1742 1742 1742 1742 1742 1742 1672 1672 1672 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1672 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1662 1662 1612 1612 1612 1612 1612 1612 1612 1612 1672 1672 1672 1672 2108 2108 2108 2108 2108 2108 2138 2138 2138 2138 2138 2138 2088 2088 2088 2198 2198 2108 2108 2068 2068 2188 2188 2188 2188 2128 2128 1808 1808 1948 1948 1948 +1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1716 1716 1716 1716 1716 1716 1716 1716 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1766 1626 1626 1626 1626 1626 1626 1626 1626 1626 1626 1626 1626 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1716 1586 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1746 1746 1746 1746 1746 1746 1746 1746 1746 1746 1666 1666 1596 1596 1596 1646 1646 1716 1636 1636 1636 1636 1596 1596 1626 1626 1626 1766 1766 1766 1766 1766 1766 1716 1716 1716 1716 1716 1716 1716 1786 1786 1786 1786 1656 1656 1736 1736 1736 1636 1636 1596 1626 1626 1766 1766 1766 1716 1716 1716 1716 1786 1786 1786 1786 1656 1656 1736 1736 1666 1666 1596 1596 1596 1666 1666 1666 1666 1786 1656 1656 1666 1666 1596 1596 1596 1596 1666 1666 1666 1666 1666 1666 1786 1786 1656 1606 1606 1666 2099 2099 2099 2099 2099 2099 2129 2129 2129 2129 2129 2079 2079 2079 2079 2079 2189 2189 2099 2099 2099 2059 2059 2059 2059 2059 2059 2179 2179 2179 2179 2179 2179 2179 2179 2179 2179 2179 2179 2179 2179 2179 1656 1656 1736 1736 1736 1736 1736 1736 1736 1736 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1596 1596 1596 1596 1596 1596 1596 1596 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1666 1786 1786 1786 1786 1786 1786 1656 1656 1656 1656 1606 1606 1606 1606 1666 1666 1666 1666 2099 2099 2099 2099 2099 2099 2129 2129 2129 2129 2129 2079 2079 2079 2189 2189 2099 2059 2059 2179 2179 2179 2179 2119 1769 1769 1769 1909 +1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1760 1760 1760 1760 1760 1760 1760 1760 1760 1760 1760 1760 1760 1620 1620 1620 1620 1620 1620 1620 1620 1620 1620 1620 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1710 1580 1580 1580 1580 1580 1660 1660 1660 1660 1660 1660 1660 1660 1740 1740 1740 1740 1740 1740 1740 1740 1740 1740 1660 1660 1660 1590 1590 1640 1640 1710 1630 1630 1630 1630 1590 1590 1620 1620 1760 1760 1760 1760 1760 1760 1710 1710 1710 1710 1710 1710 1710 1780 1780 1780 1780 1650 1650 1710 1630 1630 1630 1630 1590 1620 1620 1760 1760 1710 1710 1710 1710 1710 1780 1780 1780 1650 1650 1730 1730 1660 1660 1590 1590 1590 1660 1660 1660 1660 1780 1650 1730 1730 1660 1590 1590 1590 1590 1660 1660 1660 1660 1660 1660 1780 1780 1650 1600 1600 1660 2090 2090 2090 2090 2090 2090 2120 2120 2120 2120 2120 2070 2070 2070 2070 2070 2070 2180 2180 2090 2090 2050 2050 2050 2050 2050 2050 2050 2170 2170 2170 2170 2170 2170 2170 2170 2170 2170 2170 2170 1780 1650 1650 1650 1650 1650 1730 1730 1730 1730 1730 1730 1730 1730 1730 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1660 1780 1780 1780 1780 1780 1650 1650 1650 1600 1600 1600 1600 1600 1660 1660 1660 1660 2090 2090 2090 2090 2090 2120 2120 2120 2120 2120 2070 2070 2070 2180 2090 2050 2050 2170 2170 2170 2110 2110 1730 1730 +1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1754 1754 1754 1754 1754 1754 1754 1754 1754 1754 1754 1754 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1704 1574 1574 1574 1574 1574 1574 1574 1574 1574 1574 1654 1654 1654 1734 1734 1734 1734 1734 1734 1734 1734 1734 1734 1654 1654 1584 1584 1634 1634 1704 1624 1624 1624 1624 1584 1614 1614 1614 1754 1754 1754 1754 1754 1704 1704 1704 1704 1704 1704 1774 1774 1774 1774 1584 1584 1634 1704 1624 1624 1624 1584 1614 1614 1754 1754 1704 1704 1704 1704 1704 1774 1774 1774 1774 1644 1724 1724 1654 1654 1584 1584 1584 1584 1654 1654 1774 1644 1644 1724 1724 1654 1654 1584 1584 1584 1584 1654 1654 1654 1654 1654 1774 1774 1644 1594 1594 1654 2081 2081 2081 2081 2081 2081 2111 2111 2111 2111 2111 2061 2061 2061 2061 2061 2061 2171 2171 2081 2081 2081 2041 2041 2041 2041 2041 2041 2041 2161 2161 2161 2161 2161 2161 2161 2161 2161 2161 1774 1774 1644 1644 1644 1644 1644 1644 1644 1724 1724 1724 1724 1724 1724 1724 1724 1724 1724 1724 1654 1654 1654 1654 1654 1654 1654 1654 1654 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1654 1774 1774 1774 1774 1774 1644 1644 1644 1594 1594 1594 1594 1654 1654 1654 1654 2081 2081 2081 2081 2081 2111 2111 2111 2111 2061 2061 2061 2081 2081 2041 2041 2161 2161 2161 2101 2101 +1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1748 1748 1748 1748 1748 1748 1748 1748 1748 1748 1748 1608 1608 1608 1608 1608 1608 1608 1608 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1698 1698 1698 1698 1698 1698 1698 1698 1698 1698 1568 1568 1568 1568 1568 1568 1568 1568 1568 1648 1648 1648 1648 1728 1728 1728 1728 1728 1728 1728 1728 1728 1648 1578 1578 1578 1628 1698 1698 1618 1618 1618 1618 1578 1608 1608 1748 1748 1748 1748 1748 1748 1698 1698 1698 1698 1698 1768 1728 1728 1648 1578 1628 1698 1618 1618 1618 1578 1578 1608 1748 1748 1748 1698 1698 1698 1698 1768 1768 1768 1768 1638 1638 1718 1648 1648 1648 1578 1578 1578 1768 1768 1768 1638 1638 1718 1718 1648 1648 1578 1578 1578 1578 1648 1648 1648 1648 1648 1648 1768 1768 1588 1588 1648 1648 2072 2072 2072 2072 2072 2102 2102 2102 2102 2102 2052 2052 2052 2052 2052 2052 2162 2162 2162 2072 2072 2032 2032 2032 2032 2032 2032 2032 2032 2032 2152 2152 2152 2152 2152 2152 2152 1698 1768 1768 1768 1768 1768 1638 1638 1638 1638 1638 1638 1638 1718 1718 1718 1718 1718 1718 1718 1718 1718 1718 1718 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1648 1648 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1648 1768 1768 1768 1768 1638 1638 1638 1588 1588 1588 1588 1648 1648 1648 1648 2072 2072 2072 2072 2102 2102 2102 2102 2052 2052 2162 2072 2072 2032 2032 2152 2152 2152 +1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1792 1642 1642 1642 1642 1642 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1742 1742 1742 1742 1742 1742 1742 1742 1742 1742 1602 1602 1602 1602 1602 1602 1602 1602 1602 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1692 1692 1692 1692 1692 1692 1692 1692 1562 1562 1562 1562 1562 1562 1562 1642 1642 1642 1642 1642 1722 1722 1722 1722 1722 1722 1722 1722 1722 1642 1572 1572 1572 1622 1692 1692 1612 1612 1612 1572 1602 1602 1602 1742 1742 1742 1742 1742 1692 1692 1692 1692 1722 1722 1722 1642 1572 1572 1622 1692 1612 1612 1612 1572 1572 1602 1742 1742 1692 1692 1692 1692 1762 1762 1762 1762 1632 1632 1712 1712 1642 1642 1572 1572 1692 1692 1762 1762 1632 1632 1712 1712 1642 1642 1572 1572 1572 1572 1642 1642 1642 1642 1642 1642 1762 1762 1582 1582 1642 1642 2063 2063 2063 2063 2063 2093 2093 2093 2093 2093 2043 2043 2043 2043 2043 2043 2043 2153 2153 2063 2063 2063 2023 2023 2023 2023 2023 2023 2023 2023 2023 2143 2143 2143 2143 1762 1692 1692 1692 1692 1762 1762 1762 1762 1762 1762 1632 1632 1632 1632 1632 1632 1632 1712 1712 1712 1712 1712 1712 1712 1712 1712 1712 1712 1712 1712 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1642 1642 1642 1642 1642 1642 1642 1642 1642 1642 1762 1762 1762 1762 1632 1632 1582 1582 1582 1582 1642 1642 1642 2063 2063 2063 2063 2093 2093 2093 2093 2043 2043 2153 2063 2023 2023 2143 2143 +1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1786 1636 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1686 1736 1736 1736 1736 1736 1736 1736 1736 1736 1596 1596 1596 1596 1596 1596 1596 1596 1596 1596 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1686 1686 1686 1686 1686 1686 1686 1686 1556 1556 1556 1556 1636 1636 1636 1636 1636 1636 1716 1716 1716 1716 1716 1716 1716 1716 1716 1636 1566 1566 1616 1616 1686 1606 1606 1606 1566 1566 1596 1596 1736 1736 1736 1736 1736 1686 1636 1636 1716 1716 1716 1636 1636 1566 1616 1686 1686 1606 1606 1566 1566 1596 1736 1736 1686 1686 1686 1686 1686 1756 1756 1756 1626 1626 1706 1706 1636 1636 1686 1686 1686 1686 1756 1756 1626 1626 1706 1706 1636 1636 1566 1566 1566 1566 1566 1636 1636 1636 1636 1636 1756 1756 1576 1576 1636 1636 2054 2054 2054 2054 2054 2084 2084 2084 2084 2084 2034 2034 2034 2034 2034 2034 2034 2144 2144 2144 2054 2054 2054 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 2134 1756 1736 1736 1686 1686 1686 1686 1686 1756 1756 1756 1756 1756 1756 1756 1626 1626 1626 1626 1626 1626 1626 1626 1626 1706 1706 1706 1706 1706 1706 1706 1706 1706 1706 1706 1706 1706 1706 1706 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1636 1566 1566 1566 1566 1566 1566 1566 1566 1566 1566 1566 1566 1566 1566 1636 1636 1636 1636 1636 1636 1636 1636 1636 1756 1756 1756 1756 1626 1626 1576 1576 1576 1636 1636 1636 2054 2054 2054 2054 2084 2084 2084 2034 2034 2034 2054 2054 2014 2014 +1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1780 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1680 1730 1730 1730 1730 1730 1730 1730 1730 1730 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1590 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1680 1680 1680 1680 1680 1680 1680 1550 1550 1630 1630 1630 1630 1630 1630 1710 1710 1710 1710 1710 1710 1710 1710 1710 1630 1630 1560 1560 1610 1680 1680 1600 1600 1600 1560 1560 1590 1590 1730 1730 1630 1630 1630 1630 1710 1710 1710 1710 1630 1560 1560 1610 1610 1680 1600 1600 1560 1590 1730 1730 1730 1680 1680 1680 1680 1750 1750 1750 1750 1620 1620 1700 1730 1730 1680 1680 1680 1680 1750 1750 1750 1620 1700 1700 1630 1630 1560 1560 1560 1560 1560 1630 1630 1630 1630 1630 1750 1750 1570 1570 1630 1630 2045 2045 2045 2045 2045 2075 2075 2075 2075 2075 2075 2025 2025 2025 2025 2025 2025 2025 2135 2135 2045 2045 2045 2045 2005 2005 2005 2005 2005 2005 2005 2005 2005 1590 1730 1730 1730 1730 1730 1680 1680 1680 1680 1680 1680 1750 1750 1750 1750 1750 1750 1750 1620 1620 1620 1620 1620 1620 1620 1620 1620 1620 1620 1620 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1700 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1630 1560 1560 1560 1560 1560 1560 1560 1560 1560 1560 1630 1630 1630 1630 1630 1630 1630 1630 1750 1750 1750 1750 1620 1620 1570 1570 1630 1630 1630 2045 2045 2045 2045 2075 2075 2075 2025 2025 2135 2045 2005 +1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1774 1774 1774 1774 1774 1774 1774 1774 1774 1774 1774 1774 1624 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1674 1724 1724 1724 1724 1724 1724 1724 1724 1724 1724 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1584 1624 1624 1624 1624 1624 1624 1624 1624 1624 1624 1674 1674 1674 1674 1674 1674 1674 1544 1544 1624 1624 1624 1624 1624 1704 1704 1704 1704 1704 1704 1704 1704 1704 1624 1554 1554 1604 1604 1674 1594 1594 1594 1594 1554 1554 1584 1544 1544 1624 1624 1624 1624 1704 1704 1704 1624 1624 1554 1604 1604 1674 1594 1594 1554 1554 1584 1724 1724 1674 1674 1674 1674 1744 1744 1744 1744 1744 1584 1584 1724 1724 1724 1674 1674 1674 1744 1744 1744 1614 1694 1694 1624 1624 1624 1554 1554 1554 1554 1624 1624 1624 1624 1624 1744 1744 1614 1564 1624 1624 2036 2036 2036 2036 2036 2066 2066 2066 2066 2066 2066 2016 2016 2016 2016 2016 2016 2016 2126 2126 2126 2036 2036 2036 2036 1996 1996 1996 1996 1996 1996 1624 1584 1584 1584 1584 1584 1724 1724 1724 1724 1724 1724 1724 1674 1674 1674 1674 1674 1744 1744 1744 1744 1744 1744 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1614 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1694 1624 1624 1624 1624 1624 1624 1624 1624 1554 1554 1554 1554 1554 1554 1554 1554 1624 1624 1624 1624 1624 1624 1624 1624 1744 1744 1744 1614 1614 1564 1564 1624 1624 1624 2036 2036 2036 2066 2066 2066 2066 2016 2016 2036 +1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1768 1768 1768 1768 1768 1768 1768 1768 1768 1768 1768 1768 1618 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1668 1718 1718 1718 1718 1718 1718 1718 1718 1718 1718 1718 1718 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1578 1618 1618 1618 1618 1618 1618 1618 1618 1618 1668 1668 1668 1668 1668 1668 1668 1538 1538 1538 1538 1618 1618 1698 1698 1698 1698 1698 1698 1698 1698 1698 1618 1618 1548 1548 1598 1668 1588 1588 1588 1588 1618 1668 1668 1538 1538 1618 1618 1618 1698 1698 1698 1698 1618 1548 1548 1598 1668 1588 1588 1588 1548 1578 1718 1718 1718 1668 1668 1668 1668 1738 1738 1668 1578 1578 1578 1578 1718 1718 1668 1668 1668 1738 1738 1738 1608 1688 1688 1618 1618 1618 1548 1548 1548 1548 1618 1618 1618 1618 1618 1738 1738 1608 1558 1618 1618 2027 2027 2027 2027 2027 2057 2057 2057 2057 2057 2057 2007 2007 2007 2007 2007 2007 2007 2007 2117 2117 2117 2027 2027 2027 2027 2027 1987 1987 1987 1738 1548 1548 1548 1578 1578 1578 1578 1578 1578 1578 1718 1718 1718 1718 1718 1718 1668 1668 1668 1668 1668 1668 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1738 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1608 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1688 1618 1618 1618 1618 1618 1548 1548 1548 1548 1548 1548 1548 1548 1618 1618 1618 1618 1618 1618 1618 1738 1738 1738 1738 1608 1558 1558 1618 1618 1618 2027 2027 2027 2057 2057 2057 2007 2007 +1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1762 1762 1762 1762 1762 1762 1762 1762 1762 1762 1762 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1662 1712 1712 1712 1712 1712 1712 1712 1712 1712 1712 1712 1572 1572 1572 1572 1572 1572 1572 1572 1572 1572 1612 1612 1612 1612 1612 1612 1612 1612 1612 1612 1662 1662 1662 1662 1662 1662 1662 1532 1532 1532 1612 1612 1692 1692 1692 1692 1692 1692 1692 1692 1692 1692 1612 1542 1542 1592 1662 1662 1612 1612 1612 1612 1662 1532 1532 1532 1612 1612 1612 1692 1692 1692 1692 1612 1542 1542 1592 1582 1582 1582 1542 1572 1712 1712 1712 1662 1662 1662 1712 1662 1662 1662 1572 1572 1572 1572 1712 1712 1662 1662 1662 1732 1732 1732 1602 1682 1682 1682 1612 1612 1542 1542 1542 1542 1612 1612 1612 1612 1612 1732 1732 1602 1552 1612 1612 2018 2018 2018 2018 2018 2048 2048 2048 2048 2048 2048 2048 1998 1998 1998 1998 1998 1998 1998 1998 2108 2108 2108 2018 2018 2018 2018 2018 2018 1712 1582 1582 1582 1582 1542 1542 1542 1542 1572 1572 1572 1572 1572 1572 1572 1572 1572 1712 1712 1662 1662 1662 1662 1662 1662 1662 1662 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1732 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1602 1682 1682 1682 1682 1682 1682 1682 1682 1682 1682 1682 1612 1612 1612 1612 1612 1612 1542 1542 1542 1542 1612 1612 1612 1612 1612 1612 1612 1732 1732 1732 1602 1552 1612 1612 1612 2018 2018 2018 2048 2048 2048 1998 +1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 +1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 1500 diff --git a/examples/helmholtz/crossPoints/mesh.cpp b/examples/helmholtz/crossPoints/mesh.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a7423d4b7b1c28a0de64114bd0a983b318c8ed06 --- /dev/null +++ b/examples/helmholtz/crossPoints/mesh.cpp @@ -0,0 +1,1351 @@ +#include "mesh.h" + +#include "gmsh.h" + +#include <gmshfem/Message.h> + +#include <tuple> +#include <algorithm> + +static int newPoint(const double x, const double y, const double z, const double lc) +{ + int tag = 0; + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(x, y, z, x, y, z, tags, 0); + if(tags.size() != 0) { + tag = tags[0].second; + } + else { + tag = gmsh::model::geo::addPoint(x, y, z, lc); + } + return tag; +} + +static int newLine(const int p0, const int p1) +{ + double xMin = 0., yMin = 0., zMin = 0., xMax = 0., yMax = 0., zMax = 0.; + gmsh::model::getBoundingBox(0, p0, xMin, yMin, zMin, xMin, yMin, zMin); + gmsh::model::getBoundingBox(0, p1, xMax, yMax, zMax, xMax, yMax, zMax); + if(xMin > xMax) std::swap(xMin, xMax); + if(yMin > yMax) std::swap(yMin, yMax); + if(zMin > zMax) std::swap(zMin, zMax); + + int tag = 0; + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(xMin, yMin, zMin, xMax, yMax, zMax, tags, 1); + if(tags.size() != 0) { + for(unsigned int i = 0; i < tags.size(); ++i) { + std::vector< std::pair< int, int > > outTags; + gmsh::model::getBoundary({tags[i]}, outTags); + if((std::abs(outTags[0].second) == p0 && std::abs(outTags[1].second) == p1) || (std::abs(outTags[0].second) == p1 && std::abs(outTags[1].second) == p0)) { + tag = -tags[i].second; + break; + } + } + } + + if(tag == 0) { + tag = gmsh::model::geo::addLine(p0, p1); + } + + return tag; +} + +static int newSurface(const int l0, const int l1, const int l2, const int l3) +{ + double xMin[4], yMin[4], zMin[4], xMax[4], yMax[4], zMax[4]; + gmsh::model::getBoundingBox(1, std::abs(l0), xMin[0], yMin[0], zMin[0], xMax[0], yMax[0], zMax[0]); + gmsh::model::getBoundingBox(1, std::abs(l1), xMin[1], yMin[1], zMin[1], xMax[1], yMax[1], zMax[1]); + gmsh::model::getBoundingBox(1, std::abs(l2), xMin[2], yMin[2], zMin[2], xMax[2], yMax[2], zMax[2]); + gmsh::model::getBoundingBox(1, std::abs(l3), xMin[3], yMin[3], zMin[3], xMax[3], yMax[3], zMax[3]); + xMin[0] = std::min({xMin[0], xMin[1], xMin[2], xMin[3]}); + yMin[0] = std::min({yMin[0], yMin[1], yMin[2], yMin[3]}); + zMin[0] = std::min({zMin[0], zMin[1], zMin[2], zMin[3]}); + xMax[0] = std::max({xMax[0], xMax[1], xMax[2], xMax[3]}); + yMax[0] = std::max({yMax[0], yMax[1], yMax[2], yMax[3]}); + zMax[0] = std::max({zMax[0], zMax[1], zMax[2], zMax[3]}); + + int tag = 0; + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(xMin[0], yMin[0], zMin[0], xMax[0], yMax[0], zMax[0], tags, 2); + if(tags.size() != 0) { + for(unsigned int i = 0; i < tags.size(); ++i) { + std::vector< std::pair< int, int > > outTags; + gmsh::model::getBoundary({tags[i]}, outTags); + std::vector< int > bndTag {std::abs(outTags[0].second), std::abs(outTags[1].second), std::abs(outTags[2].second), std::abs(outTags[3].second)}; + std::vector< int > myTag {std::abs(l0), std::abs(l1), std::abs(l2), std::abs(l3)}; + if(std::is_permutation(bndTag.begin(), bndTag.end(), myTag.begin())) { + tag = -tags[i].second; + break; + } + } + } + + if(tag == 0) { + int curveLoop = gmsh::model::geo::addCurveLoop({ l0, l1, l2, l3 }, -1, true); + tag = gmsh::model::geo::addPlaneSurface({ curveLoop }); + } + + return tag; +} + +static void fixOrientationOfLine(std::vector< int > &cubeLines, const std::vector< int > &cubePoints) +{ + for(unsigned int i = 0; i < 4; ++i) { + // bottom + { + std::vector< std::pair< int, int > > outTags; + gmsh::model::getBoundary({std::make_pair(1, cubeLines[i])}, outTags, false, false); + if(outTags[0].second == cubePoints[i] && outTags[1].second == cubePoints[(i+1)%4]) { + cubeLines[i] = cubeLines[i]; + } + else { + cubeLines[i] = -cubeLines[i]; + } + } + + // vertical + cubeLines[i+4] = std::abs(cubeLines[i+4]); + + // above + { + std::vector< std::pair< int, int > > outTags; + gmsh::model::getBoundary({std::make_pair(1, cubeLines[i+8])}, outTags, false, false); + if(outTags[0].second == cubePoints[i+4] && outTags[1].second == cubePoints[(i+1)%4+4]) { + cubeLines[i+8] = cubeLines[i+8]; + } + else { + cubeLines[i+8] = -cubeLines[i+8]; + } + } + } +} + +namespace D2 { + + + void subdomain(const int index, const int jndex, const double xSize, const double ySize, const double circleSize, const double lc, const double pmlSizeE, const double pmlSizeN, const double pmlSizeW, const double pmlSizeS, bool transfinite) + { + // square + double posX[4] = {xSize, xSize, 0., 0.}; + double posY[4] = {0., ySize, ySize, 0.}; + if(index != -1 && jndex != -1) { + posX[0] = (index+1) * xSize; + posX[1] = (index+1) * xSize; + posX[2] = index * xSize; + posX[3] = index * xSize; + + posY[0] = jndex * ySize; + posY[1] = (jndex+1) * ySize; + posY[2] = (jndex+1) * ySize; + posY[3] = jndex * ySize; + } + std::vector< int > squarePoints(4); + squarePoints[0] = newPoint(posX[0], posY[0], 0., lc); + squarePoints[1] = newPoint(posX[1], posY[1], 0., lc); + squarePoints[2] = newPoint(posX[2], posY[2], 0., lc); + squarePoints[3] = newPoint(posX[3], posY[3], 0., lc); + gmsh::model::geo::synchronize(); +// gmshfem::msg::error << "Points : " << squarePoints[0] << " " << squarePoints[1] << " " << squarePoints[2] << " " << squarePoints[3] << gmshfem::msg::endl; + + std::vector< int > squareLines(4); + for(unsigned int i = 0; i < 4; ++i) { + squareLines[i] = newLine(squarePoints[i], squarePoints[(i+1)%4]); + } + gmsh::model::geo::synchronize(); +// gmshfem::msg::error << "Lines : " << squareLines[0] << " " << squareLines[1] << " " << squareLines[2] << " " << squareLines[3] << gmshfem::msg::endl; + + int squareCurveLoop = gmsh::model::geo::addCurveLoop(squareLines); + int omega = 0; + + // circle + std::vector< int > circleLines; + if(circleSize != 0.) { + int center = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2., 0., lc); // Center + + std::vector< int > circlePoints(4); + circlePoints[0] = gmsh::model::geo::addPoint(posX[0] - xSize/2. + circleSize, posY[1] - ySize/2., 0., lc); + circlePoints[1] = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2. + circleSize, 0., lc); + circlePoints[2] = gmsh::model::geo::addPoint(posX[0] - xSize/2. - circleSize, posY[1] - ySize/2., 0., lc); + circlePoints[3] = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2. - circleSize, 0., lc); + + circleLines.resize(4); + for(unsigned int i = 0; i < 4; ++i) { + circleLines[i] = gmsh::model::geo::addCircleArc(circlePoints[i], center, circlePoints[(i+1)%4]); + } + + int circleCurveLoop = gmsh::model::geo::addCurveLoop(circleLines); + omega = gmsh::model::geo::addPlaneSurface({ squareCurveLoop,circleCurveLoop }); + } + else { + omega = gmsh::model::geo::addPlaneSurface({ squareCurveLoop }); + } + + std::vector< int > pml(4); + std::vector< int > pmlInf(4); + std::vector< std::pair< int, int > > pmlBnd(4); + std::vector< std::pair< int, int > > pmlPoint(4); + const double pmlSizes[4] = {pmlSizeE, pmlSizeN, pmlSizeW, pmlSizeS}; + + for(unsigned int i = 0; i < 4; ++i) { + if(pmlSizes[i] != 0.) { + const double orientation = i > 1 ? -1. : 1.; + std::vector< std::pair< int, int > > extrudeEntities; + gmsh::model::geo::extrude({std::make_pair(1, -squareLines[i])}, orientation * (i % 2 == 0 ? pmlSizes[i] : 0.), orientation * (i % 2 == 0 ? 0. : pmlSizes[i]), 0., extrudeEntities, {static_cast< int >(pmlSizes[i] / lc)}, std::vector< double >(), true); + if(extrudeEntities.size() != 0) { + pmlInf[i] = extrudeEntities[0].second; + pml[i] = extrudeEntities[1].second; + if(squareLines[i] < 0) { + pmlBnd[i].first = extrudeEntities[2].second; + pmlBnd[i].second = extrudeEntities[3].second; + } + else { + pmlBnd[i].first = extrudeEntities[3].second; + pmlBnd[i].second = extrudeEntities[4].second; + } + } + } + } + + // pmls corner + std::vector< std::pair< int, int > > pmlCornerInf(4); + std::vector< int > pmlCorner(4); + + for(unsigned int i = 0; i < 4; ++i) { + if(pmlSizes[i] != 0. && pmlSizes[(i+1)%4] != 0.) { + const double orientation = i == 0 || i == 3 ? 1. : -1.; + std::vector< std::pair< int, int > > extrudeEntities; + gmsh::model::geo::extrude({std::make_pair(1, -pmlBnd[i].second)}, orientation * (i % 2 == 0 ? 0. : pmlSizes[(i+1)%4]), orientation * (i % 2 == 0 ? pmlSizes[(i+1)%4] : 0.), 0., extrudeEntities, {static_cast< int >(pmlSizes[(i+1)%4] / lc)}, std::vector< double >(), true); + if(extrudeEntities.size() != 0) { + pmlCornerInf[i].first = extrudeEntities[0].second; + pmlCorner[i] = extrudeEntities[1].second; + pmlCornerInf[i].second = extrudeEntities[2].second; + } + } + } + + gmsh::model::geo::synchronize(); + + // physicals + const unsigned int tag = (index != -1 && jndex != -1 ? index * 10000 + jndex * 100 : 0); + std::string subdomainTag; + if(index != -1 && jndex != -1) { + subdomainTag = "_" + std::to_string(index) + "_" + std::to_string(jndex); + } + + gmsh::model::addPhysicalGroup(2, {omega}, 1+tag); + gmsh::model::setPhysicalName(2, 1+tag, "omega" + subdomainTag); + if(circleLines.size() != 0) { + gmsh::model::addPhysicalGroup(1, circleLines, 1); + gmsh::model::setPhysicalName(1, 1, "gamma"); + } + + std::vector< std::string > dir {"E", "N", "W", "S"}; + for(unsigned int i = 0; i < 4; ++i) { + gmsh::model::addPhysicalGroup(1, {squareLines[i]}, i+10+tag); + gmsh::model::setPhysicalName(1, i+10+tag, "sigma" + dir[i] + subdomainTag); + + if(pml[i] != 0) { + gmsh::model::addPhysicalGroup(2, {pml[i]}, i+10+tag); + gmsh::model::setPhysicalName(2, i+10+tag, "pml" + dir[i] + subdomainTag); + } + + if(pmlInf[i] != 0) { + gmsh::model::addPhysicalGroup(1, {pmlInf[i]}, i+20+tag); + gmsh::model::setPhysicalName(1, i+20+tag, "pmlInf" + dir[i] + subdomainTag); + } + + if(pmlBnd[i].first != 0) { + gmsh::model::addPhysicalGroup(1, {pmlBnd[i].first}, i+30+tag); + gmsh::model::setPhysicalName(1, i+30+tag, "pmlBnd" + dir[i] + "_first" + subdomainTag); + } + + if(pmlBnd[i].second != 0) { + gmsh::model::addPhysicalGroup(1, {pmlBnd[i].second}, i+40+tag); + gmsh::model::setPhysicalName(1, i+40+tag, "pmlBnd" + dir[i] + "_second" + subdomainTag); + } + + if(pmlCorner[i] != 0) { + gmsh::model::addPhysicalGroup(2, {pmlCorner[i]}, i+20+tag); + gmsh::model::setPhysicalName(2, i+20+tag, "pmlCorner" + dir[i] + dir[(i+1)%4] + subdomainTag); + } + + if(pmlCorner[i] != 0) { + gmsh::model::addPhysicalGroup(1, {pmlCornerInf[i].first, pmlCornerInf[i].second}, i+50+tag); + gmsh::model::setPhysicalName(1, i+50+tag, "pmlCornerInf" + dir[i] + dir[(i+1)%4] + subdomainTag); + } + + gmsh::model::addPhysicalGroup(0, {squarePoints[(i+1)%4]}, i+1+tag); + gmsh::model::setPhysicalName(0, i+1+tag, "corner" + dir[i] + dir[(i+1)%4] + subdomainTag); + } + + gmsh::model::geo::synchronize(); + + if(transfinite) { + gmsh::model::mesh::setTransfiniteSurface(omega); + gmsh::model::mesh::setRecombine(2, omega); + } + } + + void monoDomain(const double lc, const double pmlSize, const double R, const int order) + { + gmsh::model::add("mesh"); + + subdomain(-1, -1, 2., 2., R, lc, pmlSize, pmlSize, pmlSize, pmlSize, false); + + gmsh::model::mesh::generate(); + gmsh::model::mesh::setOrder(order); + } + + void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const double xSize, const double ySize, const double circleSize, const double lc, const bool pml, const double pmlSize, const bool pmlExt, const double pmlSizeExt, const int order, const unsigned int circlePosX, const unsigned int circlePosY, bool transfinite) + { + for(int i = 0; i < nDomX; ++i) { + for(int j = 0; j < nDomY; ++j) { + double pmlSizeE = 0.; + if(i == nDomX - 1) { + if(pmlExt) { + pmlSizeE = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeE = pmlSize; + } + } + + double pmlSizeN = 0.; + if(j == nDomY - 1) { + if(pmlExt) { + pmlSizeN = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeN = pmlSize; + } + } + + double pmlSizeW = 0.; + if(i == 0) { + if(pmlExt) { + pmlSizeW = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeW = pmlSize; + } + } + + double pmlSizeS = 0.; + if(j == 0) { + if(pmlExt) { + pmlSizeS = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeS = pmlSize; + } + } + + subdomain(i, j, xSize, ySize, (circlePosX == i && circlePosY == j ? circleSize : 0.), lc, pmlSizeE, pmlSizeN, pmlSizeW, pmlSizeS, transfinite); + } + } + + gmsh::model::mesh::generate(); + gmsh::model::mesh::setOrder(order); + } + + +} + +namespace D3 { + + + void subdomain(const int index, const int jndex, const int kndex, const double xSize, const double ySize, const double zSize, const double sphereSize, const double lc, const double pmlSizeE, const double pmlSizeN, const double pmlSizeW, const double pmlSizeS, const double pmlSizeD, const double pmlSizeU, bool transfinite) + { + double posX[8] = {xSize, xSize, 0., 0., xSize, xSize, 0., 0.}; + double posY[8] = {0., ySize, ySize, 0., 0., ySize, ySize, 0.}; + double posZ[8] = {0., 0., 0., 0., zSize, zSize, zSize, zSize}; + if(index != -1 && jndex != -1) { + posX[0] = (index+1) * xSize; + posX[1] = (index+1) * xSize; + posX[2] = index * xSize; + posX[3] = index * xSize; + posX[4] = (index+1) * xSize; + posX[5] = (index+1) * xSize; + posX[6] = index * xSize; + posX[7] = index * xSize; + + posY[0] = jndex * ySize; + posY[1] = (jndex+1) * ySize; + posY[2] = (jndex+1) * ySize; + posY[3] = jndex * ySize; + posY[4] = jndex * ySize; + posY[5] = (jndex+1) * ySize; + posY[6] = (jndex+1) * ySize; + posY[7] = jndex * ySize; + + posZ[0] = kndex * zSize; + posZ[1] = kndex * zSize; + posZ[2] = kndex * zSize; + posZ[3] = kndex * zSize; + posZ[4] = (kndex+1) * zSize; + posZ[5] = (kndex+1) * zSize; + posZ[6] = (kndex+1) * zSize; + posZ[7] = (kndex+1) * zSize; + } + + // square + std::vector< int > cubePoints(8); + cubePoints[0] = newPoint(posX[0], posY[0], posZ[0], lc); + cubePoints[1] = newPoint(posX[1], posY[1], posZ[1], lc); + cubePoints[2] = newPoint(posX[2], posY[2], posZ[2], lc); + cubePoints[3] = newPoint(posX[3], posY[3], posZ[3], lc); + + cubePoints[4] = newPoint(posX[4], posY[4], posZ[4], lc); + cubePoints[5] = newPoint(posX[5], posY[5], posZ[5], lc); + cubePoints[6] = newPoint(posX[6], posY[6], posZ[6], lc); + cubePoints[7] = newPoint(posX[7], posY[7], posZ[7], lc); + gmsh::model::geo::synchronize(); +// gmshfem::msg::warning << "Points : " << cubePoints[0] << " " << cubePoints[1] << " " << cubePoints[2] << " " << cubePoints[3] << " " << cubePoints[4] << " " << cubePoints[5] << " " << cubePoints[6] << " " << cubePoints[7] << gmshfem::msg::endl; + + std::vector< int > cubeLines(12); + cubeLines[0] = newLine(cubePoints[0], cubePoints[1]); + cubeLines[1] = newLine(cubePoints[1], cubePoints[2]); + cubeLines[2] = newLine(cubePoints[2], cubePoints[3]); + cubeLines[3] = newLine(cubePoints[3], cubePoints[0]); + + cubeLines[4] = newLine(cubePoints[0], cubePoints[4]); + cubeLines[5] = newLine(cubePoints[1], cubePoints[5]); + cubeLines[6] = newLine(cubePoints[2], cubePoints[6]); + cubeLines[7] = newLine(cubePoints[3], cubePoints[7]); + + cubeLines[8] = newLine(cubePoints[4], cubePoints[5]); + cubeLines[9] = newLine(cubePoints[5], cubePoints[6]); + cubeLines[10] = newLine(cubePoints[6], cubePoints[7]); + cubeLines[11] = newLine(cubePoints[7], cubePoints[4]); + gmsh::model::geo::synchronize(); + fixOrientationOfLine(cubeLines, cubePoints); +// gmshfem::msg::warning << "Lines : " << cubeLines[0] << " " << cubeLines[1] << " " << cubeLines[2] << " " << cubeLines[3] << " " << cubeLines[4] << " " << cubeLines[5] << " " << cubeLines[6] << " " << cubeLines[7] << " " << cubeLines[8] << " " << cubeLines[9] << " " << cubeLines[10] << " " << cubeLines[11] << gmshfem::msg::endl; + + std::vector< int > cubeSurface(6); + cubeSurface[0] = newSurface(cubeLines[0], cubeLines[5], cubeLines[8], cubeLines[4]); + cubeSurface[1] = newSurface(cubeLines[1], cubeLines[6], cubeLines[9], cubeLines[5]); + cubeSurface[2] = newSurface(cubeLines[2], cubeLines[7], cubeLines[10], cubeLines[6]); + cubeSurface[3] = newSurface(cubeLines[3], cubeLines[4], cubeLines[11], cubeLines[7]); + cubeSurface[4] = newSurface(-cubeLines[0], cubeLines[1], cubeLines[2], cubeLines[3]); + cubeSurface[5] = newSurface(cubeLines[8], cubeLines[9], cubeLines[10], cubeLines[11]); + gmsh::model::geo::synchronize(); +// gmshfem::msg::warning << "Surfaces : " << cubeSurface[0] << " " << cubeSurface[1] << " " << cubeSurface[2] << " " << cubeSurface[3] << " " << cubeSurface[4] << " " << cubeSurface[5] << gmshfem::msg::endl; + + int cubeSurfaceLoop = gmsh::model::geo::addSurfaceLoop(cubeSurface); + int omega = 0; + + // sphere + std::vector< int > sphereSurface; + if(sphereSize != 0.) { + int center = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1]- ySize/2., posZ[4] - zSize/2., lc); // Center + + std::vector< int > spherePoints(6); + spherePoints[0] = gmsh::model::geo::addPoint(posX[0] - xSize/2. + sphereSize, posY[1] - ySize/2., posZ[4] - zSize/2., lc); + spherePoints[1] = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2. + sphereSize, posZ[4] - zSize/2., lc); + spherePoints[2] = gmsh::model::geo::addPoint(posX[0] - xSize/2. - sphereSize, posY[1] - ySize/2., posZ[4] - zSize/2., lc); + spherePoints[3] = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2. - sphereSize, posZ[4] - zSize/2., lc); + spherePoints[4] = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2., posZ[4] - zSize/2 + sphereSize, lc); + spherePoints[5] = gmsh::model::geo::addPoint(posX[0] - xSize/2., posY[1] - ySize/2., posZ[4] - zSize/2 - sphereSize, lc); + + std::vector< int > sphereLines(12); + sphereLines[0] = gmsh::model::geo::addCircleArc(spherePoints[0], center, spherePoints[1]); + sphereLines[1] = gmsh::model::geo::addCircleArc(spherePoints[1], center, spherePoints[2]); + sphereLines[2] = gmsh::model::geo::addCircleArc(spherePoints[2], center, spherePoints[3]); + sphereLines[3] = gmsh::model::geo::addCircleArc(spherePoints[3], center, spherePoints[0]); + + sphereLines[4] = gmsh::model::geo::addCircleArc(spherePoints[0], center, spherePoints[4]); + sphereLines[5] = gmsh::model::geo::addCircleArc(spherePoints[4], center, spherePoints[2]); + sphereLines[6] = gmsh::model::geo::addCircleArc(spherePoints[2], center, spherePoints[5]); + sphereLines[7] = gmsh::model::geo::addCircleArc(spherePoints[5], center, spherePoints[0]); + + sphereLines[8] = gmsh::model::geo::addCircleArc(spherePoints[1], center, spherePoints[4]); + sphereLines[9] = gmsh::model::geo::addCircleArc(spherePoints[4], center, spherePoints[3]); + sphereLines[10] = gmsh::model::geo::addCircleArc(spherePoints[3], center, spherePoints[5]); + sphereLines[11] = gmsh::model::geo::addCircleArc(spherePoints[5], center, spherePoints[1]); + + std::vector< int > sphereCurveLoop(8); + sphereCurveLoop[0] = gmsh::model::geo::addCurveLoop({ sphereLines[0], sphereLines[8], sphereLines[4] }, -1, true); + sphereCurveLoop[1] = gmsh::model::geo::addCurveLoop({ sphereLines[1], sphereLines[5], sphereLines[8] }, -1, true); + sphereCurveLoop[2] = gmsh::model::geo::addCurveLoop({ sphereLines[2], sphereLines[9], sphereLines[5] }, -1, true); + sphereCurveLoop[3] = gmsh::model::geo::addCurveLoop({ sphereLines[3], sphereLines[4], sphereLines[9] }, -1, true); + + sphereCurveLoop[4] = gmsh::model::geo::addCurveLoop({ -sphereLines[0], sphereLines[7], sphereLines[11] }, -1, true); + sphereCurveLoop[5] = gmsh::model::geo::addCurveLoop({ -sphereLines[1], sphereLines[11], sphereLines[6] }, -1, true); + sphereCurveLoop[6] = gmsh::model::geo::addCurveLoop({ -sphereLines[2], sphereLines[6], sphereLines[10] }, -1, true); + sphereCurveLoop[7] = gmsh::model::geo::addCurveLoop({ -sphereLines[3], sphereLines[10], sphereLines[7] }, -1, true); + + sphereSurface.resize(8); + sphereSurface[0] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[0] }, -1, center); + sphereSurface[1] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[1] }, -1, center); + sphereSurface[2] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[2] }, -1, center); + sphereSurface[3] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[3] }, -1, center); + + sphereSurface[4] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[4] }, -1, center); + sphereSurface[5] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[5] }, -1, center); + sphereSurface[6] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[6] }, -1, center); + sphereSurface[7] = gmsh::model::geo::addSurfaceFilling({ sphereCurveLoop[7] }, -1, center); + + int sphereSurfaceLoop = gmsh::model::geo::addSurfaceLoop(sphereSurface); + omega = gmsh::model::geo::addVolume({sphereSurfaceLoop,cubeSurfaceLoop}); + } + else { + omega = gmsh::model::geo::addVolume({cubeSurfaceLoop}); + } + + // pmls + std::vector< int > pml(6); + std::vector< int > pmlInf(6); + std::vector< std::tuple< int, int, int, int > > pmlBnd(6); + const double pmlSizes[6] = {pmlSizeE, pmlSizeN, pmlSizeW, pmlSizeS, pmlSizeD, pmlSizeU}; + const int extrudePmlFace[6][4][6] = { + { + {0, 0, 0, 1, 1, 0}, + {0, 1, 0, 1, 1, 1}, + {0, 0, 1, 1, 1, 1}, + {0, 0, 0, 1, 0, 1} + }, + { + {0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 1, 1}, + {0, 0, 1, 1, 1, 1}, + {1, 0, 0, 1, 1, 1} + }, + { + {0, 0, 0, 1, 1, 0}, + {0, 0, 0, 1, 0, 1}, + {0, 0, 1, 1, 1, 1}, + {0, 1, 0, 1, 1, 1} + }, + { + {0, 0, 0, 1, 1, 0}, + {1, 0, 0, 1, 1, 1}, + {0, 0, 1, 1, 1, 1}, + {0, 0, 0, 0, 1, 1} + }, + { + {1, 0, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1}, + {0, 1, 0, 1, 1, 1} + }, + { + {1, 0, 0, 1, 1, 1}, + {0, 1, 0, 1, 1, 1}, + {0, 0, 0, 0, 1, 1}, + {0, 0, 0, 1, 0, 1} + } + }; + + for(unsigned int i = 0; i < 6; ++i) { + if(pmlSizes[i] != 0.) { + const double orientation = i > 1 ? -1. : 1.; + std::vector< std::pair< int, int > > extrudeEntities; + gmsh::model::geo::extrude({std::make_pair(2, cubeSurface[i])}, orientation * (i < 4 ? ((i%4) % 2 == 0 ? pmlSizes[i] : 0.) : 0.), orientation * (i < 4 ? ((i%4) % 2 == 0 ? 0. : pmlSizes[i]) : 0.), (i > 3 ? (i == 4 ? -pmlSizes[i] : pmlSizes[i]) : 0.), extrudeEntities, {static_cast< int >(pmlSizes[i] / lc)}, std::vector< double >(), true); + pmlInf[i] = extrudeEntities[0].second; + pml[i] = extrudeEntities[1].second; + gmsh::model::geo::synchronize(); + + double bbx[2], bby[2], bbz[2]; + gmsh::model::getBoundingBox(extrudeEntities[1].first, extrudeEntities[1].second, bbx[0], bby[0], bbz[0], bbx[1], bby[1], bbz[1]); + + for(unsigned int j = 0; j < 4; ++j) { + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(bbx[extrudePmlFace[i][j][0]], bby[extrudePmlFace[i][j][1]], bbz[extrudePmlFace[i][j][2]], bbx[extrudePmlFace[i][j][3]], bby[extrudePmlFace[i][j][4]], bbz[extrudePmlFace[i][j][5]], tags, 2); + if(tags.size() == 0) { + gmshfem::msg::error << "Unable to find a PML boundary" << gmshfem::msg::endl; + return; + } + else if(tags.size() > 1) { + for(unsigned int k = 0; k < tags.size(); ++k) { + double tmpbbx[2], tmpbby[2], tmpbbz[2]; + gmsh::model::getBoundingBox(tags[k].first, tags[k].second, tmpbbx[0], tmpbby[0], tmpbbz[0], tmpbbx[1], tmpbby[1], tmpbbz[1]); + if(tmpbbx[0] == bbx[extrudePmlFace[i][j][0]] && tmpbbx[1] == bbx[extrudePmlFace[i][j][3]] && tmpbby[0] == bby[extrudePmlFace[i][j][1]] && tmpbby[1] == bby[extrudePmlFace[i][j][4]] && tmpbbz[0] == bbz[extrudePmlFace[i][j][2]] && tmpbbz[1] == bbz[extrudePmlFace[i][j][5]]) { + tags[0].first = tags[k].first; + tags[0].second = tags[k].second; + break; + } + } + } + + if(j == 0) { + std::get<0>(pmlBnd[i]) = tags[0].second; + } + else if(j == 1) { + std::get<1>(pmlBnd[i]) = tags[0].second; + } + else if(j == 2) { + std::get<2>(pmlBnd[i]) = tags[0].second; + } + else if(j == 3) { + std::get<3>(pmlBnd[i]) = tags[0].second; + } + } + } + } + + // pmls edge + std::vector< int > pmlEdge(12); + std::vector< std::vector< int > > pmlEdgeInf(12); + std::vector< std::pair< int, int > > pmlEdgeBnd(12); + std::vector< int > edge(12); + const std::vector< std::vector< double > > pmlEdgeExtrude { + std::vector< double > {0., pmlSizeN, 0.}, // E + std::vector< double > {-pmlSizeW, 0., 0.}, // N + std::vector< double > {0., -pmlSizeS, 0.}, // W + std::vector< double > {pmlSizeE, 0., 0.}, // S + }; + const int extrudePmlEdge[12][3][6] = { + // Down + { + {0, 0, 0, 1, 0, 1}, + {0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 1, 1} + }, + { + {1, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 1, 1}, + {0, 1, 0, 1, 1, 1} + }, + { + {0, 1, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1} + }, + { + {0, 0, 0, 0, 1, 1}, + {1, 0, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 1} + }, + // Rot + { + {0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1}, + {1, 0, 0, 1, 1, 1} + }, + { + {0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1}, + {0, 1, 0, 1, 1, 1} + }, + { + {0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1}, + {0, 0, 0, 0, 1, 1} + }, + { + {0, 0, 0, 1, 1, 0}, + {0, 0, 1, 1, 1, 1}, + {0, 0, 0, 1, 0, 1} + }, + // Up + { + {0, 0, 0, 1, 0, 1}, + {0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 1, 1} + }, + { + {1, 0, 0, 1, 1, 1}, + {0, 0, 0, 0, 1, 1}, + {0, 0, 0, 1, 0, 1} + }, + { + {0, 1, 0, 1, 1, 1}, + {0, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1} + }, + { + {0, 0, 0, 0, 1, 1}, + {1, 0, 0, 1, 1, 1}, + {0, 1, 0, 1, 1, 1} + } + }; + + for(unsigned int i = 0; i < 4; ++i) { + std::vector< std::pair< int, int > > extrudeEntities; + // Down + if(pmlSizeD != 0.) { + gmsh::model::geo::extrude({std::make_pair(2, std::get<0>(pmlBnd[i]))}, 0., 0., -pmlSizeD, extrudeEntities, {static_cast< int >(pmlSizeD / lc)}, std::vector< double >(), true); + pmlEdgeInf[i].push_back(extrudeEntities[0].second); + pmlEdge[i] = extrudeEntities[1].second; + gmsh::model::geo::synchronize(); + + double bbx[2], bby[2], bbz[2]; + gmsh::model::getBoundingBox(extrudeEntities[1].first, extrudeEntities[1].second, bbx[0], bby[0], bbz[0], bbx[1], bby[1], bbz[1]); + + for(unsigned int j = 0; j < 3; ++j) { + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(bbx[extrudePmlEdge[i][j][0]], bby[extrudePmlEdge[i][j][1]], bbz[extrudePmlEdge[i][j][2]], bbx[extrudePmlEdge[i][j][3]], bby[extrudePmlEdge[i][j][4]], bbz[extrudePmlEdge[i][j][5]], tags, 2); + if(tags.size() == 0) { + gmshfem::msg::error << "Unable to find a edge-PML boundary" << gmshfem::msg::endl; + return; + } + else if(tags.size() > 1) { + for(unsigned int k = 0; k < tags.size(); ++k) { + double tmpbbx[2], tmpbby[2], tmpbbz[2]; + gmsh::model::getBoundingBox(tags[k].first, tags[k].second, tmpbbx[0], tmpbby[0], tmpbbz[0], tmpbbx[1], tmpbby[1], tmpbbz[1]); + if(tmpbbx[0] == bbx[extrudePmlEdge[i][j][0]] && tmpbbx[1] == bbx[extrudePmlEdge[i][j][3]] && tmpbby[0] == bby[extrudePmlEdge[i][j][1]] && tmpbby[1] == bby[extrudePmlEdge[i][j][4]] && tmpbbz[0] == bbz[extrudePmlEdge[i][j][2]] && tmpbbz[1] == bbz[extrudePmlEdge[i][j][5]]) { + tags[0].first = tags[k].first; + tags[0].second = tags[k].second; + break; + } + } + } + + if(j == 0) { + pmlEdgeBnd[i].first = tags[0].second; + } + else if(j == 1) { + pmlEdgeBnd[i].second = tags[0].second; + } + else if(j == 2) { + pmlEdgeInf[i].push_back(tags[0].second); + } + } + extrudeEntities.clear(); + } + edge[i] = cubeLines[i]; + + // Rot + if(std::abs(pmlEdgeExtrude[i][0] + pmlEdgeExtrude[i][1]) != 0.) { + gmsh::model::geo::extrude({std::make_pair(2, std::get<1>(pmlBnd[i]))}, pmlEdgeExtrude[i][0], pmlEdgeExtrude[i][1], pmlEdgeExtrude[i][2], extrudeEntities, {static_cast< int >(std::abs(pmlEdgeExtrude[i][0] + pmlEdgeExtrude[i][1]) / lc)}, std::vector< double >(), true); + pmlEdgeInf[i+4].push_back(extrudeEntities[0].second); + pmlEdge[i+4] = extrudeEntities[1].second; + gmsh::model::geo::synchronize(); + + double bbx[2], bby[2], bbz[2]; + gmsh::model::getBoundingBox(extrudeEntities[1].first, extrudeEntities[1].second, bbx[0], bby[0], bbz[0], bbx[1], bby[1], bbz[1]); + + for(unsigned int j = 0; j < 3; ++j) { + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(bbx[extrudePmlEdge[i+4][j][0]], bby[extrudePmlEdge[i+4][j][1]], bbz[extrudePmlEdge[i+4][j][2]], bbx[extrudePmlEdge[i+4][j][3]], bby[extrudePmlEdge[i+4][j][4]], bbz[extrudePmlEdge[i+4][j][5]], tags, 2); + if(tags.size() == 0) { + gmshfem::msg::error << "Unable to find a edge-PML boundary" << gmshfem::msg::endl; + return; + } + else if(tags.size() > 1) { + for(unsigned int k = 0; k < tags.size(); ++k) { + double tmpbbx[2], tmpbby[2], tmpbbz[2]; + gmsh::model::getBoundingBox(tags[k].first, tags[k].second, tmpbbx[0], tmpbby[0], tmpbbz[0], tmpbbx[1], tmpbby[1], tmpbbz[1]); + if(tmpbbx[0] == bbx[extrudePmlEdge[i][j][0]] && tmpbbx[1] == bbx[extrudePmlEdge[i][j][3]] && tmpbby[0] == bby[extrudePmlEdge[i][j][1]] && tmpbby[1] == bby[extrudePmlEdge[i][j][4]] && tmpbbz[0] == bbz[extrudePmlEdge[i][j][2]] && tmpbbz[1] == bbz[extrudePmlEdge[i][j][5]]) { + tags[0].first = tags[k].first; + tags[0].second = tags[k].second; + break; + } + } + } + + if(j == 0) { + pmlEdgeBnd[i+4].first = tags[0].second; + } + else if(j == 1) { + pmlEdgeBnd[i+4].second = tags[0].second; + } + else if(j == 2) { + pmlEdgeInf[i+4].push_back(tags[0].second); + } + } + extrudeEntities.clear(); + } + edge[i+4] = cubeLines[(i+1)%4+4]; + + // Up + if(pmlSizeU != 0.) { + gmsh::model::geo::extrude({std::make_pair(2, std::get<2>(pmlBnd[i]))}, 0., 0., pmlSizeU, extrudeEntities, {static_cast< int >(pmlSizeU / lc)}, std::vector< double >(), true); + pmlEdgeInf[i+8].push_back(extrudeEntities[0].second); + pmlEdge[i+8] = extrudeEntities[1].second; + gmsh::model::geo::synchronize(); + + double bbx[2], bby[2], bbz[2]; + gmsh::model::getBoundingBox(extrudeEntities[1].first, extrudeEntities[1].second, bbx[0], bby[0], bbz[0], bbx[1], bby[1], bbz[1]); + + for(unsigned int j = 0; j < 3; ++j) { + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(bbx[extrudePmlEdge[i+8][j][0]], bby[extrudePmlEdge[i+8][j][1]], bbz[extrudePmlEdge[i+8][j][2]], bbx[extrudePmlEdge[i+8][j][3]], bby[extrudePmlEdge[i+8][j][4]], bbz[extrudePmlEdge[i+8][j][5]], tags, 2); + if(tags.size() == 0) { + gmshfem::msg::error << "Unable to find a edge-PML boundary" << gmshfem::msg::endl; + return; + } + else if(tags.size() > 1) { + for(unsigned int k = 0; k < tags.size(); ++k) { + double tmpbbx[2], tmpbby[2], tmpbbz[2]; + gmsh::model::getBoundingBox(tags[k].first, tags[k].second, tmpbbx[0], tmpbby[0], tmpbbz[0], tmpbbx[1], tmpbby[1], tmpbbz[1]); + if(tmpbbx[0] == bbx[extrudePmlEdge[i][j][0]] && tmpbbx[1] == bbx[extrudePmlEdge[i][j][3]] && tmpbby[0] == bby[extrudePmlEdge[i][j][1]] && tmpbby[1] == bby[extrudePmlEdge[i][j][4]] && tmpbbz[0] == bbz[extrudePmlEdge[i][j][2]] && tmpbbz[1] == bbz[extrudePmlEdge[i][j][5]]) { + tags[0].first = tags[k].first; + tags[0].second = tags[k].second; + break; + } + } + } + + if(j == 0) { + pmlEdgeBnd[i+8].first = tags[0].second; + } + else if(j == 1) { + pmlEdgeBnd[i+8].second = tags[0].second; + } + else if(j == 2) { + pmlEdgeInf[i+8].push_back(tags[0].second); + } + } + extrudeEntities.clear(); + } + edge[i+8] = cubeLines[i+8]; + } + + // pmls corner + std::vector< int > pmlCorner(8); + std::vector< std::tuple< int, int, int > > pmlCornerEdge(8); + std::vector< std::vector< int > > pmlCornerInf(8); + std::vector< int > corner(8); + const int extrudePmlCorner[8][2][6] = { + // Down + { + {0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 1, 1} + }, + { + {0, 0, 0, 0, 1, 1}, + {0, 1, 0, 1, 1, 1} + }, + { + {0, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1} + }, + { + {0, 0, 0, 1, 0, 1}, + {1, 0, 0, 1, 1, 1} + }, + // Up + { + {0, 1, 0, 1, 1, 1}, + {1, 0, 0, 1, 1, 1} + }, + { + {0, 0, 0, 0, 1, 1}, + {0, 1, 0, 1, 1, 1} + }, + { + {0, 0, 0, 1, 0, 1}, + {0, 0, 0, 0, 1, 1} + }, + { + {0, 0, 0, 1, 0, 1}, + {1, 0, 0, 1, 1, 1} + } + }; + + for(unsigned int i = 0; i < 4; ++i) { + std::vector< std::pair< int, int > > extrudeEntities; + // Down + if(pmlSizeD != 0.) { + gmsh::model::geo::extrude({std::make_pair(2, pmlEdgeBnd[i+4].first)}, 0., 0., -pmlSizeD, extrudeEntities, {static_cast< int >(pmlSizeD / lc)}, std::vector< double >(), true); + pmlCornerInf[i].push_back(extrudeEntities[0].second); + pmlCorner[i] = extrudeEntities[1].second; + gmsh::model::geo::synchronize(); + + double bbx[2], bby[2], bbz[2]; + gmsh::model::getBoundingBox(extrudeEntities[1].first, extrudeEntities[1].second, bbx[0], bby[0], bbz[0], bbx[1], bby[1], bbz[1]); + + for(unsigned int j = 0; j < 2; ++j) { + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(bbx[extrudePmlCorner[i][j][0]], bby[extrudePmlCorner[i][j][1]], bbz[extrudePmlCorner[i][j][2]], bbx[extrudePmlCorner[i][j][3]], bby[extrudePmlCorner[i][j][4]], bbz[extrudePmlCorner[i][j][5]], tags, 2); + if(tags.size() == 0) { + gmshfem::msg::error << "Unable to find a corner-PML boundary" << gmshfem::msg::endl; + return; + } + else if(tags.size() > 1) { + for(unsigned int k = 0; k < tags.size(); ++k) { + double tmpbbx[2], tmpbby[2], tmpbbz[2]; + gmsh::model::getBoundingBox(tags[k].first, tags[k].second, tmpbbx[0], tmpbby[0], tmpbbz[0], tmpbbx[1], tmpbby[1], tmpbbz[1]); + if(tmpbbx[0] == bbx[extrudePmlCorner[i][j][0]] && tmpbbx[1] == bbx[extrudePmlCorner[i][j][3]] && tmpbby[0] == bby[extrudePmlCorner[i][j][1]] && tmpbby[1] == bby[extrudePmlCorner[i][j][4]] && tmpbbz[0] == bbz[extrudePmlCorner[i][j][2]] && tmpbbz[1] == bbz[extrudePmlCorner[i][j][5]]) { + tags[0].first = tags[k].first; + tags[0].second = tags[k].second; + break; + } + } + } + + pmlCornerInf[i].push_back(tags[0].second); + } + extrudeEntities.clear(); + } + corner[i] = cubePoints[(i+1)%4]; + + // Up + if(pmlSizeU != 0.) { + gmsh::model::geo::extrude({std::make_pair(2, pmlEdgeBnd[i+4].second)}, 0., 0., pmlSizeU, extrudeEntities, {static_cast< int >(pmlSizeU / lc)}, std::vector< double >(), true); + pmlCornerInf[i+4].push_back(extrudeEntities[0].second); + pmlCorner[i+4] = extrudeEntities[1].second; + gmsh::model::geo::synchronize(); + + double bbx[2], bby[2], bbz[2]; + gmsh::model::getBoundingBox(extrudeEntities[1].first, extrudeEntities[1].second, bbx[0], bby[0], bbz[0], bbx[1], bby[1], bbz[1]); + + for(unsigned int j = 0; j < 2; ++j) { + std::vector< std::pair< int, int > > tags; + gmsh::model::getEntitiesInBoundingBox(bbx[extrudePmlCorner[i+4][j][0]], bby[extrudePmlCorner[i+4][j][1]], bbz[extrudePmlCorner[i+4][j][2]], bbx[extrudePmlCorner[i+4][j][3]], bby[extrudePmlCorner[i+4][j][4]], bbz[extrudePmlCorner[i+4][j][5]], tags, 2); + if(tags.size() == 0) { + gmshfem::msg::error << "Unable to find a corner-PML boundary" << gmshfem::msg::endl; + return; + } + else if(tags.size() > 1) { + for(unsigned int k = 0; k < tags.size(); ++k) { + double tmpbbx[2], tmpbby[2], tmpbbz[2]; + gmsh::model::getBoundingBox(tags[k].first, tags[k].second, tmpbbx[0], tmpbby[0], tmpbbz[0], tmpbbx[1], tmpbby[1], tmpbbz[1]); + if(tmpbbx[0] == bbx[extrudePmlCorner[i][j][0]] && tmpbbx[1] == bbx[extrudePmlCorner[i][j][3]] && tmpbby[0] == bby[extrudePmlCorner[i][j][1]] && tmpbby[1] == bby[extrudePmlCorner[i][j][4]] && tmpbbz[0] == bbz[extrudePmlCorner[i][j][2]] && tmpbbz[1] == bbz[extrudePmlCorner[i][j][5]]) { + tags[0].first = tags[k].first; + tags[0].second = tags[k].second; + break; + } + } + } + + pmlCornerInf[i+4].push_back(tags[0].second); + } + extrudeEntities.clear(); + } + corner[i+4] = cubePoints[(i+1)%4+4]; + } + + gmsh::model::geo::removeAllDuplicates(); + gmsh::model::geo::synchronize(); + + std::vector< std::pair< int, int > > entites; + std::vector< std::pair< int, int > > boundary; + gmsh::model::getEntities(entites, 1); + for(unsigned int i = 0; i < entites.size(); ++i) { + double xmin = 0., ymin = 0., zmin = 0.; + double xmax = 0., ymax = 0., zmax = 0.; + gmsh::model::getBoundingBox(entites[i].first, entites[i].second, xmin, ymin, zmin, xmax, ymax, zmax); + gmsh::model::getBoundary({ entites[i] }, boundary, true, false, false); + + // down + if(boundary[0].second == cubePoints[1] || boundary[1].second == cubePoints[1]) { + if(xmin == posX[1] && xmax == posX[1] + pmlSizeE && ymin == posY[1] && ymax == posY[1] && zmin == posZ[1] && zmax == posZ[1]) { + std::get< 0 >(pmlCornerEdge[0]) = entites[i].second; + } + else if(xmin == posX[1] && xmax == posX[1] && ymin == posY[1] && ymax == posY[1] + pmlSizeN && zmin == posZ[1] && zmax == posZ[1]) { + std::get< 1 >(pmlCornerEdge[0]) = entites[i].second; + } + else if(xmin == posX[1] && xmax == posX[1] && ymin == posY[1] && ymax == posY[1] && zmin == posZ[1] - pmlSizeD && zmax == posZ[1]) { + std::get< 2 >(pmlCornerEdge[0]) = entites[i].second; + } + } + else if(boundary[0].second == cubePoints[2] || boundary[1].second == cubePoints[2]) { + if(xmin == posX[2] - pmlSizeW && xmax == posX[2] && ymin == posY[2] && ymax == posY[2] && zmin == posZ[2] && zmax == posZ[2]) { + std::get< 1 >(pmlCornerEdge[1]) = entites[i].second; + } + else if(xmin == posX[2] && xmax == posX[2] && ymin == posY[2] && ymax == posY[2] + pmlSizeN && zmin == posZ[2] && zmax == posZ[2]) { + std::get< 0 >(pmlCornerEdge[1]) = entites[i].second; + } + else if(xmin == posX[2] && xmax == posX[2] && ymin == posY[2] && ymax == posY[2] && zmin == posZ[2] - pmlSizeD && zmax == posZ[2]) { + std::get< 2 >(pmlCornerEdge[1]) = entites[i].second; + } + } + else if(boundary[0].second == cubePoints[3] || boundary[1].second == cubePoints[3]) { + if(xmin == posX[3] - pmlSizeW && xmax == posX[3] && ymin == posY[3] && ymax == posY[3] && zmin == posZ[3] && zmax == posZ[3]) { + std::get< 0 >(pmlCornerEdge[2]) = entites[i].second; + } + else if(xmin == posX[3] && xmax == posX[3] && ymin == posY[3] - pmlSizeS && ymax == posY[3] && zmin == posZ[3] && zmax == posZ[3]) { + std::get< 1 >(pmlCornerEdge[2]) = entites[i].second; + } + else if(xmin == posX[3] && xmax == posX[3] && ymin == posY[3] && ymax == posY[3] && zmin == posZ[3] - pmlSizeD && zmax == posZ[3]) { + std::get< 2 >(pmlCornerEdge[2]) = entites[i].second; + } + } + else if(boundary[0].second == cubePoints[0] || boundary[1].second == cubePoints[0]) { + if(xmin == posX[0] && xmax == posX[0] + pmlSizeE && ymin == posY[0] && ymax == posY[0] && zmin == posZ[0] && zmax == posZ[0]) { + std::get< 1 >(pmlCornerEdge[3]) = entites[i].second; + } + else if(xmin == posX[0] && xmax == posX[0] && ymin == posY[0] - pmlSizeS && ymax == posY[0] && zmin == posZ[0] && zmax == posZ[0]) { + std::get< 0 >(pmlCornerEdge[3]) = entites[i].second; + } + else if(xmin == posX[0] && xmax == posX[0] && ymin == posY[0] && ymax == posY[0] && zmin == posZ[0] - pmlSizeD && zmax == posZ[0]) { + std::get< 2 >(pmlCornerEdge[3]) = entites[i].second; + } + } + + // up + if(boundary[0].second == cubePoints[5] || boundary[1].second == cubePoints[5]) { + if(xmin == posX[5] && xmax == posX[5] + pmlSizeE && ymin == posY[5] && ymax == posY[5] && zmin == posZ[5] && zmax == posZ[5]) { + std::get< 0 >(pmlCornerEdge[4]) = entites[i].second; + } + else if(xmin == posX[5] && xmax == posX[5] && ymin == posY[5] && ymax == posY[5] + pmlSizeN && zmin == posZ[5] && zmax == posZ[5]) { + std::get< 1 >(pmlCornerEdge[4]) = entites[i].second; + } + else if(xmin == posX[5] && xmax == posX[5] && ymin == posY[5] && ymax == posY[5] && zmin == posZ[5] && zmax == posZ[5] + pmlSizeU) { + std::get< 2 >(pmlCornerEdge[4]) = entites[i].second; + } + } + else if(boundary[0].second == cubePoints[6] || boundary[1].second == cubePoints[6]) { + if(xmin == posX[6] - pmlSizeW && xmax == posX[6] && ymin == posY[6] && ymax == posY[6] && zmin == posZ[6] && zmax == posZ[6]) { + std::get< 1 >(pmlCornerEdge[5]) = entites[i].second; + } + else if(xmin == posX[6] && xmax == posX[6] && ymin == posY[6] && ymax == posY[6] + pmlSizeN && zmin == posZ[6] && zmax == posZ[6]) { + std::get< 0 >(pmlCornerEdge[5]) = entites[i].second; + } + else if(xmin == posX[6] && xmax == posX[6] && ymin == posY[6] && ymax == posY[6] && zmin == posZ[6] && zmax == posZ[6] + pmlSizeU) { + std::get< 2 >(pmlCornerEdge[5]) = entites[i].second; + } + } + else if(boundary[0].second == cubePoints[7] || boundary[1].second == cubePoints[7]) { + if(xmin == posX[7] - pmlSizeW && xmax == posX[7] && ymin == posY[7] && ymax == posY[7] && zmin == posZ[7] && zmax == posZ[7]) { + std::get< 0 >(pmlCornerEdge[6]) = entites[i].second; + } + else if(xmin == posX[7] && xmax == posX[7] && ymin == posY[7] - pmlSizeS && ymax == posY[7] && zmin == posZ[7] && zmax == posZ[7]) { + std::get< 1 >(pmlCornerEdge[6]) = entites[i].second; + } + else if(xmin == posX[7] && xmax == posX[7] && ymin == posY[7] && ymax == posY[7] && zmin == posZ[7] && zmax == posZ[7] + pmlSizeU) { + std::get< 2 >(pmlCornerEdge[6]) = entites[i].second; + } + } + else if(boundary[0].second == cubePoints[4] || boundary[1].second == cubePoints[4]) { + if(xmin == posX[4] && xmax == posX[4] + pmlSizeE && ymin == posY[4] && ymax == posY[4] && zmin == posZ[4] && zmax == posZ[4]) { + std::get< 1 >(pmlCornerEdge[7]) = entites[i].second; + } + else if(xmin == posX[4] && xmax == posX[4] && ymin == posY[4] - pmlSizeS && ymax == posY[4] && zmin == posZ[4] && zmax == posZ[4]) { + std::get< 0 >(pmlCornerEdge[7]) = entites[i].second; + } + else if(xmin == posX[4] && xmax == posX[4] && ymin == posY[4] && ymax == posY[4] && zmin == posZ[4] && zmax == posZ[4] + pmlSizeU) { + std::get< 2 >(pmlCornerEdge[7]) = entites[i].second; + } + } + + // up + } + + gmsh::model::geo::synchronize(); + + // physicals + const unsigned int tag = (index != -1 && jndex != -1 && kndex != -1 ? index * 10000000 + jndex * 100000 + kndex * 1000 : 0); + std::string subdomainTag; + if(index != -1 && jndex != -1) { + subdomainTag = "_" + std::to_string(index) + "_" + std::to_string(jndex) + "_" + std::to_string(kndex); + } + + gmsh::model::addPhysicalGroup(3, {omega}, 1 + tag); + gmsh::model::setPhysicalName(3, 1 + tag, "omega" + subdomainTag); + if(sphereSurface.size() != 0) { + gmsh::model::addPhysicalGroup(2, sphereSurface, 1); + gmsh::model::setPhysicalName(2, 1, "gamma"); + } + + std::vector< std::string > dir {"E", "N", "W", "S", "D", "U"}; + for(unsigned int i = 0; i < 6; ++i) { + gmsh::model::addPhysicalGroup(2, {cubeSurface[i]}, i+10 + tag); + gmsh::model::setPhysicalName(2, i+10 + tag, "sigma" + dir[i] + subdomainTag); + + if(pml[i] != 0) { + gmsh::model::addPhysicalGroup(3, {pml[i]}, i+10 + tag); + gmsh::model::setPhysicalName(3, i+10 + tag, "pml" + dir[i] + subdomainTag); + } + + if(pmlInf[i] != 0) { + gmsh::model::addPhysicalGroup(2, {pmlInf[i]}, i+20 + tag); + gmsh::model::setPhysicalName(2, i+20 + tag, "pmlInf" + dir[i] + subdomainTag); + } + + if(i == 4) { // Down + if(std::get<0>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<0>(pmlBnd[i])}, i+30 + tag); + gmsh::model::setPhysicalName(2, i+30 + tag, "pmlBnd" + dir[i] + "_first" + subdomainTag); + } + + if(std::get<1>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<1>(pmlBnd[i])}, i+40 + tag); + gmsh::model::setPhysicalName(2, i+40 + tag, "pmlBnd" + dir[i] + "_fourth" + subdomainTag); + } + + if(std::get<2>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<2>(pmlBnd[i])}, i+50 + tag); + gmsh::model::setPhysicalName(2, i+50 + tag, "pmlBnd" + dir[i] + "_third" + subdomainTag); + } + + if(std::get<3>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<3>(pmlBnd[i])}, i+60 + tag); + gmsh::model::setPhysicalName(2, i+60 + tag, "pmlBnd" + dir[i] + "_second" + subdomainTag); + } + } + else { + if(std::get<0>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<0>(pmlBnd[i])}, i+30 + tag); + gmsh::model::setPhysicalName(2, i+30 + tag, "pmlBnd" + dir[i] + "_first" + subdomainTag); + } + + if(std::get<1>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<1>(pmlBnd[i])}, i+40 + tag); + gmsh::model::setPhysicalName(2, i+40 + tag, "pmlBnd" + dir[i] + "_second" + subdomainTag); + } + + if(std::get<2>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<2>(pmlBnd[i])}, i+50 + tag); + gmsh::model::setPhysicalName(2, i+50 + tag, "pmlBnd" + dir[i] + "_third" + subdomainTag); + } + + if(std::get<3>(pmlBnd[i]) != 0) { + gmsh::model::addPhysicalGroup(2, {std::get<3>(pmlBnd[i])}, i+60 + tag); + gmsh::model::setPhysicalName(2, i+60 + tag, "pmlBnd" + dir[i] + "_fourth" + subdomainTag); + } + } + } + + for(unsigned int i = 0; i < 4; ++i) { + if(pmlEdge[i] != 0) { + gmsh::model::addPhysicalGroup(3, {pmlEdge[i]}, i+20 + tag); + gmsh::model::setPhysicalName(3, i+20 + tag, "pml" + dir[i] + "D" + subdomainTag); + } + + if(pmlEdgeInf[i].size() != 0) { + gmsh::model::addPhysicalGroup(2, pmlEdgeInf[i], i+100 + tag); + gmsh::model::setPhysicalName(2, i+100 + tag, "pmlInf" + dir[i] + "D" + subdomainTag); + } + + if(pmlEdgeBnd[i].first != 0) { + gmsh::model::addPhysicalGroup(2, {pmlEdgeBnd[i].first}, i+200 + tag); + gmsh::model::setPhysicalName(2, i+200 + tag, "pmlBnd" + dir[i] + "D_first" + subdomainTag); + } + + if(pmlEdgeBnd[i].second != 0) { + gmsh::model::addPhysicalGroup(2, {pmlEdgeBnd[i].second}, i+210 + tag); + gmsh::model::setPhysicalName(2, i+210 + tag, "pmlBnd" + dir[i] + "D_second" + subdomainTag); + } + + if(edge[i] != 0) { + gmsh::model::addPhysicalGroup(1, {edge[i]}, i+20 + tag); + gmsh::model::setPhysicalName(1, i+20 + tag, "edge" + dir[i] + "D" + subdomainTag); + } + + + if(pmlEdge[i+4] != 0) { + gmsh::model::addPhysicalGroup(3, {pmlEdge[i+4]}, i+30 + tag); + gmsh::model::setPhysicalName(3, i+30 + tag, "pml" + dir[i] + dir[(i+1)%4] + subdomainTag); + } + + if(pmlEdgeInf[i+4].size() != 0) { + gmsh::model::addPhysicalGroup(2, pmlEdgeInf[i+4], i+110 + tag); + gmsh::model::setPhysicalName(2, i+110 + tag, "pmlInf" + dir[i] + dir[(i+1)%4] + subdomainTag); + } + + if(pmlEdgeBnd[i+4].first != 0) { + gmsh::model::addPhysicalGroup(2, {pmlEdgeBnd[i+4].first}, i+220 + tag); + gmsh::model::setPhysicalName(2, i+220 + tag, "pmlBnd" + dir[i] + dir[(i+1)%4] + "_first" + subdomainTag); + } + + if(pmlEdgeBnd[i+4].second != 0) { + gmsh::model::addPhysicalGroup(2, {pmlEdgeBnd[i+4].second}, i+230 + tag); + gmsh::model::setPhysicalName(2, i+230 + tag, "pmlBnd" + dir[i] + dir[(i+1)%4] + "_second" + subdomainTag); + } + + if(edge[i+4] != 0) { + gmsh::model::addPhysicalGroup(1, {edge[i+4]}, i+30 + tag); + gmsh::model::setPhysicalName(1, i+30 + tag, "edge" + dir[i] + dir[(i+1)%4] + subdomainTag); + } + + + if(pmlEdge[i+8] != 0) { + gmsh::model::addPhysicalGroup(3, {pmlEdge[i+8]}, i+40 + tag); + gmsh::model::setPhysicalName(3, i+40 + tag, "pml" + dir[i] + "U" + subdomainTag); + } + + if(pmlEdgeInf[i+8].size() != 0) { + gmsh::model::addPhysicalGroup(2, pmlEdgeInf[i+8], i+120 + tag); + gmsh::model::setPhysicalName(2, i+120 + tag, "pmlInf" + dir[i] + "U" + subdomainTag); + } + + if(pmlEdgeBnd[i+8].first != 0) { + gmsh::model::addPhysicalGroup(2, {pmlEdgeBnd[i+8].first}, i+240 + tag); + gmsh::model::setPhysicalName(2, i+240 + tag, "pmlBnd" + dir[i] + "U_first" + subdomainTag); + } + + if(pmlEdgeBnd[i+8].second != 0) { + gmsh::model::addPhysicalGroup(2, {pmlEdgeBnd[i+8].second}, i+250 + tag); + gmsh::model::setPhysicalName(2, i+250 + tag, "pmlBnd" + dir[i] + "U_second" + subdomainTag); + } + + if(edge[i+8] != 0) { + gmsh::model::addPhysicalGroup(1, {edge[i+8]}, i+40 + tag); + gmsh::model::setPhysicalName(1, i+40 + tag, "edge" + dir[i] + "U" + subdomainTag); + } + + + + if(pmlCorner[i] != 0) { + gmsh::model::addPhysicalGroup(3, {pmlCorner[i]}, i+50 + tag); + gmsh::model::setPhysicalName(3, i+50 + tag, "pml" + dir[i] + dir[(i+1)%4] + "D" + subdomainTag); + } + + if(pmlCornerInf[i].size() != 0) { + gmsh::model::addPhysicalGroup(2, pmlCornerInf[i], i+130 + tag); + gmsh::model::setPhysicalName(2, i+130 + tag, "pmlInf" + dir[i] + dir[(i+1)%4] + "D" + subdomainTag); + } + + if(corner[i] != 0) { + gmsh::model::addPhysicalGroup(0, {corner[i]}, i+10 + tag); + gmsh::model::setPhysicalName(0, i+10 + tag, "corner" + dir[i] + dir[(i+1)%4] + "D" + subdomainTag); + } + + if(std::get< 0 >(pmlCornerEdge[i]) != 0) { + gmsh::model::addPhysicalGroup(1, {std::get< 0 >(pmlCornerEdge[i])}, i+100 + tag); + gmsh::model::setPhysicalName(1, i+100 + tag, "cornerEdge" + dir[i] + dir[(i+1)%4] + "D_first" + subdomainTag); + } + + if(std::get< 1 >(pmlCornerEdge[i]) != 0) { + gmsh::model::addPhysicalGroup(1, {std::get< 1 >(pmlCornerEdge[i])}, i+110 + tag); + gmsh::model::setPhysicalName(1, i+110 + tag, "cornerEdge" + dir[i] + dir[(i+1)%4] + "D_second" + subdomainTag); + } + + if(std::get< 2 >(pmlCornerEdge[i]) != 0) { + gmsh::model::addPhysicalGroup(1, {std::get< 2 >(pmlCornerEdge[i])}, i+120 + tag); + gmsh::model::setPhysicalName(1, i+120 + tag, "cornerEdge" + dir[i] + dir[(i+1)%4] + "D_third" + subdomainTag); + } + + if(pmlCorner[i+4] != 0) { + gmsh::model::addPhysicalGroup(3, {pmlCorner[i+4]}, i+60 + tag); + gmsh::model::setPhysicalName(3, i+60 + tag, "pml" + dir[i] + dir[(i+1)%4] + "U" + subdomainTag); + } + + if(pmlCornerInf[i+4].size() != 0) { + gmsh::model::addPhysicalGroup(2, pmlCornerInf[i+4], i+140 + tag); + gmsh::model::setPhysicalName(2, i+140 + tag, "pmlInf" + dir[i] + dir[(i+1)%4] + "U" + subdomainTag); + } + + if(corner[i+4] != 0) { + gmsh::model::addPhysicalGroup(0, {corner[i+4]}, i+20 + tag); + gmsh::model::setPhysicalName(0, i+20 + tag, "corner" + dir[i] + dir[(i+1)%4] + "U" + subdomainTag); + } + + if(std::get< 0 >(pmlCornerEdge[i+4]) != 0) { + gmsh::model::addPhysicalGroup(1, {std::get< 0 >(pmlCornerEdge[i+4])}, i+130 + tag); + gmsh::model::setPhysicalName(1, i+130 + tag, "cornerEdge" + dir[i] + dir[(i+1)%4] + "U_first" + subdomainTag); + } + + if(std::get< 1 >(pmlCornerEdge[i+4]) != 0) { + gmsh::model::addPhysicalGroup(1, {std::get< 1 >(pmlCornerEdge[i+4])}, i+140 + tag); + gmsh::model::setPhysicalName(1, i+140 + tag, "cornerEdge" + dir[i] + dir[(i+1)%4] + "U_second" + subdomainTag); + } + + if(std::get< 2 >(pmlCornerEdge[i+4]) != 0) { + gmsh::model::addPhysicalGroup(1, {std::get< 2 >(pmlCornerEdge[i+4])}, i+150 + tag); + gmsh::model::setPhysicalName(1, i+150 + tag, "cornerEdge" + dir[i] + dir[(i+1)%4] + "U_third" + subdomainTag); + } + } + + if(transfinite) { + gmsh::model::mesh::setTransfiniteSurface(cubeSurface[0]); + gmsh::model::mesh::setTransfiniteSurface(cubeSurface[1]); + gmsh::model::mesh::setTransfiniteSurface(cubeSurface[2]); + gmsh::model::mesh::setTransfiniteSurface(cubeSurface[3]); + gmsh::model::mesh::setTransfiniteSurface(cubeSurface[4]); + gmsh::model::mesh::setTransfiniteSurface(cubeSurface[5]); + + gmsh::model::mesh::setTransfiniteVolume(omega, cubePoints); + } + } + + void monoDomain(const double lc, const double pmlSize, const double R, const int order) + { + gmsh::model::add("mesh"); + + subdomain(-1, -1, -1, 2., 2., 2., R, lc, pmlSize, pmlSize, pmlSize, pmlSize, pmlSize, pmlSize, false); + + gmsh::model::mesh::generate(); + gmsh::model::mesh::setOrder(order); + } + + void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const unsigned int nDomZ, const double xSize, const double ySize, const double zSize, const double sphereSize, const double lc, const bool pml, const double pmlSize, const bool pmlExt, const double pmlSizeExt, const int order, const unsigned int spherePosX, const unsigned int spherePosY, const unsigned int spherePosZ, bool transfinite) + { + for(int i = 0; i < nDomX; ++i) { + for(int j = 0; j < nDomY; ++j) { + for(int k = 0; k < nDomZ; ++k) { + double pmlSizeE = 0.; + if(i == nDomX - 1) { + if(pmlExt) { + pmlSizeE = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeE = pmlSize; + } + } + + double pmlSizeN = 0.; + if(j == nDomY - 1) { + if(pmlExt) { + pmlSizeN = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeN = pmlSize; + } + } + + double pmlSizeW = 0.; + if(i == 0) { + if(pmlExt) { + pmlSizeW = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeW = pmlSize; + } + } + + double pmlSizeS = 0.; + if(j == 0) { + if(pmlExt) { + pmlSizeS = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeS = pmlSize; + } + } + + double pmlSizeD = 0.; + if(k == 0) { + if(pmlExt) { + pmlSizeD = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeD = pmlSize; + } + } + + double pmlSizeU = 0.; + if(k == nDomZ - 1) { + if(pmlExt) { + pmlSizeU = pmlSizeExt; + } + } + else { + if(pml) { + pmlSizeU = pmlSize; + } + } + + subdomain(i, j, k, xSize, ySize, zSize, (spherePosX == i && spherePosY == j && spherePosZ == k ? sphereSize : 0.), lc, pmlSizeE, pmlSizeN, pmlSizeW, pmlSizeS, pmlSizeD, pmlSizeU, transfinite); + } + } + } + + gmsh::model::mesh::generate(); + gmsh::model::mesh::setOrder(order); + } + + +} diff --git a/examples/helmholtz/crossPoints/mesh.h b/examples/helmholtz/crossPoints/mesh.h new file mode 100755 index 0000000000000000000000000000000000000000..604f9b133051c775e20fa3e42266f37d39f62242 --- /dev/null +++ b/examples/helmholtz/crossPoints/mesh.h @@ -0,0 +1,22 @@ +#ifndef H_MESH +#define H_MESH + +#include <gmshfem/Function.h> + +namespace D2 { + + void subdomain(const int index, const int jndex, const double xSize, const double ySize, const double circleSize, const double lc, const double pmlSizeE, const double pmlSizeN, const double pmlSizeW, const double pmlSizeS, bool transfinite); + void monoDomain(const double lc, const double pmlSize, const double R, const int order); + void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const double xSize, const double ySize, const double circleSize, const double lc, const bool pml, const double pmlSize, const bool pmlExt, const double pmlSizeExt, const int order, const unsigned int circlePosX = 0, const unsigned int circlePosY = 0, bool transfinite = false); + +} + +namespace D3 { + + void subdomain(const int index, const int jndex, const int kndex, const double xSize, const double ySize, const double zSize, const double sphereSize, const double lc, const double pmlSizeE, const double pmlSizeN, const double pmlSizeW, const double pmlSizeS, const double pmlSizeD, const double pmlSizeU, bool transfinite); + void monoDomain(const double lc, const double pmlSize, const double R, const int order); + void checkerboard(const unsigned int nDomX, const unsigned int nDomY, const unsigned int nDomZ, const double xSize, const double ySize, const double zSize, const double sphereSize, const double lc, const bool pml, const double pmlSize, const bool pmlExt, const double pmlSizeExt, const int order, const unsigned int spherePosX = 0, const unsigned int spherePosY = 0, const unsigned int spherePosZ = 0, bool transfinite = false); + +} + +#endif // H_MESH diff --git a/examples/helmholtz/crossPoints/monoDomain.cpp b/examples/helmholtz/crossPoints/monoDomain.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d5f15947872c37562e6a01358bd60edb23823662 --- /dev/null +++ b/examples/helmholtz/crossPoints/monoDomain.cpp @@ -0,0 +1,694 @@ +#include "mesh.h" +#include "SubproblemDomains.h" +#include "Subproblem2D.h" +#include "Subproblem3D.h" + +#include <gmshfem/GmshFem.h> +#include <gmshfem/FieldInterface.h> +#include <gmshfem/Formulation.h> +#include <gmshfem/AnalyticalFunction.h> +#include <gmshfem/Post.h> +#include <gmshfem/Function.h> +#include <gmshfem/io.h> + +#include <gmshddm/GmshDdm.h> +#include <gmshddm/Subdomain.h> +#include <gmshddm/Interface.h> +#include <gmshddm/SubdomainField.h> +#include <gmshddm/InterfaceField.h> +#include <gmshddm/Formulation.h> +#include <gmshddm/MPIInterface.h> + +#include <algorithm> +#include <fstream> + +using gmshfem::equation::dof; +using gmshfem::equation::tf; +using gmshfem::function::operator-; +using gmshfem::function::operator*; +using gmshfem::function::abs; + +namespace D2 { + + + void monoDomain() + { + gmshddm::common::GmshDdm *gmshDdm = gmshddm::common::GmshDdm::currentInstance(); + + // ************************ + // P H Y S I C S + // ************************ + double pi = 3.141592653589793238462643383279; + double k = 4. * pi; + gmshDdm->userDefinedParameter(k, "k"); + double R = 0.5; + gmshDdm->userDefinedParameter(R, "R"); + + // ************************ + // M E S H + // ************************ + double lc = 0.03333333333333; // Marmousi = 20; other = 0.03333333333333 + gmshDdm->userDefinedParameter(lc, "lc"); + int meshOrder = 1; + gmshDdm->userDefinedParameter(meshOrder, "meshOrder"); + + // ************************ + // M O D E L I N G + // ************************ + std::string boundary = "sommerfeld"; // sommerfeld, pml, habc + gmshDdm->userDefinedParameter(boundary, "boundary"); + std::string pmlMethod = "continuous"; // continuous, discontinuous, withoutMultiplier + gmshDdm->userDefinedParameter(pmlMethod, "pmlMethod"); + std::string pmlType = "hs"; // hs, h, q + gmshDdm->userDefinedParameter(pmlType, "pmlType"); + + double N = 6; + gmshDdm->userDefinedParameter(N, "N"); + double pmlSize = N * lc; + if(pmlSize == 0.) { + pmlSize = 0.3; + } + + std::string gauss = "Gauss10"; + gmshDdm->userDefinedParameter(gauss, "gauss"); + int fieldOrder = 1; + gmshDdm->userDefinedParameter(fieldOrder, "fieldOrder"); + int neumannOrder = 1; + gmshDdm->userDefinedParameter(neumannOrder, "neumannOrder"); + double stab = 0.11; + gmshDdm->userDefinedParameter(stab, "stab"); + double thetaPade = 0.; + gmshDdm->userDefinedParameter(thetaPade, "thetaPade"); + thetaPade *= pi; + + // ************************ + // P O S T + // ************************ + bool computeError = false; + gmshDdm->userDefinedParameter(computeError, "error"); + bool computeInterfaceError = false; + gmshDdm->userDefinedParameter(computeInterfaceError, "interfaceError"); + bool getMatrices = false; + gmshDdm->userDefinedParameter(getMatrices, "getMatrices"); + bool convergence = false; + gmshDdm->userDefinedParameter(convergence, "convergence"); + std::string fileName = "none"; + gmshDdm->userDefinedParameter(fileName, "file"); + bool saveNeumannTraces = false; + gmshDdm->userDefinedParameter(saveNeumannTraces, "saveNeumannTraces"); + bool spy = false; + gmshDdm->userDefinedParameter(spy, "spy"); + + // mesh + monoDomain(lc, pmlSize, R, meshOrder); + // source + gmshfem::analytics::AnalyticalFunction< gmshfem::analytics::helmholtz2D::ScatteringByASoftCylinder< std::complex< double > > > fAnalytic(k, R, 1., 1., 2 * k); + + gmshfem::msg::info << "Running 'monoDomain2D'" << gmshfem::msg::endl; + gmshfem::msg::info << "Parameters:" << gmshfem::msg::endl; + gmshfem::msg::info << " * physics:" << gmshfem::msg::endl; + gmshfem::msg::info << " - k: " << k << " (" << k/pi << "*pi" << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - R: " << R << gmshfem::msg::endl; + gmshfem::msg::info << " * mesh:" << gmshfem::msg::endl; + gmshfem::msg::info << " - lc: " << lc << " (eta_h = " << (2*pi/k)/lc << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - meshOrder: " << meshOrder << gmshfem::msg::endl; + gmshfem::msg::info << " * modeling:" << gmshfem::msg::endl; + gmshfem::msg::info << " - boundary: " << boundary << gmshfem::msg::endl; + gmshfem::msg::info << " - N: " << N << gmshfem::msg::endl; + if(boundary == "pml") { + gmshfem::msg::info << " - pmlSize: " << pmlSize << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlMethod: " << pmlMethod << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlType: " << pmlType << gmshfem::msg::endl; + } + else if(boundary == "habc") { + gmshfem::msg::info << " - thetaPade: " << thetaPade << " (" << thetaPade/pi << "*pi" << ")" << gmshfem::msg::endl; + } + gmshfem::msg::info << " - gauss: " << gauss << gmshfem::msg::endl; + gmshfem::msg::info << " - fieldOrder: " << fieldOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - neumannOrder: " << neumannOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - stab: " << stab << " * lc (= " << stab * lc << ")" << gmshfem::msg::endl; + + + gmshfem::domain::Domain omega("omega"); + gmshfem::domain::Domain gamma("gamma"); + gmshfem::domain::Domain sigmas; + std::vector< gmshfem::domain::Domain > pml(4); + std::vector< gmshfem::domain::Domain > pmlCorner(4); + std::vector< gmshfem::domain::Domain > sigma(4); + std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > pmlBnd(4); + std::vector< gmshfem::domain::Domain > corner(4); + std::vector< std::string > dir {"E", "N", "W", "S"}; + for(unsigned int i = 0; i < 4; ++i) { + pml[i] = gmshfem::domain::Domain("pml" + dir[i]); + pmlCorner[i] = gmshfem::domain::Domain("pmlCorner"+ dir[i] + dir[(i+1)%4]); + sigma[i] = gmshfem::domain::Domain("sigma" + dir[i]); + pmlBnd[i].first = gmshfem::domain::Domain("pmlBnd" + dir[i] + "_second"); + pmlBnd[i].second = gmshfem::domain::Domain("pmlBnd" + dir[(i+1)%4] + "_first"); + corner[i] = gmshfem::domain::Domain("corner" + dir[i] + dir[(i+1)%4]); + + sigmas |= sigma[i]; + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > u("u", omega | sigmas | gamma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + u.addConstraint(gamma, fAnalytic); + + gmshfem::problem::Formulation< std::complex< double > > formulation("HelmholtzMonoDomain"); + + formulation.integral(-grad(dof(u)), grad(tf(u)), omega, gauss); + formulation.integral(k * k * dof(u), tf(u), omega, gauss); + + SubproblemDomains domains; + domains.setOmega(omega); + domains.setSigma(sigma); + domains.setPml(pml); + domains.setPmlBnd(pmlBnd); + domains.setPmlCorner(pmlCorner); + domains.setCorner(corner); + + SubproblemParameters parameters; + parameters.setGauss(gauss); + parameters.setKappa(k); + parameters.setNeumannOrder(neumannOrder); + parameters.setFieldOrder(fieldOrder); + parameters.setStab(stab * lc); + + std::string bnd = boundary; + if(boundary == "habc") { + bnd += "_" + std::to_string(N) + "_" + std::to_string(thetaPade); + } + else if(boundary == "pml") { + if(pmlMethod == "continuous") { + bnd += "Continuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + else if(pmlMethod == "discontinuous") { + bnd += "Discontinuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + else if(pmlMethod == "withoutMultiplier") { + bnd += "WithoutMultiplier_" + std::to_string(pmlSize) + "_" + pmlType; + } + } + Subproblem subproblem(formulation, u.name(), domains, parameters, bnd, bnd, bnd, bnd); + subproblem.writeFormulation(); + + if(spy) { + gmshfem::common::Options::instance()->dofsSortAlgorithm = gmshfem::problem::DofsSort::Algorithm::None; + } + formulation.pre(); + gmshfem::common::Timer assembleTime = formulation.assemble(); + gmshfem::common::Timer solveTime = formulation.solve(); + + // POST + + double errorL2 = 0.; + if(computeError) { + const double num = std::real(gmshfem::post::integrate(pow(abs(u - fAnalytic), 2), omega, gauss)); + const double den = std::real(gmshfem::post::integrate(pow(abs(fAnalytic), 2), omega, gauss)); + errorL2 = std::sqrt(num/den); + + gmshfem::msg::info << "Error L2 = " << errorL2 << gmshfem::msg::endl; + + gmshfem::post::save(u - fAnalytic, omega, "e"); + } + + if(computeInterfaceError) { + if(boundary == "pml") { + double numInterface = 0.; + double denInterface = 0.; + + for(unsigned int b = 0; b < 4; ++b) { + const Boundary *boundary = subproblem.getBoundary(b); + if(auto *bnd = dynamic_cast< const PmlContinuous * >(boundary)) { + numInterface += std::real(gmshfem::post::integrate(pow(abs(u - *bnd->getUPml()), 2), sigma[b], gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(u), 2), sigma[b], gauss)); + } + else if(auto *bnd = dynamic_cast< const PmlDiscontinuous * >(boundary)) { + numInterface += std::real(gmshfem::post::integrate(pow(abs(u - *bnd->getUPml()), 2), sigma[b], gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(u), 2), sigma[b], gauss)); + } + else if(auto *bnd = dynamic_cast< const PmlWithoutMultiplier * >(boundary)) { + numInterface += std::real(gmshfem::post::integrate(pow(abs(u - *bnd->getUPml()), 2), sigma[b], gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(u), 2), sigma[b], gauss)); + } + } + + for(unsigned int c = 0; c < 4; ++c) { + const Corner *corner = subproblem.getCorner(c); + if(auto *cr = dynamic_cast< const PmlContinuous_PmlContinuous * >(corner)) { + numInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->firstBoundary()->getUPml() - *cr->getUPml()), 2), pmlBnd[c].first, gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->firstBoundary()->getUPml()), 2), pmlBnd[c].first, gauss)); + + numInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->secondBoundary()->getUPml() - *cr->getUPml()), 2), pmlBnd[c].second, gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->secondBoundary()->getUPml()), 2), pmlBnd[c].second, gauss)); + } + else if(auto *cr = dynamic_cast< const PmlDiscontinuous_PmlDiscontinuous * >(corner)) { + numInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->firstBoundary()->getUPml() - *cr->getUPml()), 2), pmlBnd[c].first, gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->firstBoundary()->getUPml()), 2), pmlBnd[c].first, gauss)); + + numInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->secondBoundary()->getUPml() - *cr->getUPml()), 2), pmlBnd[c].second, gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->secondBoundary()->getUPml()), 2), pmlBnd[c].second, gauss)); + } + else if(auto *cr = dynamic_cast< const PmlWithoutMultiplier_PmlWithoutMultiplier * >(corner)) { + numInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->firstBoundary()->getUPml() - *cr->getUPml()), 2), pmlBnd[c].first, gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->firstBoundary()->getUPml()), 2), pmlBnd[c].first, gauss)); + + numInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->secondBoundary()->getUPml() - *cr->getUPml()), 2), pmlBnd[c].second, gauss)); + denInterface += std::real(gmshfem::post::integrate(pow(abs(*cr->secondBoundary()->getUPml()), 2), pmlBnd[c].second, gauss)); + } + } + + gmshfem::msg::info << "Interface L2 error = " << std::sqrt(numInterface/denInterface) << gmshfem::msg::endl; + + if(fileName != "none") { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); + file << (2*pi/k)/lc << lc << 1./lc << std::sqrt(numInterface/denInterface) << gmshfem::csv::endl; + file.close(); + } + } + else { + gmshfem::msg::error << "Unable to define a boundary error with 'boundary = " << boundary << "'" << gmshfem::msg::endl; + } + } + + if(getMatrices) { +// gmshfem::algebra::MatrixCRS< std::complex< double > > U; +// gmshfem::algebra::MatrixCRS< std::complex< double > > L; +// gmshfem::algebra::MatrixCRS< std::complex< double > > M; +// gmshfem::algebra::MatrixCRS< std::complex< double > > C; + gmshfem::algebra::MatrixCRS< std::complex< double > > A; +// +// std::vector< const gmshfem::field::FieldInterface< std::complex< double > > * > fieldsU; +// fieldsU.push_back(&u); +// for(unsigned int i = 0; i < 4; ++i) { +// fieldsU.push_back(subproblem.getU(i)); +// } +// for(unsigned int i = 0; i < 4; ++i) { +// fieldsU.push_back(subproblem.getUC(i)); +// } +// +// std::vector< const gmshfem::field::FieldInterface< std::complex< double > > * > fieldsL; +// for(unsigned int i = 0; i < 4; ++i) { +// fieldsL.push_back(subproblem.getV(i)); +// } +// if(boundary == "pml") { +// for(unsigned int i = 0; i < 4; ++i) { +// fieldsL.push_back(subproblem.getVC(i, 0)); +// fieldsL.push_back(subproblem.getVC(i, 1)); +// } +// } + + // std::vector< const gmshfem::field::FieldInterface< std::complex< double > > * > fieldsC; + // if(boundary == "pml") { + // if(form == "form0") { + // for(unsigned int i = 0; i < 4; ++i) { + // fieldsC.push_back(static_cast< NeumannTrace< gmshfem::field::Form::Form0 > * >(neumannTrace)->get("vC_" + orientation[(i-1)%4] + "_" + orientation[i])); + // } + // } + // } + // else if (boundary == "habc") { + // for(unsigned int i = 0; i < 4; ++i) { + // for(unsigned int n = 0; n < N; ++n) { + // fieldsC.push_back(static_cast< NeumannTrace< gmshfem::field::Form::Form0 > * >(neumannTrace)->get("vC_" + orientation[i] + "_" + std::to_string(n) + "_first")); + // fieldsC.push_back(static_cast< NeumannTrace< gmshfem::field::Form::Form0 > * >(neumannTrace)->get("vC_" + orientation[(i-1)%4] + "_" + std::to_string(n) + "_second")); + // } + // } + // } + +// formulation.getLHSBlock(U, fieldsU, fieldsU); +// formulation.getLHSBlock(L, fieldsL, fieldsU); +// formulation.getLHSBlock(C, fieldsC, fieldsL); +// formulation.getLHSBlock(M, fieldsL, fieldsL); + formulation.getLHS(A); +// +// U.save("U"); +// L.save("L"); +// C.save("C"); +// M.save("M"); + A.save("A"); + } + + gmshfem::post::save(u, omega, "u"); + + if(convergence) { + gmshfem::common::CSVio file(fileName, ';', gmshfem::common::OpeningMode::Append); +// file << lc << (2*pi/k)/lc << errorL2 << assembleTime << solveTime << formulation.getTotalNumberOfDof() << gmshfem::csv::endl; + file << k << (2*pi/k)/lc << errorL2 << assembleTime << solveTime << gmshfem::csv::endl; + } + + if(saveNeumannTraces) { + for(unsigned int b = 0; b < 4; ++b) { + const Boundary *boundary = subproblem.getBoundary(b); + if(auto *bnd = dynamic_cast< const Sommerfeld * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const HABC * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const PmlContinuous * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const PmlDiscontinuous * >(boundary)) { + auto n = gmshfem::function::normal< std::complex< double > >(); + gmshfem::post::save(*(bnd->getV()) * n, bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const PmlWithoutMultiplier * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + } + + for(unsigned int c = 0; c < 4; ++c) { + const Corner *corner = subproblem.getCorner(c); + if(auto *cr = dynamic_cast< const PmlContinuous_PmlContinuous * >(corner)) { + gmshfem::post::save(*(cr->getV(0)), cr->getV(0)->domain(), cr->getV(0)->name()); + gmshfem::post::save(*(cr->getV(1)), cr->getV(1)->domain(), cr->getV(1)->name()); + } + else if(auto *cr = dynamic_cast< const PmlDiscontinuous_PmlDiscontinuous * >(corner)) { + auto n = gmshfem::function::normal< std::complex< double > >(); + gmshfem::post::save(*(cr->getV(0)) * n, cr->getV(0)->domain(), cr->getV(0)->name()); + gmshfem::post::save(*(cr->getV(1)) * n, cr->getV(1)->domain(), cr->getV(1)->name()); + } + else if(auto *cr = dynamic_cast< const PmlWithoutMultiplier_PmlWithoutMultiplier * >(corner)) { + gmshfem::post::save(*(cr->getV(0)), cr->getV(0)->domain(), cr->getV(0)->name()); + gmshfem::post::save(*(cr->getV(1)), cr->getV(1)->domain(), cr->getV(1)->name()); + } + } + } + + if(spy) { + gmshfem::algebra::MatrixCRSFast< std::complex< double > > A; + formulation.getLHS(A); + A.saveSpyPlot("spy", 8); + } + + } + + +} + + +namespace D3 { + + + void monoDomain() + { + gmshddm::common::GmshDdm *gmshDdm = gmshddm::common::GmshDdm::currentInstance(); + + // ************************ + // P H Y S I C S + // ************************ + double pi = 3.141592653589793238462643383279; + double k = 2. * pi; + gmshDdm->userDefinedParameter(k, "k"); + double R = 0.5; + gmshDdm->userDefinedParameter(R, "R"); + + // ************************ + // M E S H + // ************************ + double lc = 0.06666666666666; // Marmousi = 20; other = 0.06666666666666 + gmshDdm->userDefinedParameter(lc, "lc"); + int meshOrder = 1; + gmshDdm->userDefinedParameter(meshOrder, "meshOrder"); + + // ************************ + // M O D E L I N G + // ************************ + std::string boundary = "sommerfeld"; // sommerfeld, pml, habc + gmshDdm->userDefinedParameter(boundary, "boundary"); + std::string pmlMethod = "continuous"; // continuous, discontinuous + gmshDdm->userDefinedParameter(pmlMethod, "pmlMethod"); + std::string pmlType = "hs"; // hs, h, q + gmshDdm->userDefinedParameter(pmlType, "pmlType"); + + double N = 6; + gmshDdm->userDefinedParameter(N, "N"); + double pmlSize = N * lc; + if(pmlSize == 0.) { + pmlSize = 0.3; + } + + std::string gauss = "Gauss10"; + gmshDdm->userDefinedParameter(gauss, "gauss"); + int fieldOrder = 1; + gmshDdm->userDefinedParameter(fieldOrder, "fieldOrder"); + int neumannOrder = 1; + gmshDdm->userDefinedParameter(neumannOrder, "neumannOrder"); + double stab = 0.11; + gmshDdm->userDefinedParameter(stab, "stab"); + double thetaPade = 0.; + gmshDdm->userDefinedParameter(thetaPade, "thetaPade"); + thetaPade *= pi; + + // ************************ + // P O S T + // ************************ + bool onPlane = false; + gmshDdm->userDefinedParameter(onPlane, "onPlane"); + bool computeError = false; + gmshDdm->userDefinedParameter(computeError, "error"); + bool computeInterfaceError = false; + gmshDdm->userDefinedParameter(computeInterfaceError, "interfaceError"); + bool getMatrices = false; + gmshDdm->userDefinedParameter(getMatrices, "getMatrices"); + bool saveNeumannTraces = false; + gmshDdm->userDefinedParameter(saveNeumannTraces, "saveNeumannTraces"); + + // mesh + monoDomain(lc, pmlSize, R, meshOrder); + // source + gmshfem::analytics::AnalyticalFunction< gmshfem::analytics::helmholtz3D::ScatteringByASoftSphere< std::complex< double > > > fAnalytic(k, R, 1., 1., 1., 2 * k); + + gmshfem::msg::info << "Running 'monoDomain3D'" << gmshfem::msg::endl; + gmshfem::msg::info << "Parameters:" << gmshfem::msg::endl; + gmshfem::msg::info << " * physics:" << gmshfem::msg::endl; + gmshfem::msg::info << " - k: " << k << " (" << k/pi << "*pi" << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - R: " << R << gmshfem::msg::endl; + gmshfem::msg::info << " * mesh:" << gmshfem::msg::endl; + gmshfem::msg::info << " - lc: " << lc << " (eta_h = " << (2*pi/k)/lc << ")" << gmshfem::msg::endl; + gmshfem::msg::info << " - meshOrder: " << meshOrder << gmshfem::msg::endl; + gmshfem::msg::info << " * modeling:" << gmshfem::msg::endl; + gmshfem::msg::info << " - boundary: " << boundary << gmshfem::msg::endl; + gmshfem::msg::info << " - N: " << N << gmshfem::msg::endl; + if(boundary == "pml") { + gmshfem::msg::info << " - pmlSize: " << pmlSize << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlMethod: " << pmlMethod << gmshfem::msg::endl; + gmshfem::msg::info << " - pmlType: " << pmlType << gmshfem::msg::endl; + } + else if(boundary == "habc") { + gmshfem::msg::info << " - thetaPade: " << thetaPade << " (" << thetaPade/pi << "*pi" << ")" << gmshfem::msg::endl; + } + gmshfem::msg::info << " - gauss: " << gauss << gmshfem::msg::endl; + gmshfem::msg::info << " - fieldOrder: " << fieldOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - neumannOrder: " << neumannOrder << gmshfem::msg::endl; + gmshfem::msg::info << " - stab: " << stab << " * lc (= " << stab * lc << ")" << gmshfem::msg::endl; + + gmshfem::domain::Domain omega("omega"); + gmshfem::domain::Domain gamma("gamma"); + gmshfem::domain::Domain sigmas; + std::vector< gmshfem::domain::Domain > pml(6); + std::vector< gmshfem::domain::Domain > pmlEdge(12); + std::vector< gmshfem::domain::Domain > pmlCorner(8); + std::vector< gmshfem::domain::Domain > sigma(6); + std::vector< std::pair< gmshfem::domain::Domain, gmshfem::domain::Domain > > pmlBnd(12); + std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > pmlEdgeBnd(8); + std::vector< gmshfem::domain::Domain > edge(12); + std::vector< gmshfem::domain::Domain > corner(8); + std::vector< std::tuple< gmshfem::domain::Domain, gmshfem::domain::Domain, gmshfem::domain::Domain > > cornerEdge(8); + std::vector< std::string > dir {"E", "N", "W", "S", "D", "U"}; + // face + for(unsigned int i = 0; i < 6; ++i) { + pml[i] = gmshfem::domain::Domain("pml" + dir[i]); + sigma[i] = gmshfem::domain::Domain("sigma" + dir[i]); + sigmas |= sigma[i]; + } + // edge + for(unsigned int i = 0; i < 12; ++i) { + std::vector< std::string > count {"first", "second", "third", "fourth"}; + if(i < 4) { + pmlEdge[i] = gmshfem::domain::Domain("pml" + dir[i%4] + "D"); + pmlBnd[i].first = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + "_first"); + pmlBnd[i].second = gmshfem::domain::Domain("pmlBndD_" + count[i%4]); + edge[i] = gmshfem::domain::Domain("edge" + dir[i%4] + "D"); + } + else if(i >= 4 && i < 8) { + pmlEdge[i] = gmshfem::domain::Domain("pml" + dir[i%4] + dir[(i+1)%4]); + pmlBnd[i].first = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + "_second"); + pmlBnd[i].second = gmshfem::domain::Domain("pmlBnd" + dir[(i+1)%4] + "_fourth"); + edge[i] = gmshfem::domain::Domain("edge" + dir[i%4] + dir[(i+1)%4]); + } + else { + pmlEdge[i] = gmshfem::domain::Domain("pml" + dir[i%4] + "U"); + pmlBnd[i].first = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + "_third"); + pmlBnd[i].second = gmshfem::domain::Domain("pmlBndU_" + count[i%4]); + edge[i] = gmshfem::domain::Domain("edge" + dir[i%4] + "U"); + } + } + // corner + for(unsigned int i = 0; i < 8; ++i) { + if(i < 4) { + pmlCorner[i] = gmshfem::domain::Domain("pml" + dir[i%4] + dir[(i+1)%4] + "D"); + std::get<0>(pmlEdgeBnd[i]) = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + "D_second"); + std::get<1>(pmlEdgeBnd[i]) = gmshfem::domain::Domain("pmlBnd" + dir[(i+1)%4] + "D_first"); + std::get<2>(pmlEdgeBnd[i]) = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + dir[(i+1)%4] + "_first"); + corner[i] = gmshfem::domain::Domain("corner" + dir[i%4] + dir[(i+1)%4] + "D"); + std::get<0>(cornerEdge[i]) = gmshfem::domain::Domain("cornerEdge" + dir[i%4] + dir[(i+1)%4] + "D_first"); + std::get<1>(cornerEdge[i]) = gmshfem::domain::Domain("cornerEdge" + dir[i%4] + dir[(i+1)%4] + "D_second"); + std::get<2>(cornerEdge[i]) = gmshfem::domain::Domain("cornerEdge" + dir[i%4] + dir[(i+1)%4] + "D_third"); + } + else { + pmlCorner[i] = gmshfem::domain::Domain("pml" + dir[i%4] + dir[(i+1)%4] + "U"); + std::get<0>(pmlEdgeBnd[i]) = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + "U_second"); + std::get<1>(pmlEdgeBnd[i]) = gmshfem::domain::Domain("pmlBnd" + dir[(i+1)%4] + "U_first"); + std::get<2>(pmlEdgeBnd[i]) = gmshfem::domain::Domain("pmlBnd" + dir[i%4] + dir[(i+1)%4] + "_second"); + corner[i] = gmshfem::domain::Domain("corner" + dir[i%4] + dir[(i+1)%4] + "U"); + std::get<0>(cornerEdge[i]) = gmshfem::domain::Domain("cornerEdge" + dir[i%4] + dir[(i+1)%4] + "U_first"); + std::get<1>(cornerEdge[i]) = gmshfem::domain::Domain("cornerEdge" + dir[i%4] + dir[(i+1)%4] + "U_second"); + std::get<2>(cornerEdge[i]) = gmshfem::domain::Domain("cornerEdge" + dir[i%4] + dir[(i+1)%4] + "U_third"); + } + } + + gmshfem::field::Field< std::complex< double >, gmshfem::field::Form::Form0 > u("u", omega | sigmas | gamma, gmshfem::field::FunctionSpaceTypeForm0::HierarchicalH1, fieldOrder); + u.addConstraint(gamma, fAnalytic); + + gmshfem::problem::Formulation< std::complex< double > > formulation("HelmholtzMonoDomain"); + + formulation.integral(-grad(dof(u)), grad(tf(u)), omega, gauss); + formulation.integral(k * k * dof(u), tf(u), omega, gauss); + + SubproblemDomains domains; + domains.setOmega(omega); + domains.setSigma(sigma); + domains.setPml(pml); + domains.setPmlBnd(pmlBnd); + domains.setPmlEdge(pmlEdge); + domains.setEdge(edge); + domains.setPmlEdgeBnd(pmlEdgeBnd); + domains.setPmlCorner(pmlCorner); + domains.setCorner(corner); + domains.setCornerEdge(cornerEdge); + + SubproblemParameters parameters; + parameters.setGauss(gauss); + parameters.setKappa(k); + parameters.setNeumannOrder(neumannOrder); + parameters.setFieldOrder(fieldOrder); + parameters.setStab(stab * lc); + + std::string bnd = boundary; + if(boundary == "habc") { + bnd += "_" + std::to_string(N) + "_" + std::to_string(thetaPade); + } + else if(boundary == "pml") { + if(pmlMethod == "continuous") { + bnd += "Continuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + else if(pmlMethod == "discontinuous") { + bnd += "Discontinuous_" + std::to_string(pmlSize) + "_" + pmlType; + } + } + Subproblem subproblem(formulation, u.name(), domains, parameters, bnd, bnd, bnd, bnd, bnd, bnd); + subproblem.writeFormulation(); + + formulation.pre(); + formulation.assemble(); + formulation.solve(); + + // POST + const double eps = 0.01; + gmshfem::post::Plane planeXY("planeXY", -1.+eps, -1.+eps, 0., 2.-2.*eps, 0., 0., 0., 2.-2.*eps, 0., 100., 100.); + gmshfem::post::Plane planeYZ("planeYZ", -1.+eps, -1.+eps, -1.+eps, 2.-2.*eps, 2.-2.*eps, 0., 0., 0., 2.-2.*eps, 100., 100.); + gmshfem::post::Plane planeZX("planeZX", -1.+eps, 1.-eps, -1.+eps, 2.-2.*eps, -2.+2.*eps, 0., 0., 0., 2.-2.*eps, 100., 100.); + gmshfem::post::Sphere scatter("scatter", 0., 0., 0., R+eps, 100. * R); + + if(computeError) { + const double num = std::real(gmshfem::post::integrate(pow(abs(u - fAnalytic), 2), omega, gauss)); + const double den = std::real(gmshfem::post::integrate(pow(abs(fAnalytic), 2), omega, gauss)); + + gmshfem::msg::info << "Error L2 = " << std::sqrt(num/den) << gmshfem::msg::endl; + + if(onPlane) { + gmshfem::post::save(gmshfem::function::heaviside(gmshfem::function::r3d< std::complex< double > >() - R) * (u - fAnalytic), planeXY, "e_XY", "pos"); + gmshfem::post::save(gmshfem::function::heaviside(gmshfem::function::r3d< std::complex< double > >() - R) * (u - fAnalytic), planeYZ, "e_YZ", "pos"); + gmshfem::post::save(gmshfem::function::heaviside(gmshfem::function::r3d< std::complex< double > >() - R) * (u - fAnalytic), planeZX, "e_ZX", "pos"); + gmshfem::post::save(u - fAnalytic, scatter, "e_SCAT", "pos"); + } + else { + gmshfem::post::save(gmshfem::function::norm(u - fAnalytic), omega, "e"); + } + } + + if(onPlane) { + gmshfem::post::save(u, planeXY, "u_XY", "pos"); + gmshfem::post::save(u, planeYZ, "u_YZ", "pos"); + gmshfem::post::save(u, planeZX, "u_ZX", "pos"); + gmshfem::post::save(u, scatter, "u_SCAT", "pos"); + } + else { + gmshfem::post::save(u, omega, "u"); + } + + if(getMatrices) { + gmshfem::algebra::MatrixCRS< std::complex< double > > A; + formulation.getLHS(A); + A.save("A"); + } + + if(saveNeumannTraces) { + for(unsigned int b = 0; b < 6; ++b) { + const Boundary *boundary = subproblem.getBoundary(b); + if(auto *bnd = dynamic_cast< const Sommerfeld * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const HABC * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const PmlContinuous * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const PmlDiscontinuous * >(boundary)) { + auto n = gmshfem::function::normal< std::complex< double > >(); + gmshfem::post::save(*(bnd->getV()) * n, bnd->getV()->domain(), bnd->getV()->name()); + } + else if(auto *bnd = dynamic_cast< const PmlWithoutMultiplier * >(boundary)) { + gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); + } + } + + for(unsigned int e = 0; e < 12; ++e) { + const Edge *edge = subproblem.getEdge(e); + if(auto *eg = dynamic_cast< const PmlContinuous_PmlContinuous * >(edge)) { + gmshfem::post::save(*(eg->getV(0)), eg->getV(0)->domain(), eg->getV(0)->name()); + gmshfem::post::save(*(eg->getV(1)), eg->getV(1)->domain(), eg->getV(1)->name()); + } +// else if(auto *eg = dynamic_cast< const PmlDiscontinuous_PmlDiscontinuous * >(edge)) { +// auto n = gmshfem::function::normal< std::complex< double > >(); +// gmshfem::post::save(*(eg->getV(0)) * n, eg->getV(0)->domain(), eg->getV(0)->name()); +// gmshfem::post::save(*(eg->getV(1)) * n, eg->getV(1)->domain(), eg->getV(1)->name()); +// } +// else if(auto *eg = dynamic_cast< const PmlWithoutMultiplier_PmlWithoutMultiplier * >(boundary)) { +// gmshfem::post::save(*(bnd->getV()), bnd->getV()->domain(), bnd->getV()->name()); +// } + } + + for(unsigned int c = 0; c < 8; ++c) { + const Corner *corner = subproblem.getCorner(c); + if(auto *cr = dynamic_cast< const PmlContinuous_PmlContinuous_PmlContinuous * >(corner)) { + gmshfem::post::save(*(cr->getV(0)), cr->getV(0)->domain(), cr->getV(0)->name()); + gmshfem::post::save(*(cr->getV(1)), cr->getV(1)->domain(), cr->getV(1)->name()); + gmshfem::post::save(*(cr->getV(2)), cr->getV(2)->domain(), cr->getV(2)->name()); + } +// else if(auto *cr = dynamic_cast< const PmlDiscontinuous_PmlDiscontinuous_PmlDiscontinuous * >(corner)) { +// auto n = gmshfem::function::normal< std::complex< double > >(); +// gmshfem::post::save(*(cr->getV(0)) * n, cr->getV(0)->domain(), cr->getV(0)->name()); +// gmshfem::post::save(*(cr->getV(1)) * n, cr->getV(1)->domain(), cr->getV(1)->name()); +// gmshfem::post::save(*(cr->getV(2)) * n, cr->getV(2)->domain(), cr->getV(2)->name()); +// } +// else if(auto *cr = dynamic_cast< const PmlWithoutMultiplier_PmlWithoutMultiplier_PmlWithoutMultiplier * >(corner)) { +// gmshfem::post::save(*(cr->getV(0)), cr->getV(0)->domain(), cr->getV(0)->name()); +// gmshfem::post::save(*(cr->getV(1)), cr->getV(1)->domain(), cr->getV(1)->name()); +// } + } + } + } + + +} diff --git a/examples/helmholtz/crossPoints/monoDomain.h b/examples/helmholtz/crossPoints/monoDomain.h new file mode 100755 index 0000000000000000000000000000000000000000..9807fc8cd9e9d8982a52359dbab78d0b1e3c0118 --- /dev/null +++ b/examples/helmholtz/crossPoints/monoDomain.h @@ -0,0 +1,17 @@ +#ifndef H_MONODOMAIN +#define H_MONODOMAIN + +namespace D2 { + + void monoDomain(); + +} + +namespace D3 { + + void monoDomain(); + +} + + +#endif // H_MONODOMAIN