diff --git a/.github/workflows/deploys.yml b/.github/workflows/deploys.yml new file mode 100644 index 0000000..60242a4 --- /dev/null +++ b/.github/workflows/deploys.yml @@ -0,0 +1,50 @@ +name: Build and Deploy Docs + +on: + push: + branches: [devel] + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Install doc tools + run: | + sudo apt install -y doxygen + pip install sphinx myst-parser sphinx_rtd_theme + + - name: Build libaries + run: | + sudo apt install cmake build-essential gfortran liblapack-dev liblapacke-dev + wget https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz + tar -xvf eigen-3.4.0.tar.gz + pip install pybind11-global + mkdir -p build + cd build + cmake .. -DCXX=g++ -DFC=gfortran -DEIGEN_INC=./eigen-3.4.0/ -DBUILD_LIBS=ON -DPython3_EXECUTABLE=`which python` + make -j4 + make install + cd .. + + + - name: Build Doxygen C++ API Docs + run: doxygen misc/doxygen/doxygen.cfg + + - name: Build Python docs (Sphinx) + run: | + sphinx-apidoc -o misc/source/python ./specd + + - name: Build master docs (Sphinx) + run: | + pip install numpy scipy + sphinx-build -b html misc/source docs + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 6a8301e..a1db332 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,16 +1,17 @@ { "configurations": [ { - "name": "MACOS", + "name": "LINUX", "includePath": [ "${workspaceFolder}/**", "~/software/eigen-3.4.0", + "/opt/homebrew/Cellar/open-mpi/5.0.7/include", "/Users/nqdu/software/miniconda3/include/python3.11", "/Users/nqdu/software/miniconda3/lib/python3.11/site-packages/pybind11/include" ], "compilerPath": "/usr/bin/g++", "cStandard": "gnu17", - "cppStandard": "gnu++14", + "cppStandard": "gnu++17", "intelliSenseMode": "linux-gcc-x64" } ], diff --git a/.vscode/launch.json b/.vscode/launch.json index 385d0a4..fed5ae2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,10 +5,12 @@ "name": "(lldb) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/bin/surfvti_ac", - "args": ["model.txt","0.01","0.5","100"], + "program": "${workspaceFolder}/bin/surfrayl", + "args": ["model.txt","0.01","1","1"], + "cwd": "${workspaceFolder}/example/rayleigh", "stopAtEntry": false, - "cwd": "${workspaceFolder}/example/ac", + // "program": "${workspaceFolder}/a.out", + // "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "lldb" diff --git a/.vscode/settings.json b/.vscode/settings.json index 0369086..1492a87 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -116,4 +116,5 @@ "eigenvalues": "cpp" }, //"C_Cpp.errorSquiggles": "disabled" + "fortran.linter.includePaths": ["/opt/homebrew/Cellar/open-mpi/5.0.7/include"] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e2d4e3..4fda72d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # CMakeLists.txt -cmake_minimum_required(VERSION 3.13.0) +cmake_minimum_required(VERSION 3.25.0) ################## compiler options ################## # compiler @@ -13,8 +13,8 @@ set(CMAKE_CXX_FLAGS ${CXXFLAGS}) ################## dependencies ################## # preferred installation prefix of dependencies set(EIGEN_INC ${EIGEN_INC}) -set(USE_LAPACK ${USE_LAPACK}) -set(BUILD_PYLIB ${BUILD_PYLIB}) + +option(BUILD_LIBS "BUILD_LIBS" OFF) # set default values @@ -24,59 +24,61 @@ set(${var} ${val}) endif() endmacro() setDefault(EIGEN_INC "~/software/eigen-3.4.0") -setDefault(USE_LAPACK FALSE) -setDefault(BUILD_PYLIB FALSE) # project project(SWDTTI LANGUAGES CXX Fortran) # build type set(CMAKE_BUILD_TYPE RELEASE) -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_Fortran_MODULE_DIRECTORY ${PROJECT_SOURCE_DIR}/build/obj) ################# cmake setup ################# -set(CMAKE_CXX_FLAGS "-g") +set(CMAKE_CXX_FLAGS "-g -Wall") set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native -ffast-math") +if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -march=native -ffixed-line-length-none") - set(CMAKE_CXX_FLAGS_RELEASE "-O2") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + #set(CMAKE_CXX_FLAGS_RELEASE "-O0 -D_GLIBCXX_DEBUG") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "Intel") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -xHost -DEIGEN_STRONG_INLINE=inline") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -xHost -extend-source") +else () + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -march=native -ffixed-line-length-none") + #set(CMAKE_CXX_FLAGS_RELEASE "-O0 -D_GLIBCXX_DEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -march=native") endif() -set(CMAKE_VERBOSE_MAKEFILE off) +set(CMAKE_VERBOSE_MAKEFILE on) ################# find packages ################# # path of *.cmake files -set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/include/cmake) +#set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/include/cmake) # eigen include_directories(${EIGEN_INC}) # lapack -if(${USE_LAPACK}) - find_package(LAPACK) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEIGEN_USE_LAPACKE") -endif() +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +find_package(LAPACK REQUIRED) +find_package(LAPACKE REQUIRED) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEIGEN_USE_LAPACKE") ################# include paths ################# include_directories(${PROJECT_SOURCE_DIR}/src) -include_directories(${PROJECT_SOURCE_DIR}/include) +#include_directories(${PROJECT_SOURCE_DIR}/include) # subs add_subdirectory(${PROJECT_SOURCE_DIR}/src/shared) +add_subdirectory(${PROJECT_SOURCE_DIR}/src/mesh) add_subdirectory(${PROJECT_SOURCE_DIR}/src/vti) -add_subdirectory(${PROJECT_SOURCE_DIR}/src/tti) -add_subdirectory(${PROJECT_SOURCE_DIR}/src/multiphysics) +# add_subdirectory(${PROJECT_SOURCE_DIR}/src/tti) +# add_subdirectory(${PROJECT_SOURCE_DIR}/src/multiphysics) -# check build pylib -if(${BUILD_PYLIB}) - #find_package(pybind11 REQUIRED) - find_package(Python COMPONENTS Interpreter Development) +# check build libraries +if(BUILD_LIBS) + find_package(Python3 COMPONENTS Interpreter Development) find_package(pybind11 CONFIG) add_subdirectory(src/cps330) add_subdirectory(src/libswd) diff --git a/README.md b/README.md index 7fe60f7..33cf68c 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,6 @@ -# SPECSWD -**SpecSWD** utilizes spectral element method and quadratic eigenvalue solver to compute surface wave dispersion, eigen function and sensitivity kernels for **general layered models**. +# SpecSWD +**SpecSWD** is a software to compute surface wave dispersions and do sensitivity analysis for 1-D fully anisotropic, wealy anelastic media. It utilizes spectral element method and quadratic eigenvalue solver to handle multiphysics (elastic-acoustic coupling), strong anisotropy and discontinuities inside the study region. -It can handle dispersion values for several type of complex media, such as VTI, TTI(Tilted Transversely Isotropic), acoustic-VTI coupling, and at any frequency, and any mode. And it can support both 1-D layered -model (1-D model with discontinuities) and gradient model (continous variation in both fluid and elastic domain). - -## Requirements and Installation -1. **Compilers:** C++/Fortran compilers which support c++14 (tested on `GCC >=7.5`), `cmake >= 3.12` - -2. packages: -* [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page) >= 3.4.0 -* [MKL/LAPACK](https://www.netlib.org/lapack/lapacke.html), optional. -* [doxygen](https://www.doxygen.nl/) for api document generation, optional. - -3. Install: -```bash -mkdir -p build; cd build; -cmake .. -DCXX=g++ -DFC=gfortran -DEIGEN_INC=/path/to/eigen/ -DUSE_LAPACK=FALSE -make -j4; make install -``` -If you want to use `LAPACKE/MKL`, you can set `-DUSE_LAPACK=TRUE`. This program also provides python libraries (`.so`) and you can install them by adding ```-DBUILD_PYLIB=TRUE -DPYTHON_EXECUTABLE=`which python` ``` - -4. install API docs -```bash -cd doxygen -doxygen config.cfg -``` - -# Gallery -### Benchmark: SWDTTI with CPS330 -![image](example//rayleigh/phase.jpg) -### HTI model: Phase velocity vs. Azimuthal angle -![image](example/tti/group-direc.jpg) - -### Fluid-Elastic Coupling phase and group velocity -![image](example/ac/phase.jpg) -![image](example/ac/group.jpg) -### Acoustic +**SpecSWD** also provides high-level sensitivity analysis framework (adjoint methods) for any user-defined quantities. +For installation, user manual, please refer to [docs](https://nqdu.github.io/SpecSWD/). \ No newline at end of file diff --git a/__pycache__/setup.cpython-311.pyc b/__pycache__/setup.cpython-311.pyc new file mode 100644 index 0000000..916905a Binary files /dev/null and b/__pycache__/setup.cpython-311.pyc differ diff --git a/src/multiphysics/CMakeLists.txt b/bak/src.bak/multiphysics/CMakeLists.txt similarity index 100% rename from src/multiphysics/CMakeLists.txt rename to bak/src.bak/multiphysics/CMakeLists.txt diff --git a/src/multiphysics/frechet.cpp b/bak/src.bak/multiphysics/frechet.cpp similarity index 100% rename from src/multiphysics/frechet.cpp rename to bak/src.bak/multiphysics/frechet.cpp diff --git a/src/multiphysics/initialize.cpp b/bak/src.bak/multiphysics/initialize.cpp similarity index 100% rename from src/multiphysics/initialize.cpp rename to bak/src.bak/multiphysics/initialize.cpp diff --git a/src/multiphysics/main.cpp b/bak/src.bak/multiphysics/main.cpp similarity index 100% rename from src/multiphysics/main.cpp rename to bak/src.bak/multiphysics/main.cpp diff --git a/src/multiphysics/sem.cpp b/bak/src.bak/multiphysics/sem.cpp similarity index 100% rename from src/multiphysics/sem.cpp rename to bak/src.bak/multiphysics/sem.cpp diff --git a/src/multiphysics/vti_acoustic.hpp b/bak/src.bak/multiphysics/vti_acoustic.hpp similarity index 100% rename from src/multiphysics/vti_acoustic.hpp rename to bak/src.bak/multiphysics/vti_acoustic.hpp diff --git a/bak/src.bak/solver.bak/CMakeLists.txt b/bak/src.bak/solver.bak/CMakeLists.txt new file mode 100644 index 0000000..25d5676 --- /dev/null +++ b/bak/src.bak/solver.bak/CMakeLists.txt @@ -0,0 +1,8 @@ +file(GLOB SOURCE "*.cpp" ) +list(FILTER SOURCE EXCLUDE REGEX "main*.cpp") + +add_library(libsolver ${SOURCE}) + + +add_executable(surflove ${PROJECT_SOURCE_DIR}/src/solver/main_love.cpp) +target_link_libraries(surflove libsolver shared ${LAPACK_LIBRARIES}) \ No newline at end of file diff --git a/bak/src.bak/solver.bak/database.cpp b/bak/src.bak/solver.bak/database.cpp new file mode 100644 index 0000000..39571c3 --- /dev/null +++ b/bak/src.bak/solver.bak/database.cpp @@ -0,0 +1,154 @@ +#include "solver/solver.hpp" +#include + +void solve_christoffel(float phi, const float *c21,float &cmin,float &cmax); + +void SolverSEM:: +compute_minmax_veloc_(double phi,std::vector &vmin,std::vector &vmax) +{ + vmin.resize(nregion_); + vmax.resize(nregion_); + + for(int ig = 0; ig < nregion_; ig ++ ) { + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + float v0 = 1.0e20, v1 = -1.0e20; + + for(int i = istart; i <= iend; i ++) { + if(SWD_TYPE == 0) { // love wave + float vsh = vsh_[i]; + v0 = std::min(v0,vsh); + // if(HAS_ATT) { + // vsh *= 1. + 0.125 / std::pow(QN_[i],2); // correction to second order + // } + v1 = std::max(v1,vsh); + } + else if (SWD_TYPE == 1) { // rayleigh + if(is_el_reg[ig]) { + v0 = std::min(v0,std::min(vsv_[i],vsh_[i])); + v1 = std::max(v1,std::max(vsv_[i],vsh_[i])); + } + else { + v0 = std::min(v0,vpv_[i]); + v1 = std::max(v1,vpv_[i]); + } + } + else { // aniso + float temp[21],cmin,cmax; + for(int j = 0; j < 21; j ++) { + temp[j] = c21_[j*21+i]; + } + solve_christoffel(phi,temp,cmin,cmax); + v0 = std::min(cmin,v0); + v1 = std::max(cmax,v1); + } + } + + // set value + vmin[ig] = v0; + vmax[ig] = v1; + } +} + +/** + * @brief create database for Love wave + * @param freq current frequency,in Hz + */ +void SolverSEM:: +create_db_love_(double freq) +{ + size_t size = ibool_el.size(); + + // interpolate macro + #define INTP(A,v1d) this -> interp_model(&v1d[0],el_elmnts,xtemp); \ + for(size_t i = 0; i < size; i ++) {\ + A[i] = xtemp[i] * xtemp[i] * xrho_el[i];} + + // interpolate base model + xrho_el.resize(size); + xL.resize(size); + xN.resize(size); + this -> interp_model(&rho_[0],el_elmnts,xrho_el); + this -> interp_model(&vsh_[0],el_elmnts,xN); + this -> interp_model(&vsv_[0],el_elmnts,xL); + for(size_t i = 0; i < size; i ++) { + xN[i] = std::pow(xN[i],2) * xrho_el[i]; + xL[i] = std::pow(xL[i],2) * xrho_el[i]; + } + + // Q model + nQmodel_ani = 0; + if(HAS_ATT) { + // interpolate Q model + xQL.resize(size); xQN.resize(size); + this -> interp_model(&QL_[0],el_elmnts,xQL); + this -> interp_model(&QN_[0],el_elmnts,xQN); + nQmodel_ani = 2; + } +} + +/** + * @brief create database for Love wave + * @param freq current frequency,in Hz + */ +void SolverSEM:: +create_db_rayl_(double freq) +{ + size_t size_el = ibool_el.size(); + size_t size_ac = ibool_ac.size(); + + // allocate space for density + xrho_el.resize(size_el); + xrho_ac.resize(size_ac); + + // interpolate xrho + this -> interp_model(rho_.data(),el_elmnts,xrho_el); + this -> interp_model(rho_.data(),ac_elmnts,xrho_ac); + + // temp arrays + std::vector xtemp_el(size_el); + xA.resize(size_el); xL.resize(size_el); + xC.resize(size_el); xeta.resize(size_el); + xkappa_ac.resize(size_ac); + + // interpolate parameters in elastic domain + this -> interp_model(&vph_[0],el_elmnts,xA); + this -> interp_model(&vpv_[0],el_elmnts,xC); + this -> interp_model(&vsv_[0],el_elmnts,xL); + this -> interp_model(&eta_[0],el_elmnts,xeta); + for(size_t i = 0; i < size_el; i ++) { + double r = xrho_el[i]; + xA[i] = xA[i] * xA[i] * r; + xC[i] = xC[i] * xC[i] * r; + xL[i] = xL[i] * xL[i] * r; + } + + // acoustic domain + this -> interp_model(&vph_[0],ac_elmnts,xkappa_ac); + for(size_t i = 0; i < size_ac; i ++) { + xkappa_ac[i] = xkappa_ac[i] * xkappa_ac[i] * xrho_ac[i]; + } + + nQmodel_ani = 0; + if(HAS_ATT) { + // allocate space for Q + xQL.resize(size_el); xQA.resize(size_el); + xQC.resize(size_el); xQk_ac.resize(size_ac); + this -> interp_model(QL_.data(),el_elmnts,xQL); + this -> interp_model(QC_.data(),el_elmnts,xQC); + this -> interp_model(QA_.data(),el_elmnts,xQA); + this -> interp_model(QC_.data(),ac_elmnts,xQk_ac); + + nQmodel_ani = 3; + } +} + +/** + * @brief create database for Love wave + * @param freq current frequency,in Hz + */ +void SolverSEM:: +create_db_aniso_(double freq) +{ + +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/eigenvalues.cpp b/bak/src.bak/solver.bak/eigenvalues.cpp new file mode 100644 index 0000000..02f7291 --- /dev/null +++ b/bak/src.bak/solver.bak/eigenvalues.cpp @@ -0,0 +1,389 @@ +#include "solver/solver.hpp" +#include +#include + +#include +#include + +typedef std::complex dcmplx; + + +/** + * @brief compute Love wave dispersion and eigenfunctions + * + * @param freq current frequency + * @param vmin,vmax min/max velocity for your model + * @param c dispersion, shape(nc) + * @param displ eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if true, save QZ matrix, where K^{-1} (om^2 M -E) = Q^T Sigma Q + */ +void SolverSEM:: +compute_slegn(double freq,std::vector &c, + std::vector &displ,bool use_qz) +{ + this -> prepare_matrices_love_(freq); + typedef Eigen::Matrix dmat2; + using Eigen::MatrixXd; + using Eigen::all; + + // mapping M,K,E to matrix + int ng = nglob_el; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map E(Emat.data(),ng,ng); + + // construct A = (om^2 M - E), B = K + double om = 2. * M_PI * freq; + double omega2 = std::pow(om,2); + MatrixXd A = MatrixXd((1. / K.array()).matrix().asDiagonal()) * + (-E + dmat2(M.asDiagonal()) * omega2); + MatrixXd displ_all = A * 0.; + + // get eigen values/eigen vectors + Eigen::Array kr(ng),ki(ng); + LAPACKE_dgeev(LAPACK_COL_MAJOR,'N','V',ng,A.data(),ng,kr.data(),ki.data(), + nullptr,ng,displ_all.data(),ng); + + // filter swd + Eigen::Array k = (kr + dcmplx{0,1.} * kr).sqrt(); + Eigen::Array c_all = (om / k).real(); + auto mask = ((c_all.real() >= PHASE_VELOC_MIN)&& + (c_all.real() <= PHASE_VELOC_MAX) && + k.real().abs() >= 10 *k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + for(int i = 0; i < c_all.size(); i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort to ascending order + int nc = idx0.size(); + std::vector idx(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c/displ + int size = displ_all.rows(); + c.resize(nc); displ.resize(nc * size); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + for(int i = 0; i < size; i ++) { + displ[ic * size + i] = displ_all(i,id); + } + } + + // compute QZ if required + if(use_qz) { + // resize all matrices + Qmat_.resize(ng*ng); Zmat_.resize(ng*ng); + Smat_.resize(ng*ng); Spmat_.resize(ng*ng); + + // get hessenburg form by Schur decomposition + A = -E + dmat2(M.asDiagonal()) * omega2; + MatrixXd B = MatrixXd(K.asDiagonal()); + Eigen::VectorXd alphar(ng),alphai(ng),beta(ng); + + // decompose A = Q @ S @ Z.T, B = Q@ + int sdim; + LAPACKE_dgges(LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,A.data(),ng,B.data(),ng,&sdim,alphar.data(), + alphai.data(),beta.data(),Qmat_.data(),ng, + Zmat_.data(),ng); + memcpy(Smat_.data(),A.data(),A.size()*sizeof(double)); + memcpy(Spmat_.data(),B.data(),B.size()*sizeof(double)); + + } +} + +/** + * @brief compute Love wave dispersion and eigenfunctions, visco-elastic case + * + * @param freq current frequency + * @param vmin,vmax min/max velocity for your model + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param displ eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if true, save QZ matrix, where K^{-1} (om^2 M -E) = Q^T Sigma Q + */ +void SolverSEM:: +compute_slegn_att(double freq,std::vector> &c, + std::vector> &displ, + bool use_qz) +{ + this -> prepare_matrices_love_att_(freq); + using Eigen::MatrixXcd; + typedef Eigen::Matrix cdmat2; + + // construct matrix + int ng = nglob_el; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(CKmat.data(),ng); + Eigen::Map E(CEmat.data(),ng,ng); + + // construct A = K^{-1}(om^2 M - E) + double om = 2. * M_PI * freq; + double omega2 = std::pow(om,2); + MatrixXcd A = (cdmat2((1. / K.array()).matrix().asDiagonal()) * + (-E + cdmat2(M.cast().asDiagonal()) * omega2)); + + // solve it + typedef lapack_complex_double lscmplx; + MatrixXcd displ_all = A,A_cp = A; + Eigen::ArrayXcd k(ng); + LAPACKE_zgeev(LAPACK_COL_MAJOR,'N','V',ng, + (lscmplx*)A_cp.data(),ng,(lscmplx*)k.data(), + nullptr,ng,(lscmplx*)displ_all.data(),ng); + k = k.sqrt(); + + // filter SWD + using Eigen::all; + Eigen::ArrayXcd c_all = om / k; + auto mask = ((c_all.real() >= PHASE_VELOC_MIN)&& + (c_all.real() <= PHASE_VELOC_MAX) && + k.real().abs() >= k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + int nc = idx0.size(); + + // sort according to ascending order + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c/displ + c.resize(nc); displ.resize(nc * ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + for(int i = 0; i < ng; i ++) { + displ[ic * ng + i] = displ_all(i,id); + } + } + + // save QZ matrix + if(use_qz) { + // resize all matrices + cQmat_.resize(ng*ng); cZmat_.resize(ng*ng); + cSmat_.resize(ng*ng); cSpmat_.resize(ng*ng); + + // get hessenburg form by Schur decomposition + typedef lapack_complex_double ldcmplx; + A = -E + cdmat2(M.asDiagonal()) * omega2; + MatrixXcd B = MatrixXcd(K.asDiagonal()); + Eigen::VectorXcd alpha(ng),beta(ng); + + // decompose A = Q @ S @ Z.H, B = Q@ S' @ Z.H + int sdim; + LAPACKE_zgges(LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,(ldcmplx*)A.data(),ng,(ldcmplx*)B.data(), + ng,&sdim,(ldcmplx*)alpha.data(),(ldcmplx*)beta.data(), + (ldcmplx*)cQmat_.data(),ng, + (ldcmplx*)cZmat_.data(),ng); + memcpy(cSmat_.data(),A.data(),A.size()*sizeof(dcmplx)); + memcpy(cSpmat_.data(),B.data(),B.size()*sizeof(dcmplx)); + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, elastic case + * + * @param freq current frequency + * @param vmin,vmax min/max velocity for your model + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param ur/ul left/right eigenvectors, shape(nc,nglob_el*2+nglob_ac) + * @param use_qz if true, save QZ matrix + */ +void SolverSEM:: +compute_sregn(double freq,std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::Matrix dmat2; + using Eigen::MatrixXd; using Eigen::ArrayXd; + + // prepare matrices + this -> prepare_matrices_rayl_(freq); + + // mapping M,K,E to matrix + int ng = nglob_ac + nglob_el * 2; + + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(Kmat.data(),ng,ng); + Eigen::Map E(Emat.data(),ng,ng); + + // prepare matrix A = om^2 M -E + double om = 2. * M_PI * freq; + double omega2 = om * om; + + // solve this system + MatrixXd A = omega2 * dmat2(M.asDiagonal()) - E; + MatrixXd B = K; + ArrayXd alphar(ng),alphai(ng),beta(ng); + MatrixXd vsl(ng,ng),vsr(ng,ng); + + // generalized eigenvalue problem + // A x = k B x + LAPACKE_dggev(LAPACK_COL_MAJOR,'V','V',ng,A.data(),ng,B.data(),ng, + alphar.data(),alphai.data(),beta.data(),vsl.data(),ng, + vsr.data(),ng); + + // eigenvalue + const std::complex imag_i = {0,1.}; + Eigen::ArrayXcd k = ((alphar + imag_i * alphai) / beta).sqrt(); + + // filter SWD + using Eigen::all; + Eigen::ArrayXd c_all = (om / k).real(); + auto mask = ((c_all.real() >= PHASE_VELOC_MIN)&& + (c_all.real() <= PHASE_VELOC_MAX) && + k.real().abs() >= 10 *k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort according to ascending order + int nc = idx0.size(); + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c/displ + c.resize(nc); ur.resize(nc * nglob); ul.resize(nc*nglob); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + for(int i = 0; i < nglob; i ++) { + ur[ic*nglob+i] = vsr(i,id); + ul[ic*nglob+i] = vsl(i,id); + } + } + + // save qz matrix + if(use_qz) { + Qmat_.resize(ng*ng); Zmat_.resize(ng*ng); + Smat_.resize(ng*ng); Spmat_.resize(ng*ng); + + // get hessenburg form by Schur decomposition + // A = Q @ S @ Z.T; B = Q @ S' @ Z.T + int sdim = 0; + LAPACKE_dgges(LAPACK_COL_MAJOR,'V','V','N',nullptr,ng, + A.data(),ng,B.data(),ng,&sdim,alphar.data(), + alphai.data(),beta.data(),Qmat_.data(),ng, + Zmat_.data(),ng); + memcpy(Smat_.data(),A.data(),A.size()*sizeof(double)); + memcpy(Spmat_.data(),B.data(),B.size()*sizeof(double)); + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, visco-elastic case + * + * @param freq current frequency + * @param vmin,vmax min/max velocity for your model + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param ur/ul left/right eigenvectors, shape(nc,nglob_el*2+nglob_ac) + * @param use_qz if true, save QZ matrix + */ +void SolverSEM:: +compute_sregn_att(double freq,std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::Matrix cdmat2; + typedef lapack_complex_double lscmplx; + + // prepare matrices + this -> prepare_matrices_rayl_att_(freq); + + // mapping M,K,E to matrix + int ng = nglob_ac + nglob_el * 2; + + Eigen::Map M(CMmat.data(),ng); + Eigen::Map K(CKmat.data(),ng,ng); + Eigen::Map E(CEmat.data(),ng,ng); + + // prepare matrix A = om^2 M -E + double om = 2. * M_PI * freq; + double omega2 = om * om; + + // solve this system + Eigen::MatrixXcd A = omega2 * cdmat2(M.asDiagonal()) - E; + Eigen::MatrixXcd B = K; + Eigen::ArrayXcd alpha(ng),beta(ng); + Eigen::MatrixXcd vsl(ng,ng),vsr(ng,ng); + + // generalized eigenvalue problem + // A x = k B x + // eigenvalues + LAPACKE_zggev(LAPACK_COL_MAJOR,'V','V',ng,(lscmplx*)A.data(),ng,(lscmplx*)B.data(),ng, + (lscmplx*)alpha.data(),(lscmplx*)beta.data(),(lscmplx*)vsl.data(),ng, + (lscmplx*)vsr.data(),ng); + Eigen::ArrayXcd k = (alpha / beta).sqrt(); + + // filter SWD + using Eigen::all; + Eigen::ArrayXcd c_all = om / k; + auto mask = ((c_all.real() >= PHASE_VELOC_MIN)&& + (c_all.real() <= PHASE_VELOC_MAX) && + k.real().abs() >= k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + int nc = idx0.size(); + + // sort according to ascending order + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c/displ + c.resize(nc); ur.resize(nc * ng); ul.resize(nc*ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + for(int i = 0; i < ng; i ++) { + ul[ic * ng + i] = vsl(i,id); + ur[ic * ng + i] = vsr(i,id); + } + } + + // save qz matrix + if(use_qz) { + cQmat_.resize(ng*ng); cZmat_.resize(ng*ng); + cSmat_.resize(ng*ng); cSpmat_.resize(ng*ng); + + // Schur decomposition + int sdim = 0; + LAPACKE_zgges(LAPACK_COL_MAJOR,'V','V','N',nullptr,ng, + (lscmplx*)A.data(),ng,(lscmplx*)B.data(),ng,&sdim,(lscmplx*)alpha.data(), + (lscmplx*)beta.data(),(lscmplx*)cQmat_.data(),ng, + (lscmplx*)cZmat_.data(),ng); + + + memcpy(cSmat_.data(),A.data(),A.size()*sizeof(A(0,0))); + memcpy(cSpmat_.data(),B.data(),B.size()*sizeof(B(0,0))); + } +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/frechet.cpp b/bak/src.bak/solver.bak/frechet.cpp new file mode 100644 index 0000000..a703a90 --- /dev/null +++ b/bak/src.bak/solver.bak/frechet.cpp @@ -0,0 +1,186 @@ +#include "solver/solver.hpp" +#include "solver/frechet.hpp" + +#include + +typedef std::complex dcmplx; + + +/** + * @brief compute group velocity and kernels for love wave phase velocity, elastic case + * + * @param freq current frequency + * @param c current phase velocity + * @param displ eigen function, shape(nglob_el) + * @param frekl Frechet kernels (N/L/rho) for elastic parameters, shape(3,nspec*NGLL + NGRL) + * @return double u group velocity + */ +double SolverSEM:: +compute_love_kl(double freq,double c,const double *displ, std::vector &frekl) const +{ + int ng = nglob_el; + Eigen::Map x(displ,ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map M(Mmat.data(),ng); + + // group velocity + // u = x^T K x / (c x^T M x) + double u = (x * K * x).sum() / (c * (x * M * x).sum()); + + // coefs for phase kernel + double om = 2 * M_PI * freq; + double coef = -0.5 * std::pow(c,3) / std::pow(om,2) / (x * K * x).sum(); + + // allocate phase velocity kernels + int size = ibool_el.size(); + frekl.resize(3*size,0); // N/L/rho + get_deriv_love_(freq,c,coef,displ,displ,nspec_el,nglob_el, + ibool_el.data(),jaco.data(), + nullptr,nullptr,nullptr,nullptr, + frekl.data(),nullptr); + + // return group velocity + return u; +} + + + +/** + * @brief compute group velocity and kernels for love wave phase velocity, visco-elastic case + * + * @param freq current frequency + * @param c current complex phase velocity + * @param displ eigen function, shape(nglob_el) + * @param frekl_c dRe(c)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + * @param frekl_q d(qi)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + * @return double u group velocity + */ +dcmplx SolverSEM:: +compute_love_kl_att(double freq,dcmplx c,const dcmplx *displ, + std::vector &frekl_c, + std::vector &frekl_q) const +{ + int ng = nglob_el; + Eigen::Map x(displ,ng); + Eigen::Map K(CKmat.data(),ng); + Eigen::Map M(Mmat.data(),ng); + + // group velocity + dcmplx u = (x * K * x).sum() / (c * (x * M * x).sum()); + + // coefs for phase kernel + double om = 2 * M_PI * freq; + dcmplx coef = -0.5 * std::pow(c,3) / std::pow(om,2) / (x * K * x).sum(); + + // allocate phase velocity kernels + int size = ibool_el.size(); + frekl_c.resize(5*size,0); // dc_L/d(N/L/QN/QL/rho) + frekl_q.resize(5*size,0); // d(Qi_L)/d(N/L/QN/QL/rho) + + // get kernels + get_deriv_love_(freq,c,coef,displ,displ,nspec_el,nglob_el,ibool_el.data(), + jaco.data(),xN.data(),xL.data(), + xQN.data(),xQL.data(),frekl_c.data(), + frekl_q.data()); + + return u; +} + + +/** + * @brief compute group velocity and kernels for love wave + * + * @param freq current frequency + * @param c current phase velocity + * @param displ eigen function, shape(nglob * 2) + * @param frekl Frechet kernels A/C/L/eta/rho_kl kernels for elastic parameters, shape(5,nspec*NGLL + NGRL) + * @return double u group velocity + */ +double SolverSEM:: +compute_rayl_kl(double freq,double c,const double *displ, + const double *ldispl, std::vector &frekl) const +{ + int ng = nglob_el*2 + nglob_ac; + typedef Eigen::Matrix dmat2; + Eigen::Map x(displ,ng),y(ldispl,ng); + Eigen::Map K(Kmat.data(),ng,ng); + Eigen::Map M(Mmat.data(),ng); + + // group velocity + // u = x^T K x / (c x^T M x) + double u_nume = (y.transpose() * K * x); + double u_deno = c* y.transpose() * M.asDiagonal() * x; + double u = u_nume / u_deno; + + // coefs for phase kernel + double om = 2 * M_PI * freq; + double coef = - 0.5 * std::pow(c,3) / std::pow(om,2) / (y.transpose() * K * x).sum(); + + // allocate phase velocity kernels + using namespace GQTable; + int size = ibool.size(); + frekl.resize(6*size,0); // A/C/L/eta/kappa_ac/rho_kl + + // compute phase kernels + get_deriv_rayl_(freq,c,coef,ldispl,displ,nspec_el,nspec_ac, + nspec_el_grl,nspec_ac_grl,nglob_el,nglob_ac, + el_elmnts.data(),ac_elmnts.data(), + ibool_el.data(),ibool_ac.data(),jaco.data(), + xrho_el.data(),xrho_ac.data(),xA.data(),xC.data(), + xL.data(),xeta.data(),xQA.data(),xQC.data(), + xQL.data(),xkappa_ac.data(),xQk_ac.data(), + frekl.data(),nullptr); + + return u; +} + + + +/** + * @brief compute group velocity and kernels for love wave + * + * @param freq current frequency + * @param c current phase velocity + * @param displ eigen function, shape(nglob * 2) + * @param frekl Frechet kernels A/C/L/eta/rho_kl kernels for elastic parameters, shape(5,nspec*NGLL + NGRL) + * @return double u group velocity + */ +dcmplx SolverSEM:: +compute_rayl_kl_att(double freq,dcmplx c,const dcmplx *displ, + const dcmplx *ldispl, std::vector &frekl_c, + std::vector &frekl_q) const +{ + int ng = nglob_el*2 + nglob_ac; + typedef Eigen::Matrix dcmat2; + Eigen::Map x(displ,ng),y(ldispl,ng); + Eigen::Map K(CKmat.data(),ng,ng); + Eigen::Map M(CMmat.data(),ng); + + // group velocity + // u = x^T K x / (c x^T M x) + dcmplx u_nume = (y.adjoint() * K * x); + dcmplx u_deno = c* y.adjoint() * M.asDiagonal() * x; + dcmplx u = u_nume / u_deno; + + // coefs for phase kernel + double om = 2 * M_PI * freq; + dcmplx coef = - 0.5 * std::pow(c,3) / std::pow(om,2) / (y.adjoint() * K * x).sum(); + + // allocate phase velocity kernels + using namespace GQTable; + int size = ibool.size(); + frekl_c.resize(10*size,0); // A/C/L/eta/kappa_ac/rho_kl + frekl_q.resize(10*size,0); // A/C/L/eta/kappa_ac/rho_kl + + // compute phase kernels + get_deriv_rayl_(freq,c,coef,ldispl,displ,nspec_el,nspec_ac, + nspec_el_grl,nspec_ac_grl,nglob_el,nglob_ac, + el_elmnts.data(),ac_elmnts.data(), + ibool_el.data(),ibool_ac.data(),jaco.data(), + xrho_el.data(),xrho_ac.data(),xA.data(),xC.data(), + xL.data(),xeta.data(),xQA.data(),xQC.data(), + xQL.data(),xkappa_ac.data(),xQk_ac.data(), + frekl_c.data(),frekl_q.data()); + + return u; +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/frechet.hpp b/bak/src.bak/solver.bak/frechet.hpp new file mode 100644 index 0000000..df8b7fd --- /dev/null +++ b/bak/src.bak/solver.bak/frechet.hpp @@ -0,0 +1,354 @@ +#ifndef SPECSWD_FRECHET_H_ +#define SPECSWD_FRECHET_H_ + +#include "shared/attenuation.hpp" +#include "GQTable.hpp" + + +/** + * @brief convert d\tilde{c}/dm to dcL/dm, dQiL/dm, where \tilde{c} = c(1 + 1/2 i Qi) + * @param dcdm, Frechet kernel for complex phase velocity, rst m + * @param c complex phase velocity + * @param dcLdm,dQiLdm dc / dm and dQi / dm + */ +template void +get_cQ_kl(T &dcdm,T c, + double &dcLdm,double &dQiLdm) +{ + static_assert(std::is_same_v,T>); + double cl = c.real(); + double Qi = 2. * c.imag() / cl; + dcLdm = dcdm.real(); + dQiLdm = (dcdm.imag() * 2. - Qi * dcLdm) / cl; +} + +/** + * @brief compute coef * y^T @ d( (w^2 M -E) - k^ K)/dm_i @ x dm_i + * @param freq current frequency + * @param c current phase velocity + * @param coef scaling coefs + * @param egn eigen vector,shape(nglob_el) + * @param nspec_el/nglob_el mesh nelemnts/unique points for elastic + * @param ibool_el elastic connectivity matrix, shape(nspec_el*NGLL+NGRL) + * @param jaco jacobian matrix, shape (nspec_el + 1) + * @param xN/xL/xQN/xQL/rho model parameters, shape(nspec_el*NGLL+NGRL) + * @param frekl_c dc/d(N/L/rho) (elastic) or dc/d(N/L/QN/QL/rho) (anelstic) + * @param frekl_q nullptr or dqc/d(N/L/QN/QL/rho) (anelstic) + * @note frekl_c and frekl_q should be set to 0 before calling this routine + */ +template +void get_deriv_love_(double freq, T c, T coef,const T *y,const T *x, + int nspec_el,int nglob_el, const int *ibool_el, + const double *jaco, const double *xN, + const double *xL,const double *xQN, + const double *xQL, double * __restrict frekl_c, + double * __restrict frekl_q) +{ + // check template type + static_assert(std::is_same_v || std::is_same_v,T>); + + using namespace GQTable; + std::array rW,lW; + size_t size = nspec_el*NGLL + NGRL; + double om = 2 * M_PI * freq; + T k2 = (om * om) / (c * c); + for(int ispec = 0; ispec < nspec_el + 1; ispec ++) { + const double *hp = &hprime[0]; + const double *w = &wgll[0]; + double J = jaco[ispec]; // jacobians in this layers + int NGL = NGLL; + int id = ispec * NGLL; + + // GRL layer + if(ispec == nspec_el) { + hp = &hprime_grl[0]; + w = &wgrl[0]; + NGL = NGRL; + } + + // cache displ in a element + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id+i]; + rW[i] = x[iglob]; + lW[i] = y[iglob]; + } + + // compute kernels + T dc_drho{}, dc_dN{}, dc_dL{}; + T dc_dqni{}, dc_dqli{}; + T sn = 1., sl = 1.; + T dsdqni{}, dsdqli{}; + for(int m = 0; m < NGL; m ++) { + dc_drho = w[m] * J * om * om * rW[m] * lW[m] * coef; + + // get sls derivative if required + if constexpr (std::is_same_v>) { + get_sls_Q_derivative(freq,xQN[id+m],sn,dsdqni); + get_sls_Q_derivative(freq,xQL[id+m],sl,dsdqli); + dsdqni *= xN[id+m]; + dsdqli *= xL[id+m]; + } + + // N kernel + T temp = -k2 * rW[m] * lW[m] * J * w[m] * coef; + dc_dN = temp * sn; + dc_dqni = temp * dsdqni; + + // L kernel + T sx{},sy{}; + for(int i = 0; i < NGL; i ++) { + sx += hp[m*NGL+i] * rW[i]; + sy += hp[m*NGL+i] * lW[i]; + } + temp = -sx * sy * w[m] / J * coef; + dc_dL = temp * sl; + dc_dqli = temp * dsdqli; + + // copy to frekl + int id1 = id + m; + if constexpr (std::is_same_v>) { + get_cQ_kl(dc_dN,c,frekl_c[0*size+id1],frekl_q[0*size+id1]); + get_cQ_kl(dc_dL,c,frekl_c[1*size+id1],frekl_q[1*size+id1]); + get_cQ_kl(dc_dqni,c,frekl_c[2*size+id1],frekl_q[2*size+id1]); + get_cQ_kl(dc_dqli,c,frekl_c[3*size+id1],frekl_q[3*size+id1]); + get_cQ_kl(dc_drho,c,frekl_c[4*size+id1],frekl_q[4*size+id1]); + } + else { + frekl_c[0*size+id1] = dc_dN; + frekl_c[1*size+id1] = dc_dL; + frekl_c[2*size+id1] = dc_drho; + } + } + } +} + + +/** + * @brief compute coef * y^dag @ d( (w^2 M -E) - k^2 K)/dm_i @ x dm_i + * @param freq current frequency + * @param c current phase velocity + * @param coef derivative scaling coefs + * @param y/x dot vector,shape(nglob_el*2+nglob_ac) + * @param nspec_el/nglob_el mesh nelemnts/unique points for elastic + * @param nspec_ac/nglob_ac mesh nelemnts/unique points for acoustic + * @param nspec_el/ac_grl no. of GRL elements + * @param ibool_el elastic connectivity matrix, shape(nspec_el*NGLL+nspec_el_grl*NGRL) + * @param ibool_ac elastic connectivity matrix, shape(nspec_ac*NGLL+nspec_ac_grl*NGRL) + * @param jaco jacobian matrix, shape (nspec_el + 1) + * @param xA/xC/xL/xeta/xQA/xQC/xQL/xrho elastic model parameters,ibool_el.shape + * @param xkappa_ac/xQk_ac/xrho_ac acoustic model parameters, ibool_ac.shape + * @param frekl_c dc/d(A/C/L/kappa/rho) (elastic) or dc/d(A/C/L/QA/QC/QL/kappa/Qk/rho) (anelstic) + * @param frekl_q nullptr or dqc/d(A/C/L/QA/QC/QL/kappa/Qk/rho) (anelstic) + * @note frekl_c and frekl_q should be set to 0 before calling this routine + */ +template +void +get_deriv_rayl_(double freq,T c,T coef,const T *y, const T *x, + int nspec_el,int nspec_ac,int nspec_el_grl,int nspec_ac_grl,int nglob_el, + int nglob_ac, const int *el_elmnts,const int *ac_elmnts, + const int* ibool_el, const int* ibool_ac, + const double *jaco,const double *xrho_el,const double *xrho_ac, + const double *xA, const double *xC,const double *xL,const double *xeta, + const double *xQA, const double *xQC,const double *xQL, + const double *xkappa_ac, const double *xQk_ac, + double *__restrict frekl_c, + double *__restrict frekl_q) +{ + // check template type + static_assert(std::is_same_v || std::is_same_v,T>); + + // constants + using namespace GQTable; + size_t size = nspec_el * NGLL + nspec_el_grl * NGRL + + nspec_ac * NGLL + nspec_ac_grl * NGRL; + double om = 2 * M_PI * freq; + T k2 = std::pow(om / c,2); + + // loop elastic elements + std::array U,V,lU,lV; + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id = ispec * NGLL; + + const double *weight = wgll.data(); + const double *hp = hprime.data(); + int NGL = NGLL; + + // jacobian + double J = jaco[iel]; + + // grl case + if(ispec == nspec_el) { + weight = wgrl.data(); + hp = hprime_grl.data(); + NGL = NGRL; + } + + // cache U,V and lU,lV + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id + i]; + U[i] = x[iglob]; + V[i] = x[iglob + nglob_el]; + lU[i] = y[iglob]; + lV[i] = y[iglob + nglob_el]; + if constexpr (std::is_same_v>) { + lU[i] = std::conj(lU[i]); + lV[i] = std::conj(lV[i]); + } + } + + // compute kernel + T dc_drho{}, dc_dA{}, dc_dC{}, dc_dL{}; + T dc_deta{}, dc_dQci{},dc_dQai{},dc_dQli{}; + for(int m = 0; m < NGL; m ++) { + T temp = weight[m] * J * coef; + dc_drho = temp * om * om * + (U[m] * lU[m] + V[m] * lV[m]); + + // get sls factor if required + T sa = 1.,sl = 1.,sc = 1.; + T dsdqai{},dsdqci{},dsdqli{}; + double C = xC[id+m], A = xA[id+m], + L = xL[id+m], eta = xeta[m]; + if constexpr (std::is_same_v>) { + get_sls_Q_derivative(freq,xQA[id+m],sa,dsdqai); + get_sls_Q_derivative(freq,xQC[id+m],sc,dsdqai); + get_sls_Q_derivative(freq,xQL[id+m],sl,dsdqai); + dsdqai *= A; + dsdqci *= C; + dsdqli *= L; + } + + // K matrix + // dc_dA + temp = -weight[m] * J * k2 * U[m] * lU[m] * coef; + dc_dA = temp * sa; dc_dQai = temp * dsdqai; + + // dc_dL + temp = -weight[m] * J * k2 * V[m] * lV[m] * coef; + dc_dL = temp * sl; dc_dQli = temp * dsdqli; + + // Ematrix + T sx{},sy{},lsx{},lsy{}; + for(int i = 0; i < NGL; i ++) { + sx += hp[m*NGL+i] * U[i]; + sy += hp[m*NGL+i] * V[i]; + lsx += hp[m*NGL+i] * lU[i]; + lsy += hp[m*NGL+i] * lV[i]; + } + temp = -weight[m] / J * sx * lsx * coef ; + dc_dL += temp * sl; dc_dQli += temp * dsdqli; + + temp = - weight[m] / J * sy * lsy * coef; + dc_dC = temp * sc; dc_dQci = temp * dsdqci; + + // eta + temp = - (k2 * weight[m] * U[m] * lsy + + weight[m] * lU[m] * sy) * coef; + dc_deta = temp * (A*sa - 2.*L*sl); + + temp *= eta; + dc_dA += temp * sa; dc_dQai += temp * dsdqai; + dc_dL += - temp * 2. * sl; dc_dQli += -temp * 2. * dsdqli; + + temp = k2 * weight[m] * lV[m] * sx + weight[m] * V[m] * lsx; + temp *= coef; + dc_dL += temp * sl; + dc_dQli += temp * dsdqli; + + // copy them to frekl + int id1 = iel * NGLL + m; + if constexpr (std::is_same_v) { + frekl_c[0*size+id1] = dc_dA; + frekl_c[1*size+id1] = dc_dC; + frekl_c[2*size+id1] = dc_dL; + frekl_c[3*size+id1] = dc_deta; + frekl_c[5*size+id1] = dc_drho; + } + else { + get_cQ_kl(dc_dA,c,frekl_c[0*size+id1],frekl_q[0*size+id1]); + get_cQ_kl(dc_dC,c,frekl_c[1*size+id1],frekl_q[1*size+id1]); + get_cQ_kl(dc_dL,c,frekl_c[2*size+id1],frekl_q[2*size+id1]); + get_cQ_kl(dc_deta,c,frekl_c[3*size+id1],frekl_q[3*size+id1]); + get_cQ_kl(dc_dQai,c,frekl_c[4*size+id1],frekl_q[4*size+id1]); + get_cQ_kl(dc_dQci,c,frekl_c[5*size+id1],frekl_q[5*size+id1]); + get_cQ_kl(dc_dQli,c,frekl_c[6*size+id1],frekl_q[6*size+id1]); + get_cQ_kl(dc_drho,c,frekl_c[9*size+id1],frekl_q[9*size+id1]); + } + } + } + + // acoustic eleemnts + std::array chi,lchi; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { + int iel = ac_elmnts[ispec]; + int id = ispec * NGLL; + const double *weight = wgll.data(); + const double *hp = hprime.data(); + int NGL = NGLL; + + // jacobians + double J = jaco[iel]; + + // grl case + if(ispec == nspec_ac) { + weight = wgrl.data(); + hp = hprime_grl.data(); + NGL = NGRL; + } + + // cache chi and lchi in one element + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_ac[id + i]; + chi[i] = (iglob == -1) ? 0: x[iglob+nglob_el*2]; + lchi[i] = (iglob == -1) ? 0.: y[iglob+nglob_el*2]; + if constexpr (std::is_same_v>) { + lchi[i] = std::conj(lchi[i]); + } + } + + // derivatives + T dc_dkappa{},dc_drho{}, dc_dqki{}; + T sk = 1., dskdqi = 0.; + for(int m = 0; m < NGL; m ++ ){ + // copy material + double rho = xrho_ac[id+m]; + double kappa = xkappa_ac[id+m]; + if constexpr (std::is_same_v>) { + get_sls_Q_derivative(freq,xQk_ac[id+m],sk,dskdqi); + dskdqi *= kappa; + } + + // kappa kernel + T temp = std::pow(om/(sk * kappa),2) *weight[m]* J* + chi[m] * lchi[m] * coef; + dc_dkappa = temp * sk; + dc_dqki = temp * dskdqi; + + dc_drho = -k2 * std::pow(om/rho,2) *weight[m]* J* + chi[m] * lchi[m] * coef; + + T sx{},sy{}; + for(int i = 0; i < NGL; i ++) { + sx += hp[m*NGL+i] * chi[i]; + sy += hp[m*NGL+i] * lchi[i]; + } + dc_drho += weight[m] / J / (rho*rho) * sx * sy * coef; + + // copy to frekl + int id1 = iel * NGLL + m; + if constexpr (std::is_same_v) { + frekl_c[4*size+id1] = dc_dkappa; + frekl_c[5*size+id1] = dc_drho; + } + else { + get_cQ_kl(dc_dkappa,c,frekl_c[7*size+id1],frekl_q[7*size+id1]); + get_cQ_kl(dc_dqki,c,frekl_c[8*size+id1],frekl_q[8*size+id1]); + get_cQ_kl(dc_drho,c,frekl_c[9*size+id1],frekl_q[9*size+id1]); + } + + } + } +} + +#endif \ No newline at end of file diff --git a/bak/src.bak/solver.bak/group_kernels.cpp b/bak/src.bak/solver.bak/group_kernels.cpp new file mode 100644 index 0000000..f3727ce --- /dev/null +++ b/bak/src.bak/solver.bak/group_kernels.cpp @@ -0,0 +1,56 @@ +#include "solver/solver.hpp" +#include "solver/frechet.hpp" + +#include + +void SolverSEM:: +compute_love_group_kl(double freq,double c,const double *displ, + std::vector &frekl) const +{ + int ng = nglob_el; + Eigen::Map x(displ,ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map M(Mmat.data(),ng); + + // set frekl to 0 + frekl.resize(3*ibool_el.size(),0); + + // group velocity + // du / alpha = du/dc * dc/dalpha + double om = 2 * M_PI * freq; + double k2 = std::pow(om/c,2); + double xTKx = (x * K * x).sum(), xTMx = (x * M * x).sum(); + double du_dalpha = -xTKx / (c*c * xTMx); + du_dalpha *= -0.5 * std::pow(c,3) / std::pow(om,2) / xTKx; + + // du /dx + Eigen::VectorXd du_dx = 2. * K * x / (c * xTMx) - + 2. * xTKx * M * x / std::pow(c*xTMx,2); + + // mapping Q,Z,S,Sp + Eigen::Map Q(Qmat_.data(),ng,ng); + Eigen::Map Z(Zmat_.data(),ng,ng); + Eigen::Map S(Smat_.data(),ng,ng); + Eigen::Map Sp(Spmat_.data(),ng,ng); + + // solve (A.T - k^2 B.T) lambda = du_dx + du_dx = Z.transpose() * du_dx; + Eigen::VectorXd lamb = (S - k2 * Sp).eval().triangularView(). + solve(du_dx); + lamb = Q * lamb; + + // - lambda^T (dA / dm_i - k^2 dB / dm) x + get_deriv_love_(freq,c,-1.,lamb.data(),displ,nspec_el, + nglob_el,ibool_el.data(),jaco.data(), + nullptr,nullptr,nullptr,nullptr, + frekl.data(),nullptr); + + // c1+ c2 + double c12 = - (du_dalpha + (lamb.array() * K * x).sum()) / xTKx; + + // -(c1+c2) x^T (dA / dm_i - k^2 dB / dm) x + get_deriv_love_(freq,c,-c12,displ,displ,nspec_el, + nglob_el,ibool_el.data(),jaco.data(), + nullptr,nullptr,nullptr,nullptr, + frekl.data(),nullptr); +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/initialize.cpp b/bak/src.bak/solver.bak/initialize.cpp new file mode 100644 index 0000000..fc7c212 --- /dev/null +++ b/bak/src.bak/solver.bak/initialize.cpp @@ -0,0 +1,315 @@ +#include "solver/solver.hpp" +#include "GQTable.hpp" +#include + + +/** + * @brief find location of z0 in ascending list z + * + * @param z depth list, shape(nlayer) + * @param z0 current loc, must be inside z + * @param nlayer + * @return int location of z0 in z, satisfies z0 >= z[i] && z0 < z[i + 1] + */ +static int +find_loc(const float *z,float z0,int nz) +{ + + int i = 0; + while(i < nz - 1) { + if(z0 >= z[i] && z0 < z[i + 1]) { + break; + } + i += 1; + } + + return i; +} + + +/** + * @brief interpolate elastic/acoustic model by using coordinates + * + * @param param input model parameter, shape(nz_) + * @param elmnts all elements used, ispec = elmnts[i] + * @param md model required to interpolate, shape(nspec_el*NGLL + nspec_el_grl * NGRL) + */ +void SolverSEM:: +interp_model(const float *param,const std::vector &elmnts,std::vector &md) const +{ + using GQTable :: NGLL; using GQTable :: NGRL; + int nel = elmnts.size(); + + for(int ireg = 0; ireg < nregion_; ireg ++) { + int istart = region_bdry[ireg*2]; + int iend = region_bdry[ireg*2+1]; + int npts = iend - istart + 1; + + for(int ispec_md = 0; ispec_md < nel; ispec_md ++) { + int ispec = elmnts[ispec_md]; + int NGL = NGLL; + if(ispec == nspec) { + NGL = NGRL; + } + + if(ireg != iregion_flag[ispec]) continue; + + // interpolate + for(int i = 0; i < NGL; i ++) { + int id = ispec_md * NGLL + i; + + double z0 = znodes[ispec * NGLL + i]; + + // find loc in this region + int j = find_loc(&depth_[istart],z0,npts) + istart; + if(j < istart || j >= iend) { + j = j < istart ? istart : iend; + md[id] = param[j]; + } + else { + float dzinv = 1./ (depth_[j + 1] - depth_[j]); + md[id] = param[j] + (param[j+1]-param[j]) * dzinv * (z0-depth_[j]); + } + + } + } + } + +} + +void SolverSEM:: +create_material_info_() +{ + using namespace GQTable; + ac_elmnts.resize(0); el_elmnts.resize(0); + ac_elmnts.reserve(nspec_ac + nspec_ac_grl); + el_elmnts.reserve(nspec_el + nspec_el_grl); + is_elastic.resize(nspec + nspec_grl); + is_acoustic.resize(nspec + nspec_grl); + for(int ispec = 0; ispec < nspec + nspec_grl; ispec ++) { + if(is_elastic[ispec]) { + el_elmnts.push_back(ispec); + } + if(is_acoustic[ispec]) { + ac_elmnts.push_back(ispec); + } + } + + // get nglob_el for elastic + ibool_el.resize(nspec_el * NGLL + nspec_el_grl * NGRL); + nglob_el = 0; + int idx = -1; + for(int i = 0; i < nspec_el + nspec_el_grl; i += 1) { + int ispec = el_elmnts[i]; + if(idx == ibool[ispec * NGLL]) nglob_el -= 1; + + int NGL = NGLL; + if(i == nspec_el) NGL = NGRL; + for(int igll = 0; igll < NGL; igll ++) { + ibool_el[i * NGLL + igll] = nglob_el; + nglob_el += 1; + } + idx = ibool[ispec * NGLL + NGLL-1]; + } + + // regular boundary condition at infinity + // if(nspec_el_grl == 1) { + // nglob_el -= 1; + // ibool_el[nspec_el*NGLL + NGRL-1] = -1; + // } + + // get nglob_ac for acoustic + ibool_ac.resize(nspec_ac * NGLL + nspec_ac_grl * NGRL); + idx = -10; + nglob_ac = 0; + if(is_acoustic[0]) nglob_ac = -1; // the top point of acoustic wave is 0 + for(int i = 0; i < nspec_ac + nspec_ac_grl; i += 1) { + int ispec = ac_elmnts[i]; + if(idx == ibool[ispec * NGLL]) nglob_ac -= 1; + + int NGL = NGLL; + if(i == nspec_ac) NGL = NGRL; + for(int igll = 0; igll < NGL; igll ++) { + ibool_ac[i * NGLL + igll] = nglob_ac; + nglob_ac += 1; + } + idx = ibool[ispec * NGLL + NGLL-1]; + } + + // elastic-acoustic boundary + nfaces_bdry = 0; + for(int i = 0; i < nspec; i ++) { + if(is_elastic[i] != is_elastic[i+1]) { + nfaces_bdry += 1; + } + } + ispec_bdry.resize(nfaces_bdry*2); + bdry_norm_direc.resize(nfaces_bdry); + idx = 0; + for(int i = 0; i < nspec; i ++) { + if(is_elastic[i] != is_elastic[i+1]) { + int iloc_el = i + 1, iloc_ac = i; + if(is_elastic[i]) { + bdry_norm_direc[i] = 0; + iloc_el = i; + iloc_ac = i + 1; + } + else { + bdry_norm_direc[idx] = 1; + } + auto it = std::find(el_elmnts.begin(),el_elmnts.end(),iloc_el); + int ispec_el = it - el_elmnts.begin(); + it = std::find(ac_elmnts.begin(),ac_elmnts.end(),iloc_ac); + int ispec_ac = it - ac_elmnts.begin(); + ispec_bdry[idx * 2 + 0] = ispec_ac; + ispec_bdry[idx * 2 + 1] = ispec_el; + idx += 1; + } + } + +#ifdef SPECSWD_DEBUG + // debug + for(int iface = 0; iface < nfaces_bdry; iface ++) { + printf("\nface %d, ispec_ac,ispec_el = %d %d\n",iface,ispec_bdry[iface*2],ispec_bdry[iface*2+1]); + printf("acoustic -> elastic = %d\n",bdry_norm_direc[iface]); + } +#endif +} + +/** + * @brief Create SEM database by using input model info + * + * @param freq current frequency + * @param phi directional angle + */ +void SolverSEM:: +create_database(double freq,double phi) +{ + using namespace GQTable; + + std::vector vmin,vmax; + this -> compute_minmax_veloc_(phi,vmin,vmax); + + // find min/max vs + PHASE_VELOC_MAX = -1.; + PHASE_VELOC_MIN = 1.0e20; + for(int i = 0; i < nregion_; i ++) { + PHASE_VELOC_MAX = std::max((double)vmax[i],PHASE_VELOC_MAX); + PHASE_VELOC_MIN = std::min((double)vmin[i],PHASE_VELOC_MIN); + } + PHASE_VELOC_MIN *= 0.85; + + // loop every region to find best element size + nspec = 0; + std::vector nel(nregion_ - 1); + for(int ig = 0; ig < nregion_ - 1; ig ++) { + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + + float maxdepth = depth_[iend] - depth_[istart]; + nel[ig] = 1.5 * (maxdepth * freq) / vmin[ig] + 1; + if(nel[ig] <=0) nel[ig] = 1; + nspec += nel[ig]; + } + nspec_grl = 1; + + // allocate space + size_t size = nspec * NGLL + NGRL; + ibool.resize(size); znodes.resize(size); + jaco.resize(nspec+1); iregion_flag.resize(nspec+1); + skel.resize(nspec*2+2); + + // connectivity matrix + int idx = 0; + for(int ispec = 0; ispec < nspec; ispec ++) { + for(int igll = 0; igll < NGLL; igll ++) { + ibool[ispec * NGLL + igll] = idx; + idx += 1; + } + idx -= 1; + } + for(int i = 0; i < NGRL; i ++) { + ibool[nspec * NGLL + i] = idx; + idx += 1; + } + nglob = ibool[nspec * NGLL + NGRL - 1] + 1; + + // skeleton and nspec/ac/el + int id = 0; + nspec_ac = 0; nspec_el = 0; + is_elastic.resize(nspec+1); + is_acoustic.resize(nspec+1); + for(int ig = 0; ig < nregion_ - 1; ig ++) { + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + double h = (depth_[iend] - depth_[istart]) / nel[ig]; + for(int j = 0; j < nel[ig]; j ++) { + skel[id * 2 + 0] = depth_[istart] + h * j; + skel[id * 2 + 1] = depth_[istart] + h * (j + 1.); + is_elastic[id] = is_el_reg[ig]; + is_acoustic[id] = is_ac_reg[ig]; + if(is_elastic[id]) nspec_el += 1; + if(is_acoustic[id]) nspec_ac += 1; + + // set iregion flag + iregion_flag[id] = ig; + + id += 1; + } + } + + // half space skeleton + nspec_el_grl = 0; nspec_ac_grl = 0; + double scale = PHASE_VELOC_MAX / freq / xgrl[NGRL-1] * 30; // up to 50 wavelength + skel[nspec * 2 + 0] = depth_[nz_-1]; + skel[nspec * 2 + 1] = depth_[nz_-1] + xgrl[NGRL-1] * scale; + iregion_flag[nspec] = nregion_ - 1; + + // half space material type + is_elastic[nspec] = is_el_reg[nregion_-1]; + is_acoustic[nspec] = is_ac_reg[nregion_-1]; + if(is_acoustic[nspec]) nspec_ac_grl = 1; + if(is_elastic[nspec]) nspec_el_grl = 1; + + // jacobians and coordinates + for(int ispec = 0; ispec < nspec; ispec ++) { + double h = skel[ispec*2+1] - skel[ispec*2+0]; + jaco[ispec] = h / 2.; + for(int i = 0; i < NGLL; i ++) { + double xi = xgll[i]; + znodes[ispec * NGLL + i] = skel[ispec*2] + h * 0.5 * (xi + 1); + } + } + // compute coordinates and jaco in GRL layer + for(int ispec = nspec; ispec < nspec + 1; ispec ++) { + jaco[ispec] = scale; + for(int i = 0; i < NGRL; i ++) { + double xi = xgrl[i]; + znodes[ispec*NGLL+i] = skel[ispec*2] + xi * scale; + } + } + + // UNIQUE coordinates + zstore.resize(nglob); + for(int i = 0; i < nspec * NGLL + NGRL; i ++) { + int iglob = ibool[i]; + zstore[iglob] = znodes[i]; + } + + // create connectivity matrix for each material + this -> create_material_info_(); + + // interpolate model + switch (SWD_TYPE) + { + case 0: + this -> create_db_love_(freq); + break; + case 1: + this -> create_db_rayl_(freq); + break; + default: + this -> create_db_aniso_(freq); + break; + } +} diff --git a/bak/src.bak/solver.bak/io.cpp b/bak/src.bak/solver.bak/io.cpp new file mode 100644 index 0000000..0ecf0cd --- /dev/null +++ b/bak/src.bak/solver.bak/io.cpp @@ -0,0 +1,445 @@ +#include "solver/solver.hpp" +#include +#include +#include + + +template +void +allocate(int n,T &vec1,Args& ...args) +{ + vec1.resize(n); + std::fill(vec1.begin(),vec1.end(),0); + if constexpr(sizeof...(args) > 0){ + allocate(n,args...); + } +} + +void SolverSEM:: +allocate_1D_model(int nz0,int swd_type,int has_att) +{ + // copy value to mesh type + SWD_TYPE = swd_type; + nz_ = nz0; + HAS_ATT = has_att; + + // allocate space + switch (SWD_TYPE) + { + case 0: + allocate(nz_,vsv_,vsh_,rho_); + if(HAS_ATT) { + allocate(nz_,QN_,QL_); + } + break; + case 1: + allocate(nz_,vpv_,vph_,vsv_,rho_,eta_); + if(HAS_ATT) allocate(nz_,QC_,QA_,QL_); + break; + + case 2: + allocate(nz_*21,c21_); + allocate(nz_,rho_); + if(HAS_ATT) allocate(nz_*21,Qc21_); + + break; + default: + printf("SWD_TYPE should in [0,1,2]!\n"); + printf("current value is %d\n",SWD_TYPE); + exit(1); + break; + } + + // allocate depth + allocate(nz_,depth_); +} + + +/** + * @brief read header of 1D model, including wave type, attenutation flag, + * attenuation model flag + * @param filename model filename + */ +void SolverSEM:: +read_model_header_(const char *filename) +{ + std::ifstream infile; infile.open(filename); + if(infile.fail()) { + printf("cannot open %s\n",filename); + exit(1); + } + + // read first line + std::string line; + std::getline(infile,line); + + // read SWD_TYPE and HAS_ATT + int dummy[2]; + { + std::istringstream info(line); + info >> dummy[0] >> dummy[1]; + } + + // find how many depth points in this file + int nz = 0; + while (std::getline(infile,line)) + { + nz += 1; + } + infile.close(); + + // allocate model + this -> allocate_1D_model(nz,dummy[0],dummy[1]); + + // allocate depth + float z = 0.; + + // read depth in file + infile.open(filename); + std::getline(infile,line); + for(int i = 0; i < nz; i ++) { + std::getline(infile,line); + std::istringstream info(line); + info >> depth_[i]; + info.clear(); + + if(i >= 1) { + // make sure depth is no descreasing + if(depth_[i] - z < 0) { + printf("depth should not decrease!\n"); + printf("current/previous depth = %f %f\n",depth_[i],z); + exit(1); + } + z = depth_[i]; + } + } +} + +/** + * @brief read 1D VTI model for Love wave + * @param filename 1D model file + */ +void SolverSEM:: +read_model_love_(const char *filename) +{ + std::string line; + std::ifstream infile; infile.open(filename); + + // skip header + std::getline(infile,line); + + float temp; + for(int i = 0; i < nz_; i ++) { + std::getline(infile,line); + std::istringstream info(line); + info >> temp >> rho_[i] >> vsh_[i] >> vsv_[i]; + if(HAS_ATT) { + info >> QN_[i] >> QL_[i]; + } + info.clear(); + } + infile.close(); +} + +/** + * @brief read 1D VTI model for Rayleigh wave + * @param filename 1D model file + */ +void SolverSEM:: +read_model_rayl_(const char *filename) +{ + std::ifstream infile; infile.open(filename); + std::string line; + + // skip header + std::getline(infile,line); + + for(int i = 0; i < nz_; i ++) { + std::getline(infile,line); + std::istringstream info(line); + float temp; + info >> temp >> rho_[i] >> vph_[i] >> vpv_[i] + >> vsv_[i] >> eta_[i]; + if(HAS_ATT) { + info >> QA_[i] >> QC_[i] >> QL_[i]; + } + info.clear(); + } + infile.close(); +} + +/** + * @brief read 1D full anisotropy model model for Rayleigh wave + * @param filename 1D model file + */ +void SolverSEM:: +read_model_full_aniso_(const char *filename) +{ + std::ifstream infile; infile.open(filename); + std::string line; + + // skip header + std::getline(infile,line); + + for(int i = 0; i < nz_; i ++) { + float temp; + infile >> temp >> rho_[i]; + for(int j = 0; j < 21; j ++ ) { + infile >> c21_[j*21+i]; + } + if(HAS_ATT) { + for(int j = 0; j < 21; j ++) { + infile >> Qc21_[j*21+i]; + } + } + } + + // close + infile.close(); +} + +/** + * @brief read 1D model + * @param filename 1D model file + */ +void SolverSEM:: +read_model(const char *filename) +{ + this -> read_model_header_(filename); + switch (SWD_TYPE) + { + case 0: + this -> read_model_love_(filename); + break; + case 1: + this -> read_model_rayl_(filename); + break; + case 2: + this -> read_model_full_aniso_(filename); + break; + default: + printf("SWD_TYPE should in [0,1,2]"); + printf("current SWD_TYPE = %d\n",SWD_TYPE); + exit(1); + } +} + +static bool +check_fluid_c21(const float *c21) +{ + bool flag = true; + float c0 = c21[0]; + flag = flag & (c0 > 0); + for(int i = 2; i < 21; i ++) { + if(i == 1 || i == 6 || i == 11 ) { + flag = flag && (c21[i] == c0); + } + else if(i == 2 || i == 7) { + flag = flag && (c21[i] == 2 * c0); + } + else { + flag = flag && (c21[i] == 0.); + } + } + + return flag; + +} + +void SolverSEM:: +create_model_attributes() +{ + // first check discontinuities + region_bdry.resize(0); + region_bdry.reserve(10); + int ndis = 0; + int ipt0 = 0,ipt1 = 0; + for(int i = 1; i < nz_; i ++) { + if(depth_[i] == depth_[i-1]) { + ndis += 1; + ipt1 = i-1; + + // add to region_bdry + region_bdry.push_back(ipt0); + region_bdry.push_back(ipt1); + ipt0 = ipt1 + 1; + } + } + + // check a discontinuity is add to half space + if(region_bdry[region_bdry.size() - 1] != nz_ - 2) { + printf("Please add a discontinuity at half space !\n"); + exit(1); + } + + // half space is another region + region_bdry.push_back(nz_-1); + region_bdry.push_back(nz_-1); + nregion_ = region_bdry.size() / 2; + + // now check where the fluid is + std::vector is_ac_pts; + is_ac_pts.resize(nz_); + for(int i = 0; i < nz_; i ++) { + is_ac_pts[i] = 0; + if(SWD_TYPE == 0) { // Love + if(vsh_[i] < 1.0e-6 || vsv_[i] < 1.0e-6) { + printf("Love wave cannot exist in fluid layers!\n"); + printf("current velocity vsv = %f vsh = %f\n",vsv_[i],vsh_[i]); + exit(1); + } + } + else if(SWD_TYPE == 1) { // Rayleigh + if(vsv_[i] < 1.0e-6) { + is_ac_pts[i] = 1; + + // check if vpv == vph || Qvpv == Qvph + bool flag = vpv_[i] == vph_[i]; + if(HAS_ATT) flag = flag &(QC_[i] == QA_[i]); + if(!flag) { + printf("vpv and vph should be same in fluid layers\n"); + printf("current velocity vpv = %f vph = %f\n",vpv_[i],vph_[i]); + printf("current velocity Qvpv = %f Qvph = %f\n",QC_[i],QA_[i]); + exit(1); + } + } + } + else { // full aniso + float temp_c21[21], temp_Qc21[21]; + for(int j = 0; j < 21; j ++) { + temp_c21[j] = c21_[j*21+i]; + } + bool flag = check_fluid_c21(temp_c21); + + if(HAS_ATT) { + for(int j = 0; j < 21; j ++) { + temp_Qc21[j] = Qc21_[j*21+i]; + } + flag = flag && check_fluid_c21(temp_Qc21); + } + + if(flag) { + is_ac_pts[i] = 1; + } + } + } + + // allocate material flag + allocate(nregion_,is_ac_reg,is_el_reg); + + // check if all points in a region is fluid/elastic only + for(int ig = 0; ig < nregion_; ig ++) { + int startid = region_bdry[ig*2+0]; + int endid = region_bdry[ig*2+1]; + bool flag = is_ac_pts[startid]; + for(int i = startid+1; i <= endid; i ++) { + if(flag != is_ac_pts[i]) { + printf("in one region, you can only have one material !\n"); + printf("Problem region %d, index= %d - %d",ig,startid,endid); + exit(1); + } + } + + // set flag + is_ac_reg[ig] = is_ac_pts[startid]; + is_el_reg[ig] = !is_ac_pts[startid]; + } +} + +void SolverSEM:: +print_model() const +{ + printf("\n====================================\n"); + printf("========= Model Description ========\n"); + printf("====================================\n\n"); + + std::string outinfo = "elastic"; + if(HAS_ATT) { + outinfo = "visco-elastic"; + } + + if(SWD_TYPE == 0) { // love wave + printf("compute dispersions for %s Love wave\n",outinfo.c_str()); + } + else if(SWD_TYPE == 1) { // rayleigh wave + printf("compute dispersions for %s Rayleigh wave\n",outinfo.c_str()); + } + else { + printf("compute dispersions for %s fully anisotropic wave\n",outinfo.c_str()); + } + + for(int ig = 0; ig < nregion_; ig ++) { + if(ig == nregion_ - 1) { + printf("\nhalf space begin at depth = %f\n",depth_[nz_ - 1]); + } + printf("\nregion %d:\n",ig + 1); + printf("=======================\n"); + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + + if(SWD_TYPE == 0) { + printf("depth\t rho\t vsh\t vsv (QN QL)\t \n"); + for(int i = istart; i <= iend; i ++) { + printf("%f %f %f %f", + depth_[i],rho_[i], vsh_[i],vsv_[i]); + if(HAS_ATT) { + printf(" %f %f\n",QN_[i],QL_[i]); + } + else { + printf("\n"); + } + } + } + else if (SWD_TYPE == 1) { + printf("depth\t rho\t vph\t vpv\t vsv\t eta (Qvpv Qvph Qvsv)\n"); + for(int i = istart; i <= iend; i ++) { + printf("%f %f %f %f %f", + depth_[i],rho_[i], vph_[i],vpv_[i],vsv_[i]); + if(HAS_ATT) { + printf(" %f %f %f\n",QA_[i],QC_[i],QL_[i]); + } + else { + printf("\n"); + } + } + } + else { + + } + } +} + +void SolverSEM:: +print_database() const +{ + + // print SEM mesh information for debug + printf("\n====================================\n"); + printf("========= DATABASE Description ========\n"); + printf("====================================\n\n"); + + printf("elements:\n"); + printf("=========================\n"); + printf("no. of nelemnts = %d\n",nspec + nspec_grl); + printf("no. of elastic GLL/GRL nelemnts = %d %d\n",nspec_el,nspec_el_grl); + printf("no. of acoustic GLL/GRL nelemnts = %d %d\n",nspec_ac,nspec_ac_grl); + printf("no. of elastic wavefield points = %d\n",nglob_el); + printf("no. of acoustic wavefield points = %d\n",nglob_ac); + + printf("\nSimulation parameters:\n"); + printf("=========================\n"); + printf("phase velocity min/max = %f %f\n",PHASE_VELOC_MIN,PHASE_VELOC_MAX); + + printf("\nElastic-Acoustic Boundary:\n"); + printf("=========================\n"); + printf("no. of E-A boundaries = %d\n",nfaces_bdry); + for(int iface = 0; iface < nfaces_bdry; iface ++) { + int ispec_ac = ispec_bdry[iface * 2 + 0]; + int ispec_el = ispec_bdry[iface * 2 + 1]; + printf("boundary %d:\n",iface); + printf("\tispec_ac = %d ispec_el = %d\n",ispec_ac,ispec_el); + int top_is_fluid = bdry_norm_direc[iface]; + printf("top material is fluid = %d\n",top_is_fluid); + } + +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/main_love.cpp b/bak/src.bak/solver.bak/main_love.cpp new file mode 100644 index 0000000..4c621c0 --- /dev/null +++ b/bak/src.bak/solver.bak/main_love.cpp @@ -0,0 +1,181 @@ +#include "solver/solver.hpp" +#include "GQTable.hpp" +#include "swdio.hpp" + +#include +#include + +int main (int argc, char **argv){ + // read model name + if(argc != 5) { + printf("Usage: ./surflove modelfile f1 f2 nt\n"); + printf("freqs = logspace(log10(f1),log10(f2),nt)\n"); + exit(1); + } + + // initialize GLL + GQTable:: initialize(); + + // read model + const char *filename = argv[1]; + SolverSEM sol; + sol.read_model(filename); + sol.create_model_attributes(); + int nz = sol.tomo_size(); + + // check if it's love wave + if(sol.SWD_TYPE != 0) { + printf("THis module can only handle love wave!\n"); + exit(1); + } + + // print info to debug + sol.print_model(); + + // Period + int nt; + float f1,f2; + sscanf(argv[2],"%g",&f1); sscanf(argv[3],"%g",&f2); + sscanf(argv[4],"%d",&nt); + f1 = std::log10(f1); f2 = std::log10(f2); + if(f1 > f2) std::swap(f1,f2); + std::vector freq(nt); + for(int it = 0; it < nt; it ++) { + double coef = (nt - 1); + if(coef == 0.) coef = 1.; + coef = 1. / coef; + double f = f1 + (f2 - f1) * coef * it; + freq[it] = std::pow(10,f); + } + + // create output dir + if(!std::filesystem::exists("out/")) + std::filesystem::create_directory("out/"); + + // open file to write out data + FILE *fp = fopen("out/swd.txt","w"); + FILE *fio = fopen("out/database.bin","wb"); +#ifdef SPEC_DEBUG + FILE *fdb = fopen("mesh.bin","wb"); +#endif + for(int it = 0; it < nt; it ++) { + fprintf(fp,"%g ",1. / freq[it]); + } + fprintf(fp,"\n"); + + // write meta data int database + int nkers = 3,ncomp = 1; + write_binary_f(fio,&sol.SWD_TYPE,1); + write_binary_f(fio,&sol.HAS_ATT,1); + if(sol.HAS_ATT) { + nkers = 5; + } + write_binary_f(fio,&nz,1); + write_binary_f(fio,&nkers,1); + write_binary_f(fio,&ncomp,1); + + // compute phase velocity for each frequency + typedef std::complex dcmplx; + for(int it = 0; it < nt; it ++) { + // create database + sol.create_database(freq[it],0.); + + // write coordinates + write_binary_f(fio,sol.znodes.data(),sol.znodes.size()); + +#ifdef SPEC_DEBUG + // write mesh + using namespace GQTable; + write_binary_f(fdb,sol.ibool_el.data(),sol.ibool_el.size()); + write_binary_f(fdb,sol.jaco.data(),sol.jaco.size()); + write_binary_f(fdb,sol.xN.data(),sol.xN.size()); + write_binary_f(fdb,sol.xQN.data(),sol.xQN.size()); + write_binary_f(fdb,wgll.data(),wgll.size()); + write_binary_f(fdb,wgrl.data(),wgrl.size()); +#endif + + // get database dimension + int ng = sol.nglob_el; + + if(!sol.HAS_ATT) { + std::vector c,egn,u,frekl; + std::vector frekl_tomo; + std::vector displ; + sol.compute_slegn(freq[it],c,egn,true); + + // allocate group velocity + int nc = c.size(); + u.resize(nc); + + for(int ic = 0; ic < nc; ic ++) { + u[ic] = sol.compute_love_kl(freq[it],c[ic],&egn[ic*ng],frekl); + + // write T,c,u,mode + fprintf(fp,"%d %g %g %d\n",it,c[ic],u[ic],ic); + + // write displ + displ.resize(sol.ibool_el.size()); + sol.egn2displ_vti(freq[it],c[ic],&egn[ic*ng],displ.data()); + write_binary_f(fio,displ.data(),displ.size()); + + // transform kernels + sol.transform_kernels(frekl); + frekl_tomo.resize(nkers*nz); + int npts = sol.ibool_el.size(); + for(int iker = 0; iker < nkers; iker ++) { + sol.project_kl(&frekl[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + } + } + else { + std::vector c,egn,legn,u; + std::vector frekl_c,frekl_q; + std::vector frekl_tomo; + std::vector displ; + sol.compute_slegn_att(freq[it],c,egn,true); + + // allocate group velocity + int nc = c.size(); + u.resize(nc); + + for(int ic = 0; ic < nc; ic ++) { + u[ic] = sol.compute_love_kl_att(freq[it],c[ic],&egn[ic*ng],frekl_c,frekl_q); + + // write T,c,u,mode + fprintf(fp,"%d %g %g %g %g %d\n",it,c[ic].real(),c[ic].imag(), + u[ic].real(),u[ic].imag(),ic); + + // write displ + displ.resize(sol.ibool_el.size()); + sol.egn2displ_vti_att(freq[it],c[ic],&egn[ic*ng],displ.data()); + write_binary_f(fio,displ.data(),displ.size()); + + // write kernels + sol.transform_kernels(frekl_c); + sol.transform_kernels(frekl_q); + frekl_tomo.resize(nkers*nz); + int npts = sol.ibool_el.size(); + for(int iker = 0; iker < nkers; iker ++) { + sol.project_kl(&frekl_c[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + + for(int iker = 0; iker < nkers; iker ++) { + sol.project_kl(&frekl_q[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + } + } + } + + // close file + fclose(fio); + fclose(fp); + +#ifdef SPEC_DEBUG + fclose(fdb); +#endif + + return 0; +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/sem.cpp b/bak/src.bak/solver.bak/sem.cpp new file mode 100644 index 0000000..266fa31 --- /dev/null +++ b/bak/src.bak/solver.bak/sem.cpp @@ -0,0 +1,538 @@ +#include "solver/solver.hpp" +#include "GQTable.hpp" +#include "shared/attenuation.hpp" + +typedef std::complex dcmplx; +using std::vector; + +template +static void +prepare_love_mat(double freq,int nspec,int nglob_el,const double *xrho, + const int* ibool_el,const double *jaco,const double *xL, + const double *xN,const double *xQL,const double *xQN, + vector &Mmat,vector &Kmat,vector &Emat) +{ + using namespace GQTable; + std::array sum_terms; + + // allocate space and set zero + int nglob = nglob_el; + Mmat.resize(nglob); Kmat.resize(nglob); + Emat.resize(nglob*nglob); + std::fill(Mmat.begin(),Mmat.end(),0.); + std::fill(Kmat.begin(),Kmat.end(),(T)0); + std::fill(Emat.begin(),Emat.end(),(T)0); + + for(int ispec = 0; ispec < nspec + 1; ispec ++) { + int id = ispec * NGLL; + const double *weight = wgll.data(); + const double *hpT = hprimeT.data(); + int NGL = NGLL; + + // grl case + if(ispec == nspec) { + weight = wgrl.data(); + hpT = hprimeT_grl.data(); + NGL = NGRL; + } + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + T sl = 1.; + if constexpr (std::is_same_v) { + sl = get_sls_modulus_factor(freq,xQL[id+i]); + } + sum_terms[i] = xL[id + i] * sl * weight[i] / jaco[ispec]; + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id + i]; + if(iglob == -1) continue; + + double temp = weight[i] * jaco[ispec]; + T sn = 1.; + if constexpr(std::is_same_v) { + sn = get_sls_modulus_factor(freq,xQN[id+i]); + } + Mmat[iglob] += temp * xrho[id + i]; + Kmat[iglob] += temp * xN[id + i] * sn; + + for(int j = 0; j < NGL; j ++) { + int iglob1 = ibool_el[id + j]; + if(iglob1 == -1) continue; + T s{}; + for(int m = 0; m < NGL; m ++) { + s += sum_terms[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * nglob + iglob1] += s; + } + } + } +} + + +/** + * @brief prepare M/K/E matrices for Love wave, elastic case + * + */ +void SolverSEM:: +prepare_matrices_love_(double freq) +{ + prepare_love_mat(freq,nspec_el,nglob_el,xrho_el.data(),ibool_el.data(), + jaco.data(),xL.data(),xN.data(),nullptr,nullptr, + Mmat,Kmat,Emat); +} + +/** + * @brief prepare M/K/E matrices for Love wave, visco-elastic case, K,E are complex + * + */ +void SolverSEM:: +prepare_matrices_love_att_(double freq) +{ + prepare_love_mat(freq,nspec_el,nglob_el,xrho_el.data(),ibool_el.data(), + jaco.data(),xL.data(),xN.data(),xQL.data(), + xQN.data(),Mmat,CKmat,CEmat); +} + +template +static void +prepare_rayl_mat(double freq,int nspec_el,int nspec_ac, + int nspec_el_grl,int nspec_ac_grl,int nglob_el,int nglob_ac, + const int *el_elmnts,const int *ac_elmnts, + const double *xrho_el,const double *xrho_ac, + const int* ibool_el, const int* ibool_ac,const double *jaco, + const double *xA,const double *xC,const double *xL,const double *xeta, + const double *xQA, const double *xQC, const double *xQL, + const double *xkappa_ac, const double *xQk_ac,int nfaces_bdry, + const int* ispec_bdry,const char *bdry_norm_direc,vector &Mmat, + vector &Kmat,vector &Emat) +{ + // allocate space and set zero + int ng = nglob_ac + nglob_el * 2; + Mmat.resize(ng); + Emat.resize(ng * ng); + Kmat.resize(ng * ng); + std::fill(Mmat.begin(),Mmat.end(),(T)0.); + std::fill(Emat.begin(),Emat.end(),(T)0.); + std::fill(Kmat.begin(),Kmat.end(),(T)0.); + + // compute M/K/E for gll/grl layer, elastic + using namespace GQTable; + std::array A,L,C,F; + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id = ispec * NGLL; + const double *weight = wgll.data(); + const double *hpT = hprimeT.data(); + const double *hp = hprime.data(); + int NGL = NGLL; + + // jacobian + double J = jaco[iel]; + + // grl case + if(ispec == nspec_el) { + weight = wgrl.data(); + hpT = hprimeT_grl.data(); + hp = hprime_grl.data(); + NGL = NGRL; + } + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + T sl = 1.,sa = 1.,sc = 1.; + if constexpr (std::is_same_v) { + sl = get_sls_modulus_factor(freq,xQL[id+i]); + sa = get_sls_modulus_factor(freq,xQA[id+i]); + sc = get_sls_modulus_factor(freq,xQC[id+i]); + } + // C[i] = xC[id + i] * weight[i] / jaco[iel]; + // L[i] = xL[id + i] * weight[i] / jaco[iel]; + C[i] = xC[id+i] * sc; + L[i] = xL[id+i] * sl; + A[i] = xA[id+i] * sa; + F[i] = xeta[id+i] * (A[i] - 2. * L[i]); + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id + i]; + T temp = weight[i] * J; + + // element wise M/K1/K3 + T M0 = temp * xrho_el[id + i]; + T K1 = temp * A[i]; + T K3 = temp * L[i]; + + // assemble + Mmat[iglob] += M0; + Mmat[iglob + nglob_el] += M0; + Kmat[iglob * ng + iglob] += K1; + Kmat[(nglob_el + iglob) * ng + (nglob_el + iglob)] += K3; + + // other matrices + for(int j = 0; j < NGL; j ++) { + int iglob1 = ibool_el[id + j]; + T E1{},E3{}; + for(int m = 0; m < NGL; m ++) { + E1 += L[m] * weight[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + E3 += C[m] * weight[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * ng + iglob1] += E1 / J; + Emat[(iglob + nglob_el) * ng + (iglob1 + nglob_el)] += E3 / J; + + // K2/E2 + T K2 = weight[j] * F[j] * hpT[i * NGL + j] - + weight[i] * L[i] * hp[i * NGL + j]; + T E2 = weight[i] * F[i] * hp[i * NGL + j] - + weight[j] * L[j] * hpT[i * NGL + j]; + Kmat[(nglob_el + iglob) * ng + iglob1] += K2; + Emat[iglob * ng + nglob_el + iglob1] += E2; + } + } + } + + // acoustic case + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { + int iel = ac_elmnts[ispec]; + int id = ispec * NGLL; + const double *weight = wgll.data(); + const double *hpT = hprimeT.data(); + int NGL = NGLL; + + // jacobian + double J = jaco[iel]; + + // grl case + if(ispec == nspec_ac) { + weight = wgrl.data(); + hpT = hprimeT_grl.data(); + NGL = NGRL; + } + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + L[i] = weight[i] / (J * xrho_ac[id+i]); + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int ig0 = ibool_ac[id + i]; + if(ig0 == -1) continue; + int iglob = ig0 + nglob_el * 2; + T temp = weight[i] * J; + + + // assemble M and K + T sk = 1.; + if constexpr (std::is_same_v) { + sk = get_sls_modulus_factor(freq,xQk_ac[id+i]); + } + Mmat[iglob] += temp / (sk * xkappa_ac[id + i]); + Kmat[iglob * ng + iglob] += temp / xrho_ac[id + i]; + + // assemble E + for(int j = 0; j < NGL; j ++) { + int ig1 = ibool_ac[id + j]; + if(ig1 == -1) continue; + int iglob1 = ig1 + nglob_el * 2; + T s{}; + for(int m = 0; m < NGL; m ++) { + s += L[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * ng + iglob1] += s; + } + } + } + + // acoustic-elastic boundary + double om = M_PI * 2 * freq; + for(int iface = 0; iface < nfaces_bdry; iface ++) { + int ispec_ac = ispec_bdry[iface * 2 + 0]; + int ispec_el = ispec_bdry[iface * 2 + 1]; + T norm = -1.; + int igll_el = 0; + int igll_ac = NGLL - 1; + if(!bdry_norm_direc[iface]) { + norm = 1.; + igll_ac = 0; + igll_el = NGLL - 1; + } + + // get ac/el global loc + int iglob_el = ibool_el[ispec_el * NGLL + igll_el]; + int iglob_ac = ibool_ac[ispec_ac * NGLL + igll_ac]; + + // add contribution to E mat, elastic case + // E(nglob_el + iglob_el, nglob_el*2 + iglob_ac) += + int id = (nglob_el*2 + iglob_el) * ng + (nglob_el * 3 + iglob_ac); + Emat[id] += (T)(om * om * norm); + + // acoustic case + // E(nglob_el*2 + iglob_ac, nglob_el + iglob_el) += norm + id = (nglob_el*3 + iglob_ac) * ng + (nglob_el*2 + iglob_el); + Emat[id] += (T)norm; + } +} + +void SolverSEM:: +prepare_matrices_rayl_(double freq) +{ + prepare_rayl_mat(freq,nspec_el,nspec_ac, + nspec_el_grl,nspec_ac_grl,nglob_el,nglob_ac, + el_elmnts.data(),ac_elmnts.data(), + xrho_el.data(),xrho_ac.data(),ibool_el.data(), + ibool_ac.data(),jaco.data(),xA.data(),xC.data(),xL.data(), + xeta.data(),nullptr,nullptr,nullptr,xkappa_ac.data(), + nullptr,nfaces_bdry,ispec_bdry.data(),bdry_norm_direc.data(), + Mmat,Kmat,Emat); +} + + +void SolverSEM:: +prepare_matrices_rayl_att_(double freq) +{ + prepare_rayl_mat(freq,nspec_el,nspec_ac, + nspec_el_grl,nspec_ac_grl,nglob_el,nglob_ac, + el_elmnts.data(),ac_elmnts.data(), + xrho_el.data(),xrho_ac.data(),ibool_el.data(), + ibool_ac.data(),jaco.data(),xA.data(),xC.data(),xL.data(), + xeta.data(),xQA.data(),xQC.data(),xQL.data(),xkappa_ac.data(), + xQk_ac.data(),nfaces_bdry,ispec_bdry.data(),bdry_norm_direc.data(), + CMmat,CKmat,CEmat); +} + +const int voigt_index[3][3] = { + {0, 5, 5}, // (1,1) -> 1, (1,2) -> 6, (1,3) -> 5 + {5, 1, 3}, // (2,1) -> 6, (2,2) -> 2, (2,3) -> 4 + {4, 3, 2} // (3,1) -> 5, (3,2) -> 4, (3,3) -> 3 +}; + + +static int Index(int i,int j,int k, int l) +{ + int m = voigt_index[i][j]; + int n = voigt_index[k][l]; + if(m > n) { + std::swap(m,n); + } + int idx = m * 6 + n - (m * (m + 1)) / 2; + + return idx; +} + +template +static void +prepare_aniso_mat(double freq,int nspec_el,int nspec_ac,int nspec_el_grl, + int nspec_ac_grl,int nglob_el,int nglob_ac,int nQmodel, + const int *el_elmnts,const int *ac_elmnts, + const double *xrho_el,const double *xrho_ac, + const int* ibool_el, const int* ibool_ac, + const double *jaco,const double *xc21, + const double *xQani,const double *xkappa_ac, + const double *xQk_ac,int nfaces_bdry, + const int* ispec_bdry,const char *bdry_norm_direc, + double phi,vector &Mmat, + vector &Kmat,vector &Hmat,vector &Emat) +{ + // allocate space and set zero + int ng = nglob_ac + nglob_el * 3; + Mmat.resize(ng); + Emat.resize(ng * ng); + Kmat.resize(ng); Hmat.resize(ng*ng); + std::fill(Mmat.begin(),Mmat.end(),(T)0.); + std::fill(Emat.begin(),Emat.end(),(T)0.); + std::fill(Kmat.begin(),Kmat.end(),(T)0.); + std::fill(Hmat.begin(),Hmat.end(),(T)0.); + + // direction + double k[2] = {std::cos(phi),std::sin(phi)}; + + // temp arrays to save elastic tensor + using namespace GQTable; + const int size_el = nspec_el*NGLL + nspec_el_grl * NGRL; + std::array sumC21; + #define C21(i,j,p,q,a) sumC21[a*NGRL + Index(i,j,p,q)] + + // compute M/K/H/E for gll/grl layer, elastic + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id = ispec * NGLL; + const double *weight = wgll.data(); + const double *hpT = hprimeT.data(); + const double *hp = hprime.data(); + int NGL = NGLL; + double J = jaco[iel]; + + // grl case + if(ispec == nspec_el) { + weight = wgrl.data(); + hpT = hprimeT_grl.data(); + hp = hprime_grl.data(); + NGL = NGRL; + } + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + for(int idx = 0; idx < 21; idx ++) { + sumC21[i*NGRL+idx] = xc21[idx*size_el+i]; + } + + // apply Q model to C21 if required + if constexpr (std::is_same_v) { + std::array Qm; + for(int q = 0; q < nQmodel; q ++) { + Qm[q] = xQani[q*size_el+i]; + } + set_C21_att_model(freq,Qm.data(),nQmodel, + &sumC21[i*NGRL]); + } + + + // add other terms + for(int idx = 0; idx < 21; idx ++) { + sumC21[i*NGRL+idx] *= J * weight[i]; + } + } + + // assemble H/E + for(int a = 0; a < NGL; a ++) { + int iglob = ibool_el[id + a]; + for(int b = 0; b < NGL; b ++) { + int iglob1 = ibool_el[id+b]; + + // loop each component + for(int i = 0; i < 3; i ++) { + for(int p = 0; p < 3; p ++) { + int idx = (i*nglob_el+iglob)*ng+(p*nglob_el+iglob1); + + // E + T sx{}; + for(int s = 0; s < NGL; s ++) { + sx += C21(i,2,p,2,s) * hpT[a*NGL+s] * hpT[b*NGL+s]; + } + Emat[idx] += sx / (J * J); + + // H + T temp1 = C21(i,0,p,2,a) * k[0] + + C21(i,1,p,2,a) * k[1]; + T temp2 = C21(i,2,p,0,b) * k[0] + + C21(i,2,p,1,b) * k[1]; + Hmat[idx] += temp1 * hp[a*NGL+b] - + temp2 * hpT[a*NGL+b]; + }} + } + } + + // compute M/K + for(int a = 0; a < NGL; a ++) { + int iglob = ibool_el[id + a]; + + // compute mass matrix + T M0 = weight[a] * J * xrho_el[id + a]; + for(int i = 0; i < 3; i ++) { + Mmat[iglob + nglob_el * i] += M0; + for(int p = 0; p < 3; p ++) { + T temp = C21(i,0,p,0,a) * k[0] * k[0] + + C21(i,0,p,1,a) * k[0] * k[1] + + C21(i,1,p,0,a) * k[0] * k[1] + + C21(i,1,p,1,a) * k[1] * k[1]; + int idx = (i*nglob_el+iglob) * ng + (p*nglob_el+iglob); + Kmat[idx] += temp; + } + } + } + } + + // acoustic case + std::array sumL; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { + int iel = ac_elmnts[ispec]; + int id = ispec * NGLL; + const double *weight = wgll.data(); + const double *hpT = hprimeT.data(); + int NGL = NGLL; + + // grl case + if(ispec == nspec_ac) { + weight = wgrl.data(); + hpT = hprimeT_grl.data(); + NGL = NGRL; + } + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + sumL[i] = weight[i] / jaco[iel] / xrho_ac[id+i]; + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int ig0 = ibool_ac[id + i]; + if(ig0 == -1) continue; + int iglob = ig0 + nglob_el * 3; + T temp = weight[i] * jaco[iel]; + + // assemble M and K + T sk = 1.; + if constexpr (std::is_same_v) { + sk = get_sls_modulus_factor(freq,xQk_ac[id+i]); + } + Mmat[iglob] += temp / (sk * xkappa_ac[id + i]); + Kmat[iglob * ng + iglob] += temp / xrho_ac[id + i]; + + // assemble E + for(int j = 0; j < NGL; j ++) { + int ig1 = ibool_ac[id + j]; + if(ig1 == -1) continue; + int iglob1 = ig1 + nglob_el * 3; + T s{}; + for(int m = 0; m < NGL; m ++) { + s += sumL[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * ng + iglob1] += s; + } + } + } + + // acoustic-elastic boundary + double om = M_PI * 2 * freq; + for(int iface = 0; iface < nfaces_bdry; iface ++) { + int ispec_ac = ispec_bdry[iface * 2 + 0]; + int ispec_el = ispec_bdry[iface * 2 + 1]; + T norm = -1.; + int igll_el = 0; + int igll_ac = NGLL - 1; + if(!bdry_norm_direc[iface]) { + norm = 1.; + igll_ac = 0; + igll_el = NGLL - 1; + } + + // get ac/el global loc + int iglob_el = ibool_el[ispec_el * NGLL + igll_el]; + int iglob_ac = ibool_ac[ispec_ac * NGLL + igll_ac]; + + // add contribution to E mat, elastic case + // E(nglob_el + iglob_el, nglob_el*2 + iglob_ac) += + int id = (nglob_el*2 + iglob_el) * ng + (nglob_el * 3 + iglob_ac); + Emat[id] += (T)(om * om * norm); + + // acoustic case + // E(nglob_el*2 + iglob_ac, nglob_el + iglob_el) += norm + id = (nglob_el*3 + iglob_ac) * ng + (nglob_el*2 + iglob_el); + Emat[id] += (T)norm; + } + + #undef C21 +} + +void SolverSEM:: +prepare_mat_aniso_(double freq,double phi) +{ + prepare_aniso_mat(freq,nspec_el,nspec_ac,nspec_el_grl,nspec_ac_grl, + nglob_el,nglob_ac,nQmodel_ani,el_elmnts.data(),ac_elmnts.data(), + xrho_el.data(),xrho_ac.data(),ibool_el.data(), + ibool_ac.data(),jaco.data(),xC21.data(),xQani.data(), + xkappa_ac.data(),xQk_ac.data(), + nfaces_bdry,ispec_bdry.data(),bdry_norm_direc.data(), + phi,Mmat,Kmat,Hmat,Emat); +} \ No newline at end of file diff --git a/bak/src.bak/solver.bak/solver.hpp b/bak/src.bak/solver.bak/solver.hpp new file mode 100644 index 0000000..cdff6a0 --- /dev/null +++ b/bak/src.bak/solver.bak/solver.hpp @@ -0,0 +1,174 @@ +#ifndef SPECSWD_SOLVER_H_ +#define SPECSWD_SOLVER_H_ + +#include +#include +#include + +class SolverSEM { + + typedef std::complex dcmplx; + +public: + // GLL/GRL nodes and weight + // SEM Mesh + int nspec,nspec_grl; // no. of elements for gll/grl layer + int nglob; // no. of unique points + std::vector ibool; // connectivity matrix, shape(nspec * NGLL + NGRL) + std::vector skel; // skeleton, shape(nspec * 2 + 2) + std::vector znodes; // shape(nspec * NGLL + NGRL) + std::vector jaco; // jacobian for GLL, shape(nspec + 1) dz / dxi + std::vector zstore; // shape(nglob) + + // element type for each medium + int nspec_ac,nspec_el; + int nspec_ac_grl,nspec_el_grl; + std::vector is_elastic, is_acoustic; + std::vector el_elmnts,ac_elmnts; // elements for each media, shape(nspec_? + nspec_?_grl) + + // unique array for acoustic/elastic + int nglob_ac, nglob_el; + std::vector ibool_el, ibool_ac; // connectivity matrix, shape shape(nspec_? + nspec_?_grl) + + // density and elastic parameters + std::vector xrho_ac; // shape(nspec_ac * NGLL + nspec_ac_grl * NGRL) + std::vector xrho_el; // shape (nsepc_el * NGLL + nspec_el_grl * NGRL) + + // attenuation/type flag + bool HAS_ATT; + int SWD_TYPE; // =0 Love wave, = 1 for Rayleigh = 2 full aniso + + // vti media + std::vector xA,xC,xL,xeta,xN; // shape(nspec_el * NGLL+ nspec_el_grl * NGRL) + std::vector xQA,xQC,xQL,xQN; // shape(nspec_el * NGLL+ nspec_el_grl * NGRL), Q model + + // full anisotropy + int nQmodel_ani; // no. of Q used for anisotropy + std::vector xC21; // shape(21,nspec_el * NGLL+ nspec_el_grl * NGRL) + std::vector xQani; // shape(nQmodel_ani,nspec_el * NGLL+ nspec_el_grl * NGRL) + + // fluid vti + std::vector xkappa_ac,xQk_ac; + + // fluid-elastic boundary + int nfaces_bdry; + std::vector ispec_bdry; // shape(nfaces_bdry,2) (i,:) = [ispec_ac,ispec_el] + std::vector bdry_norm_direc; // shape(nfaces_bdry), = 1 point from acoustic -> z direc elastic + +private: + double PHASE_VELOC_MIN,PHASE_VELOC_MAX; + + int nz_, nregion_; + std::vector rho_; + std::vector vpv_,vph_,vsv_,vsh_,eta_; + std::vector QC_,QA_,QL_,QN_; + std::vector c21_,Qc21_; + std::vector depth_; + std::vector region_bdry; // shape(nregion_,2) + std::vector iregion_flag; // shape(nspec + 1), return region flag + + // interface with layered model + std::vector is_el_reg, is_ac_reg; // shape(nregion_) + + // solver matrices + std::vector Mmat,Emat,Kmat,Hmat; + std::vector CMmat,CEmat,CKmat,CHmat; + + // QZ matrix all are column major + std::vector Qmat_,Zmat_,Smat_,Spmat_; // column major! + std::vector cQmat_,cZmat_,cSmat_,cSpmat_; + + +//functions +public: + SolverSEM(){}; + void read_model(const char *filename); + void create_database(double freq,double phi); + void print_model() const; + void print_database() const; + void allocate_1D_model(int nz0,int swd_type,int has_att); + void create_model_attributes(); + + // 1-D model info + int tomo_size()const {return nz_;} + + // eigenfunction + void compute_slegn(double freq,std::vector &c, + std::vector &displ, + bool use_qz=false); + void compute_slegn_att(double freq,std::vector &c, + std::vector &displ, + bool use_qz=false); + void compute_sregn(double freq,std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz = false); + void compute_sregn_att(double freq,std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz = false); + + void compute_egn_aniso(double freq,std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz = false); + void compute_egn_aniso_att(double freq,std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz = false); + + // group velocity + double get_group_vti(double freq,double c,const double *legn,const double *regn) const; + + // group velocity and phase velocity kernels + double compute_love_kl(double freq,double c,const double *displ, std::vector &frekl) const; + dcmplx compute_love_kl_att(double freq,dcmplx c,const dcmplx *displ, + std::vector &frekl_c, + std::vector &frekl_q) const; + double compute_rayl_kl(double freq,double c,const double *displ, + const double *ldispl, std::vector &frekl) const; + dcmplx compute_rayl_kl_att(double freq,dcmplx c,const dcmplx *displ, + const dcmplx *ldispl, + std::vector &frekl_c, + std::vector &frekl_q) const; + + // group velocity kernels + void compute_love_group_kl(double freq,double c,const double *displ, std::vector &frekl) const; + + void interp_model(const float *param,const std::vector &elmnts,std::vector &md) const; + void project_kl(const double *frekl, double *kl_out) const; + + // transformation + void egn2displ_vti(double freq,double c,const double *egn, + double * __restrict displ) const; + void egn2displ_vti_att(double freq,dcmplx c,const dcmplx *egn, + dcmplx * __restrict disp) const; + void egn2displ_aniso(double freq,dcmplx c,double phi,const dcmplx *egn, + dcmplx * __restrict disp) const; + void transform_kernels(std::vector &frekl) const; + +private: + void create_material_info_(); + + // 1-D model + void read_model_header_(const char *filename); + void read_model_love_(const char *filename); + void read_model_rayl_(const char *filename); + void read_model_full_aniso_(const char *filename); + + // create SEM database + void compute_minmax_veloc_(double phi,std::vector &vmin,std::vector &vmax); + void create_db_love_(double freq); + void create_db_rayl_(double freq); + void create_db_aniso_(double freq); + + // eigenvalue part + void prepare_matrices_love_(double freq); + void prepare_matrices_love_att_(double freq); + void prepare_matrices_rayl_(double freq); + void prepare_matrices_rayl_att_(double freq); + void prepare_mat_aniso_(double freq,double phi); + +}; + +#endif \ No newline at end of file diff --git a/bak/src.bak/solver.bak/transform.cpp b/bak/src.bak/solver.bak/transform.cpp new file mode 100644 index 0000000..fc33899 --- /dev/null +++ b/bak/src.bak/solver.bak/transform.cpp @@ -0,0 +1,460 @@ +#include "solver/solver.hpp" +#include "GQTable.hpp" + +template +void egn2displ_love_(int nspec,const int *ibool_el,const T *egn, + T * __restrict displ) +{ + using namespace GQTable; + for(int ispec = 0; ispec < nspec + 1; ispec ++) { + int NGL = NGLL; + if(ispec == nspec) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[ispec*NGLL+i]; + displ[ispec*NGLL+i] = (iglob!=-1) ?egn[iglob] : 0; + } + } +} + + +template +void egn2displ_rayl_(int nspec_el,int nspec_ac,int nspec_el_grl,int nspec_ac_grl, + int nglob_el,int nglob_ac,const double* jaco,const int *ibool_el, + const int *ibool_ac, const int *el_elmnts, + const int *ac_elmnts,const double *xrho_ac, + const T *egn, double freq,T c, T * __restrict displ) +{ + + // get wave number + T k = 2 * M_PI * freq / c; + + // size + using namespace GQTable; + int npts = (nspec_el + nspec_ac) * NGLL + (nspec_ac_grl + nspec_el_grl) * NGRL; + + // loop elastic elements + for(int ispec = 0; ispec < nspec_el+nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + int NGL = NGLL; + + // grl case + if(ispec == nspec_el) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id0+i]; + displ[0*npts + id1+i] = egn[iglob]; + displ[1*npts + id1+i] = egn[iglob + nglob_el] / k; // this is V\bar = kV + } + } + + // loop each acoustic element + std::array chi; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec += 1) { + int iel = ac_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + const double *hp = &hprime[0]; + const double J = jaco[iel]; + + // GRL layer + if(ispec == nspec_ac) { + NGL = NGRL; + hp = &hprime_grl[0]; + } + + // cache chi in an element + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int iglob = ibool_ac[id]; + chi[i] = (iglob == -1) ? (T)0.: egn[nglob_el * 2 + iglob] / k; + } + + + // compute derivative dchi / dz + for(int i = 0; i < NGL; i ++) { + T dchi{}; + for(int j = 0; j < NGL; j ++) { + dchi += chi[j] * hp[i * NGL + j]; + } + dchi /= J; + + // set value to displ + displ[0*npts + id1+i] = k / xrho_ac[id0 + i] * chi[i]; + displ[1*npts + id1+i] = dchi / xrho_ac[id0 + i]; + } + } + +} + +void SolverSEM:: +egn2displ_vti(double freq,double c,const double *egn, double * __restrict displ) const +{ + switch (SWD_TYPE) + { + case 0: + egn2displ_love_(nspec,ibool_el.data(),egn,displ); + break; + case 1: + egn2displ_rayl_(nspec_el,nspec_ac,nspec_el_grl,nspec_ac_grl, + nglob_el,nglob_ac,jaco.data(),ibool_el.data(),ibool_ac.data(), + el_elmnts.data(),ac_elmnts.data(),xrho_ac.data(), + egn,freq,c,displ); + break; + default: + printf("this function is only for VTI case!\n"); + exit(1); + break; + } +} + +void SolverSEM:: +egn2displ_vti_att(double freq,dcmplx c,const dcmplx *egn, dcmplx * __restrict displ) const +{ + switch (SWD_TYPE) + { + case 0: + egn2displ_love_(nspec,ibool_el.data(),egn,displ); + break; + case 1: + egn2displ_rayl_(nspec_el,nspec_ac,nspec_el_grl,nspec_ac_grl, + nglob_el,nglob_ac,jaco.data(),ibool_el.data(),ibool_ac.data(), + el_elmnts.data(),ac_elmnts.data(),xrho_ac.data(), + egn,freq,c,displ); + break; + default: + printf("this function is only for VTI case!\n"); + exit(1); + break; + } +} + + +void SolverSEM:: +egn2displ_aniso(double freq,dcmplx c,double phi,const dcmplx *egn, + dcmplx * __restrict displ) const +{ + + // get wave number + dcmplx wavnum = 2 * M_PI * freq / c; + dcmplx k[2] = {wavnum * std::cos(phi),wavnum * std::sin(phi)}; + + // size + using namespace GQTable; + int npts = (nspec_el + nspec_ac) * NGLL + (nspec_ac_grl + nspec_el_grl) * NGRL; + + // loop elastic elements + for(int ispec = 0; ispec < nspec_el+nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + int NGL = NGLL; + + // grl case + if(ispec == nspec_el) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id0+i]; + for(int j = 0; j < 3; j ++) { + displ[j*npts + id1+i] = egn[iglob + nglob_el*j]; + } + } + } + + // loop each acoustic element + std::array chi; + const dcmplx I = {0,1.}; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec += 1) { + int iel = ac_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + const double *hp = &hprime[0]; + const double J = jaco[iel]; + + // GRL layer + if(ispec == nspec_ac) { + NGL = NGRL; + hp = &hprime_grl[0]; + } + + // cache chi in an element + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int iglob = ibool_ac[id]; + chi[i] = (iglob == -1) ? 0.: egn[nglob_el * 3 + iglob]; + } + + + // compute derivative dchi / dz + for(int i = 0; i < NGL; i ++) { + dcmplx dchi{}; + for(int j = 0; j < NGL; j ++) { + dchi += chi[j] * hp[i * NGL + j]; + } + dchi /= J; + + // set value to displ + displ[0*npts + id1+i] = -I * k[0] / xrho_ac[id0 + i] * chi[i]; + displ[1*npts + id1+i] = -I * k[1] / xrho_ac[id0 + i] * chi[i]; + displ[2*npts + id1+i] = dchi / xrho_ac[id0 + i]; + } + } +} + +static void +check_kernel_size(const std::vector &frekl,int npts, + int SWD_TYPE, bool HAS_ATT,int nQmodel) +{ + int nker = frekl.size() / npts; + int nker0 = 0; + if(SWD_TYPE == 0) { + nker0 = 3; + if(HAS_ATT) nker0 = 5; + } + else if(SWD_TYPE == 1) { + nker0 = 6; + if(HAS_ATT) nker0 = 10; + } + else { + nker0 = 23; // 21 (elastic) + 1(acoustic) + rho + if(HAS_ATT) { + nker0 = 23 + nQmodel + 1; + } + } + + if(nker0 != nker) { + printf("target/current number of kernels = %d %d\n",nker0,nker); + printf("please check the size of frekl!\n"); + exit(1); + } +} + +/** + * @brief transform modulus kernel to velocity kernel + * @param frekl frechet kernels, the shape depends on: + * - `1`: elastic love wave: N/L/rho -> vsh/vsv/rho + * - `2`: anelastic love wave: N/L/QNi/QLi/rho -> vsh/vsv/QNi/QLi/rho + * - `3`: elastic rayleigh wave: A/C/L/eta/kappa/rho -> vph/vpv/vsv/eta/vp/rho + * - `4`: anelastic rayleigh wave: A/C/L/eta/QAi/QCi/QLi/kappa/Qki/rho -> vph/vpv/vsv/eta/QAi/QCi/QLi/vp/Qki/rho + */ +void SolverSEM:: +transform_kernels(std::vector &frekl) const +{ + using namespace GQTable; + int npts = nspec * NGLL + NGRL; + + // check kenrel size + check_kernel_size(frekl,npts,SWD_TYPE,HAS_ATT,nQmodel_ani); + + if(SWD_TYPE == 0) { + + for(int ipt = 0; ipt < npts; ipt ++) { + double N_kl,L_kl,rho_kl; + N_kl = frekl[0 * npts + ipt]; + L_kl = frekl[1 * npts + ipt]; + + int i = 2; + if(HAS_ATT) i =4; + rho_kl = frekl[i * npts + ipt]; + + // get variables + double L = xL[ipt], N = xN[ipt], rho = xrho_el[ipt]; + double vsh = std::sqrt(N / rho), vsv = std::sqrt(L / rho); + + // transform kernels + double vsh_kl = 2. * rho * vsh * N_kl, vsv_kl = 2. * rho * vsv * L_kl; + double r_kl = vsh * vsh * N_kl + + vsv * vsv * L_kl + rho_kl; + + // copy back to frekl array + frekl[0 * npts + ipt] = vsh_kl; + frekl[1 * npts + ipt] = vsv_kl; + frekl[i * npts + ipt] = r_kl; + } + } + else if (SWD_TYPE == 1) { + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec += 1) { + int iel = el_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + + // GRL layer + if(ispec == nspec_el) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int ipt = iel * NGLL + i; + double A_kl{},C_kl{}, L_kl{}, rho_kl{}; + + // loc of rho + int loc = 5; + if(HAS_ATT) loc = 9; + + // kernels + A_kl = frekl[0 * npts + ipt]; + C_kl = frekl[1 * npts + ipt]; + L_kl = frekl[2 * npts + ipt]; + rho_kl = frekl[loc * npts + ipt]; + + // compute vph/vpv/vsh/vsv/ + double rho = xrho_el[ipt]; + double vph = std::sqrt(xA[id] / rho); + double vpv = std::sqrt(xC[id] / rho); + double vsv = std::sqrt(xL[id] / rho); + + double vph_kl = 2. * rho * vph * A_kl; + double vpv_kl = 2. * rho * vpv * C_kl; + double vsv_kl = 2. * rho * vsv * L_kl; + double r_kl = vph * vph * A_kl + vpv * vpv * C_kl + + + vsv * vsv * L_kl + rho_kl; + frekl[0 * npts + ipt] = vph_kl; + frekl[1 * npts + ipt] = vpv_kl; + frekl[2 * npts + ipt] = vsv_kl; + frekl[loc * npts + ipt] = r_kl; + } + } + + // acoustic domain + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec += 1) { + int iel = ac_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + + // GRL layer + if(ispec == nspec_ac) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int ipt = iel * NGLL + i; + + // kernels + double kappa_kl{}, rho_kl{}; + + // loc + int loc_k = 4, loc_r = 5; + if(HAS_ATT) { + loc_k = 7; + loc_r = 9; + } + + // modulus kernels + kappa_kl = frekl[loc_k * npts + ipt]; + rho_kl = frekl[loc_r * npts + ipt]; + + // velocity + double rho = xrho_el[id]; + double vp = std::sqrt(xkappa_ac[id] / rho); + + //velocity kernels + double vp_kl = 2. * rho* vp * kappa_kl; + double r_kl = vp * vp * kappa_kl + rho_kl; + frekl[loc_k * npts + ipt] = vp_kl; + frekl[loc_r * npts + ipt] = r_kl; + } + } + } +} + + +/** + * @brief find location of z0 in ascending list z + * + * @param z depth list, shape(nlayer) + * @param z0 current loc, must be inside z + * @param nlayer + * @return int location of z0 in z, satisfies z0 >= z[i] && z0 < z[i + 1] + */ +static int +find_loc(const float *z,float z0,int nz) +{ + + int i = 0; + while(i < nz - 1) { + if(z0 >= z[i] && z0 < z[i + 1]) { + break; + } + i += 1; + } + + return i; +} + +/** + * @brief project kernels to original 1-D model + * @param frekl derivatives, shape(nspec*NGLL+NGRL) + * @param kl_out derivatives on original 1-Dmodel, shape(nz_) + */ +void SolverSEM:: +project_kl(const double *frekl, double *kl_out) const +{ + using GQTable :: NGLL; using GQTable :: NGRL; + + // zero out kl_out + for(int i = 0; i < nz_; i ++) kl_out[i] = 0.; + + // loop every region + for(int ireg = 0; ireg < nregion_; ireg ++) { + int istart = region_bdry[ireg*2]; + int iend = region_bdry[ireg*2+1]; + int npts = iend - istart + 1; + + // choose domain + const int *mat_elmnts = nullptr; + int nel = 0; + for(int im = 0; im < 2; im ++) { + if(im == 0) { + nel = nspec_el + nspec_el_grl; + mat_elmnts = el_elmnts.data(); + } + else { + nel = nspec_ac + nspec_ac_grl; + mat_elmnts = ac_elmnts.data(); + } + + // elastic region + for(int ispec_md = 0; ispec_md < nel; ispec_md ++) { + int ispec = mat_elmnts[ispec_md]; + if(ireg != iregion_flag[ispec]) continue; + + // check if GRL + int NGL = NGLL; + if(ispec == nspec) { + NGL = NGRL; + } + + // find interpolate points + for(int i = 0; i < NGL; i ++) { + double z0 = znodes[ispec * NGLL + i]; + int id = ispec * NGLL + i; + + // find loc in this region + int j = find_loc(&depth_[istart],z0,npts) + istart; + if(j < istart || j >= iend) { + j = j < istart ? istart : iend; + kl_out[j] += frekl[id]; + } + else { + float dz = depth_[j + 1] - depth_[j]; + float coef = (z0 - depth_[j]) / dz; + kl_out[j] += (1 - coef) * frekl[id]; + kl_out[j+1] += coef * frekl[id]; + } + } + } + } + } +} \ No newline at end of file diff --git a/bak/src.bak/vti/CMakeLists.txt b/bak/src.bak/vti/CMakeLists.txt new file mode 100644 index 0000000..cfc8366 --- /dev/null +++ b/bak/src.bak/vti/CMakeLists.txt @@ -0,0 +1,8 @@ +file(GLOB SOURCE "*.cpp") +list(FILTER SOURCE EXCLUDE REGEX "main_vti.cpp") + +add_library(libvti ${SOURCE}) + +# exe +add_executable(surfvti ${PROJECT_SOURCE_DIR}/src/vti/main_vti.cpp) +target_link_libraries(surfvti libvti shared ${LAPACK_LIBRARIES}) \ No newline at end of file diff --git a/src/vti/main_vti.cpp b/bak/src.bak/vti/main_vti.cpp similarity index 100% rename from src/vti/main_vti.cpp rename to bak/src.bak/vti/main_vti.cpp diff --git a/src/vti/sem_vti.cpp b/bak/src.bak/vti/sem_vti.cpp similarity index 100% rename from src/vti/sem_vti.cpp rename to bak/src.bak/vti/sem_vti.cpp diff --git a/src/vti/swdlayervti.cpp b/bak/src.bak/vti/swdlayervti.cpp similarity index 100% rename from src/vti/swdlayervti.cpp rename to bak/src.bak/vti/swdlayervti.cpp diff --git a/src/vti/swdlayervti.hpp b/bak/src.bak/vti/swdlayervti.hpp similarity index 100% rename from src/vti/swdlayervti.hpp rename to bak/src.bak/vti/swdlayervti.hpp diff --git a/src/vti/vti_kernels.cpp b/bak/src.bak/vti/vti_kernels.cpp similarity index 100% rename from src/vti/vti_kernels.cpp rename to bak/src.bak/vti/vti_kernels.cpp diff --git a/bin/surflove b/bin/surflove new file mode 100755 index 0000000..9e871b5 Binary files /dev/null and b/bin/surflove differ diff --git a/bin/surfrayl b/bin/surfrayl new file mode 100755 index 0000000..aa169ee Binary files /dev/null and b/bin/surfrayl differ diff --git a/cmake/FindLAPACKE.cmake b/cmake/FindLAPACKE.cmake new file mode 100644 index 0000000..a53891e --- /dev/null +++ b/cmake/FindLAPACKE.cmake @@ -0,0 +1,421 @@ +### +# +# @copyright (c) 2009-2014 The University of Tennessee and The University +# of Tennessee Research Foundation. +# All rights reserved. +# @copyright (c) 2012-2016 Inria. All rights reserved. +# @copyright (c) 2012-2014 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria, Univ. Bordeaux. All rights reserved. +# +### +# +# - Find LAPACKE include dirs and libraries +# Use this module by invoking find_package with the form: +# find_package(LAPACKE +# [REQUIRED] # Fail with error if lapacke is not found +# [COMPONENTS ...] # dependencies +# ) +# +# LAPACKE depends on the following libraries: +# - LAPACK +# +# This module finds headers and lapacke library. +# Results are reported in variables: +# LAPACKE_FOUND - True if headers and requested libraries were found +# LAPACKE_LINKER_FLAGS - list of required linker flags (excluding -l and -L) +# LAPACKE_INCLUDE_DIRS - lapacke include directories +# LAPACKE_LIBRARY_DIRS - Link directories for lapacke libraries +# LAPACKE_LIBRARIES - lapacke component libraries to be linked +# LAPACKE_INCLUDE_DIRS_DEP - lapacke + dependencies include directories +# LAPACKE_LIBRARY_DIRS_DEP - lapacke + dependencies link directories +# LAPACKE_LIBRARIES_DEP - lapacke libraries + dependencies +# +# The user can give specific paths where to find the libraries adding cmake +# options at configure (ex: cmake path/to/project -DLAPACKE_DIR=path/to/lapacke): +# LAPACKE_DIR - Where to find the base directory of lapacke +# LAPACKE_INCDIR - Where to find the header files +# LAPACKE_LIBDIR - Where to find the library files +# The module can also look for the following environment variables if paths +# are not given as cmake variable: LAPACKE_DIR, LAPACKE_INCDIR, LAPACKE_LIBDIR +# +# If the static version of the LAPACKE libraries is required, please add the +# following in your CMakeLists.txt before calling find_package(LAPACKE): +# set(LAPACKE_STATIC TRUE) +# +# LAPACKE could be directly embedded in LAPACK library (ex: Intel MKL) so that +# we test a lapacke function with the lapack libraries found and set LAPACKE +# variables to LAPACK ones if test is successful. To skip this feature and +# look for a stand alone lapacke, please add the following in your +# CMakeLists.txt before to call find_package(LAPACKE): +# set(LAPACKE_STANDALONE TRUE) + +#============================================================================= +# Copyright 2012-2013 Inria +# Copyright 2012-2013 Emmanuel Agullo +# Copyright 2012-2013 Mathieu Faverge +# Copyright 2012 Cedric Castagnede +# Copyright 2013-2016 Florent Pruvost +# +# This file is part of a computer program whose purpose is to process +# Matrices Over Runtime Systems @ Exascale (MORSE). More information +# can be found on the following website: http://www.inria.fr/en/teams/morse. +# +# This software is governed by the CeCILL-C license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-C +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-C license and that you accept its terms. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +if (NOT LAPACKE_FOUND) + set(LAPACKE_DIR "" CACHE PATH "Installation directory of LAPACKE library") + if (NOT LAPACKE_FIND_QUIETLY) + message(STATUS "A cache variable, namely LAPACKE_DIR, has been set to specify the install directory of LAPACKE") + endif() +endif() + +# LAPACKE depends on LAPACK anyway, try to find it +if (NOT LAPACK_FOUND) + if(LAPACKE_FIND_REQUIRED) + find_package(LAPACKEXT REQUIRED) + else() + find_package(LAPACKEXT) + endif() +endif() + +# LAPACKE depends on LAPACK +if (LAPACK_FOUND) + + if (NOT LAPACKE_STANDALONE) + # check if a lapacke function exists in the LAPACK lib + include(CheckFunctionExists) + set(CMAKE_REQUIRED_LIBRARIES "${LAPACK_LINKER_FLAGS};${LAPACK_LIBRARIES}") + unset(LAPACKE_WORKS CACHE) + check_function_exists(LAPACKE_dgeqrf LAPACKE_WORKS) + mark_as_advanced(LAPACKE_WORKS) + set(CMAKE_REQUIRED_LIBRARIES) + + if(LAPACKE_WORKS) + if(NOT LAPACKE_FIND_QUIETLY) + message(STATUS "Looking for lapacke: test with lapack succeeds") + endif() + # test succeeds: LAPACKE is in LAPACK + set(LAPACKE_LIBRARIES "${LAPACK_LIBRARIES}") + set(LAPACKE_LIBRARIES_DEP "${LAPACK_LIBRARIES}") + if (LAPACK_LIBRARY_DIRS) + set(LAPACKE_LIBRARY_DIRS "${LAPACK_LIBRARY_DIRS}") + endif() + if(LAPACK_INCLUDE_DIRS) + set(LAPACKE_INCLUDE_DIRS "${LAPACK_INCLUDE_DIRS}") + set(LAPACKE_INCLUDE_DIRS_DEP "${LAPACK_INCLUDE_DIRS}") + endif() + if (LAPACK_LINKER_FLAGS) + set(LAPACKE_LINKER_FLAGS "${LAPACK_LINKER_FLAGS}") + endif() + endif() + endif (NOT LAPACKE_STANDALONE) + + if (LAPACKE_STANDALONE OR NOT LAPACKE_WORKS) + + if(NOT LAPACKE_WORKS AND NOT LAPACKE_FIND_QUIETLY) + message(STATUS "Looking for lapacke : test with lapack fails") + endif() + # test fails: try to find LAPACKE lib exterior to LAPACK + + # Try to find LAPACKE lib + ####################### + + # Looking for include + # ------------------- + + # Add system include paths to search include + # ------------------------------------------ + unset(_inc_env) + set(ENV_LAPACKE_DIR "$ENV{LAPACKE_DIR}") + set(ENV_LAPACKE_INCDIR "$ENV{LAPACKE_INCDIR}") + if(ENV_LAPACKE_INCDIR) + list(APPEND _inc_env "${ENV_LAPACKE_INCDIR}") + elseif(ENV_LAPACKE_DIR) + list(APPEND _inc_env "${ENV_LAPACKE_DIR}") + list(APPEND _inc_env "${ENV_LAPACKE_DIR}/include") + list(APPEND _inc_env "${ENV_LAPACKE_DIR}/include/lapacke") + else() + if(WIN32) + string(REPLACE ":" ";" _inc_env "$ENV{INCLUDE}") + else() + string(REPLACE ":" ";" _path_env "$ENV{INCLUDE}") + list(APPEND _inc_env "${_path_env}") + string(REPLACE ":" ";" _path_env "$ENV{C_INCLUDE_PATH}") + list(APPEND _inc_env "${_path_env}") + string(REPLACE ":" ";" _path_env "$ENV{CPATH}") + list(APPEND _inc_env "${_path_env}") + string(REPLACE ":" ";" _path_env "$ENV{INCLUDE_PATH}") + list(APPEND _inc_env "${_path_env}") + endif() + endif() + list(APPEND _inc_env "${CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES}") + list(APPEND _inc_env "${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}") + list(REMOVE_DUPLICATES _inc_env) + + + # Try to find the lapacke header in the given paths + # ------------------------------------------------- + # call cmake macro to find the header path + if(LAPACKE_INCDIR) + set(LAPACKE_lapacke.h_DIRS "LAPACKE_lapacke.h_DIRS-NOTFOUND") + find_path(LAPACKE_lapacke.h_DIRS + NAMES lapacke.h + HINTS ${LAPACKE_INCDIR}) + else() + if(LAPACKE_DIR) + set(LAPACKE_lapacke.h_DIRS "LAPACKE_lapacke.h_DIRS-NOTFOUND") + find_path(LAPACKE_lapacke.h_DIRS + NAMES lapacke.h + HINTS ${LAPACKE_DIR} + PATH_SUFFIXES "include" "include/lapacke") + else() + set(LAPACKE_lapacke.h_DIRS "LAPACKE_lapacke.h_DIRS-NOTFOUND") + find_path(LAPACKE_lapacke.h_DIRS + NAMES lapacke.h + HINTS ${_inc_env}) + endif() + endif() + mark_as_advanced(LAPACKE_lapacke.h_DIRS) + + # If found, add path to cmake variable + # ------------------------------------ + if (LAPACKE_lapacke.h_DIRS) + set(LAPACKE_INCLUDE_DIRS "${LAPACKE_lapacke.h_DIRS}") + else () + set(LAPACKE_INCLUDE_DIRS "LAPACKE_INCLUDE_DIRS-NOTFOUND") + if(NOT LAPACKE_FIND_QUIETLY) + message(STATUS "Looking for lapacke -- lapacke.h not found") + endif() + endif() + + + # Looking for lib + # --------------- + + # Add system library paths to search lib + # -------------------------------------- + unset(_lib_env) + set(ENV_LAPACKE_LIBDIR "$ENV{LAPACKE_LIBDIR}") + if(ENV_LAPACKE_LIBDIR) + list(APPEND _lib_env "${ENV_LAPACKE_LIBDIR}") + elseif(ENV_LAPACKE_DIR) + list(APPEND _lib_env "${ENV_LAPACKE_DIR}") + list(APPEND _lib_env "${ENV_LAPACKE_DIR}/lib") + else() + if(WIN32) + string(REPLACE ":" ";" _lib_env "$ENV{LIB}") + else() + if(APPLE) + string(REPLACE ":" ";" _lib_env "$ENV{DYLD_LIBRARY_PATH}") + else() + string(REPLACE ":" ";" _lib_env "$ENV{LD_LIBRARY_PATH}") + endif() + list(APPEND _lib_env "${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES}") + list(APPEND _lib_env "${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}") + endif() + endif() + list(REMOVE_DUPLICATES _lib_env) + + # Try to find the lapacke lib in the given paths + # ---------------------------------------------- + + # name of the lapacke library + set(LAPACKE_lapacke_NAMES "lapacke") + if(LAPACKE_STATIC) + if(WIN32) + set(LAPACKE_lapacke_NAMES "liblapacke.lib") + endif() + + if(UNIX) + set(LAPACKE_lapacke_NAMES "liblapacke.a") + endif() + endif() + + # call cmake macro to find the lib path + if(LAPACKE_LIBDIR) + set(LAPACKE_lapacke_LIBRARY "LAPACKE_lapacke_LIBRARY-NOTFOUND") + find_library(LAPACKE_lapacke_LIBRARY + NAMES ${LAPACKE_lapacke_NAMES} + HINTS ${LAPACKE_LIBDIR}) + else() + if(LAPACKE_DIR) + set(LAPACKE_lapacke_LIBRARY "LAPACKE_lapacke_LIBRARY-NOTFOUND") + find_library(LAPACKE_lapacke_LIBRARY + NAMES ${LAPACKE_lapacke_NAMES} + HINTS ${LAPACKE_DIR} + PATH_SUFFIXES lib lib32 lib64) + else() + set(LAPACKE_lapacke_LIBRARY "LAPACKE_lapacke_LIBRARY-NOTFOUND") + find_library(LAPACKE_lapacke_LIBRARY + NAMES ${LAPACKE_lapacke_NAMES} + HINTS ${_lib_env}) + endif() + endif() + mark_as_advanced(LAPACKE_lapacke_LIBRARY) + + # If found, add path to cmake variable + # ------------------------------------ + if (LAPACKE_lapacke_LIBRARY) + get_filename_component(lapacke_lib_path "${LAPACKE_lapacke_LIBRARY}" PATH) + # set cmake variables + set(LAPACKE_LIBRARIES "${LAPACKE_lapacke_LIBRARY}") + set(LAPACKE_LIBRARY_DIRS "${lapacke_lib_path}") + else () + set(LAPACKE_LIBRARIES "LAPACKE_LIBRARIES-NOTFOUND") + set(LAPACKE_LIBRARY_DIRS "LAPACKE_LIBRARY_DIRS-NOTFOUND") + if (NOT LAPACKE_FIND_QUIETLY) + message(STATUS "Looking for lapacke -- lib lapacke not found") + endif() + endif () + + # check a function to validate the find + if(LAPACKE_LIBRARIES) + + set(REQUIRED_LDFLAGS) + set(REQUIRED_INCDIRS) + set(REQUIRED_LIBDIRS) + set(REQUIRED_LIBS) + + # LAPACKE + if (LAPACKE_INCLUDE_DIRS) + set(REQUIRED_INCDIRS "${LAPACKE_INCLUDE_DIRS}") + endif() + if (LAPACKE_LIBRARY_DIRS) + set(REQUIRED_LIBDIRS "${LAPACKE_LIBRARY_DIRS}") + endif() + set(REQUIRED_LIBS "${LAPACKE_LIBRARIES}") + # LAPACK + if (LAPACK_INCLUDE_DIRS) + list(APPEND REQUIRED_INCDIRS "${LAPACK_INCLUDE_DIRS}") + endif() + if (LAPACK_LIBRARY_DIRS) + list(APPEND REQUIRED_LIBDIRS "${LAPACK_LIBRARY_DIRS}") + endif() + list(APPEND REQUIRED_LIBS "${LAPACK_LIBRARIES}") + if (LAPACK_LINKER_FLAGS) + list(APPEND REQUIRED_LDFLAGS "${LAPACK_LINKER_FLAGS}") + endif() + # Fortran + if (CMAKE_C_COMPILER_ID MATCHES "GNU") + find_library( + FORTRAN_gfortran_LIBRARY + NAMES gfortran + HINTS ${_lib_env} + ) + mark_as_advanced(FORTRAN_gfortran_LIBRARY) + if (FORTRAN_gfortran_LIBRARY) + list(APPEND REQUIRED_LIBS "${FORTRAN_gfortran_LIBRARY}") + endif() + elseif (CMAKE_C_COMPILER_ID MATCHES "Intel") + find_library( + FORTRAN_ifcore_LIBRARY + NAMES ifcore + HINTS ${_lib_env} + ) + mark_as_advanced(FORTRAN_ifcore_LIBRARY) + if (FORTRAN_ifcore_LIBRARY) + list(APPEND REQUIRED_LIBS "${FORTRAN_ifcore_LIBRARY}") + endif() + endif() + # m + find_library(M_LIBRARY NAMES m HINTS ${_lib_env}) + mark_as_advanced(M_LIBRARY) + if(M_LIBRARY) + list(APPEND REQUIRED_LIBS "-lm") + endif() + # set required libraries for link + set(CMAKE_REQUIRED_INCLUDES "${REQUIRED_INCDIRS}") + set(CMAKE_REQUIRED_LIBRARIES) + list(APPEND CMAKE_REQUIRED_LIBRARIES "${REQUIRED_LDFLAGS}") + foreach(lib_dir ${REQUIRED_LIBDIRS}) + list(APPEND CMAKE_REQUIRED_LIBRARIES "-L${lib_dir}") + endforeach() + list(APPEND CMAKE_REQUIRED_LIBRARIES "${REQUIRED_LIBS}") + string(REGEX REPLACE "^ -" "-" CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}") + + # test link + unset(LAPACKE_WORKS CACHE) + include(CheckFunctionExists) + check_function_exists(LAPACKE_dgeqrf LAPACKE_WORKS) + mark_as_advanced(LAPACKE_WORKS) + + if(LAPACKE_WORKS) + # save link with dependencies + set(LAPACKE_LIBRARIES_DEP "${REQUIRED_LIBS}") + set(LAPACKE_LIBRARY_DIRS_DEP "${REQUIRED_LIBDIRS}") + set(LAPACKE_INCLUDE_DIRS_DEP "${REQUIRED_INCDIRS}") + set(LAPACKE_LINKER_FLAGS "${REQUIRED_LDFLAGS}") + list(REMOVE_DUPLICATES LAPACKE_LIBRARY_DIRS_DEP) + list(REMOVE_DUPLICATES LAPACKE_INCLUDE_DIRS_DEP) + list(REMOVE_DUPLICATES LAPACKE_LINKER_FLAGS) + else() + if(NOT LAPACKE_FIND_QUIETLY) + message(STATUS "Looking for lapacke: test of LAPACKE_dgeqrf with lapacke and lapack libraries fails") + message(STATUS "CMAKE_REQUIRED_LIBRARIES: ${CMAKE_REQUIRED_LIBRARIES}") + message(STATUS "CMAKE_REQUIRED_INCLUDES: ${CMAKE_REQUIRED_INCLUDES}") + message(STATUS "Check in CMakeFiles/CMakeError.log to figure out why it fails") + endif() + endif() + set(CMAKE_REQUIRED_INCLUDES) + set(CMAKE_REQUIRED_FLAGS) + set(CMAKE_REQUIRED_LIBRARIES) + endif(LAPACKE_LIBRARIES) + + endif (LAPACKE_STANDALONE OR NOT LAPACKE_WORKS) + +else(LAPACK_FOUND) + + if (NOT LAPACKE_FIND_QUIETLY) + message(STATUS "LAPACKE requires LAPACK but LAPACK has not been found." + "Please look for LAPACK first.") + endif() + +endif(LAPACK_FOUND) + +if (LAPACKE_LIBRARIES) + list(GET LAPACKE_LIBRARIES 0 first_lib) + get_filename_component(first_lib_path "${first_lib}" PATH) + if (${first_lib_path} MATCHES "(/lib(32|64)?$)|(/lib/intel64$|/lib/ia32$)") + string(REGEX REPLACE "(/lib(32|64)?$)|(/lib/intel64$|/lib/ia32$)" "" not_cached_dir "${first_lib_path}") + set(LAPACKE_DIR_FOUND "${not_cached_dir}" CACHE PATH "Installation directory of LAPACKE library" FORCE) + else() + set(LAPACKE_DIR_FOUND "${first_lib_path}" CACHE PATH "Installation directory of LAPACKE library" FORCE) + endif() +endif() +mark_as_advanced(LAPACKE_DIR) +mark_as_advanced(LAPACKE_DIR_FOUND) + +# check that LAPACKE has been found +# --------------------------------- +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LAPACKE DEFAULT_MSG + LAPACKE_LIBRARIES + LAPACKE_WORKS) \ No newline at end of file diff --git a/code_gen/aniso_code_gen.ipynb b/code_gen/aniso_code_gen.ipynb index 7f0f1cd..40f1614 100644 --- a/code_gen/aniso_code_gen.ipynb +++ b/code_gen/aniso_code_gen.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -51,6 +51,13 @@ " return c21[idx]\n" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": 41, @@ -446,7 +453,7 @@ ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -460,7 +467,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.12.2" } }, "nbformat": 4, diff --git a/code_gen/derivative.ipynb b/code_gen/derivative.ipynb new file mode 100644 index 0000000..ccdf21e --- /dev/null +++ b/code_gen/derivative.ipynb @@ -0,0 +1,1023 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from numba import jit\n", + "import time " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "@jit(nopython=True)\n", + "def legendre(n,x):\n", + " leg = 1.\n", + " if n == 0:\n", + " leg = 1\n", + " elif n==1:\n", + " leg = x\n", + " else:\n", + " leg_down1 = x; leg_down2 = 1.\n", + " for i in range(2,n+1):\n", + " leg = (2*i-1)*x*leg_down1/i - (i-1)*leg_down2/i\n", + " leg_down2 = leg_down1\n", + " leg_down1 = leg\n", + "\n", + " return leg\n", + "\n", + "@jit(nopython=True)\n", + "def dlegendre(n,x):\n", + " dleg = 0.\n", + " if n == 0:\n", + " dleg = 0.\n", + " elif n == 1:\n", + " dleg = 1.\n", + " else:\n", + " leg_down1 = x; leg_down2 = 1.\n", + " dleg_down1 = 1.; dleg_down2 = 0.\n", + " for i in range(2,n+1):\n", + " leg = (2*i-1)*x*leg_down1/i - (i-1)*leg_down2/i\n", + " dleg = dleg_down2 + (2*i-1)*leg_down1\n", + " leg_down2 = leg_down1\n", + " leg_down1 = leg\n", + " dleg_down2 = dleg_down1\n", + " dleg_down1 = dleg\n", + "\n", + " return dleg\n", + "\n", + "@jit(nopython=True)\n", + "def gauss_legendre_lobatto(length:int):\n", + " #// define some constants\n", + " tolerance = 4.0 * 1.0e-6\n", + " nnewton_iter = 100\n", + " pi = np.pi\n", + " \n", + " # allocate space\n", + " n = length - 1; #// order of polynomial\n", + " x = np.array([0.0 for i in range(length)])\n", + " w = x * 1.\n", + " if n == 1:\n", + " x[0] = -1.; x[1] = 1.\n", + " w[0] = 1.; w[1] = 1.\n", + " else:\n", + " leg = 0.; dleg = 0.; delta = 0.\n", + " # set end points\n", + " x[0] = -1.0; x[n] = 1.\n", + " w[0] = 2./(n*(n+1.)); w[n] = 2./(n*(n+1.))\n", + "\n", + " for i in range(1,(n+1)//2):\n", + " #// initial guess from an approximate form given by SV Parter (1999)\n", + " x[i] = -np.cos( (i+0.25)*pi/n - 3/(8*n*pi*(i+0.25)))\n", + "\n", + " #// newton iteration\n", + " for j in range(nnewton_iter):\n", + " leg = legendre(n+1,x[i]) - legendre(n-1,x[i])\n", + " dleg = dlegendre(n+1,x[i]) - dlegendre(n-1,x[i])\n", + " delta = -leg/dleg\n", + " x[i] += delta\n", + " if (np.abs(delta) <= tolerance * np.abs(x[i]) ): break\n", + " \n", + " x[n-i] = - x[i]\n", + " leg = legendre(n, x[i])\n", + " w[i] = 2./(n*(n+1.)*leg*leg)\n", + " w[n-i] = w[i]\n", + "\n", + " if n %2 == 0 :\n", + " x[n//2] = 0.\n", + " leg = legendre(n, 0.0)\n", + " w[n//2] = 2./(n*(n+1.)*leg*leg)\n", + " \n", + "\n", + " return x,w\n", + "\n", + "@jit(nopython=True)\n", + "def lagrange_poly(xi,xctrl):\n", + " nctrl = len(xctrl)\n", + " hprime = np.array([0.0 for i in range(nctrl)])\n", + " h = hprime * 1.0\n", + "\n", + " #! note: this routine is hit pretty hard by the mesher, optimizing the loops here will be beneficial\n", + " for dgr in range(nctrl):\n", + " prod1 = 1.; prod2 = 1.\n", + "\n", + " #// lagrangian interpolants\n", + " x0 = xctrl[dgr]\n", + " for i in range(nctrl):\n", + " if i != dgr:\n", + " x = xctrl[i]\n", + " prod1 = prod1*(xi-x)\n", + " prod2 = prod2*(x0-x)\n", + "\n", + " #//! takes inverse to avoid additional divisions\n", + " #//! (multiplications are cheaper than divisions)\n", + " prod2_inv = 1. / prod2\n", + " h[dgr] = prod1 * prod2_inv\n", + "\n", + " #// first derivatives\n", + " s = 0.0\n", + " for i in range(nctrl):\n", + " if i != dgr :\n", + " prod3 = 1.0\n", + " for j in range(nctrl):\n", + " if j != dgr and j != i:\n", + " prod3 = prod3*(xi-xctrl[j])\n", + " s = s + prod3\n", + " hprime[dgr] = s * prod2_inv\n", + " \n", + "\n", + " return h,hprime\n", + "\n", + "\n", + "def init_gll_arrays(NGLLX):\n", + "\n", + " # gll points and weights\n", + " xgll,wxgll = gauss_legendre_lobatto(NGLLX)\n", + "\n", + " #// derivative, hprimex[i][j] = l_j'(xi_i)\n", + " hprimex = np.zeros((NGLLX,NGLLX))\n", + " for i in range(NGLLX):\n", + " _,hprimex[i,:] = lagrange_poly(xgll[i],xgll)\n", + "\n", + " #// hprimex_wgllx[i,j] = hprime_x[i,j] * wx[i] \n", + " hprimex_wgllx = np.zeros((NGLLX,NGLLX))\n", + " for i in range(NGLLX):\n", + " for j in range(NGLLX):\n", + " hprimex_wgllx[i,j] = hprimex[i,j] * wxgll[i]\n", + "\n", + "\n", + " return xgll,wxgll,hprimex,hprimex_wgllx\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def create_sem_mesh(zmax,nel,NGLL):\n", + " # connectivity matrix\n", + " ibool = np.zeros((nel,NGLL),dtype=int)\n", + " idx = 0\n", + " for i in range(nel):\n", + " for j in range(NGLL):\n", + " ibool[i,j] = idx \n", + " idx += 1\n", + " idx -= 1\n", + " \n", + " # jacobians\n", + " jaco = np.zeros((nel))\n", + " jaco[:] = zmax / nel * 0.5 \n", + "\n", + " return ibool,jaco \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "@jit(nopython=True)\n", + "def assemble_matrix(P,ibool,wgll,hprime,jaco,):\n", + " nspec,NGLL = P.shape\n", + " nglob = np.max(ibool) + 1\n", + " E = np.zeros((nglob,nglob),dtype=float)\n", + " hpT = hprime.transpose()\n", + "\n", + " for ispec in range(nspec):\n", + " sum_terms= P[ispec,:] * wgll[:] / jaco[ispec]\n", + " \n", + " for i in range(NGLL):\n", + " ig1 = ibool[ispec,i]\n", + " for j in range(NGLL):\n", + " ig2 = ibool[ispec,j]\n", + " s = np.sum(sum_terms * hpT[i,:] * hpT[j,:])\n", + " E[ig1,ig2] += s \n", + " \n", + " return E \n", + "\n", + "@jit(nopython=True)\n", + "def assemble_matrix_fd(ibool,wgll,hprime,jaco,x,y,P):\n", + " nspec,NGLL = ibool.shape \n", + " dm = np.zeros((nspec,NGLL),dtype=float)\n", + " for ispec in range(nspec):\n", + " for i in range(NGLL):\n", + " p = P[ispec,i] * 1. \n", + " dx = 0.01\n", + " P[ispec,i] = p * (1 + dx)\n", + " E = assemble_matrix(P,ibool,wgll,hprime,jaco)\n", + " s1 = y.dot(E.dot(x))\n", + "\n", + " P[ispec,i] = p * (1 - dx)\n", + " E = assemble_matrix(P,ibool,wgll,hprime,jaco)\n", + " s2 = y.dot(E.dot(x))\n", + "\n", + " dm[ispec,i] = (s1 - s2) / (p * dx * 2)\n", + "\n", + " # recover\n", + " P[ispec,i] = p * 1. \n", + " \n", + " return dm \n", + "@jit(nopython=True)\n", + "def assemble_matrix_deriv(ibool,wgll,hprime,jaco,x,y):\n", + " nspec,NGLL = ibool.shape\n", + " dE = np.zeros((nspec,NGLL))\n", + "\n", + " # element\n", + " xe = np.zeros((NGLL),dtype=float)\n", + " ye = np.zeros((NGLL),dtype=float)\n", + "\n", + " for ispec in range(nspec):\n", + " # cache element\n", + " for i in range(NGLL):\n", + " ig = ibool[ispec,i]\n", + " xe[i] = x[ig]\n", + " ye[i] = y[ig]\n", + "\n", + " # compute \n", + " sum_terms = wgll[:] / jaco[ispec]\n", + " for k in range(NGLL):\n", + " s1 = np.sum(hprime[k,:] * xe[:])\n", + " s2 = np.sum(hprime[k,:] * ye[:])\n", + " dE[ispec,k] = sum_terms[k] * s1 * s2 \n", + " \n", + " return dE" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "@jit(nopython=True)\n", + "def assemble_matrix_diag(P,ibool,wgll,jaco):\n", + " nspec,NGLL = P.shape\n", + " nglob = np.max(ibool) + 1\n", + " M = np.zeros((nglob),dtype=float)\n", + "\n", + " for ispec in range(nspec):\n", + " for i in range(NGLL):\n", + " ig = ibool[ispec,i]\n", + " M[ig] += jaco[ispec] * wgll[i] * P[ispec,i] \n", + " \n", + " return M \n", + "\n", + "@jit(nopython=True)\n", + "def assemble_matrix_diag_fd(ibool,wgll,jaco,x,y,P):\n", + " nspec,NGLL = ibool.shape \n", + " dm = np.zeros((nspec,NGLL),dtype=float)\n", + " for ispec in range(nspec):\n", + " for i in range(NGLL):\n", + " p = P[ispec,i] * 1. \n", + " dx = 0.01\n", + " P[ispec,i] = p * (1 + dx)\n", + " M = assemble_matrix_diag(P,ibool,wgll,jaco)\n", + " s1 = np.sum(y * M * x)\n", + "\n", + " P[ispec,i] = p * (1 - dx)\n", + " M = assemble_matrix_diag(P,ibool,wgll,jaco)\n", + " s2 = np.sum(y * M * x)\n", + "\n", + " dm[ispec,i] = (s1 - s2) / (p * dx * 2)\n", + "\n", + " # recover\n", + " P[ispec,i] = p * 1. \n", + " \n", + " return dm \n", + "\n", + "@jit(nopython=True)\n", + "def assemble_matrix_diag_deriv(ibool,wgll,jaco,x,y):\n", + " nspec,NGLL = ibool.shape\n", + " dM = np.zeros((nspec,NGLL),dtype=float)\n", + "\n", + " # element\n", + " xe = np.zeros((NGLL),dtype=float)\n", + " ye = np.zeros((NGLL),dtype=float)\n", + "\n", + " for ispec in range(nspec):\n", + " # cache element\n", + " for i in range(NGLL):\n", + " ig = ibool[ispec,i]\n", + " xe[i] = x[ig]\n", + " ye[i] = y[ig]\n", + "\n", + " # compute \n", + " for k in range(NGLL):\n", + " dM[ispec,k] = wgll[k] * jaco[ispec] * xe[k] * ye[k]\n", + " \n", + " return dM" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "time = 0.020659208297729492\n", + "time = 5.316734313964844e-05\n", + "True\n" + ] + } + ], + "source": [ + "nspec = 400\n", + "NGLL = 5\n", + "xgll,wgll,hprime,_ = init_gll_arrays(NGLL)\n", + "ibool,jaco = create_sem_mesh(11.5,nspec,NGLL)\n", + "nglob = np.max(ibool) + 1\n", + "\n", + "# random seed\n", + "np.random.seed(15)\n", + "P = np.random.rand(nspec,NGLL)\n", + "x = np.random.rand(nglob)\n", + "y = np.random.rand(nglob)\n", + "\n", + "tic = time.time()\n", + "dm = assemble_matrix_diag_fd(ibool,wgll,jaco,x,y,P)\n", + "toc = time.time()\n", + "print('time = ',toc-tic)\n", + "\n", + "tic = time.time()\n", + "dE = assemble_matrix_diag_deriv(ibool,wgll,jaco,x,y)\n", + "toc = time.time()\n", + "print('time = ',toc-tic)\n", + "\n", + "print(np.allclose(dm,dE))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np \n", + "import matplotlib.pyplot as plt \n", + "\n", + "plt.figure(1,figsize=(14,6))\n", + "Q = np.logspace(np.log10(3),np.log10(500),200)\n", + "y = np.sqrt(1 + 1j/ Q)\n", + "y1 = 1 + 1j / (2 * Q) \n", + "\n", + "plt.subplot(121)\n", + "plt.semilogx(Q,y.real)\n", + "plt.semilogx(Q,y1.real)\n", + "plt.subplot(122)\n", + "plt.semilogx(Q,y.imag)\n", + "plt.semilogx(Q,y1.imag)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np \n", + "def get_Q_sls_model(Q):\n", + "\n", + " y_sls_ref = np.array([1.93044501, 1.64217132, 1.73606189, 1.42826439, 1.66934129])\n", + " w_sls_ref = np.array([4.71238898e-02, 6.63370885e-01, 9.42477796e+00, 1.14672436e+02,1.05597079e+03])\n", + " dy = y_sls_ref * 0 \n", + " y = y_sls_ref * 0\n", + " NSLS = len(y)\n", + "\n", + " for i in range(NSLS):\n", + " y[i] = y_sls_ref[i] / Q \n", + " dy[0] = 1. + 0.5 * y[0]\n", + "\n", + " for i in range(1,NSLS):\n", + " dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i]\n", + "\n", + " #// copy to y_sls/w_sls\n", + " w_sls = w_sls_ref * 1. \n", + " y_sls = dy * y \n", + "\n", + " return w_sls,y_sls \n", + "\n", + "\n", + "def compute_q_sls_model(y_sls,w_sls,om,exact=False):\n", + " Q_ls = 1. \n", + " nsls = len(y_sls)\n", + " if exact:\n", + " for p in range(nsls):\n", + " Q_ls += y_sls[p] * om**2 / (om**2 + w_sls[p]**2)\n", + "\n", + " # denom\n", + " Q_demon = 0.\n", + " for p in range(nsls):\n", + " Q_demon += y_sls[p] * om * w_sls[p] / (om**2 + w_sls[p]**2)\n", + " \n", + " return Q_ls / Q_demon\n", + "\n", + "def get_sls_modulus_factor(freq,Q):\n", + " om = 2 * np.pi * freq\n", + "\n", + " w_sls,y_sls = get_Q_sls_model(Q)\n", + " s = np.sum(1j * om * y_sls / (w_sls + 1j * om))\n", + "\n", + " return s + 1.\n", + "\n", + "def get_sls_Q_deriv(freq,Q):\n", + " y_sls_ref = np.array([1.93044501, 1.64217132, 1.73606189, 1.42826439, 1.66934129])\n", + " w_sls_ref = np.array([4.71238898e-02, 6.63370885e-01, 9.42477796e+00, 1.14672436e+02,1.05597079e+03])\n", + " dy = y_sls_ref * 0 \n", + " y = y_sls_ref / Q \n", + "\n", + " # corrector\n", + " NSLS = len(y_sls_ref)\n", + " dy[0] = 1. + 0.5 * y[0]\n", + " for i in range(1,NSLS):\n", + " dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i]\n", + " dd_dqi = dy * 0\n", + " dd_dqi[0] = 0.5 * y_sls_ref[0]\n", + " for i in range(1,NSLS):\n", + " dd_dqi[i] = dd_dqi[i-1] + (dy[i-1] - 0.5) * y_sls_ref[i-1] + dd_dqi[i-1] * y[i-1] + 0.5 * y_sls_ref[i]\n", + " \n", + " dd_dqi = dd_dqi * y + dy * y_sls_ref\n", + " om = 2 * np.pi * freq\n", + " dsdqi = np.sum(1j * om * dd_dqi /(w_sls_ref + 1j * om))\n", + " s = np.sum(1j * om * y * dy / (w_sls_ref + 1j * om))\n", + "\n", + " return s + 1., dsdqi" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Q = 50.\n", + "freq= 1.\n", + "s,dsdqi = get_sls_Q_deriv(freq,Q)\n", + "\n", + "dQ = 0.001\n", + "s1 = get_sls_modulus_factor(freq,Q * (1 + dQ))\n", + "s2 = get_sls_modulus_factor(freq,Q * (1-dQ))\n", + "print(s,s1,s2)\n", + "dsdq = (s1 - s2) / (Q * dQ * 2)\n", + "dsdqi_fdf = -Q**2 * dsdq\n", + "\n", + "print(dsdqi,dsdqi_fdf)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "import sympy as sp " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "L2,L1,N2,N1,rho2,rho1,om,H,c = sp.symbols(\"L2,L1,N2,N1,r2,r1,om,H,c\")\n", + "sn1,sn2,sl1,sl2,dsdqn1,dsdqn2,dsdql1,dsdql2 = sp.symbols(\"sn1,sn2,sl1,sl2,dsdqn1,dsdqn2,dsdql1,dsdql2\")\n", + "f = L2/L1 * sp.sqrt((N2/L2) - (rho2 * c**2)/L2) - sp.sqrt((c**2 *rho1)/L1 - (N1/L1)) * sp.tan((om * H)/c *sp.sqrt((c**2 * rho1)/L1 - (N1/L1)))\n", + "\n", + "gamma2 = sp.sqrt((1 - rho2 * c**2/N2) * N2/L2)\n", + "Omega = om/c * H * gamma2 * (\n", + " ((rho1 * c**2 - N1) / (N2 - rho2 / rho1 * N1)) +\n", + " (L2 / L1) * ((N2 - rho2*c**2) / (N2 - rho2/rho1 * N1))\n", + " )\n", + "u = 1 / (c * rho1) * ( c**2 * rho1 + N1 * Omega) / ( 1 + Omega)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dcc_dcL2=(-L2*(-1/2*N2/L2**2 + (1/2)*c**2*r2/L2**2)/(L1*np.sqrt(N2/L2 - c**2*r2/L2)) - np.sqrt(N2/L2 - c**2*r2/L2)/L1)/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))\n", + "dcc_dcL1=(H*om*((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/c + ((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/np.sqrt(-N1/L1 + c**2*r1/L1) + L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1**2)/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))\n", + "dcc_dcN2=-(1/2)/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))))\n", + "dcc_dcN1=(-1/2*H*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/(L1*c) - 1/2*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))\n", + "dcc_dcr2=(1/2)*c**2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))))\n", + "dcc_dcr1=((1/2)*H*c*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/L1 + (1/2)*c**2*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))\n" + ] + } + ], + "source": [ + "all_params = (L2,L1,N2,N1,rho2,rho1)\n", + "for param in all_params:\n", + " outstr = sp.pycode(-sp.diff(f,param) / sp.diff(f,c),).replace(\"math.\",\"np.\")\n", + " print(f\"dcc_dc{str(param)}={outstr}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dcc_dcL2=(L2*(-1/2*N2/L2**2 + (1/2)*c**2*r2/L2**2)/(L1*np.sqrt(N2/L2 - c**2*r2/L2)) + np.sqrt(N2/L2 - c**2*r2/L2)/L1)*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + (-1/2*H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(L2*c) + H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)/(L1*c*(-N1*r2/r1 + N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + ((1/2)*H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(L2*c) - H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)/(L1*c*(-N1*r2/r1 + N2)))*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2)\n", + "dcc_dcL1=-H*L2*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)/(L1**2*c**2*r1*(-N1*r2/r1 + N2)*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + H*L2*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(L1**2*c**2*r1*(-N1*r2/r1 + N2)*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))*(-H*om*((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/c - ((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/np.sqrt(-N1/L1 + c**2*r1/L1) - L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1**2)/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))\n", + "dcc_dcN2=(H*L2*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((1/2)*(1 - c**2*r2/N2)/L2 + (1/2)*c**2*r2/(L2*N2))*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*c*(1 - c**2*r2/N2)) + H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-(-N1 + c**2*r1)/(-N1*r2/r1 + N2)**2 - L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)**2) + L2/(L1*(-N1*r2/r1 + N2)))/c)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*L2*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((1/2)*(1 - c**2*r2/N2)/L2 + (1/2)*c**2*r2/(L2*N2))*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*c*(1 - c**2*r2/N2)) - H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-(-N1 + c**2*r1)/(-N1*r2/r1 + N2)**2 - L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)**2) + L2/(L1*(-N1*r2/r1 + N2)))/c)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (1/2)*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))))\n", + "dcc_dcN1=-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-1/(-N1*r2/r1 + N2) + r2*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*r2*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2))/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + ((1/2)*H*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/(L1*c) + (1/2)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-1/(-N1*r2/r1 + N2) + r2*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*r2*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1))\n", + "dcc_dcr2=(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N1*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*N1*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2) - L2*c**2/(L1*(-N1*r2/r1 + N2)))/c - 1/2*H*N1*c*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + (-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N1*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*N1*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2) - L2*c**2/(L1*(-N1*r2/r1 + N2)))/c + (1/2)*H*c*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) - 1/2*c**2*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))))\n", + "dcc_dcr1=-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-N1*r2*(-N1 + c**2*r1)/(r1**2*(-N1*r2/r1 + N2)**2) + c**2/(-N1*r2/r1 + N2) - L2*N1*r2*(N2 - c**2*r2)/(L1*r1**2*(-N1*r2/r1 + N2)**2))/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (-1/2*H*c*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/L1 - 1/2*c**2*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-N1*r2*(-N1 + c**2*r1)/(r1**2*(-N1*r2/r1 + N2)**2) + c**2/(-N1*r2/r1 + N2) - L2*N1*r2*(N2 - c**2*r2)/(L1*r1**2*(-N1*r2/r1 + N2)**2))/c + c**2)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c*r1**2*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1))\n" + ] + } + ], + "source": [ + "all_params = (L2,L1,N2,N1,rho2,rho1)\n", + "for param in all_params:\n", + " expr = - sp.diff(u,c) * sp.diff(f,param) / sp.diff(f,c) + sp.diff(u,param)\n", + " outstr = sp.pycode(expr).replace(\"math.\",\"np.\")\n", + " print(f\"dcc_dc{str(param)}={outstr}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle - \\sqrt{- \\frac{N_{1}}{L_{1}} + \\frac{c^{2} r_{1}}{L_{1}}} \\left(- \\frac{H om \\sqrt{- \\frac{N_{1}}{L_{1}} + \\frac{c^{2} r_{1}}{L_{1}}}}{c^{2}} + \\frac{H om r_{1}}{L_{1} \\sqrt{- \\frac{N_{1}}{L_{1}} + \\frac{c^{2} r_{1}}{L_{1}}}}\\right) \\left(\\tan^{2}{\\left(\\frac{H om \\sqrt{- \\frac{N_{1}}{L_{1}} + \\frac{c^{2} r_{1}}{L_{1}}}}{c} \\right)} + 1\\right) - \\frac{c r_{1} \\tan{\\left(\\frac{H om \\sqrt{- \\frac{N_{1}}{L_{1}} + \\frac{c^{2} r_{1}}{L_{1}}}}{c} \\right)}}{L_{1} \\sqrt{- \\frac{N_{1}}{L_{1}} + \\frac{c^{2} r_{1}}{L_{1}}}} - \\frac{c r_{2}}{L_{1} \\sqrt{\\frac{N_{2}}{L_{2}} - \\frac{c^{2} r_{2}}{L_{2}}}}$" + ], + "text/plain": [ + "-sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*sqrt(-N1/L1 + c**2*r1/L1)))*(tan(H*om*sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*tan(H*om*sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*sqrt(N2/L2 - c**2*r2/L2))" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.diff(f,c)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'-np.sqrt(-N1/L1 + c**2*r1/L1)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c) + L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "expr = sp.diff(f,c)\n", + "outstr = sp.pycode(f).replace(\"math.\",\"np.\")\n", + "outstr" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sympy as sp " + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "# c21 vec\n", + "c21str = ''\n", + "for i in range(6):\n", + " for j in range(i,6):\n", + " c21str += f\"c{i+1}{j+1}\" + \" \"\n", + "c21vec = sp.symbols(c21str)\n", + "c66 = sp.Array.zeros(6,6)\n", + "c66 = c66.as_mutable()\n", + "for i in range(6):\n", + " for j in range(i,6):\n", + " c66[i,j] = c21vec[i*6+j-i*(i+1)//2]\n", + " c66[j,i] = c66[i,j]\n", + "\n", + "cbak = c66 * 1\n", + "eps = sp.Rational(1,3) * (c66[0,0] + c66[1,1] + c66[2,2])\n", + "mu = sp.Rational(1,3) * (c66[3,3] + c66[4,4] + c66[5,5])\n", + "kappa = eps - sp.Rational(4,3) * mu \n", + "\n", + "Qk_fac,Qmu_fac = sp.symbols(\"Qk_fac,Qmu_fac\")\n", + "\n", + "for i in range(3):\n", + " cbak[i,i] = c66[i,i] - eps + kappa * Qk_fac + sp.Rational(4,3) * mu * Qmu_fac\n", + "\n", + "for i in range(3):\n", + " for j in range(3):\n", + " if i == j: \n", + " continue\n", + " cbak[i,j] = c66[i,j] - eps + kappa * Qk_fac + 2 * mu * (1 - sp.Rational(1,3) * Qmu_fac)\n", + "\n", + "for i in range(3,6):\n", + " cbak[i,i] = c66[i,i] * Qmu_fac" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SETDC(0,0,(1.0/3.0)*Qk_fac + 2.0/3.0);\n", + "SETDC(0,6,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(0,11,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(0,15,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(0,18,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(0,20,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(1,0,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(1,1,1);\n", + "SETDC(1,6,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(1,11,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(1,15,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(1,18,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(1,20,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(2,0,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(2,2,1);\n", + "SETDC(2,6,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(2,11,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(2,15,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(2,18,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(2,20,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(3,3,1);\n", + "SETDC(4,4,1);\n", + "SETDC(5,5,1);\n", + "SETDC(6,0,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(6,6,(1.0/3.0)*Qk_fac + 2.0/3.0);\n", + "SETDC(6,11,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(6,15,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(6,18,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(6,20,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(7,0,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(7,6,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(7,7,1);\n", + "SETDC(7,11,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(7,15,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(7,18,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(7,20,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0);\n", + "SETDC(8,8,1);\n", + "SETDC(9,9,1);\n", + "SETDC(10,10,1);\n", + "SETDC(11,0,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(11,6,(1.0/3.0)*Qk_fac - 1.0/3.0);\n", + "SETDC(11,11,(1.0/3.0)*Qk_fac + 2.0/3.0);\n", + "SETDC(11,15,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(11,18,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(11,20,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac);\n", + "SETDC(12,12,1);\n", + "SETDC(13,13,1);\n", + "SETDC(14,14,1);\n", + "SETDC(15,15,Qmu_fac);\n", + "SETDC(16,16,1);\n", + "SETDC(17,17,1);\n", + "SETDC(18,18,Qmu_fac);\n", + "SETDC(19,19,1);\n", + "SETDC(20,20,Qmu_fac);\n" + ] + } + ], + "source": [ + "id = 0\n", + "for i in range(6):\n", + " for j in range(i,6):\n", + " id1 = 0\n", + " for i1 in range(6): \n", + " for j1 in range(i1,6):\n", + " expr = sp.diff(cbak[i,j],c66[i1,j1])\n", + " if expr != 0:\n", + " code = sp.ccode(expr)\n", + " print(f\"SETDC({id},{id1},{code});\")\n", + " id1 += 1\n", + " id += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SETDQ(0,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac);\n", + "SETDQ(0,1,((4.0/9.0)*C(3,3)*1. + (4.0/9.0)*C(4,4)*1. + (4.0/9.0)*C(5,5)*1.) * dQmu_fac);\n", + "SETDQ(1,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac);\n", + "SETDQ(1,1,(-2.0/9.0*C(3,3)*1. - 2.0/9.0*C(4,4)*1. - 2.0/9.0*C(5,5)*1.) * dQmu_fac);\n", + "SETDQ(2,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac);\n", + "SETDQ(2,1,(-2.0/9.0*C(3,3)*1. - 2.0/9.0*C(4,4)*1. - 2.0/9.0*C(5,5)*1.) * dQmu_fac);\n", + "SETDQ(6,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac);\n", + "SETDQ(6,1,((4.0/9.0)*C(3,3)*1. + (4.0/9.0)*C(4,4)*1. + (4.0/9.0)*C(5,5)*1.) * dQmu_fac);\n", + "SETDQ(7,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac);\n", + "SETDQ(7,1,(-2.0/9.0*C(3,3)*1. - 2.0/9.0*C(4,4)*1. - 2.0/9.0*C(5,5)*1.) * dQmu_fac);\n", + "SETDQ(11,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac);\n", + "SETDQ(11,1,((4.0/9.0)*C(3,3)*1. + (4.0/9.0)*C(4,4)*1. + (4.0/9.0)*C(5,5)*1.) * dQmu_fac);\n", + "SETDQ(15,1,(C(3,3)*1.) * dQmu_fac);\n", + "SETDQ(18,1,(C(4,4)*1.) * dQmu_fac);\n", + "SETDQ(20,1,(C(5,5)*1.) * dQmu_fac);\n" + ] + } + ], + "source": [ + "id = 0\n", + "for i in range(6):\n", + " for j in range(i,6):\n", + " for i1,p in enumerate([Qk_fac,Qmu_fac]):\n", + " expr = sp.diff(cbak[i,j],p)\n", + " if expr != 0:\n", + " code = sp.ccode(expr)\n", + " if i1 == 0:\n", + " code = f\"({code}) * dQk_fac\"\n", + " else:\n", + " code = f\"({code}) * dQmu_fac\"\n", + " \n", + " for jj in range(1,7):\n", + " for kk in range(jj,7):\n", + " code = code.replace(f\"c{jj}{kk}\",f\"C({jj-1},{kk-1})*1.\")\n", + " print(f\"SETDQ({id},{i1},{code});\")\n", + " id += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{(C(0, 0)): c11,\n", + " (C(0, 1)): c12,\n", + " (C(0, 2)): c13,\n", + " (C(0, 3)): c14,\n", + " (C(0, 4)): c15,\n", + " (C(0, 5)): c16,\n", + " (C(1, 1)): c22,\n", + " (C(1, 2)): c23,\n", + " (C(1, 3)): c24,\n", + " (C(1, 4)): c25,\n", + " (C(1, 5)): c26,\n", + " (C(2, 2)): c33,\n", + " (C(2, 3)): c34,\n", + " (C(2, 4)): c35,\n", + " (C(2, 5)): c36,\n", + " (C(3, 3)): c44,\n", + " (C(3, 4)): c45,\n", + " (C(3, 5)): c46,\n", + " (C(4, 4)): c55,\n", + " (C(4, 5)): c56,\n", + " (C(5, 5)): c66}" + ] + }, + "execution_count": 60, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "subs" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np \n", + "from scipy.linalg import qz,eig\n", + "from numba import jit " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "@jit(nopython=True)\n", + "def solve_eigenvec(AA,BB,lamb_,Q,Z,right=True):\n", + " if right:\n", + " n = AA.shape[0]\n", + " vr = np.zeros_like(AA)\n", + "\n", + " for i in range(n):\n", + " e = lamb_[i]\n", + "\n", + " # backward substitution\n", + " for j in range(i+1,n):\n", + " vr[j,i] = 0.\n", + " vr[i,i] = 1.\n", + " for j in range(i-1,-1,-1):\n", + " s = 0\n", + " for k in range(j+1,i+1):\n", + " f = AA[j,k] - e * BB[j,k]\n", + " s += f * vr[k,i]\n", + " #s = sum(S[j,j+1:i+1] * vr[j+1:i+1,i])\n", + " vr[j,i] = -s / (AA[j,j] - e * BB[j,j])\n", + " vr = Z @ vr \n", + "\n", + " # normalize\n", + " for i in range(n):\n", + " vr[:,i] = vr[:,i] / np.linalg.norm(vr[:,i])\n", + "\n", + " return vr \n", + " else:\n", + " n = AA.shape[0]\n", + " vl = np.zeros_like(AA)\n", + "\n", + " for i in range(n):\n", + " e = lamb_[i]\n", + " # S = AA - e * BB \n", + " # S[i,i] = 0\n", + " # S = np.conj(S).T \n", + "\n", + " # forward substitution\n", + " vl[:i,i] = 0\n", + " vl[i,i] = 1.\n", + " for j in range(i+1,n):\n", + " s = 0\n", + " for k in range(i,j):\n", + " f = np.conj(AA[k,j] - e * BB[k,j])\n", + " s += f * vl[k,i]\n", + " #s = sum(S[j,i:j] * vl[i:j,i])\n", + " vl[j,i] = -s / np.conj(AA[j,j] - e * BB[j,j])\n", + " vl = Q @ vl \n", + " for i in range(n):\n", + " vl[:,i] = vl[:,i] / np.linalg.norm(vl[:,i])\n", + " \n", + " return vl" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def ggev(A,B,VL=False,VR=False):\n", + " AA,BB,Q,Z = qz(A,B)\n", + "\n", + " # get eigenvalues \n", + " lamb_ = np.diag(AA) / np.diag(BB)\n", + "\n", + " # init\n", + " vr = None \n", + " vl = None \n", + "\n", + " if VR:\n", + " vr = solve_eigenvec(AA,BB,lamb_,Q,Z)\n", + " \n", + " if VL:\n", + " vl = solve_eigenvec(AA,BB,lamb_,Q,Z,False)\n", + "\n", + " if VR and VL:\n", + " return lamb_,vr,vl \n", + " elif VR and (not VL):\n", + " return lamb_,vr \n", + " elif VL and (not VR):\n", + " return lamb_,vl \n", + " else:\n", + " return lamb_" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(100)\n", + "n = 500\n", + "A = np.random.rand(n,n) + 1j * np.random.rand(n,n) \n", + "B = np.random.rand(n,n)+ 1j * np.random.rand(n,n) \n", + "\n", + "lamb_,vr0,vl0 = ggev(A,B,True,True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "w,vl,vr = eig(A,B,True)\n", + "for i in range(n):\n", + " vl[:,i] = vl[:,i] / np.linalg.norm(vl[:,i])" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.7179544901742047e-14" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.linalg.norm(vr - vr0)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.795442206848664e-14" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.linalg.norm(vl - vl0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code_gen/tti_code_gen.ipynb b/code_gen/tti_code_gen.ipynb index 20e8c49..5b32fb7 100644 --- a/code_gen/tti_code_gen.ipynb +++ b/code_gen/tti_code_gen.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -25,6 +25,104 @@ " return out" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def voigt_index(i, j):\n", + " \"\"\"\n", + " Maps tensor indices (i, j) to Voigt notation index.\n", + " \n", + " Parameters:\n", + " i (int): Row index (0-based).\n", + " j (int): Column index (0-based).\n", + " \n", + " Returns:\n", + " int: Voigt notation index (0-based).\n", + " \"\"\"\n", + " if i > j: # Ensure the indices are in upper triangular order (i <= j)\n", + " i, j = j, i\n", + "\n", + " mapping = {\n", + " (0, 0): 0, # sigma_11\n", + " (1, 1): 1, # sigma_22\n", + " (2, 2): 2, # sigma_33\n", + " (1, 2): 3, # sigma_23\n", + " (0, 2): 4, # sigma_13\n", + " (0, 1): 5 # sigma_12\n", + " }\n", + "\n", + " return mapping.get((i, j), None)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 lambda\n", + "1 lambda\n", + "2 2*lambda\n", + "3 0\n", + "4 0\n", + "5 0\n", + "6 lambda\n", + "7 2*lambda\n", + "8 0\n", + "9 0\n", + "10 0\n", + "11 lambda\n", + "12 0\n", + "13 0\n", + "14 0\n", + "15 0\n", + "16 0\n", + "17 0\n", + "18 0\n", + "19 0\n", + "20 0\n" + ] + } + ], + "source": [ + "lam = sp.symbols(\"lambda\")\n", + "c = sp.Array.zeros(3,3,3,3)\n", + "c = c.as_mutable()\n", + "for i in range(3):\n", + " for j in range(3):\n", + " for p in range(3):\n", + " for q in range(3):\n", + " c[i,j,p,q] = ctensor_tti(lam,0,lam,0,2*lam,[0,0,1],i,j,p,q)\n", + "\n", + "c21 = sp.Array.zeros(6,6)\n", + "c21 = c21.as_mutable()\n", + "for i in range(3):\n", + " for j in range(3):\n", + " i1 = voigt_index(i,j)\n", + " for p in range(3):\n", + " for q in range(3):\n", + " j1 = voigt_index(p,q)\n", + " c21[i1,j1] = c[i,j,p,q]\n", + "id = 0\n", + "for i in range(6):\n", + " for j in range(i,6):\n", + " id += 1\n", + " print(id-1,c21[i,j])" + ] + }, { "cell_type": "code", "execution_count": 72, @@ -554,11 +652,16 @@ "display(T[1] - T1.dot(t1))\n", "display(T[2] - T1[2])" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "base", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -572,7 +675,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.12.2" } }, "nbformat": 4, diff --git a/doxygen/config.cfg b/doxygen/config.cfg deleted file mode 100644 index e1b851a..0000000 --- a/doxygen/config.cfg +++ /dev/null @@ -1,5 +0,0 @@ -PROJECT_NAME = SpecSWD -INPUT = ../include ../src/multiphysics ../src/vti ../src/tti ../src/shared -GENERATE_HTML = YES -HTML_FILE_EXTENSION = .html -FULL_PATH_NAMES = NO \ No newline at end of file diff --git a/doxygen/specswd.pdf b/doxygen/specswd.pdf deleted file mode 100644 index 47daa92..0000000 Binary files a/doxygen/specswd.pdf and /dev/null differ diff --git a/example/love/benchmark.py b/example/love/benchmark.py new file mode 100644 index 0000000..5c78779 --- /dev/null +++ b/example/love/benchmark.py @@ -0,0 +1,569 @@ +import numpy as np +import h5py +import sys +import matplotlib.pyplot as plt +from numba import jit + +import matplotlib as mpl +mpl.rcParams['lines.linewidth'] = 1.5 +mpl.rcParams['font.size'] = 10 +mpl.rcParams['xtick.labelsize']=15 +mpl.rcParams['ytick.labelsize']=15 +mpl.rcParams['axes.labelsize']=15 +mpl.rcParams['legend.fontsize'] = 20 +mpl.rcParams['legend.fontsize'] = 20 +mpl.rcParams['savefig.bbox'] = 'tight' + +@jit(nopython=True) +def get_Q_sls_model(Q): + + y_sls_ref = np.array([1.93044501, 1.64217132, 1.73606189, 1.42826439, 1.66934129]) + w_sls_ref = np.array([4.71238898e-02, 6.63370885e-01, 9.42477796e+00, 1.14672436e+02,1.05597079e+03]) + dy = y_sls_ref * 0 + y = y_sls_ref * 0 + NSLS = len(y) + + for i in range(NSLS): + y[i] = y_sls_ref[i] / Q + dy[0] = 1. + 0.5 * y[0] + + for i in range(1,NSLS): + dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i] + + #// copy to y_sls/w_sls + w_sls = w_sls_ref * 1. + y_sls = dy * y + + return w_sls,y_sls + +@jit(nopython=True) +def compute_q_sls_model(y_sls,w_sls,om,exact=False): + Q_ls = 1. + nsls = len(y_sls) + if exact: + for p in range(nsls): + Q_ls += y_sls[p] * om**2 / (om**2 + w_sls[p]**2) + + # denom + Q_demon = 0. + for p in range(nsls): + Q_demon += y_sls[p] * om * w_sls[p] / (om**2 + w_sls[p]**2) + + return Q_ls / Q_demon + +@jit(nopython=True) +def get_sls_modulus_factor(freq,Q): + om = 2 * np.pi * freq + + w_sls,y_sls = get_Q_sls_model(Q) + s = np.sum(1j * om * y_sls / (w_sls + 1j * om)) + + return s + 1. + +@jit(nopython=True) +def get_sls_Q_deriv(freq,Q): + y_sls_ref = np.array([1.93044501, 1.64217132, 1.73606189, 1.42826439, 1.66934129]) + w_sls_ref = np.array([4.71238898e-02, 6.63370885e-01, 9.42477796e+00, 1.14672436e+02,1.05597079e+03]) + dy = y_sls_ref * 0 + y = y_sls_ref / Q + + # corrector + NSLS = len(y_sls_ref) + dy[0] = 1. + 0.5 * y[0] + for i in range(1,NSLS): + dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i] + dd_dqi = dy * 0 + dd_dqi[0] = 0.5 * y_sls_ref[0] + for i in range(1,NSLS): + dd_dqi[i] = dd_dqi[i-1] + (dy[i-1] - 0.5) * y_sls_ref[i-1] + dd_dqi[i-1] * y[i-1] + 0.5 * y_sls_ref[i] + + dd_dqi = dd_dqi * y + dy * y_sls_ref + om = 2 * np.pi * freq + dsdqi = np.sum(1j * om * dd_dqi /(w_sls_ref + 1j * om)) + s = np.sum(1j * om * y * dy / (w_sls_ref + 1j * om)) + + return s + 1., dsdqi + + + +def get_group(c,r1,r2,bev1,bev2,beh1,beh2,H,om,HAS_ATT,Qv1,Qv2,Qh1,Qh2): + freq = om / (2 * np.pi) + + L1 = r1 * bev1**2 + L2 = r2 * bev2**2 + N1 = r1 * beh1**2 + N2 = r2 * beh2**2 + if HAS_ATT: + L1 *= get_sls_modulus_factor(freq,Qv1) + L2 *= get_sls_modulus_factor(freq,Qv2) + N1 *= get_sls_modulus_factor(freq,Qh1) + N2 *= get_sls_modulus_factor(freq,Qh2) + else: + pass + + gamma2 = np.sqrt((1 - r2 * c**2/N2) * N2/L2) + Omega = om/c * H * gamma2 * ( + ((r1 * c**2 - N1) / (N2 - r2 / r1 * N1)) + + (L2 / L1) * ((N2 - r2*c**2) / (N2 - r2/r1 * N1)) + ) + u = N1 / (c * r1) * ( c**2 * r1 / N1 + Omega) / ( 1 + Omega) + + return u + +def get_cQ_kl(dcdm,cc): + cl = np.real(cc) + Qi = 2. * np.imag(cc) / cl + dcLdm = np.real(dcdm) + dQiLdm = (np.imag(dcdm) * 2. - Qi * dcLdm) / cl + + return dcLdm,dQiLdm + +def transform_kernel(dcc_dcL1,dcc_dcL2,dcc_dcN1,dcc_dcN2,dcc_dr1,dcc_dr2, + sl1,sl2,sn1,sn2,dsdqil1,dsdqil2,dsdqin1,dsdqin2, + L1_r,L2_r,N1_r,N2_r,rho1,rho2,c,keep_modulus=False): + # convert dm to real parameters + dcc_dL1,dcc_dQil1 = dcc_dcL1 * sl1, dcc_dcL1 * L1_r * dsdqil1 + dcc_dL2,dcc_dQil2 = dcc_dcL2 * sl2, dcc_dcL2 * L2_r * dsdqil2 + dcc_dN1,dcc_dQin1 = dcc_dcN1 * sn1, dcc_dcN1 * N1_r * dsdqin1 + dcc_dN2,dcc_dQin2 = dcc_dcN2 * sn2, dcc_dcN2 * N2_r * dsdqin2 + + # dictionary to save all derivatives + D = np.zeros((2,5,2)) # (dcordq,5params, 2 layer) + D[:,0,0] = get_cQ_kl(dcc_dL1,c) + D[:,0,1] = get_cQ_kl(dcc_dL2,c) + D[:,1,0] = get_cQ_kl(dcc_dN1,c) + D[:,1,1] = get_cQ_kl(dcc_dN2,c) + D[:,2,0] = get_cQ_kl(dcc_dQin1,c) + D[:,2,1] = get_cQ_kl(dcc_dQin2,c) + D[:,3,0] = get_cQ_kl(dcc_dQil1,c) + D[:,3,1] = get_cQ_kl(dcc_dQil2,c) + D[:,4,0] = get_cQ_kl(dcc_dr1,c) + D[:,4,1] = get_cQ_kl(dcc_dr2,c) + if keep_modulus: + temp = D[:,0,:] * 1. + D[:,0,:] = D[:,1,:] * 1. + D[:,1,:] = temp * 1. + + return D + + # transform to vsv,vsh kernels + bv1 = np.sqrt(L1_r / rho1); bv2 = np.sqrt(L2_r / rho2) + bh1 = np.sqrt(N1_r / rho1); bh2 = np.sqrt(N2_r / rho2) + + # kernels + vsv_kl = np.zeros((2,2)) + vsh_kl = np.zeros((2,2)) + rho_kl = np.zeros((2,2)) + vsv_kl[:,0] = D[:,0,0] * 2. * rho1 * bv1 + vsv_kl[:,1] = D[:,0,1] * 2. * rho2 * bv2 + vsh_kl[:,0] = D[:,1,0] * 2. * rho1 * bh1 + vsh_kl[:,1] = D[:,1,1] * 2. * rho2 * bh2 + rho_kl[:,0] = D[:,4,0] + bv1**2 * D[:,0,0] + bh1**2 * D[:,1,0] + rho_kl[:,1] = D[:,4,1] + bv2**2 * D[:,0,1] + bh2**2 * D[:,1,1] + + # copy back + D[:,0,:] = vsh_kl[:,:] + D[:,1,:] = vsv_kl[:,:] + D[:,4,:] = rho_kl[:,:] + + return D + + +def love_func(c,r1,r2,bev1,bev2,beh1,beh2,Qv1,Qv2,Qh1,Qh2,H,om,HAS_ATT,phase_kl=True): + freq = om / np.pi / 2 + L1_r = r1 * bev1**2 + L2_r = r2 * bev2**2 + N1_r = r1 * beh1**2 + N2_r = r2 * beh2**2 + + # factor and deriv + if HAS_ATT: + sn1,dsdqin1 = get_sls_Q_deriv(freq,Qh1) + sn2,dsdqin2 = get_sls_Q_deriv(freq,Qh2) + sl1,dsdqil1 = get_sls_Q_deriv(freq,Qv1) + sl2,dsdqil2 = get_sls_Q_deriv(freq,Qv2) + else: + sn1,dsdqin1 = 1.,0. + sn2,dsdqin2 = 1.,0. + sl1,dsdqil1 = 1.,0. + sl2,dsdqil2 = 1.,0. + + # complex modulus + L1 = L1_r * sl1 + L2 = L2_r * sl2 + N1 = N1_r * sn1 + N2 = N2_r * sn2 + + bv1 = np.sqrt(L1 / r1) + bv2 = np.sqrt(L2 / r2) + bh1 = np.sqrt(N1 / r1) + bh2 = np.sqrt(N2 / r2) + + k = om / c + t1 = np.sqrt(c**2 - bh1**2) + t2 = np.sqrt(bh2**2 - c**2) + temp = np.tan(k * H / bv1 * t1) + f = L2 / (L1) * t2 / bv2 + f -= t1 / bv1 * temp + #f = -np.sqrt(-N1/L1 + c**2*r1/L1)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c) + L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1 + #f = L2/L1 * np.sqrt((N2/L2)**2 - (r2 * c/L2)**2) - np.sqrt((c *r1/L1)**2 - (N1/L1)**2) * np.tan((om * H)/c *np.sqrt((c * r1/ L1)**2 - (N1/L1)**2)) + f = -np.sqrt(-N1/L1 + c**2*r1/L1)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c) + L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1 + + # derivative df/dc + fd = - L2 * bv1 / (L1 * bv2) * c / t2 + fd += -c / t1 * temp + fd += -t1 * (1 + temp**2) * (- om * H / c**2 / bv1 * t1 + om * H / bv1 / t1 ) + fd = -np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)) + + # d(\tilde{c})/dL1/L2/N1/N2/rho + if phase_kl: + dcc_dcL2=(-L2*(-1/2*N2/L2**2 + (1/2)*c**2*r2/L2**2)/(L1*np.sqrt(N2/L2 - c**2*r2/L2)) - np.sqrt(N2/L2 - c**2*r2/L2)/L1)/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + dcc_dcL1=(H*om*((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/c + ((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/np.sqrt(-N1/L1 + c**2*r1/L1) + L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1**2)/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + dcc_dcN2=-(1/2)/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))) + dcc_dcN1=(-1/2*H*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/(L1*c) - 1/2*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + dcc_dr2=(1/2)*c**2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))) + dcc_dr1=((1/2)*H*c*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/L1 + (1/2)*c**2*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + + D = transform_kernel(dcc_dcL1,dcc_dcL2,dcc_dcN1,dcc_dcN2,dcc_dr1,dcc_dr2, + sl1,sl2,sn1,sn2,dsdqil1,dsdqil2,dsdqin1,dsdqin2, + L1_r,L2_r,N1_r,N2_r,r1,r2,c) + else: + gamma2 = np.sqrt((1 - r2 * c**2/N2) * N2/L2) + Omega = om/c * H * gamma2 * ( + ((r1 * c**2 - N1) / (N2 - r2 / r1 * N1)) + + (L2 / L1) * ((N2 - r2*c**2) / (N2 - r2/r1 * N1)) + ) + u = N1 / (c * r1) * ( c**2 * r1 / N1 + Omega) / ( 1 + Omega) + dcc_dcL2=(L2*(-1/2*N2/L2**2 + (1/2)*c**2*r2/L2**2)/(L1*np.sqrt(N2/L2 - c**2*r2/L2)) + np.sqrt(N2/L2 - c**2*r2/L2)/L1)*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + (-1/2*H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(L2*c) + H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)/(L1*c*(-N1*r2/r1 + N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + ((1/2)*H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(L2*c) - H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)/(L1*c*(-N1*r2/r1 + N2)))*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + dcc_dcL1=-H*L2*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)/(L1**2*c**2*r1*(-N1*r2/r1 + N2)*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + H*L2*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N2 - c**2*r2)*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(L1**2*c**2*r1*(-N1*r2/r1 + N2)*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))*(-H*om*((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/c - ((1/2)*N1/L1**2 - 1/2*c**2*r1/L1**2)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/np.sqrt(-N1/L1 + c**2*r1/L1) - L2*np.sqrt(N2/L2 - c**2*r2/L2)/L1**2)/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + dcc_dcN2=(H*L2*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((1/2)*(1 - c**2*r2/N2)/L2 + (1/2)*c**2*r2/(L2*N2))*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*c*(1 - c**2*r2/N2)) + H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-(-N1 + c**2*r1)/(-N1*r2/r1 + N2)**2 - L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)**2) + L2/(L1*(-N1*r2/r1 + N2)))/c)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*L2*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((1/2)*(1 - c**2*r2/N2)/L2 + (1/2)*c**2*r2/(L2*N2))*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*c*(1 - c**2*r2/N2)) - H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-(-N1 + c**2*r1)/(-N1*r2/r1 + N2)**2 - L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)**2) + L2/(L1*(-N1*r2/r1 + N2)))/c)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (1/2)*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))) + dcc_dcN1=-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-1/(-N1*r2/r1 + N2) + r2*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*r2*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2))/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + ((1/2)*H*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/(L1*c) + (1/2)*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-1/(-N1*r2/r1 + N2) + r2*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*r2*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + dcc_dr2=(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N1*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*N1*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2) - L2*c**2/(L1*(-N1*r2/r1 + N2)))/c - 1/2*H*N1*c*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + (-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(N1*(-N1 + c**2*r1)/(r1*(-N1*r2/r1 + N2)**2) + L2*N1*(N2 - c**2*r2)/(L1*r1*(-N1*r2/r1 + N2)**2) - L2*c**2/(L1*(-N1*r2/r1 + N2)))/c + (1/2)*H*c*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) - 1/2*c**2*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(L1*np.sqrt(N2/L2 - c**2*r2/L2)*(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2)))) + dcc_dr1=-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-N1*r2*(-N1 + c**2*r1)/(r1**2*(-N1*r2/r1 + N2)**2) + c**2/(-N1*r2/r1 + N2) - L2*N1*r2*(N2 - c**2*r2)/(L1*r1**2*(-N1*r2/r1 + N2)**2))/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (-1/2*H*c*om*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1)/L1 - 1/2*c**2*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(-(H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c - H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 - H*N1*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)) + 2*c*r1)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)*(-H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(2*c*r1/(-N1*r2/r1 + N2) - 2*L2*c*r2/(L1*(-N1*r2/r1 + N2)))/c + H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c**2 + H*om*r2*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/(N2*(1 - c**2*r2/N2)))/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)**2) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c**2*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)))/(-np.sqrt(-N1/L1 + c**2*r1/L1)*(-H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c**2 + H*om*r1/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)))*(np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)**2 + 1) - c*r1*np.tan(H*om*np.sqrt(-N1/L1 + c**2*r1/L1)/c)/(L1*np.sqrt(-N1/L1 + c**2*r1/L1)) - c*r2/(L1*np.sqrt(N2/L2 - c**2*r2/L2))) + (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*(-N1*r2*(-N1 + c**2*r1)/(r1**2*(-N1*r2/r1 + N2)**2) + c**2/(-N1*r2/r1 + N2) - L2*N1*r2*(N2 - c**2*r2)/(L1*r1**2*(-N1*r2/r1 + N2)**2))/c + c**2)/(c*r1*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) - (H*N1*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + c**2*r1)/(c*r1**2*(H*om*np.sqrt(N2*(1 - c**2*r2/N2)/L2)*((-N1 + c**2*r1)/(-N1*r2/r1 + N2) + L2*(N2 - c**2*r2)/(L1*(-N1*r2/r1 + N2)))/c + 1)) + + D = transform_kernel(dcc_dcL1,dcc_dcL2,dcc_dcN1,dcc_dcN2,dcc_dr1,dcc_dr2, + sl1,sl2,sn1,sn2,dsdqil1,dsdqil2,dsdqin1,dsdqin2, + L1_r,L2_r,N1_r,N2_r,r1,r2,u) + + if not HAS_ATT: + D1 = np.zeros((2,3,2)) + D1[:,:,:] = D[:,[0,1,4],:] + else: + D1 = D * 1. + + return f,fd,D1 + +def get_deriv_2layer_h5(fio:h5py,HAS_ATT:bool,gname:str): + if not HAS_ATT: + kl_name = ['vsh','vsv','rho'] + D = np.zeros((2,3,2)) + + for iker in range(len(kl_name)): + a = fio[f"{gname}/C_{kl_name[iker]}"][:] + a1 = a[0] + a[1] + a2 = a[2] + + D[0,iker,:] = [a1,a2] + + return D + else: + D = np.zeros((2,5,2)) + kl_name = ['vsh','vsv','Qvsh','Qvsv','rho'] + for iker in range(len(kl_name)): + a = fio[f"{gname}/C_{kl_name[iker]}"][:] + q = fio[f"{gname}/Q_{kl_name[iker]}"][:] + a1 = a[0] + a[1] + a2 = a[2] + q1 = q[0] + q[1] + q2 = q[2] + + D[0,iker,:] = [a1,a2] + D[1,iker,:] = [q1,q2] + + return D + +def main(): + if len(sys.argv) > 3: + print("usage: python compute_group [max_order=5 phase_kl=0]") + exit(1) + print(sys.argv) + + if len(sys.argv) >= 2: + ncplot = int(sys.argv[1]) + else: + ncplot = 5 + + if len(sys.argv) == 3: + phase_kl = int(sys.argv[2]) == 0 + else: + phase_kl = True + + if phase_kl: + print("ploting phase kernels ...") + else: + print("ploting group kernels ...") + + # open h5file + fio = h5py.File("out/kernels.h5","r") + + # load velocity model + HAS_ATT = np.loadtxt("model.txt",max_rows=1,dtype=int)[1] + + # colormap + #cmap = mpl.cm.get_cmap("jet",ncplot) + cmap = plt.get_cmap("viridis",ncplot) + norm = mpl.colors.Normalize(vmin=0, vmax=ncplot-1) # Normalize the color range + + # find phase velocity + T0 = np.loadtxt("out/swd.txt",max_rows=1) + nt = len(T0) + if HAS_ATT ==0: + + # load model + model = np.loadtxt("model.txt",skiprows=1) + rho1,bh1,bv1 = model[0,1:4] + H,rho2,bh2,bv2 = model[-1,0:4] + print(H,rho2,bv2,bh2) + + # initialize figures + fig1,ax1 = plt.subplots(1,2,figsize=(15,6)) + fig2,ax2 = plt.subplots(2,2,figsize=(15,12)) + fig3,ax3 = plt.subplots(2,2,figsize=(15,12)) + + # loop every mode + for imode in range(ncplot): + gname = f"swd/mode{imode}/" + if gname not in fio.keys(): + continue + + # load data + T = fio[f"{gname}/T"][:] + c = fio[f"{gname}/c"][:] + u = fio[f"{gname}/u"][:] + + phase_deriv = np.zeros((2,3,2,len(T))) + dc = c * 0. + ua = c * 0. + phase_sem = phase_deriv * 0. + for it in range(len(T)): + f0,dfdc,D = love_func(c[it],rho1,rho2,bv1,bv2,bh1, + bh2,1.,1.,1.,1.,H,2*np.pi/T[it], + HAS_ATT,phase_kl) + ua[it] = get_group(c[it],rho1,rho2,bv1,bv2, + bh1,bh2,H,2*np.pi/T[it],HAS_ATT, + 1.,1.,1.,1.) + dc[it] = 100 * abs(f0 / dfdc / c[it]) + phase_deriv[...,it] = D * 1. + + # compute phase_sem + idx = np.where(abs(T[it]-T0) < 1.0e-4)[0][0] + phase_sem[...,it] = get_deriv_2layer_h5(fio,HAS_ATT,f"kernels/{idx}/mode{imode}") + + # plot phase + # plot + label3 = "SEM" + label4 = "Analytical" + if imode != ncplot -1: + label3 = None + label4 = None + + # phase velocity + ax1[0].scatter(1./T,dc,s=14,color=cmap(imode)) + ax1[1].plot(1./T,u,color=cmap(imode)) + ax1[1].scatter(1./T,ua.real,color='k',s=10,label=label4) + + # derivatives + for i in range(2): + for j in range(2): + a1 = phase_sem[0,i,j,:] + a2 = phase_deriv[0,i,j,:] + ax2[i,j].plot(1./T,a1,color=cmap(imode)) + ax2[i,j].scatter(1./T,a2,color='k',s=5,label=label4) + # ax2[i,j].plot(1./T,a1,color=cmap(imode)) + # ax2[i,j].scatter(1./T,a2,color='k',s=10,label=label4) + + # a1 = phase_sem[0,i+2,j,:] + # a2 = phase_deriv[0,i+2,j,:] + # ax3[i,j].plot(1./T,a1,color=cmap(imode)) + # ax3[i,j].scatter(1./T,a2,color='k',s=5,label=label4) + + # labels + # ax1.legend() + # ax2.legend() + + ax1[0].set_title("(a)",loc='left') + ax1[0].set_yscale("log") + ax1[0].set_ylabel(r"Relative Error % $|\frac{dc}{c}|$") + ax1[0].set_xlabel("Frequency,Hz") + ax1[1].set_title("(b)",loc='left') + ax1[1].set_ylabel("Group Velocity, km/s") + ax1[1].set_xlabel("Frequency,Hz") + + # ylabel + if phase_kl: + ax2[0,0].set_ylabel(r"$dc/d\beta_{h1}$") + ax2[0,1].set_ylabel(r"$dc/d\beta_{h2}$") + ax2[1,0].set_ylabel(r"$dc/d\beta_{v1}$") + ax2[1,1].set_ylabel(r"$dc/d\beta_{v2}$") + else: + ax2[0,0].set_ylabel(r"$dU/d\beta_{h1}$") + ax2[0,1].set_ylabel(r"$dU/d\beta_{h2}$") + ax2[1,0].set_ylabel(r"$dU/d\beta_{v1}$") + ax2[1,1].set_ylabel(r"$dU/d\beta_{v2}$") + + for i in range(2): ax2[1,i].set_xlabel("Frquency,Hz") + + + for i in range(2): ax3[1,i].set_xlabel("Frquency,Hz") + + kl_type = "phase" + if phase_kl == False: + kl_type = "group" + fig1.savefig("eigenvalues.jpg") + fig2.savefig(f"{kl_type}_kernel.jpg") + + else: + # load model + model = np.loadtxt("model.txt",skiprows=1) + rho1,bh1,bv1,Qh1,Qv1 = model[0,1:] + H,rho2,bh2,bv2,Qh2,Qv2 = model[-1,0:] + print(H,rho2,bv2,bh2,Qv2,Qh2) + + fig1,ax1 = plt.subplots(2,2,figsize=(14,12)) + + # axese for figure 2 + fig2,ax2 = plt.subplots(2,2,figsize=(15,12)) + + # axese for figure 3 + fig3,ax3 = plt.subplots(2,2,figsize=(15,12)) + + # loop every mode + for imode in range(ncplot): + gname = f"swd/mode{imode}/" + if gname not in fio.keys(): + continue + + # load data + T = fio[f"{gname}/T"][:] + c = fio[f"{gname}/c"][:] + cQ = fio[f"{gname}/cQ"][:] + u = fio[f"{gname}/u"][:] + uQ = fio[f"{gname}/uQ"][:] + + # compute relative error + c_cmplx = c * (1 + 1j / (2 * cQ)) + dc = c * 0.0 + ua = c_cmplx * 1.0j + phase_deriv = np.zeros((2,5,2,len(T))) + phase_sem = phase_deriv * 0. + for it in range(len(T)): + f0,dfdc,D = love_func(c_cmplx[it],rho1,rho2,bv1,bv2,bh1, + bh2,Qv1,Qv2,Qh1,Qh2,H,2*np.pi/T[it], + HAS_ATT,phase_kl) + ua[it] = get_group(c_cmplx[it],rho1,rho2,bv1,bv2, + bh1,bh2,H,2*np.pi/T[it],HAS_ATT, + Qv1,Qv2,Qh1,Qh2) + dc[it] = 100 * abs(f0 / dfdc / c_cmplx[it]) + phase_deriv[...,it] = D * 1. + + # compute phase_sem + idx = np.where(abs(T[it]-T0) < 1.0e-4)[0][0] + phase_sem[...,it] = get_deriv_2layer_h5(fio,HAS_ATT,f"kernels/{idx}/mode{imode}") + + + # plot + label3 = "SEM" + label4 = "Analytical" + if imode != ncplot -1: + label3 = None + label4 = None + + # phase velocity + ax1[0,0].plot(1./T,c,color=cmap(imode)) + ax1[0,1].scatter(1./T,dc,s=14,color=cmap(imode)) + ax1[1,0].plot(1./T,u,color=cmap(imode)) + ax1[1,0].scatter(1./T,ua.real,color='k',s=10,label=label4) + ax1[1,1].plot(1./T,uQ,color=cmap(imode)) + ax1[1,1].scatter(1./T,ua.real/ua.imag *0.5,color='k',s=10,label=label4) + + # derivatives + for i in range(2): + for j in range(2): + a1 = phase_sem[0,i,j,:] + a2 = phase_deriv[0,i,j,:] + ax2[i,j].plot(1./T,a1,color=cmap(imode)) + ax2[i,j].scatter(1./T,a2,color='k',s=5,label=label4) + # ax2[i,j].plot(1./T,a1,color=cmap(imode)) + # ax2[i,j].scatter(1./T,a2,color='k',s=10,label=label4) + + a1 = phase_sem[0,i+2,j,:] + a2 = phase_deriv[0,i+2,j,:] + ax3[i,j].plot(1./T,a1,color=cmap(imode)) + ax3[i,j].scatter(1./T,a2,color='k',s=5,label=label4) + + + ax1[0,0].set_title("(a)",loc='left') + ax1[0,0].set_ylabel("Phase Velocity, km/s") + + ax1[0,1].set_title("(b)",loc='left') + ax1[0,1].set_yscale("log") + ax1[0,1].set_ylabel(r"Relative Error % $|\frac{dc}{c}|$") + + ax1[1,1].set_xlabel("Frequency,Hz") + ax1[1,1].set_title("(d)",loc='left') + ax1[1,1].set_ylabel("Group Q") + ax1[1,1].legend() + + ax1[1,0].set_xlabel("Frequency,Hz") + ax1[1,0].set_ylabel("Group Velocity, km/s") + ax1[1,0].set_title("(c)",loc='left') + ax1[1,0].legend() + + # ylabel + if phase_kl: + ax2[0,0].set_ylabel(r"$dc/d\beta_{h1}$") + ax2[0,1].set_ylabel(r"$dc/d\beta_{h2}$") + ax2[1,0].set_ylabel(r"$dc/d\beta_{v1}$") + ax2[1,1].set_ylabel(r"$dc/d\beta_{v2}$") + ax3[0,0].set_ylabel(r"$dc/dQ^{-1}_{h1}$") + ax3[0,1].set_ylabel(r"$dc/dQ^{-1}_{h2}$") + ax3[1,0].set_ylabel(r"$dc/dQ^{-1}_{v1}$") + ax3[1,1].set_ylabel(r"$dc/dQ^{-1}_{v2}$") + else: + ax2[0,0].set_ylabel(r"$dU/d\beta_{h1}$") + ax2[0,1].set_ylabel(r"$dU/d\beta_{h2}$") + ax2[1,0].set_ylabel(r"$dU/d\beta_{v1}$") + ax2[1,1].set_ylabel(r"$dU/d\beta_{v2}$") + ax3[0,0].set_ylabel(r"$dU/dQ^{-1}_{h1}$") + ax3[0,1].set_ylabel(r"$dU/dQ^{-1}_{h2}$") + ax3[1,0].set_ylabel(r"$dU/dQ^{-1}_{v1}$") + ax3[1,1].set_ylabel(r"$dU/dQ^{-1}_{v2}$") + + for i in range(2): ax2[1,i].set_xlabel("Frquency,Hz") + + + for i in range(2): ax3[1,i].set_xlabel("Frquency,Hz") + + for i in range(2): + for j in range(2): + ax2[i,j].legend() + ax3[i,j].legend() + + #fig2.savefig("group_att.jpg",dpi=300) + sm = plt.cm.ScalarMappable(cmap=cmap,norm=norm) + fig1.colorbar(sm,ax=ax1.ravel().tolist(),label='order',location='bottom',pad=0.075,shrink=0.4,format='%d') + fig1.savefig("eigenvalues_att.jpg",dpi=300) + + # save figure2 + fig2.colorbar(sm,ax=ax2.ravel().tolist(),label='order',location='bottom',pad=0.075,shrink=0.4,format='%d') + kl_type = "phase" + if phase_kl == False: + kl_type = "group" + fig2.savefig(f"{kl_type}_deriv_veloc_att.jpg",dpi=300) + + # save figure2 + fig3.colorbar(sm,ax=ax3.ravel().tolist(),label='order',location='bottom',pad=0.075,shrink=0.4,format='%d') + fig3.savefig(f"{kl_type}_deriv_Q_att.jpg",dpi=300) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/example/love/eigenvalues_att.jpg b/example/love/eigenvalues_att.jpg new file mode 100644 index 0000000..3fe6f29 Binary files /dev/null and b/example/love/eigenvalues_att.jpg differ diff --git a/example/love/gen_model.py b/example/love/gen_model.py index cd48e2d..df9fad6 100644 --- a/example/love/gen_model.py +++ b/example/love/gen_model.py @@ -1,22 +1,14 @@ import numpy as np -# z = np.linspace(0,50,10) -# nz = len(z) -# vs = 3.5 + 0.02 * z -z = np.array([0,30]) +z = np.array([0,35,35]) nz = len(z) -vs = np.array([3.0,4.0]) +vs = np.array([3.0,3.0,5.0]) +rho = np.array([2.8,2.8,3.2]) -# vs[10:20] = 1.4 -# vs[40:50] = 2.5 +f = open("model.txt","w") +f.write("0 0\n") -vp = 1.732 * vs -rho = 0.3601 * vp + 0.541 -thk = np.zeros_like(z) -thk[0:nz-1] = np.diff(z) +for i in range(len(z)): + f.write("%f %f %f %f 200. 200.\n"%(z[i],rho[i],vs[i],vs[i])) -f = open("model.txt","w") -f.write("%d\n"%(nz)) -for i in range(nz): - f.write("%f %f %f %f %f %f 1.\n"%(thk[i],rho[i],vp[i],vp[i],vs[i],vs[i])) f.close() \ No newline at end of file diff --git a/example/love/group.jpg b/example/love/group.jpg deleted file mode 100644 index 6fb16f1..0000000 Binary files a/example/love/group.jpg and /dev/null differ diff --git a/example/love/group_deriv_Q_att.jpg b/example/love/group_deriv_Q_att.jpg new file mode 100644 index 0000000..4219008 Binary files /dev/null and b/example/love/group_deriv_Q_att.jpg differ diff --git a/example/love/group_deriv_veloc_att.jpg b/example/love/group_deriv_veloc_att.jpg new file mode 100644 index 0000000..4d49bb6 Binary files /dev/null and b/example/love/group_deriv_veloc_att.jpg differ diff --git a/example/love/kernel.jpg b/example/love/kernel.jpg deleted file mode 100644 index 9de1d7b..0000000 Binary files a/example/love/kernel.jpg and /dev/null differ diff --git a/example/love/model.txt b/example/love/model.txt index ea54240..e86913c 100644 --- a/example/love/model.txt +++ b/example/love/model.txt @@ -1,3 +1,4 @@ -2 -30.000000 2.412080 5.196000 5.196000 3.000000 3.000000 1. -0.000000 3.035773 6.928000 6.928000 4.000000 4.000000 1. +0 1 # z rho vsh vsv QN QL +0.000000 2.800000 3.300000 3.000000 220. 200. +35.000000 2.800000 3.300000 3.000000 220. 200. +35.000000 3.200000 5.500000 5.000000 330. 300. \ No newline at end of file diff --git a/example/love/model.txt.cps b/example/love/model.txt.cps new file mode 100644 index 0000000..129ff19 --- /dev/null +++ b/example/love/model.txt.cps @@ -0,0 +1,3 @@ +2 +35.000000 2.800000 6. 6. 3.000000 3.000000 200. 200. +35.000000 3.200000 6. 6. 5.000000 5.000000 200. 200. diff --git a/example/love/out/database.bin b/example/love/out/database.bin new file mode 100644 index 0000000..221ae07 Binary files /dev/null and b/example/love/out/database.bin differ diff --git a/example/love/out/kernels.h5 b/example/love/out/kernels.h5 new file mode 100644 index 0000000..08225b9 Binary files /dev/null and b/example/love/out/kernels.h5 differ diff --git a/example/love/out/swd.txt b/example/love/out/swd.txt new file mode 100644 index 0000000..65599eb --- /dev/null +++ b/example/love/out/swd.txt @@ -0,0 +1,2220 @@ +100 99.0814 98.1712 97.2693 96.3758 95.4904 94.6132 93.7441 92.8829 92.0297 91.1843 90.3466 89.5166 88.6943 87.8795 87.0722 86.2724 85.4798 84.6946 83.9166 83.1457 82.3819 81.6251 80.8752 80.1323 79.3962 78.6668 77.9442 77.2281 76.5187 75.8158 75.1193 74.4292 73.7455 73.068 72.3968 71.7317 71.0728 70.4199 69.773 69.132 68.497 67.8677 67.2443 66.6265 66.0145 65.4081 64.8072 64.2119 63.622 63.0375 62.4584 61.8847 61.3162 60.7529 60.1948 59.6418 59.094 58.5511 58.0132 57.4803 56.9523 56.4291 55.9107 55.3971 54.8882 54.384 53.8844 53.3894 52.8989 52.413 51.9315 51.4544 50.9818 50.5134 50.0494 49.5896 49.1341 48.6827 48.2355 47.7924 47.3533 46.9183 46.4873 46.0603 45.6372 45.2179 44.8025 44.391 43.9832 43.5791 43.1788 42.7821 42.3891 41.9997 41.6139 41.2316 40.8529 40.4776 40.1057 39.7373 39.3723 39.0106 38.6522 38.2971 37.9453 37.5967 37.2514 36.9092 36.5701 36.2342 35.9013 35.5715 35.2447 34.921 34.6002 34.2823 33.9674 33.6553 33.3462 33.0399 32.7363 32.4356 32.1376 31.8424 31.5499 31.2601 30.9729 30.6884 30.4065 30.1271 29.8504 29.5762 29.3045 29.0353 28.7685 28.5043 28.2424 27.983 27.7259 27.4712 27.2188 26.9688 26.7211 26.4756 26.2324 25.9914 25.7526 25.5161 25.2817 25.0494 24.8193 24.5913 24.3654 24.1416 23.9198 23.7001 23.4823 23.2666 23.0529 22.8411 22.6313 22.4234 22.2174 22.0133 21.8111 21.6107 21.4122 21.2155 21.0206 20.8275 20.6362 20.4466 20.2588 20.0727 19.8883 19.7056 19.5246 19.3452 19.1675 18.9914 18.8169 18.6441 18.4728 18.3031 18.135 17.9684 17.8033 17.6398 17.4777 17.3172 17.1581 17.0005 16.8443 16.6896 16.5362 16.3843 16.2338 16.0847 15.9369 15.7905 15.6455 15.5018 15.3593 15.2183 15.0785 14.9399 14.8027 14.6667 14.532 14.3985 14.2662 14.1352 14.0053 13.8766 13.7492 13.6229 13.4977 13.3737 13.2509 13.1291 13.0085 12.889 12.7706 12.6533 12.5371 12.4219 12.3078 12.1947 12.0827 11.9717 11.8617 11.7528 11.6448 11.5378 11.4318 11.3268 11.2228 11.1197 11.0175 10.9163 10.816 10.7167 10.6182 10.5207 10.424 10.3283 10.2334 10.1394 10.0463 9.95396 9.86252 9.77192 9.68215 9.59321 9.50508 9.41777 9.33125 9.24553 9.1606 9.07645 8.99307 8.91045 8.8286 8.7475 8.66714 8.58752 8.50863 8.43047 8.35302 8.27629 8.20026 8.12493 8.05029 7.97634 7.90307 7.83047 7.75853 7.68726 7.61664 7.54667 7.47735 7.40866 7.3406 7.27317 7.20635 7.14015 7.07456 7.00957 6.94518 6.88138 6.81816 6.75553 6.69347 6.63198 6.57106 6.51069 6.45088 6.39162 6.33291 6.27473 6.21709 6.15998 6.10339 6.04732 5.99177 5.93673 5.88219 5.82815 5.77462 5.72157 5.66901 5.61693 5.56533 5.51421 5.46355 5.41336 5.36363 5.31436 5.26554 5.21717 5.16924 5.12176 5.07471 5.02809 4.9819 4.93613 4.89079 4.84586 4.80134 4.75724 4.71353 4.67023 4.62733 4.58482 4.54271 4.50098 4.45963 4.41866 4.37807 4.33785 4.298 4.25852 4.2194 4.18064 4.14223 4.10418 4.06648 4.02912 3.99211 3.95544 3.9191 3.8831 3.84743 3.81208 3.77706 3.74237 3.70799 3.67392 3.64017 3.60673 3.5736 3.54077 3.50825 3.47602 3.44409 3.41245 3.3811 3.35004 3.31927 3.28877 3.25856 3.22863 3.19897 3.16958 3.14047 3.11162 3.08303 3.05471 3.02665 2.99884 2.9713 2.944 2.91696 2.89016 2.86361 2.8373 2.81124 2.78541 2.75983 2.73447 2.70935 2.68446 2.6598 2.63537 2.61116 2.58717 2.56341 2.53986 2.51653 2.49341 2.4705 2.44781 2.42532 2.40304 2.38097 2.3591 2.33742 2.31595 2.29468 2.2736 2.25271 2.23202 2.21151 2.1912 2.17107 2.15112 2.13136 2.11178 2.09238 2.07316 2.05412 2.03525 2.01655 1.99803 1.97967 1.96149 1.94347 1.92561 1.90792 1.8904 1.87303 1.85583 1.83878 1.82189 1.80515 1.78857 1.77214 1.75586 1.73973 1.72374 1.70791 1.69222 1.67668 1.66127 1.64601 1.63089 1.61591 1.60106 1.58636 1.57178 1.55734 1.54304 1.52886 1.51482 1.5009 1.48712 1.47345 1.45992 1.44651 1.43322 1.42005 1.40701 1.39408 1.38128 1.36859 1.35602 1.34356 1.33122 1.31899 1.30687 1.29486 1.28297 1.27118 1.25951 1.24794 1.23647 1.22511 1.21386 1.20271 1.19166 1.18071 1.16987 1.15912 1.14847 1.13792 1.12747 1.11711 1.10685 1.09668 1.08661 1.07662 1.06673 1.05693 1.04723 1.03761 1.02807 1.01863 1.00927 1 +0 5.32602 0.0100087 4.95132 0.0118744 0 +1 5.32236 0.0100209 4.94021 0.0119257 0 +2 5.31859 0.0100333 4.92887 0.0119764 0 +3 5.31474 0.0100457 4.91729 0.0120287 0 +4 5.31082 0.0100579 4.9055 0.0120815 0 +5 5.3068 0.0100702 4.89345 0.0121349 0 +6 5.30269 0.0100829 4.88117 0.0121884 0 +7 5.29852 0.0100954 4.86868 0.0122432 0 +8 5.2942 0.0101082 4.85591 0.0122977 0 +9 5.28984 0.0101211 4.8429 0.0123528 0 +10 5.28535 0.0101341 4.82963 0.0124093 0 +11 5.28078 0.0101474 4.81611 0.0124653 0 +12 5.27609 0.0101608 4.80235 0.0125227 0 +13 5.27131 0.0101743 4.78832 0.0125804 0 +14 5.26642 0.0101882 4.774 0.0126385 0 +15 5.26144 0.0102026 4.75946 0.0126966 0 +16 5.25632 0.0102171 4.74461 0.0127554 0 +17 5.25112 0.0102316 4.72952 0.0128157 0 +18 5.24579 0.0102468 4.71414 0.0128734 0 +19 5.24035 0.0102622 4.69849 0.0129337 0 +20 5.23478 0.010278 4.68257 0.0129944 0 +21 5.22909 0.0102942 4.66634 0.0130547 0 +22 5.22328 0.0103108 4.64985 0.0131153 0 +23 5.21735 0.0103277 4.63307 0.013176 0 +24 5.21128 0.0103452 4.616 0.013237 0 +25 5.2051 0.0103631 4.59867 0.0132978 0 +26 5.19874 0.0103814 4.58102 0.0133581 0 +27 5.19229 0.0104003 4.56311 0.0134186 0 +28 5.18569 0.0104196 4.54492 0.0134794 0 +29 5.17895 0.0104394 4.52645 0.013539 0 +30 5.17206 0.0104598 4.50766 0.0135983 0 +31 5.16502 0.0104808 4.48861 0.013657 0 +32 5.15783 0.0105023 4.46928 0.013715 0 +33 5.15048 0.0105241 4.44966 0.0137729 0 +34 5.14299 0.0105469 4.42979 0.0138286 0 +35 5.13532 0.0105698 4.40959 0.0138842 0 +36 5.12754 0.0105937 4.38921 0.0139375 0 +37 5.11956 0.010618 4.36852 0.0139904 0 +38 5.11143 0.0106426 4.34759 0.0140421 0 +39 5.10311 0.0106682 4.32639 0.0140908 0 +40 5.09465 0.0106943 4.30495 0.0141387 0 +41 5.08599 0.0107207 4.28329 0.0141845 0 +42 5.07717 0.010748 4.26135 0.0142268 0 +43 5.06817 0.0107757 4.23923 0.0142677 0 +44 5.059 0.0108038 4.21689 0.0143059 0 +45 5.04969 0.0108323 4.19441 0.0143411 0 +46 5.04016 0.0108616 4.17167 0.0143737 0 +47 5.03043 0.0108913 4.14875 0.0144027 0 +48 5.02055 0.0109214 4.12572 0.0144281 0 +49 5.01048 0.0109518 4.1025 0.0144503 0 +50 5.0002 0.0109828 4.07912 0.0144683 0 +51 4.98977 0.0110139 4.05566 0.0144824 0 +52 4.97912 0.0110454 4.03206 0.0144923 0 +53 4.9683 0.0110771 4.00841 0.0144978 0 +54 4.95731 0.011109 3.98466 0.0144989 0 +55 4.94611 0.0111411 3.96085 0.0144949 0 +56 4.93473 0.0111733 3.937 0.0144863 0 +57 4.92316 0.0112055 3.91313 0.0144724 0 +58 4.91142 0.0112375 3.88929 0.0144532 0 +59 4.89944 0.0112696 3.8654 0.0144287 0 +60 4.88731 0.0113015 3.84159 0.0143984 0 +61 4.875 0.011333 3.81784 0.0143624 0 +62 4.86253 0.0113643 3.79419 0.014321 0 +63 4.84985 0.0113952 3.77061 0.0142739 0 +64 4.83705 0.0114256 3.7472 0.0142207 0 +65 4.82403 0.0114553 3.7239 0.0141615 0 +66 4.81086 0.0114845 3.70078 0.0140971 0 +67 4.79752 0.0115128 3.67784 0.0140265 0 +68 4.78403 0.0115404 3.65513 0.0139498 0 +69 4.77036 0.0115671 3.63262 0.0138674 0 +70 4.75655 0.0115926 3.61039 0.0137795 0 +71 4.74262 0.0116171 3.58844 0.0136858 0 +72 4.72853 0.0116404 3.56677 0.0135867 0 +73 4.71431 0.0116625 3.54542 0.0134823 0 +74 4.69998 0.0116831 3.52442 0.0133728 0 +75 4.68549 0.0117023 3.50374 0.0132585 0 +76 4.67092 0.01172 3.48345 0.0131392 0 +77 4.65622 0.0117362 3.46353 0.0130155 0 +78 4.64144 0.0117507 3.44403 0.0128879 0 +79 4.62658 0.0117634 3.42495 0.0127563 0 +80 4.61159 0.0117744 3.40628 0.0126208 0 +81 4.59656 0.0117834 3.38807 0.0124822 0 +82 4.58148 0.0117906 3.37032 0.0123405 0 +83 4.5663 0.0117959 3.35302 0.0121962 0 +84 4.55109 0.0117993 3.3362 0.0120494 0 +85 4.53583 0.0118006 3.31986 0.0119004 0 +86 4.52053 0.0117999 3.30401 0.0117498 0 +87 4.50521 0.0117972 3.28866 0.0115978 0 +88 4.48988 0.0117925 3.27381 0.0114449 0 +89 4.47454 0.0117857 3.25946 0.0112912 0 +90 4.4592 0.0117768 3.24561 0.0111371 0 +91 4.44388 0.0117661 3.23228 0.010983 0 +92 4.42859 0.0117534 3.21944 0.0108292 0 +93 4.4133 0.0117386 3.20711 0.0106759 0 +94 4.39805 0.0117219 3.19528 0.0105235 0 +95 4.38286 0.0117035 3.18395 0.0103722 0 +96 4.3677 0.0116831 3.17312 0.0102221 0 +97 4.35261 0.0116609 3.16277 0.010074 0 +98 4.3376 0.0116372 3.1529 0.00992737 0 +99 4.32264 0.0116115 3.14351 0.00978327 0 +100 4.30776 0.0115844 3.13459 0.0096411 0 +101 4.29299 0.0115558 3.12614 0.00950141 0 +102 4.2783 0.0115258 3.11813 0.00936443 0 +103 4.2637 0.0114943 3.11057 0.00923016 0 +104 4.24923 0.0114615 3.10344 0.00909909 0 +105 4.23485 0.0114275 3.09674 0.0089709 0 +106 4.22061 0.0113925 3.09045 0.00884587 0 +107 4.20647 0.0113563 3.08457 0.00872399 0 +108 4.19248 0.0113192 3.07906 0.0086056 0 +109 4.17859 0.011281 3.07395 0.00849046 0 +110 4.16485 0.0112423 3.06921 0.00837861 0 +111 4.15126 0.0112026 3.06482 0.00827048 0 +112 4.1378 0.0111623 3.06078 0.00816578 0 +113 4.12447 0.0111214 3.05707 0.00806449 0 +114 4.11131 0.0110801 3.05369 0.00796668 0 +115 4.09831 0.0110384 3.05061 0.00787245 0 +116 4.08543 0.0109961 3.04785 0.00778171 0 +117 4.07272 0.0109537 3.04537 0.00769436 0 +118 4.06017 0.010911 3.04317 0.00761046 0 +119 4.04777 0.0108682 3.04124 0.0075299 0 +120 4.03553 0.0108252 3.03957 0.00745269 0 +121 4.02345 0.0107822 3.03814 0.00737879 0 +122 4.01155 0.0107392 3.03694 0.00730819 0 +123 3.9998 0.0106965 3.03597 0.00724067 0 +124 3.98821 0.0106537 3.03522 0.0071764 0 +125 3.97677 0.0106111 3.03468 0.00711517 0 +126 3.96551 0.0105688 3.03433 0.00705682 0 +127 3.9544 0.0105266 3.03417 0.00700148 0 +128 3.94347 0.0104849 3.03419 0.00694906 0 +129 3.93268 0.0104434 3.03438 0.00689936 0 +130 3.92207 0.0104025 3.03473 0.00685233 0 +131 3.91161 0.0103618 3.03524 0.00680802 0 +132 3.90132 0.0103217 3.03588 0.00676627 0 +133 3.89118 0.010282 3.03667 0.00672702 0 +134 3.8812 0.0102428 3.03759 0.00669024 0 +135 3.87137 0.0102042 3.03863 0.00665581 0 +136 3.86171 0.010166 3.03979 0.00662367 0 +137 3.8522 0.0101285 3.04105 0.00659375 0 +138 3.84283 0.0100916 3.04243 0.00656593 0 +139 3.83362 0.0100552 3.0439 0.00654021 0 +140 3.82458 0.0100196 3.04545 0.00651656 0 +141 3.81566 0.00998444 3.0471 0.00649476 0 +142 3.80689 0.00994996 3.04884 0.00647495 0 +143 3.79827 0.00991619 3.05064 0.00645693 0 +144 3.78981 0.00988311 3.0525 0.00644066 0 +145 3.78148 0.00985067 3.05444 0.00642605 0 +146 3.77328 0.00981895 3.05644 0.00641306 0 +147 3.76523 0.00978785 3.05849 0.00640172 0 +148 3.75731 0.00975745 3.0606 0.00639188 0 +149 3.74953 0.0097277 3.06276 0.00638359 0 +150 3.74189 0.00969869 3.06495 0.00637662 0 +151 3.73438 0.00967036 3.06719 0.00637104 0 +152 3.72699 0.00964275 3.06947 0.00636674 0 +153 3.71973 0.00961574 3.07179 0.00636374 0 +154 3.7126 0.00958948 3.07412 0.00636196 0 +155 3.70559 0.00956391 3.07649 0.0063613 0 +156 3.6987 0.00953891 3.07889 0.00636187 0 +157 3.69194 0.00951471 3.0813 0.00636341 0 +158 3.68529 0.0094911 3.08373 0.00636603 0 +159 3.67876 0.00946816 3.08619 0.00636964 0 +160 3.67234 0.00944582 3.08866 0.0063743 0 +161 3.66605 0.00942422 3.09113 0.00637973 0 +162 3.65985 0.0094032 3.09362 0.00638615 0 +163 3.65378 0.00938281 3.09611 0.00639338 0 +164 3.6478 0.00936307 3.09862 0.0064014 0 +165 3.64194 0.00934393 3.10112 0.00641022 0 +166 3.63618 0.00932536 3.10363 0.00641979 0 +167 3.63052 0.00930743 3.10613 0.00643006 0 +168 3.62496 0.00929002 3.10865 0.00644106 0 +169 3.6195 0.00927321 3.11115 0.00645264 0 +170 3.61414 0.00925696 3.11365 0.00646487 0 +171 3.60888 0.00924128 3.11615 0.00647768 0 +172 3.60371 0.00922612 3.11864 0.00649106 0 +173 3.59863 0.00921149 3.12112 0.00650501 0 +174 3.59364 0.00919735 3.1236 0.00651945 0 +175 3.58874 0.00918375 3.12607 0.00653436 0 +176 3.58394 0.00917065 3.12852 0.00654973 0 +177 3.57922 0.00915806 3.13096 0.00656554 0 +178 3.57458 0.00914588 3.13339 0.00658178 0 +179 3.57003 0.00913419 3.13581 0.00659839 0 +180 3.56556 0.0091229 3.13821 0.0066154 0 +181 3.56117 0.00911207 3.1406 0.00663273 0 +182 3.55686 0.00910164 3.14298 0.00665041 0 +183 3.55263 0.00909165 3.14533 0.00666835 0 +184 3.54847 0.00908208 3.14768 0.00668657 0 +185 3.54439 0.00907284 3.15001 0.00670511 0 +186 3.54038 0.00906401 3.15231 0.00672385 0 +187 3.53645 0.00905555 3.1546 0.00674279 0 +188 3.53259 0.00904741 3.15687 0.00676199 0 +189 3.5288 0.00903957 3.15913 0.00678141 0 +190 3.52507 0.00903207 3.16136 0.00680097 0 +190 5.49622 0.0104074 4.89229 0.0337671 1 +191 3.52142 0.00902493 3.16358 0.00682065 0 +191 5.48958 0.0107027 4.80981 0.0336963 1 +192 3.51783 0.00901804 3.16578 0.00684051 0 +192 5.48203 0.0110037 4.72731 0.0336505 1 +193 3.5143 0.00901144 3.16795 0.00686047 0 +193 5.47355 0.0113103 4.6449 0.0336255 1 +194 3.51084 0.0090051 3.17011 0.00688057 0 +194 5.46414 0.0116238 4.56243 0.0335933 1 +195 3.50745 0.00899903 3.17224 0.0069007 0 +195 5.45376 0.0119432 4.48001 0.0335582 1 +196 3.50411 0.00899324 3.17436 0.00692092 0 +196 5.4424 0.0122684 4.39771 0.0335072 1 +197 3.50084 0.00898761 3.17645 0.00694124 0 +197 5.43005 0.0126001 4.31564 0.0334241 1 +198 3.49763 0.00898229 3.17852 0.00696153 0 +198 5.41668 0.0129371 4.23393 0.0333008 1 +199 3.49447 0.00897719 3.18058 0.00698185 0 +199 5.40229 0.0132796 4.15274 0.0331268 1 +200 3.49138 0.00897221 3.18261 0.00700227 0 +200 5.38685 0.0136264 4.07232 0.0328931 1 +201 3.48833 0.00896743 3.18462 0.00702265 0 +201 5.37036 0.0139754 3.99281 0.0326014 1 +202 3.48534 0.00896282 3.18661 0.00704305 0 +202 5.35282 0.0143273 3.91446 0.0322307 1 +203 3.48241 0.00895841 3.18858 0.00706336 0 +203 5.33424 0.0146782 3.83758 0.031791 1 +204 3.47953 0.00895412 3.19053 0.00708365 0 +204 5.31462 0.0150281 3.76236 0.0312731 1 +205 3.47671 0.00894995 3.19245 0.00710391 0 +205 5.29397 0.0153741 3.68909 0.0306787 1 +206 3.47393 0.00894598 3.19436 0.00712404 0 +206 5.27232 0.0157141 3.61799 0.0300108 1 +207 3.47121 0.00894212 3.19624 0.00714411 0 +207 5.2497 0.0160462 3.54932 0.0292664 1 +208 3.46853 0.00893824 3.19811 0.00716417 0 +208 5.22612 0.0163676 3.48327 0.0284577 1 +209 3.46591 0.00893459 3.19994 0.00718402 0 +209 5.20167 0.0166764 3.42001 0.0275905 1 +210 3.46333 0.00893093 3.20177 0.00720382 0 +210 5.17635 0.0169698 3.35973 0.0266728 1 +211 3.46081 0.00892741 3.20356 0.00722346 0 +211 5.15025 0.0172457 3.30257 0.0257145 1 +212 3.45833 0.00892393 3.20534 0.00724297 0 +212 5.12342 0.0175027 3.2486 0.0247208 1 +213 3.45588 0.00892046 3.2071 0.00726234 0 +213 5.09593 0.0177381 3.1979 0.0237098 1 +214 3.45349 0.00891711 3.20884 0.00728149 0 +214 5.06786 0.0179514 3.15049 0.0226856 1 +215 3.45114 0.00891369 3.21056 0.00730057 0 +215 5.03927 0.0181406 3.10638 0.0216611 1 +216 3.44884 0.00891036 3.21225 0.00731937 0 +216 5.01025 0.018305 3.06555 0.0206442 1 +217 3.44658 0.00890705 3.21392 0.00733799 0 +217 4.98088 0.0184447 3.02791 0.0196454 1 +218 3.44436 0.00890373 3.21557 0.0073564 0 +218 4.95124 0.0185593 2.9934 0.018669 1 +219 3.44218 0.00890035 3.21721 0.00737465 0 +219 4.92138 0.0186487 2.96191 0.0177236 1 +220 3.44003 0.00889698 3.21882 0.00739263 0 +220 4.89142 0.0187136 2.93333 0.0168144 1 +221 3.43793 0.00889353 3.22042 0.00741042 0 +221 4.8614 0.0187554 2.90751 0.0159414 1 +222 3.43587 0.00889007 3.22199 0.00742794 0 +222 4.8314 0.0187745 2.88433 0.015112 1 +223 3.43384 0.00888659 3.22354 0.00744521 0 +223 4.80148 0.0187723 2.86363 0.0143266 1 +224 3.43185 0.00888303 3.22508 0.0074622 0 +224 4.77171 0.0187499 2.84526 0.0135864 1 +225 3.42991 0.0088794 3.22659 0.00747893 0 +225 4.74212 0.0187091 2.82908 0.0128912 1 +226 3.42799 0.00887568 3.22808 0.00749541 0 +226 4.71279 0.0186512 2.81495 0.0122409 1 +227 3.42611 0.00887185 3.22956 0.00751161 0 +227 4.68375 0.0185777 2.80271 0.0116355 1 +228 3.42426 0.00886794 3.23102 0.0075275 0 +228 4.65503 0.0184901 2.79223 0.0110727 1 +229 3.42245 0.00886396 3.23245 0.00754307 0 +229 4.6267 0.0183898 2.78337 0.010552 1 +230 3.42068 0.00885992 3.23387 0.00755829 0 +230 4.59876 0.0182785 2.776 0.0100708 1 +231 3.41893 0.00885567 3.23527 0.00757326 0 +231 4.57123 0.0181573 2.77001 0.00962725 1 +232 3.41722 0.00885132 3.23665 0.00758789 0 +232 4.54416 0.0180277 2.76528 0.00921948 1 +233 3.41553 0.00884682 3.23802 0.0076022 0 +233 4.51753 0.0178905 2.76169 0.00884538 1 +234 3.41388 0.0088422 3.23936 0.00761618 0 +234 4.4914 0.0177472 2.75916 0.00850326 1 +235 3.41227 0.00883744 3.24069 0.00762979 0 +235 4.46575 0.0175989 2.7576 0.00819038 1 +236 3.41067 0.00883253 3.242 0.00764306 0 +236 4.4406 0.0174462 2.7569 0.00790521 1 +237 3.40912 0.0088275 3.24329 0.00765592 0 +237 4.41595 0.0172902 2.75699 0.00764577 1 +238 3.40758 0.00882224 3.24457 0.00766848 0 +238 4.3918 0.0171315 2.75782 0.00741 1 +239 3.40608 0.00881681 3.24582 0.00768069 0 +239 4.36816 0.0169709 2.75928 0.00719627 1 +240 3.4046 0.00881126 3.24706 0.00769247 0 +240 4.34503 0.016809 2.76134 0.00700292 1 +241 3.40316 0.00880546 3.24829 0.00770392 0 +241 4.3224 0.0166463 2.76393 0.00682838 1 +242 3.40174 0.00879955 3.24949 0.00771494 0 +242 4.30028 0.0164835 2.76699 0.00667112 1 +243 3.40034 0.00879335 3.25068 0.00772567 0 +243 4.27866 0.0163207 2.77048 0.00652987 1 +244 3.39898 0.00878704 3.25185 0.00773591 0 +244 4.25752 0.0161585 2.77436 0.00640322 1 +245 3.39763 0.00878045 3.25301 0.00774586 0 +245 4.23688 0.0159972 2.77858 0.00629001 1 +246 3.39631 0.00877376 3.25415 0.00775529 0 +246 4.21671 0.015837 2.78311 0.00618924 1 +247 3.39502 0.00876679 3.25528 0.00776439 0 +247 4.19701 0.0156782 2.7879 0.00609983 1 +248 3.39375 0.00875962 3.25638 0.00777307 0 +248 4.17778 0.015521 2.79294 0.00602082 1 +249 3.3925 0.00875217 3.25748 0.00778143 0 +249 4.159 0.0153655 2.79819 0.00595129 1 +250 3.39128 0.00874458 3.25856 0.00778929 0 +250 4.14067 0.015212 2.80363 0.00589061 1 +251 3.39008 0.00873672 3.25962 0.00779679 0 +251 4.12277 0.0150605 2.80923 0.00583777 1 +252 3.3889 0.00872868 3.26067 0.00780383 0 +252 4.1053 0.0149112 2.81497 0.00579225 1 +253 3.38774 0.00872044 3.26171 0.00781045 0 +253 4.08825 0.0147641 2.82083 0.00575345 1 +254 3.38662 0.00871191 3.26272 0.0078167 0 +254 4.07161 0.0146192 2.82678 0.00572073 1 +255 3.3855 0.00870316 3.26373 0.00782253 0 +255 4.05536 0.0144766 2.83283 0.00569354 1 +256 3.38441 0.00869418 3.26472 0.00782794 0 +256 4.03951 0.0143364 2.83895 0.0056714 1 +257 3.38334 0.00868501 3.26569 0.00783288 0 +257 4.02404 0.0141986 2.84512 0.00565385 1 +258 3.38228 0.00867553 3.26666 0.0078375 0 +258 4.00894 0.0140631 2.85133 0.00564051 1 +259 3.38125 0.00866583 3.26761 0.00784166 0 +259 3.9942 0.01393 2.85758 0.00563098 1 +260 3.38024 0.00865591 3.26854 0.0078454 0 +260 3.97982 0.0137993 2.86385 0.00562489 1 +261 3.37925 0.00864575 3.26946 0.00784873 0 +261 3.96577 0.0136709 2.87013 0.00562191 1 +262 3.37827 0.00863534 3.27037 0.00785165 0 +262 3.95207 0.0135449 2.87642 0.00562181 1 +262 5.49785 0.0131934 4.44288 0.0760105 2 +263 3.37731 0.00862471 3.27127 0.00785414 0 +263 3.93869 0.0134211 2.8827 0.00562421 1 +263 5.48461 0.0140649 4.25333 0.0696195 2 +264 3.37637 0.00861386 3.27215 0.00785622 0 +264 3.92563 0.0132997 2.88897 0.00562888 1 +264 5.4688 0.0149054 4.08016 0.0642439 2 +265 3.37545 0.00860276 3.27302 0.00785787 0 +265 3.91288 0.0131805 2.89523 0.00563567 1 +265 5.45052 0.0157153 3.92123 0.0595474 2 +266 3.37455 0.00859138 3.27388 0.00785919 0 +266 3.90043 0.0130634 2.90145 0.00564428 1 +266 5.42984 0.0164923 3.77504 0.055306 2 +267 3.37366 0.00857977 3.27472 0.00786007 0 +267 3.88828 0.0129487 2.90766 0.00565451 1 +267 5.40688 0.017233 3.64054 0.0513683 2 +268 3.37279 0.00856798 3.27555 0.00786052 0 +268 3.87641 0.012836 2.91382 0.0056662 1 +268 5.38174 0.0179331 3.51714 0.0476421 2 +269 3.37193 0.00855592 3.27638 0.00786058 0 +269 3.86482 0.0127254 2.91995 0.00567919 1 +269 5.35454 0.0185837 3.4044 0.0440987 2 +270 3.3711 0.00854366 3.27718 0.00786023 0 +270 3.85351 0.012617 2.92604 0.00569331 1 +270 5.32545 0.0191808 3.30181 0.0407017 2 +271 3.37028 0.0085311 3.27798 0.00785954 0 +271 3.84246 0.0125104 2.93208 0.00570849 1 +271 5.29464 0.0197191 3.20902 0.0374543 2 +272 3.36947 0.00851842 3.27876 0.00785837 0 +272 3.83167 0.0124059 2.93808 0.0057245 1 +272 5.26229 0.0201925 3.12557 0.0343642 2 +273 3.36868 0.00850543 3.27954 0.00785689 0 +273 3.82112 0.0123033 2.94402 0.00574125 1 +273 5.22861 0.0206001 3.05102 0.0314367 2 +274 3.3679 0.00849228 3.2803 0.00785496 0 +274 3.81083 0.0122026 2.94991 0.00575865 1 +274 5.19379 0.0209382 2.98487 0.0286911 2 +275 3.36714 0.00847881 3.28105 0.00785275 0 +275 3.80077 0.0121038 2.95575 0.00577657 1 +275 5.15804 0.0212076 2.92655 0.0261314 2 +276 3.36639 0.00846532 3.28179 0.00784999 0 +276 3.79094 0.0120067 2.96152 0.00579491 1 +276 5.12157 0.0214097 2.8755 0.0237658 2 +277 3.36566 0.00845143 3.28251 0.00784702 0 +277 3.78134 0.0119114 2.96724 0.00581365 1 +277 5.08457 0.0215466 2.83112 0.0215968 2 +278 3.36494 0.00843733 3.28324 0.00784369 0 +278 3.77196 0.0118178 2.97289 0.00583267 1 +278 5.04723 0.0216234 2.79285 0.0196211 2 +279 3.36423 0.00842312 3.28394 0.00783991 0 +279 3.7628 0.011726 2.97849 0.0058518 1 +279 5.00973 0.0216435 2.76011 0.0178326 2 +280 3.36354 0.00840867 3.28464 0.00783581 0 +280 3.75383 0.0116357 2.98402 0.00587119 1 +280 4.97222 0.0216131 2.73235 0.0162208 2 +281 3.36286 0.00839406 3.28533 0.00783132 0 +281 3.74508 0.0115471 2.98949 0.00589057 1 +281 4.93485 0.0215371 2.70906 0.0147776 2 +282 3.36219 0.00837918 3.286 0.00782655 0 +282 3.73653 0.01146 2.99489 0.00591003 1 +282 4.89773 0.021421 2.68976 0.0134889 2 +283 3.36154 0.00836422 3.28667 0.00782134 0 +283 3.72816 0.0113745 3.00023 0.00592937 1 +283 4.86097 0.0212704 2.674 0.0123422 2 +284 3.3609 0.00834902 3.28732 0.00781584 0 +284 3.71998 0.0112905 3.00549 0.00594869 1 +284 4.82467 0.0210904 2.66137 0.0113247 2 +285 3.36027 0.00833352 3.28797 0.00781014 0 +285 3.71199 0.0112078 3.0107 0.00596792 1 +285 4.78891 0.0208856 2.65153 0.010425 2 +286 3.35964 0.00831799 3.28861 0.00780397 0 +286 3.70418 0.0111267 3.01583 0.00598696 1 +286 4.75373 0.0206604 2.64415 0.00963054 2 +287 3.35904 0.0083023 3.28923 0.00779748 0 +287 3.69655 0.0110469 3.0209 0.00600578 1 +287 4.7192 0.0204186 2.63892 0.00893037 2 +288 3.35844 0.00828636 3.28985 0.00779075 0 +288 3.68907 0.0109685 3.0259 0.0060244 1 +288 4.68536 0.020164 2.63558 0.00831435 2 +289 3.35786 0.00827027 3.29046 0.00778372 0 +289 3.68177 0.0108914 3.03083 0.00604278 1 +289 4.65223 0.0198993 2.63391 0.0077731 2 +290 3.35729 0.00825412 3.29106 0.00777629 0 +290 3.67462 0.0108157 3.0357 0.00606083 1 +290 4.61983 0.0196275 2.63369 0.00729872 2 +291 3.35673 0.00823775 3.29164 0.00776865 0 +291 3.66764 0.0107412 3.0405 0.00607856 1 +291 4.5882 0.0193508 2.63474 0.00688243 2 +292 3.35618 0.00822124 3.29223 0.00776072 0 +292 3.66081 0.0106679 3.04523 0.00609603 1 +292 4.55732 0.0190711 2.6369 0.00651899 2 +293 3.35563 0.0082046 3.2928 0.00775251 0 +293 3.65412 0.0105958 3.04989 0.00611317 1 +293 4.52719 0.0187902 2.64004 0.00620135 2 +294 3.3551 0.00818778 3.29336 0.00774407 0 +294 3.64759 0.0105249 3.05449 0.00612993 1 +294 4.49783 0.0185094 2.64402 0.00592471 2 +295 3.35459 0.00817097 3.29392 0.00773524 0 +295 3.64119 0.0104551 3.05903 0.00614629 1 +295 4.46923 0.01823 2.64873 0.00568413 2 +296 3.35407 0.00815387 3.29447 0.00772632 0 +296 3.63494 0.0103866 3.06349 0.00616225 1 +296 4.44138 0.0179529 2.65407 0.00547542 2 +297 3.35357 0.00813676 3.29501 0.00771705 0 +297 3.62881 0.010319 3.0679 0.00617794 1 +297 4.41426 0.0176789 2.65996 0.00529487 2 +298 3.35308 0.00811948 3.29553 0.00770761 0 +298 3.62282 0.0102526 3.07223 0.00619312 1 +298 4.38788 0.0174088 2.66632 0.00513933 2 +299 3.3526 0.00810212 3.29605 0.00769792 0 +299 3.61696 0.0101873 3.0765 0.00620788 1 +299 4.3622 0.017143 2.67308 0.00500579 2 +300 3.35212 0.00808464 3.29657 0.00768801 0 +300 3.61123 0.0101229 3.08071 0.00622228 1 +300 4.33722 0.0168821 2.68018 0.00489176 2 +301 3.35166 0.0080671 3.29708 0.00767788 0 +301 3.60562 0.0100597 3.08485 0.00623621 1 +301 4.31292 0.0166261 2.68758 0.00479489 2 +302 3.35121 0.00804954 3.29757 0.00766747 0 +302 3.60013 0.00999732 3.08894 0.00624979 1 +302 4.28928 0.0163754 2.69522 0.00471327 2 +303 3.35076 0.00803192 3.29807 0.00765685 0 +303 3.59475 0.00993599 3.09296 0.00626291 1 +303 4.26631 0.0161303 2.70305 0.00464523 2 +304 3.35032 0.00801407 3.29855 0.0076462 0 +304 3.58949 0.00987565 3.09692 0.00627556 1 +304 4.24395 0.0158907 2.71106 0.00458915 2 +305 3.34989 0.00799629 3.29902 0.00763523 0 +305 3.58434 0.00981621 3.10081 0.00628783 1 +305 4.22221 0.0156568 2.7192 0.0045436 2 +305 5.49659 0.014451 4.06354 0.102028 3 +306 3.34948 0.0079784 3.29949 0.00762415 0 +306 3.5793 0.00975772 3.10465 0.00629963 1 +306 4.20108 0.0154286 2.72743 0.00450735 2 +306 5.47661 0.0158318 3.80237 0.0839789 3 +307 3.34906 0.00796045 3.29995 0.00761291 0 +307 3.57436 0.0097001 3.10843 0.00631108 1 +307 4.18051 0.015206 2.73575 0.00447939 2 +307 5.45249 0.0170578 3.5873 0.0707551 3 +308 3.34865 0.00794246 3.30041 0.0076015 0 +308 3.56953 0.00964337 3.11214 0.00632207 1 +308 4.16051 0.0149891 2.74413 0.00445873 2 +308 5.42468 0.0181402 3.40739 0.0604598 3 +309 3.34826 0.00792447 3.30085 0.00758992 0 +309 3.5648 0.00958757 3.1158 0.00633261 1 +309 4.14106 0.0147777 2.75254 0.00444453 2 +309 5.39362 0.0190828 3.25565 0.0520659 3 +310 3.34787 0.00790642 3.30129 0.00757822 0 +310 3.56017 0.00953254 3.11941 0.0063428 1 +310 4.12214 0.0145719 2.76097 0.004436 2 +310 5.35971 0.0198875 3.12738 0.0450267 3 +311 3.34748 0.0078884 3.30173 0.00756634 0 +311 3.55564 0.00947847 3.12295 0.00635248 1 +311 4.10372 0.0143715 2.7694 0.00443251 2 +311 5.32341 0.020554 3.01905 0.0390289 3 +312 3.34711 0.0078703 3.30216 0.0075544 0 +312 3.55119 0.00942515 3.12644 0.00636185 1 +312 4.08581 0.0141764 2.77782 0.00443344 2 +312 5.28512 0.0210884 2.92787 0.0338607 3 +313 3.34674 0.00785223 3.30258 0.00754231 0 +313 3.54684 0.00937264 3.12988 0.00637081 1 +313 4.06838 0.0139865 2.78622 0.00443824 2 +313 5.24528 0.0214941 2.85154 0.0294062 3 +314 3.34638 0.00783415 3.30299 0.00753011 0 +314 3.54259 0.00932099 3.13325 0.0063793 1 +314 4.05142 0.0138017 2.79459 0.0044465 2 +314 5.20426 0.02178 2.788 0.0255691 3 +315 3.34603 0.00781609 3.30339 0.0075178 0 +315 3.53842 0.00927004 3.13658 0.00638751 1 +315 4.03492 0.013622 2.8029 0.00445764 2 +315 5.16241 0.0219567 2.73548 0.0222652 3 +316 3.34568 0.00779807 3.30379 0.00750538 0 +316 3.53434 0.00921999 3.13985 0.00639524 1 +316 4.01886 0.0134471 2.81117 0.00447147 2 +316 5.12009 0.0220364 2.69245 0.0194292 3 +317 3.34534 0.00777998 3.30419 0.00749295 0 +317 3.53033 0.00917061 3.14307 0.00640266 1 +317 4.00321 0.0132769 2.81938 0.00448749 2 +317 5.07756 0.0220304 2.65754 0.0170027 3 +318 3.345 0.00776194 3.30458 0.00748043 0 +318 3.52641 0.00912209 3.14623 0.00640964 1 +318 3.98798 0.0131112 2.82752 0.00450559 2 +318 5.03509 0.0219516 2.62957 0.0149288 3 +319 3.34467 0.00774397 3.30497 0.00746781 0 +319 3.52257 0.00907421 3.14935 0.00641636 1 +319 3.97315 0.0129501 2.8356 0.00452533 2 +319 4.99287 0.0218109 2.60753 0.0131621 3 +320 3.34435 0.00772604 3.30534 0.00745514 0 +320 3.51882 0.0090271 3.15241 0.0064227 1 +320 3.95872 0.0127934 2.84359 0.00454651 2 +320 4.9511 0.0216201 2.59053 0.0116557 3 +321 3.34404 0.00770814 3.30571 0.00744242 0 +321 3.51513 0.00898074 3.15543 0.00642866 1 +321 3.94465 0.0126409 2.8515 0.00456892 2 +321 4.9099 0.0213878 2.57781 0.0103767 3 +322 3.34373 0.00769034 3.30607 0.00742962 0 +322 3.51153 0.00893511 3.15839 0.0064343 1 +322 3.93095 0.0124925 2.85933 0.00459242 2 +322 4.8694 0.0211235 2.56874 0.00928887 3 +323 3.34343 0.00767254 3.30643 0.00741684 0 +323 3.50799 0.00889011 3.16131 0.00643967 1 +323 3.9176 0.0123481 2.86707 0.00461679 2 +323 4.82967 0.020834 2.56275 0.00836494 3 +324 3.34313 0.00765482 3.30679 0.00740403 0 +324 3.50453 0.00884586 3.16418 0.00644468 1 +324 3.9046 0.0122075 2.87472 0.00464189 2 +324 4.7908 0.0205261 2.5594 0.00758005 3 +325 3.34284 0.00763717 3.30713 0.00739121 0 +325 3.50113 0.00880227 3.167 0.00644942 1 +325 3.89193 0.0120708 2.88228 0.00466754 2 +325 4.75284 0.020205 2.55826 0.0069142 3 +326 3.34255 0.00761961 3.30748 0.00737835 0 +326 3.49781 0.0087594 3.16978 0.00645383 1 +326 3.87957 0.0119377 2.88975 0.00469372 2 +326 4.71579 0.0198749 2.559 0.00634928 3 +327 3.34227 0.00760214 3.30781 0.0073655 0 +327 3.49455 0.00871718 3.17251 0.00645799 1 +327 3.86753 0.0118081 2.89712 0.00472023 2 +327 4.6797 0.0195398 2.56135 0.00587067 3 +328 3.34199 0.00758474 3.30815 0.00735268 0 +328 3.49136 0.00867569 3.17519 0.00646181 1 +328 3.85579 0.011682 2.90439 0.00474701 2 +328 4.64458 0.0192028 2.56504 0.00546522 3 +329 3.34172 0.00756745 3.30847 0.00733986 0 +329 3.48823 0.00863478 3.17783 0.00646544 1 +329 3.84434 0.0115593 2.91157 0.00477396 2 +329 4.61043 0.0188663 2.56988 0.00512249 3 +330 3.34146 0.0075503 3.3088 0.00732704 0 +330 3.48517 0.00859457 3.18043 0.00646877 1 +330 3.83318 0.0114397 2.91865 0.00480102 2 +330 4.57723 0.0185321 2.57568 0.00483351 3 +331 3.3412 0.00753322 3.30911 0.00731427 0 +331 3.48217 0.00855493 3.18298 0.00647193 1 +331 3.8223 0.0113233 2.92562 0.00482812 2 +331 4.54498 0.0182018 2.58229 0.00459041 3 +332 3.34095 0.00751631 3.30942 0.0073015 0 +332 3.47922 0.00851606 3.18549 0.00647473 1 +332 3.81168 0.01121 2.9325 0.00485514 2 +332 4.51366 0.0178766 2.58958 0.00438667 3 +333 3.34069 0.00749944 3.30973 0.00728886 0 +333 3.47634 0.00847768 3.18796 0.00647742 1 +333 3.80133 0.0110996 2.93928 0.00488219 2 +333 4.48327 0.0175578 2.59743 0.00421675 3 +334 3.34045 0.00748278 3.31003 0.0072762 0 +334 3.47352 0.00844003 3.19038 0.00647983 1 +334 3.79123 0.0109921 2.94595 0.00490904 2 +334 4.45377 0.0172456 2.60576 0.0040759 3 +335 3.34021 0.00746624 3.31033 0.0072636 0 +335 3.47074 0.00840299 3.19277 0.00648204 1 +335 3.78137 0.0108874 2.95253 0.00493576 2 +335 4.42515 0.0169409 2.61447 0.00395999 3 +336 3.33997 0.0074498 3.31063 0.00725112 0 +336 3.46802 0.00836653 3.19512 0.00648408 1 +336 3.77175 0.0107854 2.95901 0.00496226 2 +336 4.39738 0.0166439 2.6235 0.00386573 3 +336 5.48745 0.0158233 3.66629 0.103355 4 +337 3.33975 0.00743357 3.31091 0.00723866 0 +337 3.46536 0.0083307 3.19743 0.00648593 1 +337 3.76236 0.0106861 2.96539 0.00498853 2 +337 4.37044 0.0163548 2.63278 0.00379014 3 +337 5.45961 0.017455 3.39662 0.0780317 4 +338 3.33952 0.0074175 3.31119 0.00722627 0 +338 3.46276 0.00829553 3.1997 0.00648756 1 +338 3.7532 0.0105893 2.97167 0.00501451 2 +338 4.34431 0.0160737 2.64226 0.00373061 3 +338 5.42682 0.0187755 3.19264 0.0612711 4 +339 3.33929 0.00740154 3.31147 0.00721401 0 +339 3.4602 0.00826088 3.20193 0.0064891 1 +339 3.74426 0.010495 2.97786 0.00504027 2 +339 4.31895 0.0158009 2.65191 0.003685 3 +339 5.39005 0.0198262 3.03439 0.0492476 4 +340 3.33908 0.0073857 3.31174 0.00720191 0 +340 3.45769 0.00822693 3.20412 0.00649038 1 +340 3.73552 0.0104032 2.98394 0.00506569 2 +340 4.29436 0.0155362 2.66166 0.00365143 3 +340 5.35009 0.0206389 2.91009 0.0401565 4 +341 3.33887 0.00737019 3.31202 0.00718973 0 +341 3.45523 0.00819346 3.20628 0.00649162 1 +341 3.72699 0.0103136 2.98994 0.00509085 2 +341 4.27049 0.0152796 2.67149 0.00362822 3 +341 5.3077 0.0212389 2.81193 0.0330619 4 +342 3.33866 0.00735474 3.31228 0.0071778 0 +342 3.45283 0.0081606 3.20839 0.00649273 1 +342 3.71867 0.0102264 2.99583 0.00511565 2 +342 4.24733 0.0150309 2.68137 0.00361415 3 +342 5.26358 0.0216517 2.73443 0.027425 4 +343 3.33845 0.00733948 3.31254 0.00716597 0 +343 3.45046 0.00812839 3.21048 0.00649364 1 +343 3.71054 0.0101414 3.00163 0.00514012 2 +343 4.22486 0.0147901 2.69128 0.0036078 3 +343 5.21827 0.0219015 2.67348 0.0228991 4 +344 3.33825 0.00732443 3.3128 0.00715424 0 +344 3.44815 0.00809667 3.21253 0.00649451 1 +344 3.7026 0.0100585 3.00734 0.00516426 2 +344 4.20304 0.0145569 2.7012 0.00360824 3 +344 5.17228 0.0220142 2.62589 0.0192366 4 +345 3.33805 0.00730951 3.31306 0.0071427 0 +345 3.44588 0.00806555 3.21454 0.00649526 1 +345 3.69485 0.00997781 3.01296 0.00518805 2 +345 4.18186 0.0143311 2.71109 0.00361452 3 +345 5.12604 0.0220116 2.58909 0.0162633 4 +346 3.33786 0.00729494 3.3133 0.00713114 0 +346 3.44366 0.00803508 3.21652 0.00649584 1 +346 3.68727 0.00989913 3.01848 0.00521147 2 +346 4.1613 0.0141127 2.72096 0.00362589 3 +346 5.0799 0.0219151 2.5611 0.0138412 4 +347 3.33767 0.00728046 3.31355 0.00711984 0 +347 3.44147 0.00800508 3.21847 0.00649643 1 +347 3.67986 0.00982245 3.02392 0.00523454 2 +347 4.14134 0.0139014 2.73077 0.00364159 3 +347 5.03414 0.0217439 2.54028 0.0118631 4 +348 3.33749 0.00726621 3.31379 0.00710867 0 +348 3.43933 0.00797574 3.22039 0.00649686 1 +348 3.67263 0.0097477 3.02926 0.00525729 2 +348 4.12196 0.013697 2.74052 0.003661 3 +348 4.98897 0.0215139 2.52533 0.0102454 4 +349 3.33731 0.00725222 3.31403 0.00709761 0 +349 3.43724 0.00794686 3.22227 0.00649731 1 +349 3.66557 0.00967486 3.03451 0.00527967 2 +349 4.10313 0.0134992 2.7502 0.00368373 3 +349 4.94457 0.0212395 2.51517 0.00891715 4 +350 3.33713 0.00723834 3.31427 0.00708681 0 +350 3.43518 0.00791857 3.22412 0.00649767 1 +350 3.65866 0.00960389 3.03968 0.00530168 2 +350 4.08483 0.0133079 2.75979 0.00370916 3 +350 4.90107 0.0209317 2.50894 0.00782633 4 +351 3.33695 0.00722473 3.3145 0.00707613 0 +351 3.43316 0.00789087 3.22594 0.00649797 1 +351 3.65191 0.0095347 3.04477 0.00532334 2 +351 4.06706 0.0131229 2.7693 0.00373697 3 +351 4.85856 0.0206 2.50595 0.00692873 4 +352 3.33678 0.00721139 3.31472 0.00706558 0 +352 3.43119 0.00786365 3.22772 0.00649828 1 +352 3.64531 0.00946725 3.04976 0.00534468 2 +352 4.04978 0.0129439 2.77871 0.00376678 3 +352 4.8171 0.0202523 2.50563 0.00618943 4 +353 3.33661 0.00719828 3.31495 0.0070552 0 +353 3.42925 0.00783705 3.22948 0.00649849 1 +353 3.63886 0.00940152 3.05468 0.00536566 2 +353 4.03299 0.0127707 2.78802 0.00379827 3 +353 4.77674 0.0198945 2.50749 0.00558002 4 +354 3.33645 0.00718535 3.31517 0.00704507 0 +354 3.42735 0.00781099 3.23121 0.0064987 1 +354 3.63255 0.00933746 3.05951 0.00538634 2 +354 4.01666 0.0126032 2.79723 0.0038312 3 +354 4.73751 0.0195318 2.51117 0.00507768 4 +355 3.33629 0.00717269 3.31539 0.0070351 0 +355 3.42549 0.00778544 3.2329 0.00649891 1 +355 3.62639 0.00927505 3.06426 0.00540667 2 +355 4.00079 0.0124411 2.80632 0.00386537 3 +355 4.69941 0.0191678 2.51633 0.0046643 4 +356 3.33613 0.0071603 3.3156 0.0070253 0 +356 3.42366 0.00776043 3.23457 0.00649912 1 +356 3.62036 0.0092143 3.06892 0.0054266 2 +356 3.98535 0.0122843 2.8153 0.00390048 3 +356 4.66244 0.0188058 2.52271 0.00432413 4 +357 3.33598 0.00714817 3.31581 0.00701568 0 +357 3.42186 0.00773597 3.23621 0.00649933 1 +357 3.61447 0.00915499 3.07351 0.00544636 2 +357 3.97033 0.0121327 2.82416 0.00393635 3 +357 4.6266 0.0184481 2.53011 0.00404536 4 +358 3.33582 0.00713624 3.31602 0.00700632 0 +358 3.42011 0.00771208 3.23782 0.00649952 1 +358 3.60871 0.00909723 3.07802 0.00546573 2 +358 3.95571 0.0119859 2.83291 0.00397287 3 +358 4.59185 0.0180963 2.53832 0.00381769 4 +359 3.33568 0.00712461 3.31622 0.00699712 0 +359 3.41838 0.00768857 3.23941 0.00649986 1 +359 3.60307 0.009041 3.08246 0.00548481 2 +359 3.9415 0.0118438 2.84153 0.00400994 3 +359 4.55819 0.0177517 2.54721 0.00363296 4 +360 3.33553 0.00711325 3.31642 0.00698814 0 +360 3.41669 0.00766577 3.24097 0.00650008 1 +360 3.59756 0.00898619 3.08681 0.00550361 2 +360 3.92766 0.0117063 2.85002 0.00404733 3 +360 4.52559 0.0174154 2.55664 0.00348419 4 +360 5.48053 0.0169574 3.38999 0.0995399 5 +361 3.33539 0.00710218 3.31661 0.00697933 0 +361 3.41504 0.00764352 3.2425 0.00650029 1 +361 3.59217 0.0089329 3.09109 0.00552206 2 +361 3.9142 0.0115733 2.8584 0.00408498 3 +361 4.49402 0.0170882 2.56651 0.00336587 4 +361 5.44632 0.0187027 3.13015 0.0698555 5 +362 3.33525 0.00709128 3.31681 0.00697085 0 +362 3.41341 0.00762167 3.244 0.00650067 1 +362 3.5869 0.00888089 3.0953 0.00554033 2 +362 3.90108 0.0114444 2.86665 0.00412281 3 +362 4.46345 0.0167702 2.57673 0.0032732 4 +362 5.4069 0.0199872 2.94731 0.0519004 5 +363 3.33511 0.00708073 3.31701 0.00696253 0 +363 3.41181 0.00760036 3.24548 0.00650109 1 +363 3.58174 0.00883028 3.09944 0.0055583 2 +363 3.88831 0.0113197 2.87478 0.00416072 3 +363 4.43384 0.016462 2.58721 0.0032022 4 +363 5.36367 0.0209103 2.814 0.0398617 5 +364 3.33498 0.00707043 3.31719 0.00695445 0 +364 3.41026 0.00757963 3.24693 0.00650151 1 +364 3.57669 0.00878099 3.1035 0.00557604 2 +364 3.87588 0.011199 2.88278 0.00419865 3 +364 4.40517 0.0161634 2.5979 0.00314972 4 +364 5.31775 0.0215372 2.71507 0.0312926 5 +365 3.33485 0.00706041 3.31737 0.00694661 0 +365 3.40872 0.00755931 3.24836 0.00650209 1 +365 3.57175 0.00873301 3.1075 0.00559352 2 +365 3.86377 0.0110822 2.89066 0.00423652 3 +365 4.37742 0.0158748 2.60874 0.00311277 4 +365 5.27007 0.0219254 2.64117 0.0249505 5 +366 3.33472 0.00705063 3.31756 0.00693905 0 +366 3.40722 0.00753956 3.24977 0.0065027 1 +366 3.56692 0.00868632 3.11143 0.00561075 2 +366 3.85197 0.0109689 2.89841 0.00427433 3 +366 4.35053 0.0155958 2.61968 0.00308916 4 +366 5.22135 0.0221188 2.58604 0.0201507 5 +367 3.33459 0.00704128 3.31774 0.0069316 0 +367 3.40574 0.00752037 3.25115 0.00650335 1 +367 3.56219 0.00864087 3.11528 0.00562778 2 +367 3.84047 0.0108594 2.90604 0.00431196 3 +367 4.3245 0.0153264 2.63068 0.00307702 4 +367 5.17224 0.0221588 2.54523 0.016458 5 +368 3.33447 0.00703209 3.31792 0.00692451 0 +368 3.4043 0.00750166 3.2525 0.0065041 1 +368 3.55756 0.00859661 3.11908 0.00564462 2 +368 3.82927 0.0107532 2.91355 0.0043494 3 +368 4.29927 0.0150666 2.64171 0.00307434 4 +368 5.12317 0.0220781 2.51552 0.0135862 5 +369 3.33435 0.00702322 3.31809 0.00691766 0 +369 3.40288 0.00748343 3.25383 0.00650498 1 +369 3.55304 0.00855359 3.1228 0.00566123 2 +369 3.81836 0.0106505 2.92094 0.0043866 3 +369 4.27484 0.0148158 2.65275 0.00308005 4 +369 5.07453 0.0219048 2.49446 0.0113323 5 +370 3.33423 0.00701464 3.31826 0.00691106 0 +370 3.40149 0.00746568 3.25514 0.00650598 1 +370 3.54861 0.00851171 3.12646 0.00567767 2 +370 3.80772 0.0105509 2.9282 0.00442365 3 +370 4.25115 0.014574 2.66376 0.00309274 4 +370 5.02657 0.0216619 2.48021 0.00955201 5 +371 3.33412 0.00700635 3.31843 0.00690473 0 +371 3.40012 0.00744842 3.25644 0.0065071 1 +371 3.54427 0.00847096 3.13006 0.00569395 2 +371 3.79734 0.0104545 2.93535 0.00446032 3 +371 4.2282 0.014341 2.67472 0.0031114 4 +371 4.97952 0.0213679 2.47136 0.00813766 5 +372 3.334 0.00699844 3.3186 0.00689857 0 +372 3.39878 0.0074318 3.2577 0.00650821 1 +372 3.54003 0.00843148 3.13359 0.00570995 2 +372 3.78722 0.0103611 2.94237 0.00449675 3 +372 4.20594 0.0141163 2.68563 0.00313523 4 +372 4.93352 0.0210378 2.4668 0.00700927 5 +373 3.33389 0.00699067 3.31876 0.00689283 0 +373 3.39747 0.00741559 3.25895 0.00650951 1 +373 3.53587 0.00839296 3.13707 0.0057259 2 +373 3.77736 0.0102707 2.94928 0.00453284 3 +373 4.18437 0.0138999 2.69646 0.00316336 4 +373 4.88868 0.0206831 2.46566 0.00610523 5 +374 3.33379 0.00698334 3.31892 0.00688724 0 +374 3.39619 0.00739986 3.26017 0.00651095 1 +374 3.5318 0.00835561 3.14048 0.00574164 2 +374 3.76774 0.0101831 2.95607 0.00456862 3 +374 4.16344 0.0136913 2.70719 0.00319516 4 +374 4.84505 0.020313 2.46727 0.00537923 5 +375 3.33368 0.00697632 3.31909 0.00688191 0 +375 3.39492 0.00738462 3.26137 0.00651254 1 +375 3.52782 0.0083193 3.14383 0.00575727 2 +375 3.75835 0.0100982 2.96275 0.00460412 3 +375 4.14315 0.0134903 2.71783 0.00323009 4 +375 4.80268 0.0199341 2.47109 0.00479562 5 +376 3.33357 0.00696953 3.31924 0.00687694 0 +376 3.39368 0.00736986 3.26256 0.00651427 1 +376 3.52392 0.008284 3.14713 0.00577279 2 +376 3.74919 0.010016 2.96932 0.00463928 3 +376 4.12345 0.0132967 2.72836 0.00326761 4 +376 4.76158 0.0195527 2.4767 0.00432583 5 +377 3.33348 0.00696313 3.31939 0.00687216 0 +377 3.39247 0.00735568 3.26371 0.00651605 1 +377 3.52011 0.00824982 3.15036 0.00578811 2 +377 3.74026 0.00993641 2.97577 0.00467403 3 +377 4.10434 0.0131101 2.73876 0.00330737 4 +377 4.72177 0.0191724 2.48373 0.00394854 5 +378 3.33338 0.00695701 3.31955 0.00686769 0 +378 3.39128 0.00734187 3.26485 0.0065181 1 +378 3.51637 0.00821657 3.15354 0.00580338 2 +378 3.73154 0.00985928 2.98211 0.00470849 3 +378 4.08579 0.0129304 2.74905 0.00334893 4 +378 4.68322 0.0187963 2.49191 0.00364616 5 +379 3.33328 0.00695116 3.3197 0.00686356 0 +379 3.39011 0.0073286 3.26598 0.00652025 1 +379 3.51271 0.00818432 3.15666 0.00581855 2 +379 3.72304 0.00978463 2.98834 0.00474254 3 +379 4.06778 0.0127572 2.7592 0.00339203 4 +379 4.64592 0.0184265 2.50101 0.00340501 5 +379 5.49551 0.0165843 3.40505 0.129713 6 +380 3.33318 0.00694565 3.31985 0.00685968 0 +380 3.38896 0.00731582 3.26708 0.00652255 1 +380 3.50913 0.00815303 3.15973 0.00583363 2 +380 3.71473 0.00971222 2.99446 0.00477637 3 +380 4.05028 0.01259 2.76923 0.00343649 4 +380 4.60983 0.0180651 2.51085 0.00321408 5 +380 5.46035 0.0188486 3.07979 0.0794373 6 +381 3.3331 0.00694048 3.31999 0.00685607 0 +381 3.38784 0.00730346 3.26816 0.00652506 1 +381 3.50562 0.0081227 3.16275 0.00584863 2 +381 3.70663 0.00964211 3.00048 0.00480982 3 +381 4.0333 0.0124292 2.77911 0.00348189 4 +381 4.57494 0.0177131 2.52127 0.00306454 5 +381 5.41871 0.0203759 2.8748 0.0543334 6 +382 3.33301 0.00693569 3.32014 0.00685269 0 +382 3.38674 0.00729171 3.26923 0.00652762 1 +382 3.50218 0.00809338 3.1657 0.0058635 2 +382 3.69872 0.00957443 3.00639 0.00484275 3 +382 4.01679 0.012274 2.78886 0.00352811 4 +382 4.54119 0.0173711 2.53215 0.00294948 5 +382 5.37266 0.0213941 2.73606 0.0394089 6 +383 3.33291 0.00693111 3.32028 0.0068497 0 +383 3.38566 0.0072803 3.27027 0.00653048 1 +383 3.49882 0.00806493 3.16862 0.00587835 2 +383 3.69098 0.00950866 3.0122 0.00487554 3 +383 4.00075 0.0121245 2.79846 0.00357499 4 +383 4.50857 0.0170398 2.54337 0.00286287 5 +383 5.32378 0.0220343 2.63893 0.0296348 6 +384 3.33283 0.00692695 3.32042 0.00684692 0 +384 3.3846 0.00726949 3.2713 0.0065334 1 +384 3.49552 0.00803744 3.17148 0.00589309 2 +384 3.68344 0.00944507 3.0179 0.00490793 3 +384 3.98517 0.0119805 2.80793 0.00362226 4 +384 4.47703 0.0167195 2.55486 0.00279997 5 +384 5.27323 0.0223877 2.56999 0.0228406 6 +385 3.33274 0.00692311 3.32056 0.00684444 0 +385 3.38356 0.00725902 3.27232 0.00653662 1 +385 3.49229 0.00801082 3.17429 0.00590781 2 +385 3.67607 0.00938344 3.02352 0.00494005 3 +385 3.97001 0.0118415 2.81725 0.00366998 4 +385 4.44653 0.0164102 2.56655 0.00275696 5 +385 5.22185 0.0225236 2.52102 0.017949 6 +386 3.33266 0.00691945 3.32069 0.0068424 0 +386 3.38253 0.00724905 3.27331 0.00653999 1 +386 3.48913 0.00798503 3.17705 0.00592253 2 +386 3.66888 0.00932386 3.02902 0.00497179 3 +386 3.95528 0.0117074 2.82642 0.00371795 4 +386 4.41704 0.0161119 2.57836 0.00273057 5 +386 5.17034 0.0224982 2.48665 0.0143293 6 +387 3.33258 0.00691622 3.32083 0.00684056 0 +387 3.38153 0.00723958 3.27429 0.00654353 1 +387 3.48603 0.0079602 3.17976 0.00593712 2 +387 3.66185 0.00926623 3.03443 0.0050032 3 +387 3.94095 0.0115783 2.83545 0.00376593 4 +387 4.38852 0.0158246 2.59025 0.00271826 5 +387 5.11919 0.0223512 2.46314 0.0116095 6 +388 3.3325 0.00691332 3.32096 0.00683901 0 +388 3.38055 0.00723056 3.27525 0.00654727 1 +388 3.483 0.00793614 3.18242 0.00595177 2 +388 3.65498 0.00921036 3.03975 0.00503437 3 +388 3.92702 0.0114537 2.84433 0.00381404 4 +388 4.36093 0.0155481 2.60218 0.0027175 5 +388 5.06875 0.0221158 2.44784 0.00953674 6 +389 3.33243 0.00691078 3.32109 0.00683774 0 +389 3.37959 0.00722201 3.27619 0.00655121 1 +389 3.48003 0.00791294 3.18504 0.00596638 2 +389 3.64827 0.00915634 3.04497 0.00506522 3 +389 3.91346 0.0113336 2.85307 0.0038621 4 +389 4.33424 0.0152819 2.61412 0.00272665 5 +389 5.01928 0.0218181 2.43885 0.00793981 6 +390 3.33235 0.00690851 3.32122 0.00683683 0 +390 3.37864 0.00721398 3.27712 0.00655528 1 +390 3.47712 0.00789058 3.18761 0.00598096 2 +390 3.64171 0.00910415 3.0501 0.00509573 3 +390 3.90026 0.0112176 2.86168 0.0039101 4 +390 4.30841 0.0150259 2.62603 0.00274422 5 +390 4.97096 0.021477 2.43472 0.00669976 6 +391 3.33228 0.00690665 3.32134 0.00683613 0 +391 3.37772 0.00720628 3.27803 0.00655968 1 +391 3.47427 0.00786906 3.19013 0.00599552 2 +391 3.63531 0.0090536 3.05513 0.00512602 3 +391 3.88742 0.0111058 2.87013 0.00395795 4 +391 4.28341 0.0147798 2.63789 0.00276883 5 +391 4.92392 0.0211073 2.43437 0.00573095 6 +392 3.33221 0.00690499 3.32147 0.00683587 0 +392 3.37681 0.00719909 3.27893 0.00656423 1 +392 3.47147 0.00784822 3.19262 0.00601019 2 +392 3.62905 0.00900472 3.06009 0.00515602 3 +392 3.87492 0.010998 2.87844 0.00400563 4 +392 4.25921 0.0145431 2.64968 0.00279937 5 +392 4.87823 0.0207205 2.43698 0.00497081 6 +393 3.33214 0.00690372 3.32159 0.00683587 0 +393 3.37592 0.00719236 3.27981 0.00656898 1 +393 3.46874 0.00782826 3.19505 0.0060248 2 +393 3.62293 0.00895743 3.06495 0.00518582 3 +393 3.86275 0.010894 2.88661 0.00405304 4 +393 4.23577 0.0143158 2.66137 0.00283476 5 +393 4.83391 0.0203248 2.44193 0.00437232 6 +394 3.33207 0.00690282 3.32171 0.00683613 0 +394 3.37504 0.00718606 3.28068 0.00657397 1 +394 3.46605 0.00780907 3.19745 0.00603941 2 +394 3.61695 0.00891183 3.06972 0.00521526 3 +394 3.8509 0.0107937 2.89464 0.00410013 4 +394 4.21307 0.0140973 2.67297 0.0028744 5 +394 4.791 0.0199266 2.44871 0.00390126 6 +395 3.33201 0.00690224 3.32182 0.00683671 0 +395 3.37419 0.00718023 3.28153 0.00657915 1 +395 3.46343 0.00779065 3.19979 0.00605404 2 +395 3.6111 0.0088677 3.07441 0.00524452 3 +395 3.83936 0.0106968 2.90254 0.00414709 4 +395 4.19108 0.0138874 2.68443 0.0029175 5 +395 4.74949 0.0195303 2.45694 0.00353061 6 +396 3.33195 0.00690202 3.32194 0.00683757 0 +396 3.37335 0.00717486 3.28237 0.00658452 1 +396 3.46085 0.00777301 3.20211 0.00606869 2 +396 3.60539 0.00882512 3.07902 0.00527349 3 +396 3.82811 0.0106035 2.9103 0.0041936 4 +396 4.16976 0.0136856 2.69578 0.00296355 5 +396 4.70936 0.0191395 2.46631 0.00324023 6 +396 5.47827 0.018751 3.09407 0.0999136 7 +397 3.33188 0.00690208 3.32206 0.00683879 0 +397 3.37252 0.00716986 3.28319 0.00659019 1 +397 3.45833 0.00775599 3.20438 0.00608348 2 +397 3.5998 0.00878391 3.08354 0.00530234 3 +397 3.81716 0.0105133 2.91792 0.00423993 4 +397 4.1491 0.0134917 2.707 0.00301203 5 +397 4.67059 0.0187568 2.47657 0.00301419 6 +397 5.43584 0.020696 2.84649 0.06118 7 +398 3.33182 0.00690245 3.32218 0.00684034 0 +398 3.37172 0.00716537 3.284 0.00659601 1 +398 3.45586 0.0077398 3.20661 0.00609821 2 +398 3.59434 0.00874426 3.08798 0.00533085 3 +398 3.80649 0.0104263 2.92541 0.0042858 4 +398 4.12908 0.0133054 2.71806 0.00306254 5 +398 4.63313 0.0183836 2.48753 0.00284036 6 +398 5.38809 0.0218996 2.69326 0.0415223 7 +399 3.33176 0.00690321 3.3223 0.00684215 0 +399 3.37092 0.00716131 3.28479 0.00660207 1 +399 3.45344 0.00772432 3.20879 0.006113 2 +399 3.58899 0.00870599 3.09234 0.00535915 3 +399 3.79608 0.0103424 2.93277 0.0043314 4 +399 4.10964 0.0131264 2.72899 0.00311462 5 +399 4.59697 0.0180213 2.49902 0.0027087 6 +399 5.33712 0.0226127 2.59237 0.0298131 7 +400 3.3317 0.00690428 3.32241 0.00684429 0 +400 3.37014 0.00715767 3.28557 0.00660836 1 +400 3.45107 0.00770948 3.21095 0.00612793 2 +400 3.58377 0.00866896 3.09663 0.00538739 3 +400 3.78595 0.0102615 2.94 0.00437656 4 +400 4.0908 0.0129542 2.73976 0.00316819 5 +400 4.56204 0.0176702 2.51092 0.00261177 6 +400 5.28439 0.022979 2.52419 0.0221972 7 +401 3.33165 0.00690564 3.32252 0.00684677 0 +401 3.36938 0.00715439 3.28634 0.00661495 1 +401 3.44874 0.00769537 3.21307 0.00614285 2 +401 3.57866 0.00863329 3.10083 0.00541538 3 +401 3.77606 0.0101834 2.94711 0.00442138 4 +401 4.07251 0.0127887 2.75037 0.00322272 5 +401 4.52832 0.0173312 2.52313 0.00254309 6 +401 5.23096 0.0230958 2.47794 0.0169706 7 +402 3.3316 0.00690741 3.32262 0.00684948 0 +402 3.36863 0.00715168 3.2871 0.00662163 1 +402 3.44646 0.00768202 3.21514 0.0061578 2 +402 3.57367 0.00859898 3.10497 0.00544315 3 +402 3.76643 0.0101082 2.95408 0.00446577 4 +402 4.05477 0.0126297 2.76083 0.00327807 5 +402 4.49576 0.0170044 2.53555 0.00249789 6 +402 5.17753 0.0230349 2.447 0.0132544 7 +403 3.33154 0.00690949 3.32273 0.00685253 0 +403 3.3679 0.00714925 3.28784 0.00662869 1 +403 3.44423 0.00766921 3.21719 0.00617292 2 +403 3.56878 0.00856585 3.10902 0.0054708 3 +403 3.75703 0.0100356 2.96093 0.00450986 4 +403 4.03754 0.0124768 2.77113 0.0033341 5 +403 4.4643 0.0166896 2.54811 0.00247194 6 +403 5.12466 0.0228477 2.4271 0.0105436 7 +404 3.33149 0.00691188 3.32284 0.00685591 0 +404 3.36718 0.00714737 3.28857 0.00663585 1 +404 3.44204 0.00765724 3.21919 0.00618797 2 +404 3.56399 0.00853404 3.11301 0.00549823 3 +404 3.74786 0.00996551 2.96766 0.00455356 4 +404 4.02081 0.0123298 2.78127 0.00339062 5 +404 4.43392 0.0163869 2.56076 0.00246205 6 +404 5.0727 0.0225728 2.41529 0.00852797 7 +405 3.33144 0.00691456 3.32294 0.00685962 0 +405 3.36648 0.00714581 3.28929 0.00664334 1 +405 3.4399 0.00764574 3.22116 0.00620327 2 +405 3.55932 0.0085034 3.11693 0.00552553 3 +405 3.73893 0.00989792 2.97427 0.0045969 4 +405 4.00456 0.0121884 2.79124 0.00344746 5 +405 4.40456 0.0160961 2.57345 0.0024654 6 +405 5.0219 0.0222374 2.40955 0.00701171 7 +406 3.33139 0.00691759 3.32305 0.00686364 0 +406 3.36578 0.00714468 3.28999 0.00665106 1 +406 3.43779 0.00763499 3.22309 0.00621856 2 +406 3.55474 0.00847398 3.12077 0.00555265 3 +406 3.73021 0.00983278 2.98076 0.00463986 4 +406 3.98878 0.0120523 2.80106 0.00350455 5 +406 4.37619 0.0158166 2.58613 0.00247998 6 +406 4.97243 0.0218627 2.40839 0.00585697 7 +407 3.33135 0.00692103 3.32315 0.00686787 0 +407 3.3651 0.00714403 3.29069 0.00665895 1 +407 3.43573 0.00762485 3.225 0.00623396 2 +407 3.55026 0.00844562 3.12454 0.0055797 3 +407 3.7217 0.00976999 2.98713 0.00468243 4 +407 3.97344 0.0119216 2.81071 0.00356166 5 +407 4.34877 0.0155484 2.59877 0.00250374 6 +407 4.9244 0.0214639 2.41073 0.00497178 7 +408 3.3313 0.0069247 3.32326 0.00687251 0 +408 3.36444 0.00714372 3.29137 0.00666714 1 +408 3.43371 0.00761533 3.22686 0.00624947 2 +408 3.54588 0.00841846 3.12825 0.00560657 3 +408 3.71339 0.00970944 2.99339 0.00472464 4 +408 3.95854 0.0117958 2.8202 0.00361884 5 +408 4.32226 0.0152911 2.61136 0.00253515 6 +408 4.87786 0.0210522 2.41575 0.00428954 7 +409 3.33125 0.00692867 3.32336 0.00687748 0 +409 3.36379 0.0071439 3.29204 0.0066755 1 +409 3.43174 0.00760644 3.2287 0.00626504 2 +409 3.5416 0.0083924 3.13189 0.00563329 3 +409 3.70529 0.00965109 2.99953 0.00476649 4 +409 3.94405 0.0116747 2.82953 0.0036759 5 +409 4.29663 0.0150442 2.62385 0.002573 6 +409 4.83283 0.0206358 2.42286 0.00376237 7 +410 3.33121 0.00693306 3.32345 0.00688265 0 +410 3.36315 0.00714442 3.2927 0.00668415 1 +410 3.4298 0.00759822 3.2305 0.00628068 2 +410 3.53741 0.00836735 3.13547 0.00565996 3 +410 3.69739 0.0095948 3.00557 0.00480803 4 +410 3.92996 0.0115583 2.8387 0.00373284 5 +410 4.27182 0.0148074 2.63624 0.00261622 6 +410 4.78931 0.0202202 2.43157 0.00335534 7 +410 5.49057 0.0188422 3.10242 0.124277 8 +411 3.33117 0.00693771 3.32355 0.00688819 0 +411 3.36252 0.00714532 3.29335 0.00669306 1 +411 3.42789 0.00759051 3.23227 0.00629649 2 +411 3.53329 0.00834337 3.13898 0.0056865 3 +411 3.68966 0.00954053 3.0115 0.00484924 4 +411 3.91625 0.0114462 2.84772 0.00378962 5 +411 4.24782 0.0145801 2.6485 0.00266398 6 +411 4.74728 0.01981 2.44153 0.00304224 7 +411 5.44732 0.0212336 2.81353 0.0675069 8 +412 3.33112 0.00694267 3.32365 0.00689405 0 +412 3.3619 0.00714668 3.29399 0.00670215 1 +412 3.42603 0.00758346 3.23401 0.00631235 2 +412 3.52928 0.00832038 3.14243 0.00571299 3 +412 3.68213 0.00948835 3.01732 0.00489005 4 +412 3.90293 0.0113383 2.85657 0.00384618 5 +412 4.22459 0.0143622 2.66064 0.00271534 6 +412 4.70672 0.019408 2.45245 0.00280307 7 +412 5.39787 0.022605 2.65022 0.042904 8 +413 3.33109 0.00694801 3.32375 0.00690014 0 +413 3.3613 0.00714837 3.29461 0.00671153 1 +413 3.42421 0.00757693 3.23572 0.00632839 2 +413 3.52535 0.00829841 3.14582 0.00573934 3 +413 3.67477 0.00943817 3.02302 0.00493049 4 +413 3.88996 0.0112346 2.86528 0.00390238 5 +413 4.2021 0.0141533 2.67262 0.0027698 6 +413 4.66758 0.0190164 2.4641 0.0026226 7 +413 5.34495 0.023362 2.54887 0.029539 8 +414 3.33105 0.00695362 3.32384 0.0069066 0 +414 3.36071 0.00715049 3.29523 0.00672112 1 +414 3.42242 0.00757096 3.2374 0.00634453 2 +414 3.5215 0.00827748 3.14914 0.00576557 3 +414 3.66759 0.00938969 3.02863 0.00497069 4 +414 3.87735 0.0111347 2.87382 0.00395833 5 +414 4.18032 0.0139529 2.68446 0.0028267 6 +414 4.62982 0.0186365 2.4763 0.00248952 7 +414 5.29033 0.0237165 2.48349 0.0213444 8 +415 3.33102 0.00695967 3.32393 0.00691321 0 +415 3.36013 0.00715304 3.29583 0.00673089 1 +415 3.42066 0.00756572 3.23905 0.00636064 2 +415 3.51774 0.00825748 3.1524 0.00579173 3 +415 3.66057 0.00934313 3.03414 0.00501051 4 +415 3.86507 0.0110387 2.88222 0.00401388 5 +415 4.15922 0.0137605 2.69613 0.00288573 6 +415 4.59342 0.0182691 2.48891 0.0023943 7 +415 5.23512 0.0237985 2.44103 0.0159442 8 +416 3.33098 0.00696578 3.32403 0.00692038 0 +416 3.35956 0.00715584 3.29643 0.00674105 1 +416 3.41894 0.00756082 3.24067 0.00637706 2 +416 3.51405 0.00823839 3.15561 0.00581785 3 +416 3.65372 0.00929836 3.03955 0.00504998 4 +416 3.85312 0.0109462 2.89047 0.00406905 5 +416 4.13877 0.013576 2.70765 0.00294637 6 +416 4.55828 0.0179146 2.50183 0.00232976 7 +416 5.18013 0.0236929 2.41402 0.0122239 8 +417 3.33095 0.00697234 3.32412 0.00692769 0 +417 3.359 0.007159 3.29701 0.00675146 1 +417 3.41726 0.0075566 3.24226 0.0063935 2 +417 3.51044 0.0082202 3.15876 0.00584392 3 +417 3.64702 0.00925516 3.04485 0.00508929 4 +417 3.84147 0.0108571 2.89857 0.00412393 5 +417 4.11895 0.013399 2.71899 0.00300835 6 +417 4.52439 0.0175735 2.51494 0.00229044 7 +417 5.12591 0.0234607 2.39783 0.00957623 8 +418 3.33092 0.0069792 3.32421 0.00693533 0 +418 3.35846 0.00716272 3.29759 0.00676192 1 +418 3.4156 0.00755285 3.24383 0.00641011 2 +418 3.50691 0.00820301 3.16185 0.00586982 3 +418 3.64048 0.0092137 3.05007 0.0051282 4 +418 3.83014 0.0107715 2.90652 0.00417836 5 +418 4.09974 0.0132292 2.73016 0.00307132 6 +418 4.4917 0.0172455 2.52819 0.00227166 7 +418 5.0728 0.0231425 2.38941 0.00765073 8 +419 3.33089 0.00698646 3.3243 0.00694315 0 +419 3.35792 0.00716671 3.29816 0.00677271 1 +419 3.41398 0.00754967 3.24537 0.00642681 2 +419 3.50345 0.0081865 3.16489 0.00589585 3 +419 3.63409 0.00917377 3.05519 0.0051669 4 +419 3.8191 0.0106889 2.91434 0.00423239 5 +419 4.0811 0.0130662 2.74115 0.00313515 6 +419 4.46014 0.0169304 2.5415 0.00226962 7 +419 5.02103 0.0227687 2.38669 0.00622631 8 +420 3.33086 0.00699394 3.32439 0.00695135 0 +420 3.3574 0.0071711 3.29871 0.00678371 1 +420 3.4124 0.00754708 3.24687 0.00644358 2 +420 3.50006 0.00817104 3.16787 0.00592165 3 +420 3.62785 0.00913553 3.06021 0.00520522 4 +420 3.80835 0.0106096 2.922 0.00428597 5 +420 4.06303 0.0129097 2.75197 0.00319953 6 +420 4.42968 0.0166282 2.55483 0.00228142 7 +420 4.97074 0.0223602 2.38819 0.00516034 8 +421 3.33082 0.00700173 3.32448 0.00695983 0 +421 3.35688 0.00717582 3.29926 0.00679499 1 +421 3.41083 0.00754487 3.24836 0.00646059 2 +421 3.49674 0.00815635 3.17081 0.00594747 3 +421 3.62175 0.00909871 3.06514 0.00524334 4 +421 3.79787 0.0105333 2.92954 0.00433912 5 +421 4.04548 0.0127595 2.76262 0.00326436 6 +421 4.40027 0.0163384 2.56813 0.00230474 7 +421 4.92203 0.0219324 2.39287 0.00435616 8 +422 3.3308 0.00700976 3.32456 0.00696865 0 +422 3.35638 0.00718086 3.2998 0.00680653 1 +422 3.40931 0.00754322 3.24982 0.00647769 2 +422 3.4935 0.00814238 3.17368 0.00597334 3 +422 3.61579 0.00906341 3.06998 0.00528117 4 +422 3.78766 0.0104597 2.93693 0.00439193 5 +422 4.02845 0.0126153 2.77309 0.00332944 6 +422 4.37187 0.0160606 2.58138 0.00233734 7 +422 4.87492 0.0214959 2.39997 0.00374609 8 +423 3.33077 0.00701803 3.32465 0.00697781 0 +423 3.35589 0.0071863 3.30033 0.00681825 1 +423 3.40782 0.0075421 3.25125 0.00649488 2 +423 3.49032 0.00812938 3.17651 0.00599901 3 +423 3.60997 0.00902949 3.07473 0.00531878 4 +423 3.77771 0.010389 2.94419 0.00444419 5 +423 4.01193 0.0124768 2.78338 0.00339466 6 +423 4.34443 0.0157944 2.59453 0.00237783 7 +423 4.82943 0.0210586 2.40888 0.00328303 8 +423 5.47568 0.0209068 2.8919 0.0968299 9 +424 3.33075 0.00702683 3.32474 0.00698702 0 +424 3.3554 0.00719214 3.30085 0.00683017 1 +424 3.40635 0.00754145 3.25266 0.00651223 2 +424 3.4872 0.00811711 3.17929 0.0060247 3 +424 3.60427 0.00899703 3.0794 0.00535607 4 +424 3.768 0.0103209 2.95131 0.00449606 5 +424 3.99588 0.0123438 2.79349 0.00345984 6 +424 4.31792 0.0155394 2.60758 0.00242472 7 +424 4.78553 0.0206256 2.41919 0.00293236 8 +424 5.42708 0.0228926 2.67123 0.0537589 9 +425 3.33073 0.00703583 3.32482 0.00699659 0 +425 3.35493 0.00719832 3.30136 0.00684232 1 +425 3.40492 0.00754141 3.25404 0.00652958 2 +425 3.48416 0.00810558 3.18201 0.0060504 3 +425 3.59871 0.00896591 3.08398 0.00539314 4 +425 3.75855 0.0102555 2.95831 0.00454749 5 +425 3.98029 0.0122159 2.80344 0.00352505 6 +425 4.29229 0.0152951 2.6205 0.00247695 7 +425 4.7432 0.0202008 2.43056 0.00266864 8 +425 5.37365 0.0239427 2.54695 0.0343445 9 +426 3.33071 0.00704502 3.3249 0.00700654 0 +426 3.35447 0.00720479 3.30187 0.00685475 1 +426 3.40351 0.00754169 3.2554 0.00654721 2 +426 3.48117 0.00809477 3.18468 0.0060761 3 +426 3.59327 0.00893609 3.08848 0.00542999 4 +426 3.74934 0.0101926 2.96517 0.00459841 5 +426 3.96515 0.0120933 2.8132 0.00358999 6 +426 4.26751 0.0150612 2.63328 0.00253351 7 +426 4.7024 0.0197867 2.44272 0.00247297 8 +426 5.31786 0.0244403 2.47132 0.0236355 9 +427 3.33069 0.00705454 3.32499 0.00701671 0 +427 3.35401 0.0072116 3.30237 0.0068674 1 +427 3.40212 0.00754241 3.25674 0.006565 2 +427 3.47825 0.0080848 3.18732 0.00610168 3 +427 3.58795 0.0089075 3.09289 0.00546665 4 +427 3.74034 0.0101319 2.97191 0.00464908 5 +427 3.95042 0.0119753 2.8228 0.00365483 6 +427 4.24353 0.014837 2.64591 0.00259372 7 +427 4.66308 0.0193852 2.45548 0.00233112 8 +427 5.26122 0.0245888 2.42422 0.0170423 9 +428 3.33066 0.00706436 3.32507 0.00702712 0 +428 3.35356 0.00721878 3.30285 0.00688024 1 +428 3.40077 0.00754369 3.25805 0.00658282 2 +428 3.47538 0.00807547 3.1899 0.00612731 3 +428 3.58274 0.00888013 3.09724 0.0055031 4 +428 3.73157 0.0100736 2.97853 0.00469925 5 +428 3.93612 0.011862 2.83222 0.00371935 6 +428 4.22033 0.0146222 2.65838 0.00265689 7 +428 4.62518 0.018997 2.46866 0.00223181 8 +428 5.2047 0.0245072 2.39528 0.0127044 9 +429 3.33065 0.00707433 3.32515 0.00703794 0 +429 3.35312 0.00722621 3.30333 0.00689337 1 +429 3.39944 0.00754537 3.25934 0.00660081 2 +429 3.47258 0.00806683 3.19243 0.00615294 3 +429 3.57766 0.00885408 3.10149 0.00553923 4 +429 3.72302 0.0100175 2.98502 0.00474899 5 +429 3.92221 0.0117531 2.84148 0.00378351 6 +429 4.19788 0.0144165 2.67067 0.00272234 7 +429 4.58866 0.0186229 2.48216 0.0021669 8 +429 5.14894 0.0242749 2.37855 0.00972504 9 +430 3.33063 0.00708481 3.32523 0.00704878 0 +430 3.35269 0.00723403 3.30381 0.00690666 1 +430 3.39814 0.00754758 3.26061 0.00661886 2 +430 3.46983 0.00805897 3.19492 0.00617848 3 +430 3.57269 0.00882915 3.10567 0.00557522 4 +430 3.71467 0.00996364 2.9914 0.00479828 5 +430 3.90869 0.0116484 2.85057 0.00384737 6 +430 4.17615 0.0142193 2.68278 0.00278977 7 +430 4.55345 0.018263 2.49585 0.00212935 8 +430 5.09434 0.0239441 2.37032 0.00761648 9 +431 3.33061 0.00709537 3.32531 0.00706006 0 +431 3.35227 0.00724214 3.30427 0.0069202 1 +431 3.39687 0.00755008 3.26185 0.00663718 2 +431 3.46714 0.00805173 3.19737 0.00620405 3 +431 3.56782 0.00880534 3.10977 0.00561102 4 +431 3.70653 0.00991186 2.99765 0.00484717 5 +431 3.89553 0.0115478 2.85949 0.00391075 6 +431 4.1551 0.0140306 2.69471 0.00285856 7 +431 4.51952 0.0179175 2.50967 0.00211402 8 +431 5.04116 0.0235505 2.36817 0.00609172 9 +432 3.3306 0.0071063 3.32539 0.00707151 0 +432 3.35186 0.00725061 3.30473 0.0069339 1 +432 3.39562 0.0075531 3.26308 0.00665553 2 +432 3.46451 0.00804513 3.19977 0.00622963 3 +432 3.56307 0.00878259 3.1138 0.00564666 4 +432 3.69858 0.00986211 3.00379 0.00489564 5 +432 3.88274 0.0114511 2.86825 0.00397373 6 +432 4.13471 0.0138494 2.70646 0.00292872 7 +432 4.4868 0.017586 2.52355 0.00211687 8 +432 4.98958 0.0231191 2.37045 0.0049732 9 +433 3.33058 0.00711741 3.32547 0.00708328 0 +433 3.35146 0.0072593 3.30518 0.00694791 1 +433 3.39439 0.00755651 3.26428 0.00667405 2 +433 3.46193 0.00803914 3.20213 0.00625524 3 +433 3.55841 0.00876108 3.11775 0.00568199 4 +433 3.69083 0.0098143 3.00982 0.00494373 5 +433 3.87028 0.0113581 2.87686 0.00403629 6 +433 4.11494 0.0136759 2.71803 0.00299959 7 +433 4.45524 0.0172682 2.53743 0.00213452 8 +433 4.93964 0.0226672 2.37599 0.00414333 9 +434 3.33057 0.00712884 3.32555 0.00709525 0 +434 3.35106 0.00726842 3.30562 0.006962 1 +434 3.39319 0.0075604 3.26546 0.00669262 2 +434 3.4594 0.00803387 3.20445 0.00628075 3 +434 3.55387 0.00874045 3.12163 0.00571726 4 +434 3.68326 0.00976833 3.01574 0.00499143 5 +434 3.85817 0.0112688 2.8853 0.00409833 6 +434 4.09579 0.0135094 2.7294 0.00307123 7 +434 4.42479 0.0169639 2.55127 0.00216429 8 +434 4.89141 0.0222067 2.38395 0.00352415 9 +434 5.49017 0.020957 2.92799 0.125685 10 +435 3.33056 0.00714061 3.32562 0.00710736 0 +435 3.35068 0.00727774 3.30606 0.00697638 1 +435 3.39201 0.00756462 3.26662 0.0067114 2 +435 3.45692 0.00802918 3.20673 0.0063063 3 +435 3.54941 0.00872094 3.12544 0.00575228 4 +435 3.67587 0.0097242 3.02154 0.00503876 5 +435 3.84638 0.0111829 2.89359 0.00415995 6 +435 4.07722 0.0133498 2.74058 0.00314327 7 +435 4.39541 0.0166725 2.56503 0.00220376 8 +435 4.84488 0.021746 2.39373 0.00306187 9 +435 5.44152 0.023476 2.66366 0.0612349 10 +436 3.33054 0.00715254 3.32571 0.00711982 0 +436 3.3503 0.00728741 3.30648 0.00699092 1 +436 3.39086 0.00756931 3.26776 0.00673022 2 +436 3.4545 0.00802513 3.20896 0.00633181 3 +436 3.54506 0.00870249 3.12919 0.00578706 4 +436 3.66866 0.00968186 3.02724 0.00508564 5 +436 3.8349 0.0111002 2.90173 0.00422104 6 +436 4.0592 0.0131967 2.75157 0.00321556 7 +436 4.36704 0.0163935 2.5787 0.00225152 8 +436 4.80004 0.0212911 2.40487 0.00271745 9 +436 5.3871 0.0247126 2.5276 0.0367106 10 +437 3.33054 0.00716477 3.32578 0.00713246 0 +437 3.34993 0.00729739 3.30691 0.00700564 1 +437 3.38973 0.00757433 3.26889 0.00674923 2 +437 3.45212 0.00802158 3.21116 0.00635741 3 +437 3.5408 0.00868485 3.13286 0.00582181 4 +437 3.66161 0.00964121 3.03284 0.00513218 5 +437 3.82372 0.0110208 2.90972 0.00428167 6 +437 4.04173 0.0130498 2.76237 0.00328801 7 +437 4.33965 0.0161265 2.59224 0.00230577 8 +437 4.75683 0.0208458 2.41703 0.00246357 9 +437 5.33003 0.0252712 2.44914 0.0242993 10 +438 3.33053 0.00717703 3.32586 0.00714553 0 +438 3.34956 0.00730757 3.30732 0.00702064 1 +438 3.38862 0.00757983 3.26999 0.00676826 2 +438 3.44979 0.00801865 3.21331 0.00638295 3 +438 3.53663 0.00866828 3.13647 0.00585622 4 +438 3.65474 0.00960241 3.03833 0.0051782 5 +438 3.81283 0.0109443 2.91755 0.00434172 6 +438 4.02477 0.0129088 2.77299 0.00336043 7 +438 4.31319 0.015871 2.60563 0.00236552 8 +438 4.71523 0.0204126 2.42993 0.00227921 9 +438 5.27208 0.0254246 2.40225 0.0170508 10 +439 3.33052 0.00718972 3.32593 0.00715864 0 +439 3.34921 0.00731794 3.30773 0.00703592 1 +439 3.38753 0.00758553 3.27107 0.00678758 2 +439 3.44751 0.00801632 3.21543 0.00640847 3 +439 3.53255 0.00865254 3.14001 0.00589065 4 +439 3.64802 0.00956486 3.04372 0.00522411 5 +439 3.80223 0.0108709 2.92524 0.00440125 6 +439 4.00832 0.0127734 2.78342 0.00343276 7 +439 4.28762 0.0156266 2.61887 0.00242961 8 +439 4.67517 0.0199934 2.44338 0.00214966 9 +439 5.21431 0.0253249 2.37462 0.0124465 10 +440 3.33051 0.00720266 3.32601 0.00717196 0 +440 3.34886 0.00732885 3.30813 0.00705111 1 +440 3.38646 0.00759171 3.27214 0.00680688 2 +440 3.44527 0.00801429 3.21752 0.00643421 3 +440 3.52856 0.0086376 3.14349 0.00592499 4 +440 3.64146 0.00952898 3.049 0.00526963 5 +440 3.7919 0.0108004 2.93279 0.00446023 6 +440 3.99233 0.0126435 2.79366 0.00350496 7 +440 4.2629 0.0153925 2.63193 0.00249729 8 +440 4.63658 0.0195886 2.45723 0.002063 9 +440 5.15741 0.0250638 2.35954 0.00936616 10 +441 3.33051 0.00721575 3.32608 0.00718558 0 +441 3.34852 0.00733977 3.30853 0.00706674 1 +441 3.38542 0.00759825 3.27318 0.00682633 2 +441 3.44309 0.00801314 3.21955 0.00645966 3 +441 3.52466 0.00862356 3.1469 0.00595908 4 +441 3.63505 0.00949468 3.0542 0.00531465 5 +441 3.78183 0.0107327 2.9402 0.00451861 6 +441 3.97681 0.0125188 2.80372 0.00357674 7 +441 4.239 0.0151684 2.64483 0.00256791 8 +441 4.59943 0.0191993 2.47134 0.00201073 9 +441 5.10178 0.0247003 2.35302 0.00723098 10 +442 3.3305 0.00722899 3.32616 0.00719949 0 +442 3.34818 0.00735112 3.30892 0.00708239 1 +442 3.38439 0.00760505 3.27421 0.00684596 2 +442 3.44094 0.00801242 3.22156 0.00648518 3 +442 3.52084 0.00861054 3.15025 0.0059929 4 +442 3.62879 0.00946176 3.05929 0.00535936 5 +442 3.77201 0.0106671 2.94748 0.00457686 6 +442 3.96173 0.0123991 2.8136 0.0036482 7 +442 4.21588 0.0149541 2.65753 0.00264068 8 +442 4.56365 0.0188254 2.4856 0.0019856 9 +442 5.0477 0.0242739 2.35249 0.00571365 10 +443 3.33049 0.0072426 3.32623 0.00721345 0 +443 3.34785 0.00736261 3.3093 0.00709834 1 +443 3.3834 0.00761217 3.27522 0.00686571 2 +443 3.43884 0.00801225 3.22354 0.00651063 3 +443 3.5171 0.00859839 3.15355 0.00602647 4 +443 3.62268 0.00943027 3.06429 0.00540369 5 +443 3.76245 0.0106048 2.95461 0.00463398 6 +443 3.94709 0.012284 2.82329 0.0037193 7 +443 4.19351 0.0147486 2.67004 0.00271548 8 +443 4.52917 0.0184667 2.49996 0.00198239 9 +443 4.99532 0.0238114 2.35625 0.00461677 10 +444 3.33049 0.00725639 3.32631 0.00722764 0 +444 3.34753 0.0073745 3.30968 0.0071143 1 +444 3.38241 0.00761982 3.27622 0.00688539 2 +444 3.43678 0.00801233 3.22547 0.00653637 3 +444 3.51344 0.00858679 3.15678 0.00606015 4 +444 3.6167 0.00939988 3.0692 0.005448 5 +444 3.75312 0.0105441 2.96161 0.00469119 6 +444 3.93286 0.0121735 2.83281 0.00378994 7 +444 4.17185 0.0145519 2.68235 0.00279152 8 +444 4.49596 0.018123 2.51433 0.0019968 9 +444 4.94469 0.0233305 2.36313 0.00381509 10 +445 3.33049 0.00727031 3.32638 0.00724212 0 +445 3.34722 0.00738651 3.31005 0.00713055 1 +445 3.38144 0.00762771 3.27719 0.00690527 2 +445 3.43476 0.0080132 3.22738 0.00656181 3 +445 3.50986 0.00857621 3.15995 0.00609347 4 +445 3.61086 0.00937088 3.07402 0.00549181 5 +445 3.74404 0.010486 2.96848 0.00474771 6 +445 3.91902 0.0120673 2.84215 0.0038602 7 +445 4.15088 0.0143634 2.69447 0.00286871 8 +445 4.46393 0.0177941 2.52868 0.00202569 9 +445 4.89585 0.0228437 2.37229 0.00322527 10 +445 5.45339 0.0240824 2.65673 0.0694802 11 +446 3.33049 0.0072846 3.32645 0.00725662 0 +446 3.34692 0.0073988 3.31042 0.00714692 1 +446 3.3805 0.00763589 3.27815 0.00692524 2 +446 3.43279 0.00801401 3.22925 0.00658769 3 +446 3.50635 0.00856613 3.16307 0.00612686 4 +446 3.60515 0.00934321 3.07875 0.00553536 5 +446 3.73517 0.0104303 2.97523 0.00480361 6 +446 3.90556 0.0119651 2.85132 0.00392999 7 +446 4.13057 0.0141828 2.70638 0.00294675 8 +446 4.43306 0.0174794 2.54295 0.00206594 9 +446 4.84878 0.0223589 2.38315 0.00279196 10 +446 5.39809 0.0255129 2.50938 0.038986 11 +447 3.33049 0.0072988 3.32652 0.0072716 0 +447 3.34661 0.00741131 3.31078 0.00716347 1 +447 3.37957 0.00764424 3.2791 0.00694547 2 +447 3.43085 0.00801596 3.23108 0.00661299 3 +447 3.50292 0.00855687 3.16613 0.00616004 4 +447 3.59957 0.00931727 3.08339 0.00557809 5 +447 3.72653 0.0103767 2.98184 0.00485897 6 +447 3.89248 0.0118675 2.86032 0.0039988 7 +447 4.11089 0.01401 2.7181 0.00302493 8 +447 4.40327 0.0171782 2.55713 0.00211567 9 +447 4.80346 0.0218822 2.39525 0.00247461 10 +447 5.33986 0.0261239 2.42884 0.0248475 11 +448 3.33049 0.00731366 3.3266 0.0072863 0 +448 3.34632 0.00742403 3.31114 0.00718018 1 +448 3.37866 0.00765331 3.28003 0.00696538 2 +448 3.42895 0.00801804 3.23289 0.00663858 3 +448 3.49956 0.00854837 3.16913 0.00619308 4 +448 3.59412 0.00929191 3.08795 0.00562105 5 +448 3.7181 0.0103252 2.98833 0.00491384 6 +448 3.87975 0.0117731 2.86915 0.00406738 7 +448 4.09182 0.0138439 2.72961 0.00310386 8 +448 4.37454 0.0168902 2.57117 0.00217309 9 +448 4.75985 0.021417 2.40826 0.00224573 10 +448 5.28072 0.0262756 2.3826 0.0169876 11 +449 3.33049 0.00732812 3.32667 0.00730176 0 +449 3.34603 0.00743689 3.31148 0.00719712 1 +449 3.37777 0.00766212 3.28094 0.00698591 2 +449 3.42709 0.00802057 3.23466 0.0066641 3 +449 3.49627 0.00854068 3.17208 0.00622581 4 +449 3.58879 0.00926787 3.09242 0.00566358 5 +449 3.70987 0.0102759 2.9947 0.00496814 6 +449 3.86737 0.0116825 2.87782 0.00413529 7 +449 4.07334 0.0136848 2.74092 0.00318279 8 +449 4.3468 0.0166146 2.58507 0.00223684 9 +449 4.71788 0.020966 2.42194 0.00208461 10 +449 5.22187 0.0261506 2.35647 0.0121632 11 +450 3.33049 0.00734316 3.32674 0.00731699 0 +450 3.34575 0.00745021 3.31183 0.00721397 1 +450 3.3769 0.00767159 3.28184 0.00700617 2 +450 3.42527 0.00802347 3.2364 0.00668972 3 +450 3.49305 0.00853314 3.17497 0.0062589 4 +450 3.58358 0.0092447 3.09681 0.00570593 5 +450 3.70185 0.0102279 3.00095 0.00502233 6 +450 3.85533 0.0115954 2.88632 0.00420272 7 +450 4.05541 0.0135323 2.75203 0.00326167 8 +450 4.32002 0.0163512 2.5988 0.00230536 9 +450 4.67749 0.0205305 2.43609 0.001976 10 +450 5.16398 0.0258567 2.3431 0.00901002 11 +451 3.3305 0.00735827 3.32681 0.0073325 0 +451 3.34548 0.00746347 3.31217 0.00723122 1 +451 3.37605 0.00768122 3.28271 0.00702668 2 +451 3.42349 0.00802703 3.23811 0.00671504 3 +451 3.4899 0.00852674 3.17782 0.00629134 4 +451 3.57849 0.00922323 3.10112 0.00574749 5 +451 3.69402 0.0101823 3.00709 0.00507562 6 +451 3.8436 0.0115113 2.89466 0.00426965 7 +451 4.03802 0.0133858 2.76294 0.00334043 8 +451 4.29415 0.0160993 2.61236 0.00237793 9 +451 4.63863 0.0201109 2.45056 0.00190855 10 +451 5.10748 0.0254577 2.33822 0.00686324 11 +452 3.3305 0.00737345 3.32688 0.00734826 0 +452 3.34521 0.00747708 3.3125 0.00724842 1 +452 3.37521 0.00769107 3.28358 0.00704721 2 +452 3.42174 0.00803061 3.23979 0.00674077 3 +452 3.48681 0.00852088 3.18061 0.00632385 4 +452 3.57351 0.00920222 3.10535 0.00578927 5 +452 3.68638 0.0101387 3.01311 0.00512839 6 +452 3.83219 0.0114309 2.90285 0.00433569 7 +452 4.02115 0.0132451 2.77366 0.00341913 8 +452 4.26915 0.0158581 2.62572 0.0024538 9 +452 4.60123 0.0197079 2.46522 0.00187383 10 +452 5.05266 0.0249972 2.3392 0.00536269 11 +453 3.33051 0.00738899 3.32695 0.00736398 0 +453 3.34494 0.00749081 3.31283 0.00726585 1 +453 3.37439 0.00770131 3.28444 0.00706773 2 +453 3.42002 0.00803473 3.24144 0.0067663 3 +453 3.48379 0.00851539 3.18336 0.00635636 4 +453 3.56864 0.00918267 3.1095 0.00583035 5 +453 3.67892 0.0100966 3.01901 0.00518078 6 +453 3.82107 0.0113534 2.91089 0.00440124 7 +453 4.00477 0.0131105 2.78418 0.00349716 8 +453 4.24498 0.0156274 2.6389 0.00253224 9 +453 4.56523 0.0193217 2.48 0.00186469 10 +453 4.9996 0.0245021 2.34433 0.00429205 11 +454 3.33052 0.00740457 3.32702 0.00737996 0 +454 3.34469 0.00750482 3.31316 0.00728331 1 +454 3.37359 0.00771167 3.28527 0.00708846 2 +454 3.41835 0.00803929 3.24306 0.00679179 3 +454 3.48083 0.00851065 3.18605 0.00638861 4 +454 3.56388 0.00916365 3.11357 0.00587153 5 +454 3.67164 0.0100559 3.02481 0.00523292 6 +454 3.81025 0.0112787 2.91877 0.00446624 7 +454 3.98887 0.0129807 2.7945 0.00357501 8 +454 4.22161 0.0154067 2.65186 0.00261258 9 +454 4.53057 0.0189517 2.49481 0.00187637 10 +454 4.9484 0.0239914 2.35241 0.00351957 11 +454 5.47207 0.0242583 2.69032 0.0897611 12 +455 3.33052 0.00741997 3.32709 0.00739642 0 +455 3.34444 0.0075188 3.31348 0.0073011 1 +455 3.3728 0.00772249 3.2861 0.00710905 2 +455 3.41669 0.00804421 3.24466 0.00681722 3 +455 3.47793 0.00850662 3.18869 0.00642065 4 +455 3.55922 0.00914574 3.11758 0.00591228 5 +455 3.66453 0.0100173 3.0305 0.00528417 6 +455 3.7997 0.0112072 2.9265 0.00453036 7 +455 3.97343 0.0128564 2.80464 0.00365234 8 +455 4.19901 0.0151952 2.66463 0.00269454 9 +455 4.49718 0.0185975 2.5096 0.00190427 10 +455 4.89906 0.0234771 2.36265 0.00295965 11 +455 5.41683 0.0261336 2.51144 0.0451371 12 +456 3.33053 0.00743611 3.32717 0.00741242 0 +456 3.34419 0.00753312 3.31379 0.00731882 1 +456 3.37202 0.00773327 3.28691 0.00712994 2 +456 3.41508 0.00804935 3.24622 0.00684278 3 +456 3.4751 0.00850317 3.19129 0.00645247 4 +456 3.55467 0.00912893 3.1215 0.00595261 5 +456 3.65759 0.00997974 3.03608 0.00533537 6 +456 3.78944 0.0111382 2.93408 0.00459397 7 +456 3.95844 0.012737 2.81459 0.00372909 8 +456 4.17714 0.0149929 2.67718 0.00277756 9 +456 4.465 0.0182588 2.52433 0.00194545 10 +456 4.85156 0.0229676 2.37445 0.00255386 11 +456 5.35786 0.0269081 2.42066 0.0272028 12 +457 3.33054 0.00745205 3.32723 0.00742889 0 +457 3.34395 0.00754765 3.3141 0.0073366 1 +457 3.37127 0.00774431 3.2877 0.00715087 2 +457 3.4135 0.00805504 3.24776 0.00686813 3 +457 3.47232 0.00849994 3.19384 0.00648448 4 +457 3.55022 0.00911297 3.12535 0.00599265 5 +457 3.65082 0.0099438 3.04155 0.00538599 6 +457 3.77943 0.0110718 2.94153 0.004657 7 +457 3.94387 0.0126221 2.82435 0.00380529 8 +457 4.15596 0.0147989 2.68952 0.00286146 9 +457 4.434 0.0179348 2.53895 0.00199738 10 +457 4.80587 0.0224682 2.38739 0.00226219 11 +457 5.29772 0.0271174 2.37074 0.0179597 12 +458 3.33055 0.00746834 3.3273 0.00744527 0 +458 3.34372 0.00756224 3.31441 0.00735457 1 +458 3.37052 0.00775573 3.28849 0.00717169 2 +458 3.41195 0.00806076 3.24927 0.0068937 3 +458 3.4696 0.00849772 3.19634 0.00651587 4 +458 3.54586 0.00909765 3.12914 0.00603262 5 +458 3.6442 0.00990947 3.04693 0.00543606 6 +458 3.76968 0.0110079 2.94883 0.00471937 7 +458 3.92971 0.0125116 2.83393 0.00388103 8 +458 4.13546 0.0146131 2.70165 0.00294591 9 +458 4.40409 0.0176252 2.55345 0.00205786 10 +458 4.76192 0.0219825 2.40116 0.00205675 11 +458 5.23777 0.0270026 2.34348 0.0125338 12 +459 3.33056 0.00748462 3.32737 0.00746188 0 +459 3.34349 0.00757701 3.31471 0.00737263 1 +459 3.3698 0.00776729 3.28926 0.00719263 2 +459 3.41044 0.0080671 3.25075 0.00691897 3 +459 3.46694 0.0084956 3.1988 0.00654756 4 +459 3.5416 0.00908346 3.13285 0.00607202 5 +459 3.63774 0.00987631 3.05221 0.0054858 6 +459 3.76018 0.0109467 2.956 0.00478087 7 +459 3.91596 0.0124057 2.84332 0.00395583 8 +459 4.1156 0.0144351 2.71357 0.00303045 9 +459 4.37526 0.0173292 2.56778 0.00212546 10 +459 4.71967 0.0215126 2.41549 0.00191684 11 +459 5.17881 0.0266949 2.33003 0.0090987 12 +460 3.33057 0.00750086 3.32744 0.00747878 0 +460 3.34326 0.00759176 3.31501 0.00739092 1 +460 3.36908 0.00777893 3.29002 0.00721372 2 +460 3.40895 0.00807349 3.25221 0.00694445 3 +460 3.46433 0.00849405 3.20122 0.00657898 4 +460 3.53742 0.00906966 3.1365 0.00611152 5 +460 3.63142 0.00984484 3.05738 0.00553494 6 +460 3.75092 0.0108873 2.96302 0.00484218 7 +460 3.90258 0.0123036 2.85254 0.00403016 8 +460 4.09636 0.0142643 2.72527 0.00311528 9 +460 4.34743 0.0170462 2.58195 0.0021983 10 +460 4.67904 0.0210599 2.43023 0.00182757 11 +460 5.12131 0.026273 2.32556 0.0068144 12 +461 3.33058 0.0075174 3.32751 0.00749559 0 +461 3.34304 0.00760683 3.3153 0.00740912 1 +461 3.36839 0.00779101 3.29076 0.0072346 2 +461 3.40749 0.00808034 3.25365 0.00696973 3 +461 3.46177 0.00849273 3.2036 0.00661047 4 +461 3.53334 0.00905702 3.14009 0.00615036 5 +461 3.62526 0.00981479 3.06246 0.00558337 6 +461 3.74189 0.0108304 2.96992 0.00490269 7 +461 3.88957 0.0122057 2.86159 0.00410359 8 +461 4.07771 0.0141006 2.73677 0.00319996 9 +461 4.32056 0.0167757 2.59593 0.00227566 10 +461 4.63996 0.0206247 2.44522 0.00177751 11 +461 5.06553 0.0257845 2.32714 0.0052438 12 +462 3.33059 0.0075341 3.32758 0.00751244 0 +462 3.34283 0.00762202 3.31559 0.0074274 1 +462 3.3677 0.00780292 3.2915 0.00725587 2 +462 3.40606 0.00808724 3.25506 0.0069952 3 +462 3.45927 0.00849263 3.20592 0.00664114 4 +462 3.52936 0.00904485 3.1436 0.00618921 5 +462 3.61923 0.00978544 3.06744 0.0056319 6 +462 3.73308 0.0107758 2.97668 0.00496237 7 +462 3.87692 0.0121112 2.87046 0.00417654 8 +462 4.05963 0.0139436 2.74805 0.00328431 9 +462 4.29461 0.016517 2.60971 0.00235646 10 +462 4.60237 0.0202072 2.46036 0.00175857 11 +462 5.0116 0.0252602 2.33294 0.00414163 12 +463 3.33061 0.00755069 3.32765 0.00752958 0 +463 3.34262 0.00763729 3.31588 0.00744579 1 +463 3.36703 0.00781522 3.29221 0.00727694 2 +463 3.40466 0.00809487 3.25644 0.00702018 3 +463 3.45682 0.0084923 3.20821 0.00667228 4 +463 3.52545 0.00903367 3.14705 0.00622758 5 +463 3.61335 0.00975744 3.07234 0.00567985 6 +463 3.72449 0.010723 2.98332 0.00502168 7 +463 3.86461 0.0120201 2.87917 0.00424891 8 +463 4.04209 0.0137927 2.75914 0.00336868 9 +463 4.26955 0.0162696 2.62329 0.00244011 10 +463 4.56621 0.0198075 2.47556 0.00176408 11 +463 4.95961 0.0247203 2.34171 0.00335704 12 +463 5.45114 0.0261638 2.56555 0.0651885 13 +464 3.33062 0.00756758 3.32772 0.0075466 0 +464 3.34241 0.00765263 3.31616 0.00746427 1 +464 3.36638 0.00782765 3.29292 0.00729803 2 +464 3.40329 0.0081023 3.2578 0.00704553 3 +464 3.45442 0.00849256 3.21046 0.00670312 4 +464 3.52163 0.00902304 3.15044 0.00626576 5 +464 3.6076 0.00973073 3.07714 0.00572728 6 +464 3.71612 0.0106722 2.98983 0.00508035 7 +464 3.85263 0.0119331 2.88771 0.00432003 8 +464 4.02509 0.0136479 2.77001 0.00345224 9 +464 4.24534 0.0160329 2.63665 0.00252576 10 +464 4.5314 0.0194249 2.49076 0.00178852 11 +464 4.90954 0.0241778 2.35261 0.00279572 12 +464 5.39257 0.0274606 2.43857 0.0349152 13 +465 3.33064 0.00758436 3.32778 0.00756388 0 +465 3.34222 0.00766824 3.31643 0.00748265 1 +465 3.36574 0.00784036 3.29362 0.00731907 2 +465 3.40195 0.0081102 3.25914 0.00707066 3 +465 3.45207 0.0084933 3.21267 0.00673373 4 +465 3.51789 0.00901285 3.15376 0.00630389 5 +465 3.60198 0.00970531 3.08185 0.00577413 6 +465 3.70795 0.0106232 2.99622 0.00513846 7 +465 3.84098 0.011849 2.89609 0.00439074 8 +465 4.00858 0.013509 2.78068 0.00353548 9 +465 4.22191 0.0158064 2.6498 0.00261306 10 +465 4.49789 0.019059 2.50591 0.00182884 11 +465 4.86138 0.0236414 2.36504 0.00239478 12 +465 5.33177 0.0278984 2.37337 0.0216045 13 +466 3.33066 0.0076012 3.32785 0.00758126 0 +466 3.34203 0.00768384 3.3167 0.0075012 1 +466 3.36511 0.00785324 3.2943 0.00734008 2 +466 3.40063 0.00811846 3.26045 0.00709559 3 +466 3.44977 0.00849429 3.21483 0.00676431 4 +466 3.51423 0.00900366 3.15702 0.00634142 5 +466 3.59649 0.00968068 3.08647 0.00582074 6 +466 3.69998 0.0105764 3.00249 0.00519556 7 +466 3.82963 0.0117678 2.90431 0.00446077 8 +466 3.99256 0.0133752 2.79115 0.00361827 9 +466 4.19927 0.0155893 2.66273 0.00270163 10 +466 4.4656 0.0187095 2.52095 0.00188109 11 +466 4.81507 0.0231168 2.37857 0.00211101 12 +466 5.27068 0.0278862 2.33864 0.0144461 13 +467 3.33067 0.0076184 3.32792 0.00759839 0 +467 3.34184 0.0076996 3.31697 0.0075197 1 +467 3.36449 0.00786611 3.29498 0.00736123 2 +467 3.39934 0.00812657 3.26174 0.00712082 3 +467 3.44751 0.00849576 3.21696 0.00679468 4 +467 3.51066 0.00899506 3.16023 0.00637869 5 +467 3.59112 0.00965735 3.09101 0.00586674 6 +467 3.6922 0.0105312 3.00864 0.00525232 7 +467 3.81859 0.0116897 2.91236 0.00452999 8 +467 3.977 0.0132468 2.80142 0.00370018 9 +467 4.17735 0.0153813 2.67544 0.00279092 10 +467 4.4345 0.0183753 2.53587 0.00194348 11 +467 4.77058 0.0226073 2.39287 0.00191505 12 +467 5.21038 0.0276195 2.32129 0.0101543 13 +468 3.3307 0.00763532 3.32799 0.00761593 0 +468 3.34165 0.00771528 3.31723 0.0075384 1 +468 3.36389 0.00787903 3.29564 0.00738244 2 +468 3.39808 0.00813534 3.26301 0.00714554 3 +468 3.44531 0.00849736 3.21905 0.00682511 4 +468 3.50715 0.00898695 3.16338 0.00641577 5 +468 3.58587 0.00963485 3.09546 0.0059124 6 +468 3.68461 0.0104873 3.01467 0.00530867 7 +468 3.80783 0.0116147 2.92027 0.00459818 8 +468 3.9619 0.0131234 2.8115 0.00378143 9 +468 4.15615 0.0151823 2.68793 0.00288062 10 +468 4.40451 0.018056 2.55062 0.00201349 11 +468 4.72782 0.0221152 2.40771 0.00178555 12 +468 5.15144 0.0272045 2.31473 0.00740433 13 +469 3.33071 0.00765244 3.32806 0.00763335 0 +469 3.34147 0.00773116 3.3175 0.00755702 1 +469 3.3633 0.00789226 3.29629 0.00740348 2 +469 3.39684 0.00814402 3.26425 0.00717049 3 +469 3.44314 0.00849948 3.22111 0.00685515 4 +469 3.50372 0.00897921 3.16647 0.00645276 5 +469 3.58074 0.00961322 3.09983 0.00595779 6 +469 3.67721 0.0104453 3.02059 0.00536436 7 +469 3.79736 0.0115423 2.92802 0.00466598 8 +469 3.94723 0.0130051 2.82139 0.00386175 9 +469 4.13561 0.0149914 2.70019 0.00297066 10 +469 4.3756 0.0177508 2.5652 0.00208981 11 +469 4.68673 0.0216414 2.42291 0.00170676 12 +469 5.09424 0.0267044 2.31522 0.00556629 13 +470 3.33073 0.00766971 3.32812 0.00765073 0 +470 3.34129 0.00774698 3.31776 0.00757578 1 +470 3.36272 0.00790549 3.29693 0.00742461 2 +470 3.39563 0.00815279 3.26548 0.00719544 3 +470 3.44102 0.00850208 3.22312 0.00688494 4 +470 3.50037 0.00897213 3.1695 0.00648945 5 +470 3.57573 0.00959301 3.10412 0.00600235 6 +470 3.66998 0.0104052 3.0264 0.00541901 7 +470 3.78715 0.0114724 2.93563 0.00473304 8 +470 3.93297 0.0128907 2.83109 0.00394176 9 +470 4.11573 0.0148084 2.71224 0.00306061 10 +470 4.3477 0.0174594 2.57959 0.00217088 11 +470 4.64722 0.0211868 2.43833 0.00166717 12 +470 5.03894 0.0261587 2.3205 0.00430231 13 +471 3.33075 0.00768683 3.3282 0.00766831 0 +471 3.34112 0.00776286 3.31802 0.00759453 1 +471 3.36215 0.00791893 3.29757 0.00744557 2 +471 3.39443 0.00816209 3.26669 0.00722 3 +471 3.43894 0.0085047 3.22511 0.00691482 4 +471 3.49708 0.00896589 3.17248 0.00652552 5 +471 3.57082 0.00957311 3.10833 0.00604692 6 +471 3.66292 0.0103659 3.03209 0.00547378 7 +471 3.77721 0.0114055 2.94309 0.00479882 8 +471 3.91912 0.0127808 2.8406 0.0040208 9 +471 4.09647 0.0146329 2.72406 0.00315047 10 +471 4.32079 0.0171805 2.59377 0.00225592 11 +471 4.60925 0.0207512 2.45387 0.00165817 12 +471 4.98561 0.0255916 2.3291 0.00341798 13 +471 5.44983 0.0271411 2.52784 0.0627848 14 +472 3.33077 0.00770409 3.32826 0.00768582 0 +472 3.34095 0.00777903 3.31826 0.00761307 1 +472 3.36159 0.0079324 3.29819 0.0074666 2 +472 3.39327 0.00817151 3.26787 0.0072445 3 +472 3.43691 0.00850789 3.22705 0.00694427 4 +472 3.49386 0.00896019 3.17541 0.00656129 5 +472 3.56603 0.00955405 3.11246 0.00609118 6 +472 3.65603 0.0103285 3.03769 0.00552751 7 +472 3.76752 0.0113403 2.95041 0.00486447 8 +472 3.90565 0.0126751 2.84993 0.00409894 9 +472 4.07781 0.0144646 2.73566 0.00323999 10 +472 4.2948 0.0169142 2.60774 0.00234389 11 +472 4.57272 0.020334 2.46944 0.0016733 12 +472 4.93427 0.0250195 2.34004 0.00279334 13 +472 5.38989 0.0283552 2.41037 0.0330222 14 +473 3.33079 0.00772135 3.32833 0.00770335 0 +473 3.34079 0.00779511 3.31851 0.00763174 1 +473 3.36105 0.00794584 3.2988 0.00748769 2 +473 3.39213 0.00818077 3.26903 0.00726923 3 +473 3.43492 0.00851122 3.22897 0.00697372 4 +473 3.49072 0.00895446 3.17827 0.00659728 5 +473 3.56134 0.00953595 3.11652 0.00613487 6 +473 3.6493 0.0102925 3.04317 0.00558069 7 +473 3.75808 0.0112781 2.95759 0.00492892 8 +473 3.89256 0.0125735 2.85909 0.00417607 9 +473 4.05971 0.0143028 2.74705 0.00332913 10 +473 4.26969 0.0166591 2.62149 0.00243441 11 +473 4.53758 0.0199356 2.48497 0.00170699 12 +473 4.88492 0.0244527 2.35263 0.00235294 13 +473 5.32805 0.0287043 2.35176 0.020194 14 +474 3.33082 0.00773867 3.3284 0.00772087 0 +474 3.34063 0.0078113 3.31875 0.00765029 1 +474 3.36051 0.0079595 3.2994 0.00750858 2 +474 3.39101 0.0081903 3.27017 0.00729374 3 +474 3.43297 0.00851479 3.23085 0.00700299 4 +474 3.48764 0.00894973 3.1811 0.00663245 5 +474 3.55676 0.00951889 3.1205 0.00617788 6 +474 3.64274 0.0102578 3.04855 0.0056333 7 +474 3.74888 0.0112175 2.96463 0.004993 8 +474 3.87983 0.0124753 2.86806 0.0042527 9 +474 4.04216 0.0141475 2.75823 0.00341765 10 +474 4.24543 0.016415 2.63502 0.00252653 11 +474 4.50375 0.0195545 2.50043 0.00175588 12 +474 4.8375 0.0238977 2.3664 0.00204447 13 +474 5.26621 0.0286146 2.32178 0.0133747 14 +475 3.33084 0.00775599 3.32846 0.00773838 0 +475 3.34048 0.0078274 3.319 0.00766898 1 +475 3.35999 0.00797329 3.29999 0.00752938 2 +475 3.38991 0.00820006 3.27129 0.00731802 3 +475 3.43106 0.00851897 3.23269 0.00703171 4 +475 3.48462 0.00894522 3.18386 0.0066676 5 +475 3.55228 0.00950241 3.12441 0.00622067 6 +475 3.63632 0.010224 3.05383 0.00568562 7 +475 3.73991 0.0111595 2.97154 0.00505603 8 +475 3.86744 0.0123808 2.87687 0.0043284 9 +475 4.02514 0.0139982 2.7692 0.00350571 10 +475 4.22198 0.0161813 2.64831 0.00261991 11 +475 4.47118 0.0191905 2.51577 0.00181659 12 +475 4.79195 0.0233588 2.381 0.00183335 13 +475 5.20536 0.0282821 2.30796 0.00932405 14 +476 3.33087 0.00777322 3.32853 0.00775597 0 +476 3.34033 0.00784354 3.31923 0.00768759 1 +476 3.35948 0.00798686 3.30057 0.00755039 2 +476 3.38883 0.00821 3.27241 0.00734222 3 +476 3.42918 0.00852284 3.2345 0.00706083 4 +476 3.48167 0.00894099 3.18658 0.00670256 5 +476 3.54789 0.0094867 3.12824 0.00626299 6 +476 3.63005 0.0101919 3.05901 0.005737 7 +476 3.73116 0.0111034 2.97831 0.0051184 8 +476 3.85539 0.0122899 2.8855 0.00440298 9 +476 4.00862 0.0138548 2.77995 0.00359297 10 +476 4.1993 0.0159577 2.66138 0.00271394 11 +476 4.43981 0.0188428 2.53095 0.00188668 12 +476 4.74819 0.022838 2.39616 0.00169515 13 +476 5.14606 0.0278119 2.3041 0.0067497 14 +477 3.33089 0.0077904 3.3286 0.00777358 0 +477 3.34018 0.00785963 3.31947 0.00770626 1 +477 3.35898 0.00800066 3.30114 0.00757115 2 +477 3.38779 0.00821996 3.27348 0.0073663 3 +477 3.42735 0.00852743 3.23628 0.00708924 4 +477 3.47878 0.00893726 3.18925 0.00673715 5 +477 3.54361 0.00947174 3.13201 0.00630482 6 +477 3.62393 0.0101609 3.0641 0.0057878 7 +477 3.72263 0.0110495 2.98496 0.00517985 8 +477 3.84367 0.0122021 2.89397 0.00447686 9 +477 3.99259 0.0137168 2.7905 0.00367942 10 +477 4.17737 0.0157433 2.67422 0.00280859 11 +477 4.40959 0.0185109 2.54596 0.00196407 12 +477 4.70617 0.022337 2.41169 0.00161221 13 +477 5.08861 0.0272654 2.3067 0.00504068 14 +478 3.33092 0.00780761 3.32867 0.00779112 0 +478 3.34003 0.00787564 3.31971 0.00772495 1 +478 3.35849 0.00801471 3.30171 0.00759164 2 +478 3.38675 0.00823 3.27455 0.00739034 3 +478 3.42555 0.00853161 3.23804 0.00711809 4 +478 3.47595 0.00893408 3.19187 0.00677138 5 +478 3.53941 0.00945729 3.1357 0.00634651 6 +478 3.61795 0.010131 3.06909 0.0058381 7 +478 3.71431 0.0109968 2.99148 0.00524098 8 +478 3.83225 0.0121173 2.90228 0.00455 9 +478 3.97703 0.0135842 2.80085 0.00376501 10 +478 4.15615 0.0155381 2.68682 0.00290321 11 +478 4.38045 0.0181934 2.56078 0.00204732 12 +478 4.6658 0.0218561 2.42744 0.00157163 13 +478 5.03315 0.0266807 2.31365 0.00387637 14 +478 5.47481 0.026988 2.58277 0.0899578 15 +479 3.33094 0.0078248 3.32874 0.00780863 0 +479 3.3399 0.00789164 3.31993 0.0077436 1 +479 3.35801 0.00802821 3.30226 0.00761261 2 +479 3.38574 0.00824022 3.2756 0.00741415 3 +479 3.42379 0.0085366 3.23975 0.00714616 4 +479 3.47317 0.00893113 3.19445 0.00680537 5 +479 3.53531 0.00944358 3.13933 0.00638761 6 +479 3.61211 0.010102 3.07398 0.00588792 7 +479 3.70619 0.0109466 2.99788 0.0053011 8 +479 3.82114 0.0120358 2.91042 0.00462191 9 +479 3.96193 0.0134564 2.81101 0.00384988 10 +479 4.1356 0.015341 2.6992 0.0029979 11 +479 4.35234 0.0178903 2.57539 0.00213518 12 +479 4.627 0.0213958 2.44332 0.00156358 13 +479 4.97975 0.0260809 2.32359 0.00306841 14 +479 5.41547 0.028823 2.42531 0.0410144 15 +480 3.33098 0.00784219 3.3288 0.00782587 0 +480 3.33976 0.007908 3.32016 0.00776182 1 +480 3.35754 0.00804242 3.30281 0.00763282 2 +480 3.38475 0.00825064 3.27664 0.00743771 3 +480 3.42206 0.00854156 3.24145 0.00717421 4 +480 3.47046 0.00892864 3.19698 0.00683892 5 +480 3.5313 0.00943073 3.14289 0.00642805 6 +480 3.60641 0.0100742 3.07878 0.00593714 7 +480 3.69828 0.010898 3.00414 0.00536026 8 +480 3.81033 0.0119569 2.9184 0.00469319 9 +480 3.94725 0.0133338 2.82096 0.00393356 10 +480 4.1157 0.0151521 2.71134 0.00309245 11 +480 4.32522 0.0176004 2.58978 0.00222656 12 +480 4.5897 0.020955 2.45921 0.00158087 13 +480 4.92839 0.0254805 2.33562 0.00250451 14 +480 5.35316 0.0293989 2.35274 0.0234381 15 +481 3.331 0.00785927 3.32887 0.00784332 0 +481 3.33963 0.00792407 3.32038 0.00778023 1 +481 3.35709 0.00805616 3.30335 0.0076534 2 +481 3.38378 0.00826087 3.27765 0.00746138 3 +481 3.42037 0.00854671 3.2431 0.00720205 4 +481 3.4678 0.00892645 3.19946 0.00687231 5 +481 3.52737 0.00941797 3.14638 0.00646855 6 +481 3.60083 0.0100473 3.0835 0.00598573 7 +481 3.69055 0.0108504 3.0103 0.00541944 8 +481 3.79979 0.0118809 2.92624 0.0047635 9 +481 3.933 0.0132155 2.83072 0.00401646 10 +481 4.09643 0.0149706 2.72326 0.00318665 11 +481 4.29904 0.0173231 2.60395 0.00232059 12 +481 4.55385 0.0205343 2.47507 0.00161808 13 +481 4.87907 0.0248894 2.34911 0.00211188 14 +481 5.29042 0.0293942 2.31679 0.0149093 15 +482 3.33103 0.0078765 3.32894 0.00786052 0 +482 3.3395 0.00794009 3.3206 0.0077986 1 +482 3.35664 0.00807003 3.30387 0.00767376 2 +482 3.38283 0.00827128 3.27864 0.00748478 3 +482 3.41872 0.00855216 3.24473 0.00722952 4 +482 3.4652 0.00892451 3.20189 0.00690541 5 +482 3.52353 0.00940609 3.14982 0.00650834 6 +482 3.59538 0.0100214 3.08812 0.00603395 7 +482 3.68302 0.010805 3.01634 0.00547727 8 +482 3.78954 0.0118076 2.93392 0.00483274 9 +482 3.91915 0.0131015 2.84029 0.00409837 10 +482 4.07775 0.0147965 2.73496 0.00328018 11 +482 4.27377 0.0170579 2.61788 0.0024166 12 +482 4.51935 0.0201321 2.49084 0.00167089 13 +482 4.8317 0.0243129 2.36363 0.00184271 14 +482 5.22849 0.0290872 2.30017 0.010095 15 +483 3.33106 0.0078933 3.32901 0.00787802 0 +483 3.33938 0.00795613 3.32082 0.00781682 1 +483 3.3562 0.00808376 3.3044 0.00769413 2 +483 3.3819 0.00828157 3.27962 0.00750821 3 +483 3.41709 0.00855757 3.24633 0.007257 4 +483 3.46266 0.00892298 3.20428 0.00693809 5 +483 3.51977 0.0093946 3.15319 0.00654785 6 +483 3.59005 0.00999659 3.09266 0.00608136 7 +483 3.67566 0.0107614 3.02226 0.00553415 8 +483 3.77954 0.0117364 2.94146 0.00490147 9 +483 3.90567 0.0129916 2.84969 0.00417937 10 +483 4.05965 0.0146292 2.74643 0.00337299 11 +483 4.24935 0.016804 2.63157 0.00251407 12 +483 4.48615 0.0197482 2.50648 0.00173592 13 +483 4.78622 0.0237546 2.37885 0.00166409 14 +483 5.16807 0.0286141 2.29498 0.00713765 15 +484 3.3311 0.00791033 3.32907 0.00789516 0 +484 3.33926 0.00797206 3.32104 0.00783501 1 +484 3.35577 0.0080976 3.30491 0.00771427 2 +484 3.38099 0.0082924 3.28059 0.00753098 3 +484 3.41551 0.00856322 3.2479 0.00728406 4 +484 3.46016 0.00892163 3.20664 0.00697055 5 +484 3.51609 0.00938402 3.15649 0.00658658 6 +484 3.58484 0.00997245 3.09711 0.0061283 7 +484 3.66848 0.0107188 3.02807 0.0055908 8 +484 3.7698 0.0116679 2.94884 0.00496909 9 +484 3.89259 0.0128857 2.85889 0.00425934 10 +484 4.0421 0.0144684 2.75768 0.00346516 11 +484 4.22575 0.0165613 2.64503 0.00261226 12 +484 4.45417 0.0193815 2.52196 0.00181053 13 +484 4.74257 0.0232171 2.39454 0.00155304 14 +484 5.10951 0.02805 2.29698 0.00522265 15 +485 3.33112 0.00792716 3.32914 0.00791235 0 +485 3.33914 0.00798803 3.32125 0.00785302 1 +485 3.35535 0.00811188 3.30541 0.00773386 2 +485 3.38009 0.00830292 3.28153 0.00755394 3 +485 3.41395 0.00856875 3.24945 0.00731122 4 +485 3.45772 0.00892063 3.20895 0.00700265 5 +485 3.51249 0.00937368 3.15974 0.00662514 6 +485 3.57975 0.00994913 3.10149 0.00617481 7 +485 3.66148 0.0106777 3.03377 0.00564651 8 +485 3.76031 0.0116017 2.95609 0.00503588 9 +485 3.87986 0.0127834 2.86791 0.00433847 10 +485 4.02508 0.0143139 2.76872 0.00355637 11 +485 4.20293 0.0163284 2.65825 0.0027112 12 +485 4.42338 0.0190313 2.53725 0.00189273 13 +485 4.70066 0.0227005 2.41052 0.00149303 14 +485 5.05298 0.0274396 2.30375 0.00394027 15 +485 5.47284 0.0279391 2.54322 0.0852546 16 +486 3.33116 0.00794408 3.32921 0.00792927 0 +486 3.33902 0.00800378 3.32146 0.00787107 1 +486 3.35493 0.00812533 3.30591 0.00775403 2 +486 3.37922 0.00831332 3.28247 0.00757682 3 +486 3.41242 0.00857457 3.25097 0.00733791 4 +486 3.45533 0.00891979 3.21121 0.00703448 5 +486 3.50897 0.00936409 3.16293 0.00666299 6 +486 3.57478 0.00992681 3.10578 0.00622064 7 +486 3.65463 0.0106383 3.03936 0.00570137 8 +486 3.75106 0.0115376 2.9632 0.00510162 9 +486 3.86748 0.0126848 2.87676 0.00441643 10 +486 4.00856 0.0141651 2.77955 0.00364686 11 +486 4.18086 0.0161054 2.67123 0.00281019 12 +486 4.3937 0.0186966 2.55235 0.00198092 13 +486 4.6604 0.0222055 2.42667 0.00147193 14 +486 4.99857 0.0268116 2.31372 0.0030639 15 +486 5.41216 0.029646 2.39877 0.0384784 16 +487 3.33119 0.00796058 3.32928 0.00794643 0 +487 3.33892 0.00801945 3.32167 0.007889 1 +487 3.35453 0.00813928 3.3064 0.00777356 2 +487 3.37836 0.00832392 3.28338 0.00759938 3 +487 3.41093 0.00858066 3.25246 0.0073642 4 +487 3.45298 0.00891939 3.21344 0.00706583 5 +487 3.50552 0.0093541 3.16606 0.00670118 6 +487 3.56992 0.00990509 3.10999 0.00626594 7 +487 3.64795 0.0105994 3.04485 0.00575607 8 +487 3.74205 0.0114759 2.97017 0.00516636 9 +487 3.85543 0.01259 2.88544 0.00449306 10 +487 3.99254 0.0140219 2.79016 0.00373622 11 +487 4.15951 0.0158916 2.68397 0.00290923 12 +487 4.36509 0.018377 2.56722 0.0020735 13 +487 4.62174 0.0217324 2.44286 0.00148077 14 +487 4.94626 0.0261812 2.32592 0.00245942 15 +487 5.34891 0.0301126 2.33364 0.0218227 16 +488 3.33122 0.00797736 3.32935 0.00796309 0 +488 3.33881 0.00803516 3.32187 0.0079067 1 +488 3.35413 0.00815286 3.30688 0.00779325 2 +488 3.37752 0.00833447 3.28428 0.00762178 3 +488 3.40946 0.0085866 3.25393 0.00739051 4 +488 3.45069 0.00891908 3.21563 0.00709696 5 +488 3.50215 0.00934491 3.16913 0.00673856 6 +488 3.56515 0.00988412 3.11413 0.00631065 7 +488 3.64142 0.0105622 3.05023 0.00580958 8 +488 3.73326 0.011416 2.977 0.00523047 9 +488 3.84371 0.0124978 2.89396 0.00456929 10 +488 3.97698 0.013884 2.80057 0.00382486 11 +488 4.13885 0.0156862 2.69648 0.00300806 12 +488 4.3375 0.0180715 2.58186 0.00216954 13 +488 4.58457 0.0212802 2.45905 0.00151262 14 +488 4.89603 0.02556 2.33965 0.00204325 15 +488 5.28551 0.0300237 2.30252 0.0137808 16 +489 3.33126 0.00799388 3.32941 0.00797981 0 +489 3.33871 0.00805083 3.32207 0.00792422 1 +489 3.35375 0.00816664 3.30735 0.00781254 2 +489 3.37669 0.00834509 3.28517 0.00764389 3 +489 3.40804 0.00859265 3.25536 0.00741649 4 +489 3.44844 0.00891883 3.21777 0.0071279 5 +489 3.49884 0.00933655 3.17215 0.00677523 6 +489 3.56051 0.00986404 3.11818 0.00635479 7 +489 3.63506 0.0105261 3.05551 0.00586259 8 +489 3.72468 0.0113579 2.98371 0.00529372 9 +489 3.8323 0.0124091 2.9023 0.00464406 10 +489 3.96187 0.0137512 2.81078 0.00391214 11 +489 4.11885 0.0154894 2.70874 0.00310627 12 +489 4.31088 0.0177795 2.59627 0.00226806 13 +489 4.54884 0.0208481 2.47515 0.00156251 14 +489 4.84783 0.0249547 2.35444 0.00176085 15 +489 5.22318 0.0296484 2.28928 0.00926846 16 +490 3.33129 0.00801027 3.32948 0.0079964 0 +490 3.3386 0.00806611 3.32228 0.0079419 1 +490 3.35337 0.00817998 3.30782 0.00783204 2 +490 3.37589 0.00835545 3.28603 0.00766604 3 +490 3.40663 0.00859882 3.25678 0.00744217 4 +490 3.44624 0.00891913 3.21988 0.00715813 5 +490 3.49562 0.00932807 3.1751 0.00681185 6 +490 3.55596 0.00984432 3.12215 0.00639861 7 +490 3.62884 0.0104912 3.06068 0.00591482 8 +490 3.71634 0.0113019 2.99028 0.00535598 9 +490 3.82121 0.0123233 2.91048 0.0047179 10 +490 3.94721 0.0136233 2.82079 0.00399829 11 +490 4.09947 0.0153001 2.72078 0.00320401 12 +490 4.28516 0.0175002 2.61044 0.00236856 13 +490 4.51448 0.0204358 2.49114 0.00162672 14 +490 4.80158 0.0243683 2.36996 0.00157582 15 +490 5.16249 0.0291201 2.28656 0.00651037 16 +491 3.33133 0.00802657 3.32955 0.00801283 0 +491 3.33851 0.00808151 3.32247 0.0079592 1 +491 3.353 0.00819344 3.30828 0.00785117 2 +491 3.3751 0.00836591 3.28689 0.00768786 3 +491 3.40525 0.00860493 3.25817 0.0074677 4 +491 3.44408 0.00891885 3.22195 0.00718872 5 +491 3.49245 0.00932047 3.17801 0.00684754 6 +491 3.55152 0.00982549 3.12606 0.00644157 7 +491 3.62276 0.0104572 3.06577 0.00596639 8 +491 3.70818 0.0112477 2.99674 0.00541728 9 +491 3.81039 0.0122401 2.91851 0.00479083 10 +491 3.93295 0.0134999 2.8306 0.00408345 11 +491 4.08069 0.0151184 2.73259 0.0033008 12 +491 4.26034 0.0172326 2.62436 0.00247031 13 +491 4.48141 0.020042 2.50696 0.0017017 14 +491 4.75719 0.023804 2.38594 0.00146236 15 +491 5.10378 0.028511 2.29045 0.00473467 16 +492 3.33136 0.00804259 3.32962 0.00802928 0 +492 3.33841 0.00809673 3.32267 0.00797641 1 +492 3.35264 0.0082069 3.30874 0.00787001 2 +492 3.37433 0.00837649 3.28773 0.00770931 3 +492 3.4039 0.00861111 3.25954 0.00749289 4 +492 3.44197 0.00891954 3.22399 0.00721824 5 +492 3.48936 0.00931249 3.18086 0.00688348 6 +492 3.54717 0.00980706 3.1299 0.00648426 7 +492 3.61683 0.0104245 3.07076 0.0060171 8 +492 3.70022 0.0111947 3.00306 0.00547802 9 +492 3.79986 0.0121602 2.92638 0.0048625 10 +492 3.91911 0.0133809 2.84022 0.0041677 11 +492 4.0625 0.0149438 2.74416 0.00339689 12 +492 4.23636 0.0169764 2.63804 0.00257275 13 +492 4.44957 0.0196662 2.5226 0.00178519 14 +492 4.71459 0.023262 2.40222 0.00140255 15 +492 5.04718 0.0278639 2.29866 0.00355222 16 +492 5.44535 0.0297108 2.43797 0.0550886 17 +493 3.3314 0.00805852 3.32969 0.00804552 0 +493 3.33832 0.00811179 3.32286 0.00799348 1 +493 3.35229 0.00822008 3.30918 0.00788886 2 +493 3.37357 0.00838694 3.28856 0.00773061 3 +493 3.40258 0.00861729 3.26088 0.00751784 4 +493 3.43991 0.00892 3.22599 0.00724774 5 +493 3.48633 0.00930564 3.18367 0.00691815 6 +493 3.54291 0.00978944 3.13366 0.00652605 7 +493 3.61102 0.0103926 3.07565 0.00606728 8 +493 3.69246 0.0111436 3.00927 0.0055377 9 +493 3.78961 0.0120826 2.93409 0.00493311 10 +493 3.90564 0.0132659 2.84965 0.00425078 11 +493 4.04485 0.0147756 2.75552 0.00349204 12 +493 4.21318 0.0167313 2.65147 0.00267573 13 +493 4.41891 0.0193074 2.53804 0.00187528 14 +493 4.6737 0.0227432 2.41866 0.00138342 15 +493 4.99275 0.027204 2.30978 0.00275113 16 +493 5.38213 0.030637 2.3455 0.0278578 17 +494 3.33143 0.0080743 3.32976 0.00806162 0 +494 3.33823 0.00812675 3.32306 0.00801037 1 +494 3.35194 0.00823324 3.30962 0.00790742 2 +494 3.37283 0.00839708 3.28937 0.00775192 3 +494 3.40129 0.00862373 3.2622 0.00754227 4 +494 3.43788 0.00892075 3.22795 0.00727668 5 +494 3.48337 0.00929901 3.18642 0.00695254 6 +494 3.53876 0.00977253 3.13735 0.00656723 7 +494 3.60536 0.0103616 3.08045 0.00611678 8 +494 3.68489 0.0110939 3.01536 0.00559679 9 +494 3.77962 0.0120072 2.94166 0.00500313 10 +494 3.89256 0.0131553 2.8589 0.0043323 11 +494 4.02775 0.0146139 2.76666 0.00358616 12 +494 4.19076 0.0164959 2.66465 0.00277879 13 +494 4.38936 0.0189644 2.55325 0.00197065 14 +494 4.63443 0.0222471 2.43514 0.0013954 15 +494 4.94049 0.0265473 2.32289 0.00220472 16 +494 5.31793 0.0307285 2.3031 0.0165572 17 +495 3.33147 0.00809021 3.32982 0.00807726 0 +495 3.33815 0.00814188 3.32324 0.00802674 1 +495 3.3516 0.00824642 3.31005 0.00792566 2 +495 3.3721 0.00840756 3.29018 0.00777259 3 +495 3.40002 0.00862997 3.2635 0.00756663 4 +495 3.43589 0.00892168 3.22988 0.00730528 5 +495 3.48046 0.00929199 3.18912 0.00698705 6 +495 3.53468 0.0097553 3.14098 0.00660857 7 +495 3.59982 0.0103316 3.08517 0.00616544 8 +495 3.67751 0.0110459 3.02133 0.00565474 9 +495 3.7699 0.0119347 2.94908 0.00507157 10 +495 3.87984 0.0130482 2.86797 0.00441294 11 +495 4.01115 0.0144583 2.77757 0.00367925 12 +495 4.16908 0.0162705 2.67759 0.0028815 13 +495 4.36088 0.0186371 2.56823 0.00206956 14 +495 4.59671 0.0217734 2.4516 0.00143099 15 +495 4.89034 0.0259033 2.33736 0.00183365 16 +495 5.25441 0.0304238 2.28442 0.0107011 17 +496 3.33151 0.00810563 3.32989 0.00809305 0 +496 3.33806 0.00815647 3.32343 0.00804335 1 +496 3.35127 0.0082595 3.31048 0.00794368 2 +496 3.37139 0.00841776 3.29096 0.00779323 3 +496 3.39877 0.00863628 3.26478 0.00759057 4 +496 3.43395 0.00892249 3.23177 0.00733369 5 +496 3.47762 0.00928577 3.19177 0.00702068 6 +496 3.53071 0.00973955 3.14454 0.00664856 7 +496 3.59441 0.0103026 3.08978 0.00621346 8 +496 3.6703 0.0109994 3.02718 0.00571185 9 +496 3.76041 0.011864 2.95635 0.00513943 10 +496 3.86746 0.0129446 2.87686 0.00449256 11 +496 3.99505 0.0143084 2.78828 0.00377107 12 +496 4.14811 0.0160539 2.69028 0.00298388 13 +496 4.33341 0.0183239 2.58297 0.0021714 14 +496 4.56046 0.0213211 2.46796 0.0014853 15 +496 4.84222 0.0252774 2.35277 0.00158746 16 +496 5.19243 0.0299144 2.27882 0.00729301 17 +497 3.33155 0.00812099 3.32996 0.00810856 0 +497 3.33798 0.00817081 3.32362 0.00805985 1 +497 3.35095 0.00827205 3.3109 0.00796186 2 +497 3.37069 0.00842777 3.29174 0.0078137 3 +497 3.39756 0.00864246 3.26603 0.00761437 4 +497 3.43205 0.00892318 3.23364 0.0073619 5 +497 3.47484 0.00927962 3.19438 0.00705391 6 +497 3.52681 0.0097241 3.14803 0.00668809 7 +497 3.58912 0.0102742 3.09432 0.00626104 8 +497 3.66326 0.0109542 3.03293 0.00576815 9 +497 3.75117 0.0117956 2.96349 0.00520616 10 +497 3.85542 0.0128445 2.88557 0.00457082 11 +497 3.97942 0.0141642 2.79877 0.00386157 12 +497 4.1278 0.0158466 2.70273 0.00308519 13 +497 4.30691 0.0180242 2.59746 0.00227542 14 +497 4.52561 0.0208895 2.4842 0.00155354 15 +497 4.79607 0.0246733 2.36879 0.00143191 16 +497 5.13238 0.0292988 2.28114 0.00516722 17 +498 3.33159 0.0081361 3.33003 0.00812394 0 +498 3.33791 0.00818513 3.3238 0.00807599 1 +498 3.35064 0.00828486 3.31131 0.00797942 2 +498 3.37001 0.00843765 3.2925 0.00783397 3 +498 3.39637 0.0086488 3.26726 0.00763767 4 +498 3.43019 0.00892423 3.23546 0.00738948 5 +498 3.47211 0.00927371 3.19694 0.00708675 6 +498 3.52301 0.00970887 3.15146 0.00672724 7 +498 3.58395 0.0102467 3.09877 0.00630756 8 +498 3.65639 0.0109102 3.03857 0.00582347 9 +498 3.74217 0.0117296 2.97048 0.0052715 10 +498 3.84371 0.0127476 2.89411 0.00464807 11 +498 3.96425 0.0140249 2.80906 0.00395107 12 +498 4.10814 0.0156467 2.71494 0.00318629 13 +498 4.28132 0.0177379 2.6117 0.00238045 14 +498 4.49208 0.0204774 2.50027 0.00163313 15 +498 4.75181 0.0240931 2.3852 0.00134249 16 +498 5.07446 0.0286313 2.28852 0.00378476 17 +498 5.45577 0.0300999 2.44091 0.0620436 18 +499 3.33163 0.00815098 3.3301 0.00813917 0 +499 3.33783 0.00819949 3.32398 0.00809171 1 +499 3.35033 0.00829744 3.31172 0.00799681 2 +499 3.36934 0.00844759 3.29325 0.00785376 3 +499 3.3952 0.00865521 3.26847 0.00766053 4 +499 3.42836 0.00892543 3.23726 0.00741664 5 +499 3.46945 0.0092678 3.19945 0.00711925 6 +499 3.51928 0.00969387 3.15482 0.00676603 7 +499 3.5789 0.0102201 3.10314 0.00635341 8 +499 3.64968 0.0108673 3.04409 0.00587823 9 +499 3.73339 0.0116654 2.97734 0.00533614 10 +499 3.83231 0.0126542 2.90249 0.00472404 11 +499 3.94952 0.0138904 2.81914 0.00403941 12 +499 4.08909 0.0154549 2.72691 0.00328619 13 +499 4.25662 0.0174638 2.62569 0.00248648 14 +499 4.45981 0.0200842 2.51614 0.00172119 15 +499 4.70935 0.0235369 2.40183 0.0013028 16 +499 5.01875 0.0279446 2.29923 0.00286234 17 +499 5.39213 0.0311841 2.34027 0.0295531 18 diff --git a/example/love/phase.jpg b/example/love/phase.jpg deleted file mode 100644 index ebc7725..0000000 Binary files a/example/love/phase.jpg and /dev/null differ diff --git a/example/love/phase_deriv_Q_att.jpg b/example/love/phase_deriv_Q_att.jpg new file mode 100644 index 0000000..619c4a5 Binary files /dev/null and b/example/love/phase_deriv_Q_att.jpg differ diff --git a/example/love/phase_deriv_veloc_att.jpg b/example/love/phase_deriv_veloc_att.jpg new file mode 100644 index 0000000..34d7343 Binary files /dev/null and b/example/love/phase_deriv_veloc_att.jpg differ diff --git a/example/love/plot_kernels.py b/example/love/plot_kernels.py deleted file mode 100644 index f90a6c0..0000000 --- a/example/love/plot_kernels.py +++ /dev/null @@ -1,45 +0,0 @@ -import numpy as np -import matplotlib.pyplot as plt -import h5py -import sys - -def main(): - if len(sys.argv) != 4: - print("Usage: ./plot_kernel.py filename period_id mode") - exit(1) - - # open file - fio = h5py.File(sys.argv[1],"r") - Tid = int(sys.argv[2]) - mode = int(sys.argv[3]) - - # fetch data - if f'kernels/{Tid}/mode{mode}' not in fio: - print("Tid = {Tid} and mode ={mode} don't exist!") - exit(1) - z = fio[f'kernels/{Tid}/zcords'][:] - vsv_kl = fio[f'kernels/{Tid}/mode{mode}/vsv_kl'][:] - rho_kl = fio[f'kernels/{Tid}/mode{mode}/rho_kl'][:] - W = fio[f'kernels/{Tid}/mode{mode}/W'][:] - - - plt.figure(1,figsize=(14,20)) - plt.subplot(131) - plt.plot(vsv_kl,-z,label='vsv_kl') - plt.ylabel("depth,km") - plt.legend() - - plt.subplot(132) - plt.plot(rho_kl,-z,label='rho_kl') - #plt.ylabel("depth,km") - plt.legend() - - plt.subplot(133) - plt.plot(W,-z,label='W') - #plt.ylabel("depth,km") - plt.legend() - - plt.savefig("kernel.jpg") - - -main() \ No newline at end of file diff --git a/example/love/run_att.sh b/example/love/run_att.sh new file mode 100644 index 0000000..2255f4e --- /dev/null +++ b/example/love/run_att.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +# clean directory +rm -rf out +mkdir -p out + +sourcedir=`pwd`/../../ +echo $sourcedir + +# run sem +KERNEL_TYPE=0 +time $sourcedir/bin/surflove model.txt 0.01 1 500 $KERNEL_TYPE +#time $sourcedir/bin/surflove model.txt 0.01 1 2 + +# convert database to h5file +python $sourcedir/scripts/binary2h5.py out/database.bin out/swd.txt out/kernels.h5 + +# plot displ +python benchmark.py 19 $KERNEL_TYPE + +# # plot_kernel.py file period_id mode +# python plot_kernels.py out/kernels.h5 119 0 + +# \rm -f *.so bench_cps.py diff --git a/example/love/test.py b/example/love/test.py new file mode 100644 index 0000000..913c92e --- /dev/null +++ b/example/love/test.py @@ -0,0 +1,13 @@ +import numpy as np +from specd import SpecWorkSpace + +model = np.array([ + [0.0000000, 2.800000, 3.300000, 3.000000, 220., 200.], + [35.000000, 2.800000, 3.300000, 3.000000, 220., 200.], + [35.000000, 3.200000, 5.500000, 5.000000, 330., 300.] +]) +z,rho,vsh,vsv,_,_ = (model[:, i].reshape(3) for i in range(6)) + +ws = SpecWorkSpace('love',z,rho,vsh=vsh,vsv=vsv,disp=True) +c = ws.compute_egn(1.,-1,False) +print(c) \ No newline at end of file diff --git a/example/rayleigh/benchmark.py b/example/rayleigh/benchmark.py new file mode 100644 index 0000000..8985697 --- /dev/null +++ b/example/rayleigh/benchmark.py @@ -0,0 +1,119 @@ +from specd import THSolver,SpecWorkSpace +import numpy as np +import matplotlib.pyplot as plt + +import matplotlib as mpl +mpl.rcParams['lines.linewidth'] = 1.5 +mpl.rcParams['font.size'] = 10 +mpl.rcParams['xtick.labelsize']=15 +mpl.rcParams['ytick.labelsize']=15 +mpl.rcParams['axes.labelsize']=15 +mpl.rcParams['legend.fontsize'] = 20 +mpl.rcParams['legend.fontsize'] = 20 +mpl.rcParams['savefig.bbox'] = 'tight' + +def brocher(vsz): + vpz = 0.9409 + 2.0947*vsz - 0.8206*vsz**2+ \ + 0.2683*vsz**3 - 0.0251*vsz**4 + rhoz = 1.6612 * vpz - 0.4721 * vpz**2 + \ + 0.0671 * vpz**3 - 0.0043 * vpz**4 + \ + 0.000106 * vpz**5 + + return vpz,rhoz + +def test_model(): + z = np.linspace(0,120,3) + nz = len(z) + vs = 3.0 + 0.02 * z + vp,rho = brocher(vs) + thk = np.zeros_like(z) + thk[0:nz-1] = np.diff(z) + Qa = z * 0 + Qb = z * 0 + Qb[:nz-1] = 200 + Qb[nz-1] = 400 + Qa = Qb * 9/4. + + return thk,vp,vs,rho,Qa,Qb + +def test_fluid(): + z = np.array([0.,5.,50,100.]) + nz = len(z) + vs = 3.0 + 0.02 * z + vs[0] = 0. + vp,rho = brocher(vs) + vp[0] = 1.5 + rho[0] = 1. + thk = np.zeros_like(z) + thk[0:nz-1] = np.diff(z) + Qa = z * 0 + Qb = z * 0 + Qb[:nz-1] = 200 + Qb[nz-1] = 400 + Qa = Qb * 9/4. + + return thk,vp,vs,rho,Qa,Qb + +def cps2spec(thk:np.ndarray,param:np.ndarray): + nz = len(thk) + z_spec = np.zeros((nz*2-1)) + param_spec = np.zeros_like(z_spec) + z = thk * 0. + z[1:] = np.cumsum(thk)[:nz-1] + + id = 0 + for i in range(nz): + z_spec[id] = z[i] + param_spec[id] = param[i] + id += 1 + if i < nz - 1: + z_spec[id] = z[i+1] + param_spec[id] = param[i] + id += 1 + + return z_spec,param_spec + +def main(): + thk,vp,vs,rho,Qa,Qb = test_fluid() + z_spec,vp_spec = cps2spec(thk,vp) + _,vs_spec = cps2spec(thk,vs) + _,rho_spec = cps2spec(thk,rho) + print(vs_spec) + + # frequencies + nt = 100 + freqs = 10**np.linspace(np.log10(0.01),np.log10(0.5),nt) + T = 1. / freqs + + # compute phase velocity by cps + sol = THSolver(thk,vp,vs,rho) + c = T * 0. + for i in range(nt): + c[i:i+1] = sol.compute_swd('Rc',0,T[i]) + + # init workspace + ws = SpecWorkSpace() + ws.initialize( + 'rayl', + z_spec, + rho=rho_spec, + vph = vp_spec * 1., + vpv = vp_spec * 1., + vsh = vs_spec * 1., + vsv = vs_spec * 1., + eta = vs_spec * 0 + 1. + ) + + c1 = T * 0. + for i in range(nt): + c1[i:i+1] = ws.compute_egn(freqs[i],1,False) + + fig,ax = plt.subplots(1,1,figsize=(8,4)) + ax.plot(freqs,c) + ax.plot(freqs,c1,ls='--') + fig.savefig("test.jpg",dpi=300) + + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/example/rayleigh/eigenvalues.jpg b/example/rayleigh/eigenvalues.jpg new file mode 100644 index 0000000..b3e49e4 Binary files /dev/null and b/example/rayleigh/eigenvalues.jpg differ diff --git a/example/rayleigh/eigenvalues.pdf b/example/rayleigh/eigenvalues.pdf new file mode 100644 index 0000000..8648e0a Binary files /dev/null and b/example/rayleigh/eigenvalues.pdf differ diff --git a/example/rayleigh/gen_model.py b/example/rayleigh/gen_model.py index c41dc88..ac00182 100644 --- a/example/rayleigh/gen_model.py +++ b/example/rayleigh/gen_model.py @@ -1,27 +1,36 @@ import numpy as np -from scipy.interpolate import interp1d -z = np.linspace(0,50,10) -nz = len(z) -vs = 2.5 + 0.02 * z +def brocher(vsz): + vpz = 0.9409 + 2.0947*vsz - 0.8206*vsz**2+ \ + 0.2683*vsz**3 - 0.0251*vsz**4 + rhoz = 1.6612 * vpz - 0.4721 * vpz**2 + \ + 0.0671 * vpz**3 - 0.0043 * vpz**4 + \ + 0.000106 * vpz**5 -# vs[10:20] = 1.4 -# vs[40:50] = 2.5 + return vpz,rhoz -vp = 1.732 * vs -rho = 0.3601 * vp + 0.541 +z = np.linspace(0,120,3) +nz = len(z) +vs = 3.0 + 0.02 * z +vp,rho = brocher(vs) thk = np.zeros_like(z) thk[0:nz-1] = np.diff(z) +Qa = z * 0 +Qb = z * 0 +Qb[:nz-1] = 200 +Qb[nz-1] = 400 +Qa = Qb * 9/4. -f = open("model.txt","w") -f.write("%d\n"%(nz)) +f = open("model.txt.cps","w") for i in range(nz): f.write("%f %f %f %f %f %f 1.\n"%(thk[i],rho[i],vp[i],vp[i],vs[i],vs[i])) f.close() -z = np.zeros_like(thk) -z[1:] = np.cumsum(thk)[:nz-1] - -intp = interp1d(z,vs) -print(intp(45.755604)) -#print(z) \ No newline at end of file +# write specswd file +f = open("model.txt","w") +f.write("1 0\n") +for i in range(nz): + f.write("%f %f %f %f %f 1. %f %f %f\n"%(z[i],rho[i],vp[i],vp[i],vs[i],Qa[i],Qa[i],Qb[i])) + if i < nz-1: + f.write("%f %f %f %f %f 1. %f %f %f\n"%(z[i+1],rho[i],vp[i],vp[i],vs[i],Qa[i],Qa[i],Qb[i])) +f.close() \ No newline at end of file diff --git a/example/rayleigh/group.jpg b/example/rayleigh/group.jpg deleted file mode 100644 index aaeaf00..0000000 Binary files a/example/rayleigh/group.jpg and /dev/null differ diff --git a/example/rayleigh/kernel.jpg b/example/rayleigh/kernel.jpg deleted file mode 100644 index 66ba8d7..0000000 Binary files a/example/rayleigh/kernel.jpg and /dev/null differ diff --git a/example/rayleigh/model.txt b/example/rayleigh/model.txt index 4e56353..359b1e6 100644 --- a/example/rayleigh/model.txt +++ b/example/rayleigh/model.txt @@ -1,11 +1,6 @@ -10 -5.555556 2.100233 4.330000 4.330000 2.500000 2.500000 1. -5.555556 2.169532 4.522444 4.522444 2.611111 2.611111 1. -5.555556 2.238831 4.714889 4.714889 2.722222 2.722222 1. -5.555556 2.308131 4.907333 4.907333 2.833333 2.833333 1. -5.555556 2.377430 5.099778 5.099778 2.944444 2.944444 1. -5.555556 2.446729 5.292222 5.292222 3.055556 3.055556 1. -5.555556 2.516028 5.484667 5.484667 3.166667 3.166667 1. -5.555556 2.585328 5.677111 5.677111 3.277778 3.277778 1. -5.555556 2.654627 5.869556 5.869556 3.388889 3.388889 1. -0.000000 2.723926 6.062000 6.062000 3.500000 3.500000 1. +1 0 +0.000000 2.542597 5.050600 5.050600 3.000000 1. 450.000000 450.000000 200.000000 +60.000000 2.542597 5.050600 5.050600 3.000000 1. 450.000000 450.000000 200.000000 +60.000000 3.067352 7.330709 7.330709 4.200000 1. 450.000000 450.000000 200.000000 +120.000000 3.067352 7.330709 7.330709 4.200000 1. 450.000000 450.000000 200.000000 +120.000000 3.767704 9.228505 9.228505 5.400000 1. 900.000000 900.000000 400.000000 diff --git a/example/rayleigh/model.txt.1 b/example/rayleigh/model.txt.1 deleted file mode 100644 index 4933755..0000000 --- a/example/rayleigh/model.txt.1 +++ /dev/null @@ -1,61 +0,0 @@ -60 -0.847458 2.723926 3.500000 6.062000 -0.847458 2.734497 3.516949 6.091356 -0.847458 2.745068 3.533898 6.120712 -0.847458 2.755639 3.550847 6.150068 -0.847458 2.766210 3.567797 6.179424 -0.847458 2.776782 3.584746 6.208780 -0.847458 2.787353 3.601695 6.238136 -0.847458 2.797924 3.618644 6.267492 -0.847458 2.808495 3.635593 6.296847 -0.847458 2.819066 3.652542 6.326203 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 1.414170 1.400000 2.424800 -0.847458 2.935348 3.838983 6.649119 -0.847458 2.945919 3.855932 6.678475 -0.847458 2.956490 3.872881 6.707831 -0.847458 2.967061 3.889831 6.737186 -0.847458 2.977632 3.906780 6.766542 -0.847458 2.988203 3.923729 6.795898 -0.847458 2.998774 3.940678 6.825254 -0.847458 3.009345 3.957627 6.854610 -0.847458 3.019916 3.974576 6.883966 -0.847458 3.030487 3.991525 6.913322 -0.847458 3.041058 4.008475 6.942678 -0.847458 3.051629 4.025424 6.972034 -0.847458 3.062200 4.042373 7.001390 -0.847458 3.072772 4.059322 7.030746 -0.847458 3.083343 4.076271 7.060102 -0.847458 3.093914 4.093220 7.089458 -0.847458 3.104485 4.110169 7.118814 -0.847458 3.115056 4.127119 7.148169 -0.847458 3.125627 4.144068 7.177525 -0.847458 3.136198 4.161017 7.206881 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 2.100233 2.500000 4.330000 -0.847458 3.252480 4.347458 7.529797 -0.847458 3.263051 4.364407 7.559153 -0.847458 3.273622 4.381356 7.588508 -0.847458 3.284193 4.398305 7.617864 -0.847458 3.294764 4.415254 7.647220 -0.847458 3.305335 4.432203 7.676576 -0.847458 3.315906 4.449153 7.705932 -0.847458 3.326477 4.466102 7.735288 -0.847458 3.337048 4.483051 7.764644 -0.000000 3.347619 4.500000 7.794000 diff --git a/example/rayleigh/model.txt.cps b/example/rayleigh/model.txt.cps new file mode 100644 index 0000000..5542e28 --- /dev/null +++ b/example/rayleigh/model.txt.cps @@ -0,0 +1,3 @@ +60.000000 2.542597 5.050600 5.050600 3.000000 3.000000 1. +60.000000 3.067352 7.330709 7.330709 4.200000 4.200000 1. +0.000000 3.767704 9.228505 9.228505 5.400000 5.400000 1. diff --git a/example/rayleigh/out/database.bin b/example/rayleigh/out/database.bin index dbe9f0d..2b8d711 100644 Binary files a/example/rayleigh/out/database.bin and b/example/rayleigh/out/database.bin differ diff --git a/example/rayleigh/out/kernels.h5 b/example/rayleigh/out/kernels.h5 index 57d8718..8dc54ac 100644 Binary files a/example/rayleigh/out/kernels.h5 and b/example/rayleigh/out/kernels.h5 differ diff --git a/example/rayleigh/out/swd.cps.txt b/example/rayleigh/out/swd.cps.txt index 38842a4..99b1e64 100644 --- a/example/rayleigh/out/swd.cps.txt +++ b/example/rayleigh/out/swd.cps.txt @@ -1,104 +1,104 @@ -100.000000 94.127500 88.599900 83.396900 78.499400 73.889500 69.550400 65.466000 61.621500 58.002800 54.596600 51.390400 48.372500 45.531900 42.858000 40.341200 37.972100 35.742200 33.643300 31.667600 29.807900 28.057400 26.409800 24.858800 23.399000 22.024900 20.731500 19.514000 18.368100 17.289400 16.274100 15.318400 14.418800 13.572100 12.775100 12.024900 11.318700 10.654000 10.028300 9.439440 8.885110 8.363330 7.872190 7.409900 6.974750 6.565160 6.179620 5.816730 5.475140 5.153610 4.850970 4.566090 4.297950 4.045550 3.807980 3.584360 3.373860 3.175730 2.989240 2.813700 2.648460 2.492930 2.346530 2.208730 2.079030 1.956940 1.842020 1.733840 1.632020 1.536180 1.445970 1.361060 1.281130 1.205890 1.135080 1.068420 1.005680 0.946620 0.891029 0.838704 0.789451 0.743091 0.699453 0.658377 0.619714 0.583322 0.549066 0.516822 0.486472 0.457904 0.431013 0.405702 0.381877 0.359452 0.338343 0.318474 0.299771 0.282167 0.265597 0.250000 -0 3.11266 3.04124 0 -1 3.10808 3.03196 0 -2 3.10318 3.0214 0 -3 3.09789 3.00934 0 -4 3.09213 2.99549 0 -5 3.08579 2.9797 0 -6 3.07879 2.96141 0 -7 3.07097 2.94028 0 -8 3.06221 2.91602 0 -9 3.05233 2.88811 0 -10 3.04115 2.85651 0 -11 3.02847 2.82091 0 -12 3.01411 2.78109 0 -13 2.99785 2.73739 0 -14 2.97953 2.69013 0 -15 2.95901 2.64007 0 -16 2.93625 2.58862 0 -17 2.91131 2.53702 0 -18 2.88436 2.48752 0 -19 2.85574 2.44153 0 -20 2.82588 2.40059 0 -21 2.79533 2.36573 0 -22 2.76463 2.33731 0 -23 2.73431 2.31509 0 -24 2.70481 2.29817 0 -25 2.67647 2.28598 0 -26 2.64952 2.27727 0 -27 2.62408 2.27135 0 -28 2.6002 2.26737 0 -29 2.57786 2.26468 0 -30 2.55702 2.26274 0 -31 2.53759 2.26152 0 -32 2.51949 2.26048 0 -33 2.50262 2.2596 0 -34 2.48689 2.25889 0 -35 2.47222 2.25829 0 -36 2.45851 2.25752 0 -37 2.4457 2.2568 0 -38 2.43371 2.25613 0 -39 2.42248 2.25534 0 -40 2.41196 2.25453 0 -41 2.40208 2.25367 0 -42 2.39281 2.25293 0 -43 2.38409 2.25223 0 -44 2.3759 2.25149 0 -45 2.3682 2.25095 0 -46 2.36097 2.25079 0 -47 2.35419 2.25061 0 -48 2.34785 2.25073 0 -49 2.34193 2.25135 0 -50 2.33644 2.25225 0 -51 2.33136 2.25364 0 -52 2.3267 2.25541 0 -53 2.32246 2.25767 0 -54 2.31865 2.26046 0 -55 2.31524 2.26349 0 -56 2.31223 2.26671 0 -57 2.30962 2.27019 0 -58 2.30737 2.27369 0 -59 2.30548 2.27719 0 -60 2.3039 2.28043 0 -61 2.3026 2.28351 0 -62 2.30157 2.28629 0 -63 2.30075 2.28885 0 -64 2.30011 2.29101 0 -65 2.29963 2.29284 0 -66 2.29928 2.29437 0 -67 2.29902 2.29546 0 -68 2.29884 2.29636 0 -69 2.29871 2.29707 0 -70 2.29863 2.29758 0 -71 2.29858 2.2979 0 -72 2.29854 2.29814 0 -73 2.29852 2.29831 0 -74 2.29851 2.29851 0 -75 2.2985 2.29857 0 -76 2.2985 2.29864 0 -77 2.2985 2.29864 0 -78 2.2985 2.29867 0 -79 2.2985 2.29868 0 -80 2.2985 2.29866 0 -81 2.2985 2.29863 0 -82 2.2985 2.2987 0 -83 2.2985 2.29865 0 -84 2.2985 2.29862 0 -85 2.2985 2.29863 0 -86 2.2985 2.29864 0 -87 2.2985 2.2986 0 -88 2.2985 2.29861 0 -89 2.2985 2.29864 0 -90 2.2985 2.29864 0 -91 2.2985 2.29862 0 -92 2.2985 2.29862 0 -93 2.2985 2.29864 0 -94 2.2985 2.29867 0 -95 2.2985 2.29863 0 -96 2.2985 2.29864 0 -97 2.2985 2.29862 0 -98 2.2985 2.29862 0 -99 2.2985 2.29864 0 +100.000000 96.125500 92.401100 88.821100 85.379700 82.071700 78.891800 75.835200 72.897000 70.072600 67.357600 64.747900 62.239200 59.827800 57.509800 55.281600 53.139700 51.080800 49.101700 47.199200 45.370500 43.612600 41.922900 40.298600 38.737200 37.236400 35.793600 34.406800 33.073700 31.792300 30.560500 29.376400 28.238300 27.144200 26.092500 25.081500 24.109800 23.175600 22.277700 21.414500 20.584800 19.787300 19.020600 18.283700 17.575300 16.894300 16.239800 15.610600 15.005700 14.424300 13.865500 13.328200 12.811800 12.315500 11.838300 11.379600 10.938700 10.514900 10.107500 9.715890 9.339450 8.977590 8.629760 8.295400 7.974000 7.665040 7.368060 7.082590 6.808180 6.544390 6.290830 6.047100 5.812800 5.587590 5.371100 5.162990 4.962950 4.770660 4.585830 4.408150 4.237360 4.073180 3.915370 3.763670 3.617840 3.477670 3.342930 3.213410 3.088900 2.969230 2.854180 2.743600 2.637300 2.535120 2.436890 2.342480 2.251720 2.164480 2.080610 2.000000 +0 4.35595 3.66177 0 +1 4.32148 3.56212 0 +2 4.28295 3.45214 0 +3 4.23983 3.33247 0 +4 4.19155 3.20433 0 +5 4.13764 3.07035 0 +6 4.07783 2.9344 0 +7 4.01213 2.80119 0 +8 3.94098 2.67608 0 +9 3.8653 2.56384 0 +10 3.78644 2.46818 0 +11 3.70603 2.39045 0 +12 3.62578 2.33044 0 +13 3.54722 2.28665 0 +14 3.4716 2.25699 0 +15 3.39981 2.23899 0 +16 3.33243 2.23062 0 +17 3.26978 2.23009 0 +18 3.21196 2.23608 0 +19 3.15896 2.24744 0 +20 3.11066 2.26326 0 +21 3.06685 2.28285 0 +22 3.02733 2.30528 0 +23 2.99183 2.32999 0 +24 2.96008 2.35635 0 +25 2.9318 2.38361 0 +26 2.9067 2.41134 0 +27 2.88452 2.43906 0 +28 2.86498 2.46625 0 +29 2.84783 2.49254 0 +30 2.83283 2.51784 0 +31 2.81975 2.54195 0 +32 2.8084 2.56455 0 +33 2.79859 2.58555 0 +34 2.79013 2.60505 0 +35 2.78287 2.62292 0 +36 2.77667 2.63914 0 +37 2.7714 2.65401 0 +38 2.76694 2.66723 0 +39 2.76319 2.67907 0 +40 2.76006 2.68951 0 +41 2.75745 2.69886 0 +42 2.7553 2.70679 0 +43 2.75353 2.71378 0 +44 2.7521 2.71999 0 +45 2.75094 2.72496 0 +46 2.75001 2.72923 0 +47 2.74928 2.73296 0 +48 2.7487 2.73588 0 +49 2.74825 2.73832 0 +50 2.74791 2.74042 0 +51 2.74765 2.74196 0 +52 2.74745 2.74304 0 +53 2.74731 2.74416 0 +54 2.7472 2.74488 0 +55 2.74712 2.74555 0 +56 2.74707 2.74589 0 +57 2.74703 2.74626 0 +58 2.747 2.74648 0 +59 2.74699 2.74672 0 +60 2.74698 2.74677 0 +61 2.74697 2.7468 0 +62 2.74696 2.74673 0 +63 2.74696 2.74672 0 +64 2.74696 2.74675 0 +65 2.74696 2.74677 0 +66 2.74696 2.74682 0 +67 2.74696 2.74679 0 +68 2.74696 2.74679 0 +69 2.74696 2.74679 0 +70 2.74696 2.74681 0 +71 2.74696 2.7468 0 +72 2.74696 2.7468 0 +73 2.74696 2.74678 0 +74 2.74696 2.74678 0 +75 2.74696 2.74684 0 +76 2.74696 2.74681 0 +77 2.74696 2.74677 0 +78 2.74696 2.74678 0 +79 2.74696 2.74681 0 +80 2.74696 2.74678 0 +81 2.74696 2.74681 0 +82 2.74696 2.74678 0 +83 2.74696 2.74679 0 +84 2.74696 2.74681 0 +85 2.74696 2.74681 0 +86 2.74696 2.74677 0 +87 2.74696 2.74707 0 +88 2.74696 2.74711 0 +89 2.74696 2.74712 0 +90 2.74696 2.74715 0 +91 2.74696 2.7471 0 +92 2.74696 2.74715 0 +93 2.74696 2.7471 0 +94 2.74696 2.74714 0 +95 2.74696 2.74712 0 +96 2.74696 2.74712 0 +97 2.74696 2.74712 0 +98 2.74696 2.74712 0 +99 2.74696 2.74712 0 0 0 0 1 1 0 0 1 2 0 0 1 @@ -111,94 +111,94 @@ 9 0 0 1 10 0 0 1 11 0 0 1 -12 0 0 1 -13 0 0 1 -14 0 0 1 -15 0 0 1 -16 0 0 1 -17 0 0 1 -18 0 0 1 -19 0 0 1 -20 0 0 1 -21 0 0 1 -22 0 0 1 -23 0 0 1 -24 0 0 1 -25 0 0 1 -26 0 0 1 -27 3.49759 3.40064 1 -28 3.48863 3.30717 1 -29 3.47488 3.23218 1 -30 3.45731 3.16514 1 -31 3.43631 3.09889 1 -32 3.412 3.03105 1 -33 3.38443 2.96281 1 -34 3.35375 2.89563 1 -35 3.32038 2.8336 1 -36 3.28499 2.77953 1 -37 3.24841 2.73544 1 -38 3.21151 2.70048 1 -39 3.17505 2.67354 1 -40 3.13957 2.65285 1 -41 3.10543 2.63681 1 -42 3.07281 2.62388 1 -43 3.0418 2.61334 1 -44 3.01239 2.60354 1 -45 2.98452 2.59494 1 -46 2.95813 2.58712 1 -47 2.93314 2.57933 1 -48 2.90945 2.57269 1 -49 2.88701 2.56618 1 -50 2.86574 2.5599 1 -51 2.84556 2.5541 1 -52 2.82642 2.54874 1 -53 2.80826 2.5436 1 -54 2.79104 2.53887 1 -55 2.7747 2.53461 1 -56 2.7592 2.53064 1 -57 2.74451 2.52697 1 -58 2.7306 2.52374 1 -59 2.71742 2.52093 1 -60 2.70495 2.51839 1 -61 2.69315 2.51607 1 -62 2.682 2.51397 1 -63 2.67144 2.51192 1 -64 2.66145 2.50976 1 -65 2.65196 2.50739 1 -66 2.64292 2.50445 1 -67 2.63426 2.50089 1 -68 2.6259 2.49668 1 -69 2.61779 2.49158 1 -70 2.60984 2.48587 1 -71 2.60202 2.47958 1 -72 2.59429 2.47341 1 -73 2.58669 2.46743 1 -74 2.57924 2.46359 1 -75 2.57203 2.46037 1 -76 2.56514 2.45883 1 -77 2.55863 2.45864 1 -78 2.55256 2.45967 1 -79 2.54697 2.46149 1 -80 2.54186 2.46363 1 -81 2.53722 2.4664 1 -82 2.53305 2.46937 1 -83 2.5293 2.47224 1 -84 2.52595 2.47494 1 -85 2.52297 2.47723 1 -86 2.52032 2.47976 1 -87 2.51797 2.48194 1 -88 2.51589 2.48395 1 -89 2.51405 2.48572 1 -90 2.51242 2.48711 1 -91 2.51097 2.48886 1 -92 2.5097 2.49023 1 -93 2.50857 2.49143 1 -94 2.50758 2.49225 1 -95 2.5067 2.4933 1 -96 2.50592 2.49395 1 -97 2.50523 2.49437 1 -98 2.50463 2.49524 1 -99 2.50409 2.49575 1 +12 5.38978 4.60662 1 +13 5.33744 4.12243 1 +14 5.27203 3.99017 1 +15 5.2055 3.94688 1 +16 5.14137 3.93073 1 +17 5.08037 3.91932 1 +18 5.02227 3.90374 1 +19 4.96641 3.87967 1 +20 4.9121 3.84641 1 +21 4.85863 3.80355 1 +22 4.8054 3.75251 1 +23 4.75194 3.6951 1 +24 4.69791 3.63375 1 +25 4.64319 3.57133 1 +26 4.58782 3.51071 1 +27 4.53206 3.45483 1 +28 4.4763 3.4062 1 +29 4.4211 3.3663 1 +30 4.367 3.33524 1 +31 4.31453 3.31314 1 +32 4.2641 3.29881 1 +33 4.21594 3.28894 1 +34 4.17015 3.28175 1 +35 4.12662 3.27396 1 +36 4.0851 3.26346 1 +37 4.04523 3.24834 1 +38 4.00649 3.22472 1 +39 3.96824 3.19036 1 +40 3.92974 3.14263 1 +41 3.89013 3.07915 1 +42 3.84846 3.00025 1 +43 3.80389 2.90864 1 +44 3.75582 2.81096 1 +45 3.70426 2.71825 1 +46 3.65008 2.64233 1 +47 3.5948 2.58883 1 +48 3.54022 2.55872 1 +49 3.48796 2.55005 1 +50 3.43911 2.55664 1 +51 3.39422 2.573 1 +52 3.3535 2.5963 1 +53 3.31683 2.62237 1 +54 3.28399 2.65013 1 +55 3.25464 2.67825 1 +56 3.22848 2.70497 1 +57 3.20517 2.7308 1 +58 3.18439 2.75511 1 +59 3.16587 2.77773 1 +60 3.14934 2.79852 1 +61 3.13459 2.81765 1 +62 3.12141 2.83528 1 +63 3.10963 2.85089 1 +64 3.09907 2.86533 1 +65 3.08962 2.87856 1 +66 3.08113 2.89041 1 +67 3.07351 2.90107 1 +68 3.06666 2.91085 1 +69 3.0605 2.91915 1 +70 3.05495 2.92695 1 +71 3.04994 2.93394 1 +72 3.04543 2.9406 1 +73 3.04134 2.94626 1 +74 3.03765 2.95144 1 +75 3.03431 2.95578 1 +76 3.03129 2.96 1 +77 3.02854 2.96364 1 +78 3.02606 2.96701 1 +79 3.0238 2.97002 1 +80 3.02175 2.97288 1 +81 3.01988 2.97556 1 +82 3.01818 2.97734 1 +83 3.01664 2.98 1 +84 3.01524 2.98165 1 +85 3.01395 2.98328 1 +86 3.01278 2.98452 1 +87 3.01172 2.98609 1 +88 3.01074 2.98727 1 +89 3.00985 2.98836 1 +90 3.00904 2.98947 1 +91 3.00829 2.99026 1 +92 3.00761 2.9909 1 +93 3.00699 2.99199 1 +94 3.00642 2.99217 1 +95 3.0059 2.99321 1 +96 3.00542 2.99388 1 +97 3.00498 2.99414 1 +98 3.00458 2.99504 1 +99 3.00421 2.99507 1 0 0 0 2 1 0 0 2 2 0 0 2 @@ -224,81 +224,81 @@ 22 0 0 2 23 0 0 2 24 0 0 2 -25 0 0 2 -26 0 0 2 -27 0 0 2 -28 0 0 2 -29 0 0 2 -30 0 0 2 -31 0 0 2 -32 0 0 2 -33 0 0 2 -34 0 0 2 -35 0 0 2 -36 0 0 2 -37 0 0 2 -38 0 0 2 -39 0 0 2 -40 3.49191 3.24059 2 -41 3.46997 3.07866 2 -42 3.43963 2.96234 2 -43 3.40364 2.87265 2 -44 3.36416 2.80516 2 -45 3.32309 2.75646 2 -46 3.28195 2.72262 2 -47 3.24175 2.6984 2 -48 3.20306 2.68015 2 -49 3.16615 2.66558 2 -50 3.13109 2.65311 2 -51 3.09784 2.64188 2 -52 3.06634 2.63149 2 -53 3.03648 2.62187 2 -54 3.00819 2.61288 2 -55 2.98137 2.60457 2 -56 2.95595 2.59685 2 -57 2.93187 2.59005 2 -58 2.90909 2.58397 2 -59 2.88755 2.57884 2 -60 2.86724 2.57464 2 -61 2.8481 2.57125 2 -62 2.83009 2.56815 2 -63 2.81315 2.56528 2 -64 2.79716 2.56191 2 -65 2.782 2.5572 2 -66 2.76749 2.55074 2 -67 2.75346 2.54222 2 -68 2.73976 2.53228 2 -69 2.72628 2.52196 2 -70 2.71305 2.51339 2 -71 2.70026 2.50844 2 -72 2.68816 2.50804 2 -73 2.67696 2.51107 2 -74 2.66684 2.51726 2 -75 2.65779 2.52416 2 -76 2.64976 2.53011 2 -77 2.64256 2.53413 2 -78 2.63599 2.53519 2 -79 2.62978 2.53224 2 -80 2.62362 2.52409 2 -81 2.61714 2.51027 2 -82 2.61005 2.49231 2 -83 2.60223 2.47411 2 -84 2.59388 2.46041 2 -85 2.58536 2.45251 2 -86 2.57702 2.44905 2 -87 2.56912 2.44852 2 -88 2.56177 2.45034 2 -89 2.55504 2.45334 2 -90 2.54894 2.45669 2 -91 2.54344 2.46035 2 -92 2.53852 2.46375 2 -93 2.53413 2.46769 2 -94 2.53022 2.47094 2 -95 2.52675 2.47408 2 -96 2.52367 2.47667 2 -97 2.52094 2.4794 2 -98 2.51852 2.48134 2 -99 2.51638 2.48358 2 +25 5.38964 5.02536 2 +26 5.37133 4.89771 2 +27 5.34938 4.82166 2 +28 5.32537 4.76428 2 +29 5.29993 4.71307 2 +30 5.27321 4.66085 2 +31 5.24511 4.6036 2 +32 5.21533 4.53803 2 +33 5.18345 4.46248 2 +34 5.14897 4.37541 2 +35 5.11131 4.27591 2 +36 5.06984 4.1631 2 +37 5.02377 4.03473 2 +38 4.97214 3.88737 2 +39 4.91365 3.71843 2 +40 4.84678 3.52772 2 +41 4.77003 3.32397 2 +42 4.68292 3.12909 2 +43 4.58742 2.97553 2 +44 4.48869 2.89112 2 +45 4.39368 2.88291 2 +46 4.30819 2.93561 2 +47 4.23479 3.0203 2 +48 4.17313 3.11007 2 +49 4.12127 3.18621 2 +50 4.07674 3.23875 2 +51 4.03717 3.26359 2 +52 4.00046 3.25903 2 +53 3.96465 3.22418 2 +54 3.92788 3.15738 2 +55 3.88831 3.06077 2 +56 3.84432 2.94153 2 +57 3.79493 2.81636 2 +58 3.74047 2.70638 2 +59 3.68271 2.62636 2 +60 3.62424 2.57973 2 +61 3.56741 2.56096 2 +62 3.51384 2.56167 2 +63 3.46438 2.57529 2 +64 3.4193 2.59532 2 +65 3.37853 2.61971 2 +66 3.34182 2.64484 2 +67 3.30885 2.67073 2 +68 3.27925 2.69628 2 +69 3.2527 2.72023 2 +70 3.22887 2.74354 2 +71 3.20746 2.76494 2 +72 3.18822 2.78478 2 +73 3.1709 2.80334 2 +74 3.1553 2.82037 2 +75 3.14123 2.83602 2 +76 3.12853 2.85034 2 +77 3.11706 2.86326 2 +78 3.10668 2.87568 2 +79 3.09728 2.88662 2 +80 3.08876 2.89662 2 +81 3.08104 2.90545 2 +82 3.07403 2.91354 2 +83 3.06766 2.92174 2 +84 3.06187 2.92828 2 +85 3.0566 2.93449 2 +86 3.05181 2.94024 2 +87 3.04744 2.94559 2 +88 3.04345 2.95005 2 +89 3.03982 2.95451 2 +90 3.0365 2.95817 2 +91 3.03348 2.962 2 +92 3.03071 2.96548 2 +93 3.02818 2.96823 2 +94 3.02587 2.97112 2 +95 3.02375 2.97373 2 +96 3.02182 2.97517 2 +97 3.02004 2.97772 2 +98 3.01842 2.97916 2 +99 3.01693 2.98105 2 0 0 0 3 1 0 0 3 2 0 0 3 @@ -337,65 +337,1665 @@ 35 0 0 3 36 0 0 3 37 0 0 3 -38 0 0 3 -39 0 0 3 -40 0 0 3 -41 0 0 3 -42 0 0 3 -43 0 0 3 -44 0 0 3 -45 0 0 3 -46 0 0 3 -47 3.48643 3.10982 3 -48 3.45447 2.93611 3 -49 3.4146 2.83684 3 -50 3.37144 2.77605 3 -51 3.32775 2.73798 3 -52 3.28504 2.71287 3 -53 3.24403 2.69451 3 -54 3.20499 2.67972 3 -55 3.16797 2.6668 3 -56 3.13292 2.65554 3 -57 3.09978 2.64584 3 -58 3.06853 2.63779 3 -59 3.03914 2.63184 3 -60 3.01159 2.62762 3 -61 2.98585 2.62472 3 -62 2.96183 2.62219 3 -63 2.93934 2.61829 3 -64 2.9181 2.61165 3 -65 2.89776 2.60072 3 -66 2.87792 2.58531 3 -67 2.85829 2.56793 3 -68 2.83885 2.55313 3 -69 2.82001 2.54618 3 -70 2.80232 2.54774 3 -71 2.78619 2.55402 3 -72 2.7716 2.55953 3 -73 2.75823 2.56009 3 -74 2.74551 2.55218 3 -75 2.73288 2.53719 3 -76 2.71992 2.51842 3 -77 2.70658 2.50107 3 -78 2.69316 2.48957 3 -79 2.68011 2.48545 3 -80 2.6679 2.4887 3 -81 2.65699 2.49941 3 -82 2.64772 2.51625 3 -83 2.64022 2.53455 3 -84 2.6343 2.54996 3 -85 2.62953 2.55973 3 -86 2.62546 2.56278 3 -87 2.62155 2.55624 3 -88 2.61703 2.53384 3 -89 2.6108 2.49514 3 -90 2.60257 2.46306 3 -91 2.59336 2.44761 3 -92 2.58411 2.44214 3 -93 2.57531 2.44228 3 -94 2.56716 2.44458 3 -95 2.55973 2.44802 3 -96 2.55304 2.45234 3 -97 2.54703 2.45659 3 -98 2.54167 2.46092 3 -99 2.53689 2.46486 3 +38 5.3929 4.97328 3 +39 5.37065 4.80908 3 +40 5.34505 4.75783 3 +41 5.31888 4.72913 3 +42 5.2926 4.70031 3 +43 5.26593 4.6589 3 +44 5.2381 4.60039 3 +45 5.20805 4.51392 3 +46 5.17427 4.39418 3 +47 5.13467 4.23063 3 +48 5.08658 4.02018 3 +49 5.02717 3.77542 3 +50 4.95457 3.52617 3 +51 4.86912 3.30463 3 +52 4.77349 3.12434 3 +53 4.67124 2.98406 3 +54 4.56598 2.88144 3 +55 4.46168 2.82355 3 +56 4.36298 2.82058 3 +57 4.27441 2.87306 3 +58 4.19863 2.96268 3 +59 4.13547 3.05849 3 +60 4.08249 3.13092 3 +61 4.03626 3.16315 3 +62 3.99332 3.14748 3 +63 3.95045 3.08419 3 +64 3.90474 2.9781 3 +65 3.85391 2.84766 3 +66 3.79723 2.72148 3 +67 3.73613 2.62686 3 +68 3.67361 2.57185 3 +69 3.61264 2.55081 3 +70 3.55521 2.5512 3 +71 3.50229 2.56551 3 +72 3.45415 2.58665 3 +73 3.41068 2.61169 3 +74 3.37158 2.63792 3 +75 3.33645 2.66414 3 +76 3.3049 2.68942 3 +77 3.27657 2.71365 3 +78 3.2511 2.73684 3 +79 3.22818 2.75813 3 +80 3.20753 2.7782 3 +81 3.18891 2.79642 3 +82 3.17209 2.8134 3 +83 3.15689 2.8291 3 +84 3.14313 2.8435 3 +85 3.13067 2.85669 3 +86 3.11936 2.86873 3 +87 3.1091 2.88029 3 +88 3.09977 2.88986 3 +89 3.09129 2.89933 3 +90 3.08357 2.90783 3 +91 3.07654 2.91576 3 +92 3.07013 2.92273 3 +93 3.06429 2.92918 3 +94 3.05895 2.93493 3 +95 3.05408 2.94019 3 +96 3.04963 2.94515 3 +97 3.04556 2.95012 3 +98 3.04183 2.95409 3 +99 3.03842 2.95795 3 +0 0 0 4 +1 0 0 4 +2 0 0 4 +3 0 0 4 +4 0 0 4 +5 0 0 4 +6 0 0 4 +7 0 0 4 +8 0 0 4 +9 0 0 4 +10 0 0 4 +11 0 0 4 +12 0 0 4 +13 0 0 4 +14 0 0 4 +15 0 0 4 +16 0 0 4 +17 0 0 4 +18 0 0 4 +19 0 0 4 +20 0 0 4 +21 0 0 4 +22 0 0 4 +23 0 0 4 +24 0 0 4 +25 0 0 4 +26 0 0 4 +27 0 0 4 +28 0 0 4 +29 0 0 4 +30 0 0 4 +31 0 0 4 +32 0 0 4 +33 0 0 4 +34 0 0 4 +35 0 0 4 +36 0 0 4 +37 0 0 4 +38 0 0 4 +39 0 0 4 +40 0 0 4 +41 0 0 4 +42 0 0 4 +43 0 0 4 +44 0 0 4 +45 0 0 4 +46 0 0 4 +47 5.39677 5.3888 4 +48 5.32935 4.06737 4 +49 5.26824 4.13314 4 +50 5.21408 4.16815 4 +51 5.1638 4.15716 4 +52 5.11421 4.09457 4 +53 5.0621 3.97912 4 +54 5.00445 3.82204 4 +55 4.93953 3.65636 4 +56 4.86829 3.52462 4 +57 4.79429 3.44884 4 +58 4.72162 3.42029 4 +59 4.65277 3.41513 4 +60 4.58819 3.4085 4 +61 4.52659 3.37618 4 +62 4.46508 3.29242 4 +63 4.3993 3.14351 4 +64 4.32569 2.97886 4 +65 4.24721 2.90035 4 +66 4.17267 2.92721 4 +67 4.10758 2.99668 4 +68 4.0514 3.04569 4 +69 4.00041 3.04098 4 +70 3.95022 2.97474 4 +71 3.89691 2.85949 4 +72 3.83814 2.72933 4 +73 3.77441 2.6248 4 +74 3.70868 2.5632 4 +75 3.64441 2.53954 4 +76 3.58391 2.54086 4 +77 3.52829 2.55583 4 +78 3.47781 2.57855 4 +79 3.43231 2.6042 4 +80 3.39141 2.63128 4 +81 3.35471 2.65788 4 +82 3.32177 2.68373 4 +83 3.29217 2.7083 4 +84 3.26555 2.73142 4 +85 3.2416 2.75261 4 +86 3.21999 2.77316 4 +87 3.2005 2.79186 4 +88 3.18287 2.80867 4 +89 3.16692 2.82401 4 +90 3.15246 2.83885 4 +91 3.13935 2.85219 4 +92 3.12744 2.86427 4 +93 3.11662 2.87554 4 +94 3.10677 2.88617 4 +95 3.0978 2.89538 4 +96 3.08963 2.90406 4 +97 3.08218 2.91224 4 +98 3.07538 2.91925 4 +99 3.06916 2.92566 4 +0 0 0 5 +1 0 0 5 +2 0 0 5 +3 0 0 5 +4 0 0 5 +5 0 0 5 +6 0 0 5 +7 0 0 5 +8 0 0 5 +9 0 0 5 +10 0 0 5 +11 0 0 5 +12 0 0 5 +13 0 0 5 +14 0 0 5 +15 0 0 5 +16 0 0 5 +17 0 0 5 +18 0 0 5 +19 0 0 5 +20 0 0 5 +21 0 0 5 +22 0 0 5 +23 0 0 5 +24 0 0 5 +25 0 0 5 +26 0 0 5 +27 0 0 5 +28 0 0 5 +29 0 0 5 +30 0 0 5 +31 0 0 5 +32 0 0 5 +33 0 0 5 +34 0 0 5 +35 0 0 5 +36 0 0 5 +37 0 0 5 +38 0 0 5 +39 0 0 5 +40 0 0 5 +41 0 0 5 +42 0 0 5 +43 0 0 5 +44 0 0 5 +45 0 0 5 +46 0 0 5 +47 0 0 5 +48 0 0 5 +49 0 0 5 +50 0 0 5 +51 5.38566 4.39468 5 +52 5.33395 4.29456 5 +53 5.28561 4.33701 5 +54 5.24219 4.36898 5 +55 5.20234 4.38123 5 +56 5.16471 4.37199 5 +57 5.12774 4.3297 5 +58 5.08901 4.23033 5 +59 5.04436 4.03788 5 +60 4.98682 3.71961 5 +61 4.9072 3.31847 5 +62 4.80295 3.01224 5 +63 4.6894 2.94407 5 +64 4.58972 3.09469 5 +65 4.51453 3.32662 5 +66 4.4596 3.51171 5 +67 4.41706 3.61863 5 +68 4.38089 3.64983 5 +69 4.34578 3.57676 5 +70 4.3032 3.31215 5 +71 4.24094 2.96276 5 +72 4.16574 2.86818 5 +73 4.0956 2.9167 5 +74 4.0342 2.95535 5 +75 3.9774 2.9277 5 +76 3.91985 2.83275 5 +77 3.85777 2.70802 5 +78 3.79101 2.60465 5 +79 3.72261 2.54672 5 +80 3.65619 2.52763 5 +81 3.5941 2.53281 5 +82 3.53732 2.55106 5 +83 3.48598 2.57563 5 +84 3.43981 2.6028 5 +85 3.3984 2.63052 5 +86 3.36125 2.65768 5 +87 3.32792 2.68364 5 +88 3.29798 2.70829 5 +89 3.27105 2.73142 5 +90 3.2468 2.75289 5 +91 3.22492 2.77311 5 +92 3.20516 2.79146 5 +93 3.18728 2.80775 5 +94 3.17108 2.82376 5 +95 3.15639 2.83832 5 +96 3.14306 2.85152 5 +97 3.13094 2.86332 5 +98 3.11991 2.8745 5 +99 3.10987 2.88516 5 +0 0 0 6 +1 0 0 6 +2 0 0 6 +3 0 0 6 +4 0 0 6 +5 0 0 6 +6 0 0 6 +7 0 0 6 +8 0 0 6 +9 0 0 6 +10 0 0 6 +11 0 0 6 +12 0 0 6 +13 0 0 6 +14 0 0 6 +15 0 0 6 +16 0 0 6 +17 0 0 6 +18 0 0 6 +19 0 0 6 +20 0 0 6 +21 0 0 6 +22 0 0 6 +23 0 0 6 +24 0 0 6 +25 0 0 6 +26 0 0 6 +27 0 0 6 +28 0 0 6 +29 0 0 6 +30 0 0 6 +31 0 0 6 +32 0 0 6 +33 0 0 6 +34 0 0 6 +35 0 0 6 +36 0 0 6 +37 0 0 6 +38 0 0 6 +39 0 0 6 +40 0 0 6 +41 0 0 6 +42 0 0 6 +43 0 0 6 +44 0 0 6 +45 0 0 6 +46 0 0 6 +47 0 0 6 +48 0 0 6 +49 0 0 6 +50 0 0 6 +51 0 0 6 +52 0 0 6 +53 0 0 6 +54 0 0 6 +55 0 0 6 +56 0 0 6 +57 0 5.39474 6 +58 5.35852 4.41507 6 +59 5.31352 4.3887 6 +60 5.27 4.36672 6 +61 5.22689 4.32027 6 +62 5.1831 4.26116 6 +63 5.13771 4.16933 6 +64 5.08635 3.96007 6 +65 5.02053 3.63741 6 +66 4.93488 3.30989 6 +67 4.82976 3.02436 6 +68 4.70891 2.80586 6 +69 4.58199 2.71715 6 +70 4.46824 2.86739 6 +71 4.39085 3.31099 6 +72 4.34856 3.66782 6 +73 4.32193 3.80898 6 +74 4.30025 3.81648 6 +75 4.27549 3.6058 6 +76 4.22709 2.99843 6 +77 4.1499 2.80601 6 +78 4.07601 2.85509 6 +79 4.01092 2.87799 6 +80 3.94901 2.82 6 +81 3.88457 2.70725 6 +82 3.81572 2.60066 6 +83 3.74498 2.53848 6 +84 3.67618 2.51819 6 +85 3.61193 2.52381 6 +86 3.55327 2.54311 6 +87 3.50032 2.56865 6 +88 3.45277 2.59657 6 +89 3.41017 2.62505 6 +90 3.37199 2.65279 6 +91 3.33775 2.67916 6 +92 3.30701 2.70413 6 +93 3.27936 2.72755 6 +94 3.25445 2.74912 6 +95 3.23199 2.76929 6 +96 3.21169 2.78811 6 +97 3.19332 2.80501 6 +98 3.17668 2.82076 6 +99 3.16159 2.83528 6 +0 0 0 7 +1 0 0 7 +2 0 0 7 +3 0 0 7 +4 0 0 7 +5 0 0 7 +6 0 0 7 +7 0 0 7 +8 0 0 7 +9 0 0 7 +10 0 0 7 +11 0 0 7 +12 0 0 7 +13 0 0 7 +14 0 0 7 +15 0 0 7 +16 0 0 7 +17 0 0 7 +18 0 0 7 +19 0 0 7 +20 0 0 7 +21 0 0 7 +22 0 0 7 +23 0 0 7 +24 0 0 7 +25 0 0 7 +26 0 0 7 +27 0 0 7 +28 0 0 7 +29 0 0 7 +30 0 0 7 +31 0 0 7 +32 0 0 7 +33 0 0 7 +34 0 0 7 +35 0 0 7 +36 0 0 7 +37 0 0 7 +38 0 0 7 +39 0 0 7 +40 0 0 7 +41 0 0 7 +42 0 0 7 +43 0 0 7 +44 0 0 7 +45 0 0 7 +46 0 0 7 +47 0 0 7 +48 0 0 7 +49 0 0 7 +50 0 0 7 +51 0 0 7 +52 0 0 7 +53 0 0 7 +54 0 0 7 +55 0 0 7 +56 0 0 7 +57 0 0 7 +58 0 0 7 +59 0 0 7 +60 0 0 7 +61 0 0 7 +62 5.32602 3.73587 7 +63 5.24874 3.97531 7 +64 5.19029 4.14847 7 +65 5.14422 4.27041 7 +66 5.10475 4.27824 7 +67 5.06281 4.10038 7 +68 5.00742 3.77329 7 +69 4.93465 3.51301 7 +70 4.85345 3.40009 7 +71 4.77228 3.34765 7 +72 4.6921 3.26427 7 +73 4.60726 3.07763 7 +74 4.5087 2.82477 7 +75 4.40162 2.78344 7 +76 4.32308 3.33385 7 +77 4.29103 3.82463 7 +78 4.27434 3.93776 7 +79 4.25947 3.8644 7 +80 4.22904 3.17692 7 +81 4.15218 2.74705 7 +82 4.07298 2.7934 7 +83 4.00338 2.81498 7 +84 3.93691 2.74921 7 +85 3.86777 2.63922 7 +86 3.79538 2.55328 7 +87 3.72322 2.51448 7 +88 3.65479 2.51068 7 +89 3.59191 2.52597 7 +90 3.53501 2.55038 7 +91 3.48392 2.57844 7 +92 3.43816 2.6076 7 +93 3.39719 2.63621 7 +94 3.36049 2.66377 7 +95 3.32757 2.68981 7 +96 3.29799 2.714 7 +97 3.27137 2.73675 7 +98 3.24737 2.75774 7 +99 3.22571 2.77734 7 +0 0 0 8 +1 0 0 8 +2 0 0 8 +3 0 0 8 +4 0 0 8 +5 0 0 8 +6 0 0 8 +7 0 0 8 +8 0 0 8 +9 0 0 8 +10 0 0 8 +11 0 0 8 +12 0 0 8 +13 0 0 8 +14 0 0 8 +15 0 0 8 +16 0 0 8 +17 0 0 8 +18 0 0 8 +19 0 0 8 +20 0 0 8 +21 0 0 8 +22 0 0 8 +23 0 0 8 +24 0 0 8 +25 0 0 8 +26 0 0 8 +27 0 0 8 +28 0 0 8 +29 0 0 8 +30 0 0 8 +31 0 0 8 +32 0 0 8 +33 0 0 8 +34 0 0 8 +35 0 0 8 +36 0 0 8 +37 0 0 8 +38 0 0 8 +39 0 0 8 +40 0 0 8 +41 0 0 8 +42 0 0 8 +43 0 0 8 +44 0 0 8 +45 0 0 8 +46 0 0 8 +47 0 0 8 +48 0 0 8 +49 0 0 8 +50 0 0 8 +51 0 0 8 +52 0 0 8 +53 0 0 8 +54 0 0 8 +55 0 0 8 +56 0 0 8 +57 0 0 8 +58 0 0 8 +59 0 0 8 +60 0 0 8 +61 0 0 8 +62 0 0 8 +63 0 0 8 +64 0 0 8 +65 5.34479 4.02032 8 +66 5.27678 4.01163 8 +67 5.21389 4.04677 8 +68 5.15974 4.17404 8 +69 5.11728 4.3093 8 +70 5.08049 4.2746 8 +71 5.03611 3.94946 8 +72 4.96275 3.34546 8 +73 4.85097 2.96998 8 +74 4.73529 3.04102 8 +75 4.64576 3.28376 8 +76 4.57875 3.43686 8 +77 4.52179 3.44519 8 +78 4.462 3.22667 8 +79 4.38066 2.84137 8 +80 4.2946 3.16561 8 +81 4.26306 3.90082 8 +82 4.25118 4.00849 8 +83 4.23956 3.85867 8 +84 4.19387 2.80064 8 +85 4.10694 2.71262 8 +86 4.02936 2.76541 8 +87 3.95862 2.73355 8 +88 3.88727 2.63544 8 +89 3.81307 2.54778 8 +90 3.73901 2.50698 8 +91 3.66879 2.503 8 +92 3.60431 2.51896 8 +93 3.54606 2.54416 8 +94 3.49381 2.57307 8 +95 3.44707 2.60275 8 +96 3.40525 2.63191 8 +97 3.36782 2.6599 8 +98 3.33425 2.68611 8 +99 3.3041 2.71074 8 +0 0 0 9 +1 0 0 9 +2 0 0 9 +3 0 0 9 +4 0 0 9 +5 0 0 9 +6 0 0 9 +7 0 0 9 +8 0 0 9 +9 0 0 9 +10 0 0 9 +11 0 0 9 +12 0 0 9 +13 0 0 9 +14 0 0 9 +15 0 0 9 +16 0 0 9 +17 0 0 9 +18 0 0 9 +19 0 0 9 +20 0 0 9 +21 0 0 9 +22 0 0 9 +23 0 0 9 +24 0 0 9 +25 0 0 9 +26 0 0 9 +27 0 0 9 +28 0 0 9 +29 0 0 9 +30 0 0 9 +31 0 0 9 +32 0 0 9 +33 0 0 9 +34 0 0 9 +35 0 0 9 +36 0 0 9 +37 0 0 9 +38 0 0 9 +39 0 0 9 +40 0 0 9 +41 0 0 9 +42 0 0 9 +43 0 0 9 +44 0 0 9 +45 0 0 9 +46 0 0 9 +47 0 0 9 +48 0 0 9 +49 0 0 9 +50 0 0 9 +51 0 0 9 +52 0 0 9 +53 0 0 9 +54 0 0 9 +55 0 0 9 +56 0 0 9 +57 0 0 9 +58 0 0 9 +59 0 0 9 +60 0 0 9 +61 0 0 9 +62 0 0 9 +63 0 0 9 +64 0 0 9 +65 0 0 9 +66 0 0 9 +67 0 0 9 +68 0 0 9 +69 5.35874 4.14466 9 +70 5.296 4.0753 9 +71 5.23283 3.99906 9 +72 5.17086 4.03551 9 +73 5.1205 4.19501 9 +74 5.07432 4.01056 9 +75 5.00556 3.49231 9 +76 4.90396 3.06108 9 +77 4.77505 2.75692 9 +78 4.63808 2.7291 9 +79 4.53252 3.13157 9 +80 4.47126 3.51651 9 +81 4.42895 3.61506 9 +82 4.38667 3.40589 9 +83 4.31776 2.86623 9 +84 4.25383 3.69036 9 +85 4.24072 4.04312 9 +86 4.23275 4.00167 9 +87 4.20013 2.84705 9 +88 4.10978 2.6664 9 +89 4.02821 2.72267 9 +90 3.95412 2.69114 9 +91 3.87975 2.59769 9 +92 3.80344 2.52335 9 +93 3.72862 2.49554 9 +94 3.65859 2.49989 9 +95 3.59481 2.52051 9 +96 3.53743 2.54813 9 +97 3.48609 2.57811 9 +98 3.44021 2.60837 9 +99 3.39918 2.63755 9 +0 0 0 10 +1 0 0 10 +2 0 0 10 +3 0 0 10 +4 0 0 10 +5 0 0 10 +6 0 0 10 +7 0 0 10 +8 0 0 10 +9 0 0 10 +10 0 0 10 +11 0 0 10 +12 0 0 10 +13 0 0 10 +14 0 0 10 +15 0 0 10 +16 0 0 10 +17 0 0 10 +18 0 0 10 +19 0 0 10 +20 0 0 10 +21 0 0 10 +22 0 0 10 +23 0 0 10 +24 0 0 10 +25 0 0 10 +26 0 0 10 +27 0 0 10 +28 0 0 10 +29 0 0 10 +30 0 0 10 +31 0 0 10 +32 0 0 10 +33 0 0 10 +34 0 0 10 +35 0 0 10 +36 0 0 10 +37 0 0 10 +38 0 0 10 +39 0 0 10 +40 0 0 10 +41 0 0 10 +42 0 0 10 +43 0 0 10 +44 0 0 10 +45 0 0 10 +46 0 0 10 +47 0 0 10 +48 0 0 10 +49 0 0 10 +50 0 0 10 +51 0 0 10 +52 0 0 10 +53 0 0 10 +54 0 0 10 +55 0 0 10 +56 0 0 10 +57 0 0 10 +58 0 0 10 +59 0 0 10 +60 0 0 10 +61 0 0 10 +62 0 0 10 +63 0 0 10 +64 0 0 10 +65 0 0 10 +66 0 0 10 +67 0 0 10 +68 0 0 10 +69 0 0 10 +70 0 0 10 +71 5.36321 3.79863 10 +72 5.28024 3.8527 10 +73 5.20874 3.93861 10 +74 5.14772 4.06811 10 +75 5.10304 4.31143 10 +76 5.06636 4.20339 10 +77 5.01179 3.6989 10 +78 4.93081 3.40688 10 +79 4.84246 3.30572 10 +80 4.7512 3.14559 10 +81 4.64532 2.8295 10 +82 4.52168 2.70432 10 +83 4.4277 3.26019 10 +84 4.38393 3.68831 10 +85 4.35383 3.69225 10 +86 4.31044 3.09873 10 +87 4.24301 3.60271 10 +88 4.23113 4.0782 10 +89 4.2247 4.00549 10 +90 4.17723 2.65403 10 +91 4.08377 2.65059 10 +92 4.00229 2.68779 10 +93 3.92595 2.62939 10 +94 3.84851 2.54286 10 +95 3.77103 2.49557 10 +96 3.69729 2.48899 10 +97 3.62959 2.50504 10 +98 3.56853 2.53128 10 +99 3.51387 2.56137 10 +0 0 0 11 +1 0 0 11 +2 0 0 11 +3 0 0 11 +4 0 0 11 +5 0 0 11 +6 0 0 11 +7 0 0 11 +8 0 0 11 +9 0 0 11 +10 0 0 11 +11 0 0 11 +12 0 0 11 +13 0 0 11 +14 0 0 11 +15 0 0 11 +16 0 0 11 +17 0 0 11 +18 0 0 11 +19 0 0 11 +20 0 0 11 +21 0 0 11 +22 0 0 11 +23 0 0 11 +24 0 0 11 +25 0 0 11 +26 0 0 11 +27 0 0 11 +28 0 0 11 +29 0 0 11 +30 0 0 11 +31 0 0 11 +32 0 0 11 +33 0 0 11 +34 0 0 11 +35 0 0 11 +36 0 0 11 +37 0 0 11 +38 0 0 11 +39 0 0 11 +40 0 0 11 +41 0 0 11 +42 0 0 11 +43 0 0 11 +44 0 0 11 +45 0 0 11 +46 0 0 11 +47 0 0 11 +48 0 0 11 +49 0 0 11 +50 0 0 11 +51 0 0 11 +52 0 0 11 +53 0 0 11 +54 0 0 11 +55 0 0 11 +56 0 0 11 +57 0 0 11 +58 0 0 11 +59 0 0 11 +60 0 0 11 +61 0 0 11 +62 0 0 11 +63 0 0 11 +64 0 0 11 +65 0 0 11 +66 0 0 11 +67 0 0 11 +68 0 0 11 +69 0 0 11 +70 0 0 11 +71 0 0 11 +72 0 0 11 +73 5.35899 4.08893 11 +74 5.2965 4.11674 11 +75 5.2367 4.04843 11 +76 5.17452 3.96772 11 +77 5.11914 4.18141 11 +78 5.08161 4.34727 11 +79 5.04089 3.95123 11 +80 4.95715 3.14413 11 +81 4.8349 2.98417 11 +82 4.73247 3.2327 11 +83 4.65562 3.36837 11 +84 4.58514 3.24122 11 +85 4.49485 2.79978 11 +86 4.39071 3.00307 11 +87 4.34311 3.72965 11 +88 4.31918 3.79546 11 +89 4.28241 3.09661 11 +90 4.22934 3.93628 11 +91 4.22303 4.10882 11 +92 4.21312 3.43804 11 +93 4.1247 2.58748 11 +94 4.03509 2.65187 11 +95 3.95513 2.63322 11 +96 3.87626 2.55227 11 +97 3.79703 2.49526 11 +98 3.72095 2.48202 11 +99 3.65079 2.49544 11 +0 0 0 12 +1 0 0 12 +2 0 0 12 +3 0 0 12 +4 0 0 12 +5 0 0 12 +6 0 0 12 +7 0 0 12 +8 0 0 12 +9 0 0 12 +10 0 0 12 +11 0 0 12 +12 0 0 12 +13 0 0 12 +14 0 0 12 +15 0 0 12 +16 0 0 12 +17 0 0 12 +18 0 0 12 +19 0 0 12 +20 0 0 12 +21 0 0 12 +22 0 0 12 +23 0 0 12 +24 0 0 12 +25 0 0 12 +26 0 0 12 +27 0 0 12 +28 0 0 12 +29 0 0 12 +30 0 0 12 +31 0 0 12 +32 0 0 12 +33 0 0 12 +34 0 0 12 +35 0 0 12 +36 0 0 12 +37 0 0 12 +38 0 0 12 +39 0 0 12 +40 0 0 12 +41 0 0 12 +42 0 0 12 +43 0 0 12 +44 0 0 12 +45 0 0 12 +46 0 0 12 +47 0 0 12 +48 0 0 12 +49 0 0 12 +50 0 0 12 +51 0 0 12 +52 0 0 12 +53 0 0 12 +54 0 0 12 +55 0 0 12 +56 0 0 12 +57 0 0 12 +58 0 0 12 +59 0 0 12 +60 0 0 12 +61 0 0 12 +62 0 0 12 +63 0 0 12 +64 0 0 12 +65 0 0 12 +66 0 0 12 +67 0 0 12 +68 0 0 12 +69 0 0 12 +70 0 0 12 +71 0 0 12 +72 0 0 12 +73 0 0 12 +74 0 0 12 +75 0 0 12 +76 5.38385 4.13995 12 +77 5.31679 4.0478 12 +78 5.25119 3.96618 12 +79 5.18027 3.82647 12 +80 5.11812 4.13877 12 +81 5.07716 4.18457 12 +82 5.01378 3.46782 12 +83 4.90325 2.92843 12 +84 4.76076 2.68285 12 +85 4.63388 3.00385 12 +86 4.5584 3.43109 12 +87 4.50435 3.46217 12 +88 4.43833 2.96422 12 +89 4.3445 3.07469 12 +90 4.30749 3.84476 12 +91 4.28846 3.78597 12 +92 4.23825 3.05258 12 +93 4.22025 4.11625 12 +94 4.21576 4.01046 12 +95 4.14852 2.55351 12 +96 4.05302 2.61445 12 +97 3.96948 2.61944 12 +98 3.88882 2.54761 12 +99 3.80821 2.49027 12 +0 0 0 13 +1 0 0 13 +2 0 0 13 +3 0 0 13 +4 0 0 13 +5 0 0 13 +6 0 0 13 +7 0 0 13 +8 0 0 13 +9 0 0 13 +10 0 0 13 +11 0 0 13 +12 0 0 13 +13 0 0 13 +14 0 0 13 +15 0 0 13 +16 0 0 13 +17 0 0 13 +18 0 0 13 +19 0 0 13 +20 0 0 13 +21 0 0 13 +22 0 0 13 +23 0 0 13 +24 0 0 13 +25 0 0 13 +26 0 0 13 +27 0 0 13 +28 0 0 13 +29 0 0 13 +30 0 0 13 +31 0 0 13 +32 0 0 13 +33 0 0 13 +34 0 0 13 +35 0 0 13 +36 0 0 13 +37 0 0 13 +38 0 0 13 +39 0 0 13 +40 0 0 13 +41 0 0 13 +42 0 0 13 +43 0 0 13 +44 0 0 13 +45 0 0 13 +46 0 0 13 +47 0 0 13 +48 0 0 13 +49 0 0 13 +50 0 0 13 +51 0 0 13 +52 0 0 13 +53 0 0 13 +54 0 0 13 +55 0 0 13 +56 0 0 13 +57 0 0 13 +58 0 0 13 +59 0 0 13 +60 0 0 13 +61 0 0 13 +62 0 0 13 +63 0 0 13 +64 0 0 13 +65 0 0 13 +66 0 0 13 +67 0 0 13 +68 0 0 13 +69 0 0 13 +70 0 0 13 +71 0 0 13 +72 0 0 13 +73 0 0 13 +74 0 0 13 +75 0 0 13 +76 0 0 13 +77 5.3978 5.38642 13 +78 5.31093 3.90993 13 +79 5.2457 4.10019 13 +80 5.19012 4.08591 13 +81 5.13361 4.03579 13 +82 5.08911 4.35986 13 +83 5.05369 4.10007 13 +84 4.98487 3.46139 13 +85 4.893 3.28669 13 +86 4.79387 3.05855 13 +87 4.67124 2.68714 13 +88 4.54342 2.89706 13 +89 4.47398 3.51964 13 +90 4.43133 3.55637 13 +91 4.37014 2.88464 13 +92 4.29745 3.62009 13 +93 4.27871 3.93463 13 +94 4.2525 3.12831 13 +95 4.21751 4.10889 13 +96 4.21398 4.09031 13 +97 4.15479 2.53052 13 +98 4.05615 2.58812 13 +99 3.97024 2.59811 13 +0 0 0 14 +1 0 0 14 +2 0 0 14 +3 0 0 14 +4 0 0 14 +5 0 0 14 +6 0 0 14 +7 0 0 14 +8 0 0 14 +9 0 0 14 +10 0 0 14 +11 0 0 14 +12 0 0 14 +13 0 0 14 +14 0 0 14 +15 0 0 14 +16 0 0 14 +17 0 0 14 +18 0 0 14 +19 0 0 14 +20 0 0 14 +21 0 0 14 +22 0 0 14 +23 0 0 14 +24 0 0 14 +25 0 0 14 +26 0 0 14 +27 0 0 14 +28 0 0 14 +29 0 0 14 +30 0 0 14 +31 0 0 14 +32 0 0 14 +33 0 0 14 +34 0 0 14 +35 0 0 14 +36 0 0 14 +37 0 0 14 +38 0 0 14 +39 0 0 14 +40 0 0 14 +41 0 0 14 +42 0 0 14 +43 0 0 14 +44 0 0 14 +45 0 0 14 +46 0 0 14 +47 0 0 14 +48 0 0 14 +49 0 0 14 +50 0 0 14 +51 0 0 14 +52 0 0 14 +53 0 0 14 +54 0 0 14 +55 0 0 14 +56 0 0 14 +57 0 0 14 +58 0 0 14 +59 0 0 14 +60 0 0 14 +61 0 0 14 +62 0 0 14 +63 0 0 14 +64 0 0 14 +65 0 0 14 +66 0 0 14 +67 0 0 14 +68 0 0 14 +69 0 0 14 +70 0 0 14 +71 0 0 14 +72 0 0 14 +73 0 0 14 +74 0 0 14 +75 0 0 14 +76 0 0 14 +77 0 0 14 +78 0 0 14 +79 5.39128 5.38047 14 +80 5.30622 3.88693 14 +81 5.23974 4.08798 14 +82 5.18445 4.08567 14 +83 5.12719 4.0171 14 +84 5.08381 4.38255 14 +85 5.04841 4.03895 14 +86 4.96132 3.0622 14 +87 4.83838 3.06538 14 +88 4.74402 3.29578 14 +89 4.66403 3.20956 14 +90 4.56276 2.72766 14 +91 4.45218 3.1019 14 +92 4.40385 3.67765 14 +93 4.3677 3.41843 14 +94 4.29334 3.13256 14 +95 4.26782 3.97147 14 +96 4.25086 3.45574 14 +97 4.21481 4.11573 14 +98 4.21174 4.09283 14 +99 4.14465 2.50752 14 +0 0 0 15 +1 0 0 15 +2 0 0 15 +3 0 0 15 +4 0 0 15 +5 0 0 15 +6 0 0 15 +7 0 0 15 +8 0 0 15 +9 0 0 15 +10 0 0 15 +11 0 0 15 +12 0 0 15 +13 0 0 15 +14 0 0 15 +15 0 0 15 +16 0 0 15 +17 0 0 15 +18 0 0 15 +19 0 0 15 +20 0 0 15 +21 0 0 15 +22 0 0 15 +23 0 0 15 +24 0 0 15 +25 0 0 15 +26 0 0 15 +27 0 0 15 +28 0 0 15 +29 0 0 15 +30 0 0 15 +31 0 0 15 +32 0 0 15 +33 0 0 15 +34 0 0 15 +35 0 0 15 +36 0 0 15 +37 0 0 15 +38 0 0 15 +39 0 0 15 +40 0 0 15 +41 0 0 15 +42 0 0 15 +43 0 0 15 +44 0 0 15 +45 0 0 15 +46 0 0 15 +47 0 0 15 +48 0 0 15 +49 0 0 15 +50 0 0 15 +51 0 0 15 +52 0 0 15 +53 0 0 15 +54 0 0 15 +55 0 0 15 +56 0 0 15 +57 0 0 15 +58 0 0 15 +59 0 0 15 +60 0 0 15 +61 0 0 15 +62 0 0 15 +63 0 0 15 +64 0 0 15 +65 0 0 15 +66 0 0 15 +67 0 0 15 +68 0 0 15 +69 0 0 15 +70 0 0 15 +71 0 0 15 +72 0 0 15 +73 0 0 15 +74 0 0 15 +75 0 0 15 +76 0 0 15 +77 0 0 15 +78 0 0 15 +79 0 0 15 +80 0 0 15 +81 0 0 15 +82 5.36234 3.70176 15 +83 5.27099 3.78915 15 +84 5.20288 4.05959 15 +85 5.14478 3.9527 15 +86 5.09357 4.3141 15 +87 5.05562 3.95186 15 +88 4.96542 3.07465 15 +89 4.82417 2.68287 15 +90 4.69046 3.01187 15 +91 4.61128 3.40366 15 +92 4.54641 3.2203 15 +93 4.44774 2.72993 15 +94 4.37698 3.62682 15 +95 4.34776 3.68705 15 +96 4.28867 2.9234 15 +97 4.25746 3.99691 15 +98 4.24277 3.46345 15 +99 4.21223 4.14109 15 +0 0 0 16 +1 0 0 16 +2 0 0 16 +3 0 0 16 +4 0 0 16 +5 0 0 16 +6 0 0 16 +7 0 0 16 +8 0 0 16 +9 0 0 16 +10 0 0 16 +11 0 0 16 +12 0 0 16 +13 0 0 16 +14 0 0 16 +15 0 0 16 +16 0 0 16 +17 0 0 16 +18 0 0 16 +19 0 0 16 +20 0 0 16 +21 0 0 16 +22 0 0 16 +23 0 0 16 +24 0 0 16 +25 0 0 16 +26 0 0 16 +27 0 0 16 +28 0 0 16 +29 0 0 16 +30 0 0 16 +31 0 0 16 +32 0 0 16 +33 0 0 16 +34 0 0 16 +35 0 0 16 +36 0 0 16 +37 0 0 16 +38 0 0 16 +39 0 0 16 +40 0 0 16 +41 0 0 16 +42 0 0 16 +43 0 0 16 +44 0 0 16 +45 0 0 16 +46 0 0 16 +47 0 0 16 +48 0 0 16 +49 0 0 16 +50 0 0 16 +51 0 0 16 +52 0 0 16 +53 0 0 16 +54 0 0 16 +55 0 0 16 +56 0 0 16 +57 0 0 16 +58 0 0 16 +59 0 0 16 +60 0 0 16 +61 0 0 16 +62 0 0 16 +63 0 0 16 +64 0 0 16 +65 0 0 16 +66 0 0 16 +67 0 0 16 +68 0 0 16 +69 0 0 16 +70 0 0 16 +71 0 0 16 +72 0 0 16 +73 0 0 16 +74 0 0 16 +75 0 0 16 +76 0 0 16 +77 0 0 16 +78 0 0 16 +79 0 0 16 +80 0 0 16 +81 0 0 16 +82 0 0 16 +83 5.35909 3.73913 16 +84 5.27306 3.80688 16 +85 5.20004 3.98283 16 +86 5.14652 4.14212 16 +87 5.09737 4.20703 16 +88 5.06548 4.36629 16 +89 5.00776 3.49691 16 +90 4.91312 3.24796 16 +91 4.80442 2.90828 16 +92 4.66504 2.64234 16 +93 4.55882 3.29177 16 +94 4.50344 3.4991 16 +95 4.43523 2.843 16 +96 4.35248 3.53006 16 +97 4.32591 3.78546 16 +98 4.27481 2.94587 16 +99 4.24794 4.03141 16 +0 0 0 17 +1 0 0 17 +2 0 0 17 +3 0 0 17 +4 0 0 17 +5 0 0 17 +6 0 0 17 +7 0 0 17 +8 0 0 17 +9 0 0 17 +10 0 0 17 +11 0 0 17 +12 0 0 17 +13 0 0 17 +14 0 0 17 +15 0 0 17 +16 0 0 17 +17 0 0 17 +18 0 0 17 +19 0 0 17 +20 0 0 17 +21 0 0 17 +22 0 0 17 +23 0 0 17 +24 0 0 17 +25 0 0 17 +26 0 0 17 +27 0 0 17 +28 0 0 17 +29 0 0 17 +30 0 0 17 +31 0 0 17 +32 0 0 17 +33 0 0 17 +34 0 0 17 +35 0 0 17 +36 0 0 17 +37 0 0 17 +38 0 0 17 +39 0 0 17 +40 0 0 17 +41 0 0 17 +42 0 0 17 +43 0 0 17 +44 0 0 17 +45 0 0 17 +46 0 0 17 +47 0 0 17 +48 0 0 17 +49 0 0 17 +50 0 0 17 +51 0 0 17 +52 0 0 17 +53 0 0 17 +54 0 0 17 +55 0 0 17 +56 0 0 17 +57 0 0 17 +58 0 0 17 +59 0 0 17 +60 0 0 17 +61 0 0 17 +62 0 0 17 +63 0 0 17 +64 0 0 17 +65 0 0 17 +66 0 0 17 +67 0 0 17 +68 0 0 17 +69 0 0 17 +70 0 0 17 +71 0 0 17 +72 0 0 17 +73 0 0 17 +74 0 0 17 +75 0 0 17 +76 0 0 17 +77 0 0 17 +78 0 0 17 +79 0 0 17 +80 0 0 17 +81 0 0 17 +82 0 0 17 +83 0 0 17 +84 0 5.39315 17 +85 5.32486 3.84646 17 +86 5.24546 3.85047 17 +87 5.17905 4.04251 17 +88 5.12458 4.03297 17 +89 5.07966 4.41589 17 +90 5.04585 3.95273 17 +91 4.94485 2.97678 17 +92 4.82842 3.18393 17 +93 4.73922 3.23709 17 +94 4.63681 2.7482 17 +95 4.51519 3.02764 17 +96 4.45883 3.59855 17 +97 4.40772 3.04293 17 +98 4.32849 3.54858 17 +99 4.30537 3.8161 17 +0 0 0 18 +1 0 0 18 +2 0 0 18 +3 0 0 18 +4 0 0 18 +5 0 0 18 +6 0 0 18 +7 0 0 18 +8 0 0 18 +9 0 0 18 +10 0 0 18 +11 0 0 18 +12 0 0 18 +13 0 0 18 +14 0 0 18 +15 0 0 18 +16 0 0 18 +17 0 0 18 +18 0 0 18 +19 0 0 18 +20 0 0 18 +21 0 0 18 +22 0 0 18 +23 0 0 18 +24 0 0 18 +25 0 0 18 +26 0 0 18 +27 0 0 18 +28 0 0 18 +29 0 0 18 +30 0 0 18 +31 0 0 18 +32 0 0 18 +33 0 0 18 +34 0 0 18 +35 0 0 18 +36 0 0 18 +37 0 0 18 +38 0 0 18 +39 0 0 18 +40 0 0 18 +41 0 0 18 +42 0 0 18 +43 0 0 18 +44 0 0 18 +45 0 0 18 +46 0 0 18 +47 0 0 18 +48 0 0 18 +49 0 0 18 +50 0 0 18 +51 0 0 18 +52 0 0 18 +53 0 0 18 +54 0 0 18 +55 0 0 18 +56 0 0 18 +57 0 0 18 +58 0 0 18 +59 0 0 18 +60 0 0 18 +61 0 0 18 +62 0 0 18 +63 0 0 18 +64 0 0 18 +65 0 0 18 +66 0 0 18 +67 0 0 18 +68 0 0 18 +69 0 0 18 +70 0 0 18 +71 0 0 18 +72 0 0 18 +73 0 0 18 +74 0 0 18 +75 0 0 18 +76 0 0 18 +77 0 0 18 +78 0 0 18 +79 0 0 18 +80 0 0 18 +81 0 0 18 +82 0 0 18 +83 0 0 18 +84 0 0 18 +85 0 0 18 +86 0 0 18 +87 5.33289 3.72345 18 +88 5.23659 3.6115 18 +89 5.1636 4.07894 18 +90 5.11299 4.0851 18 +91 5.07567 4.47313 18 +92 5.02445 3.42677 18 +93 4.89759 2.73873 18 +94 4.75181 2.91208 18 +95 4.66256 3.35236 18 +96 4.58716 3.03965 18 +97 4.47447 2.87199 18 +98 4.41789 3.66134 18 +99 4.37368 3.06988 18 +0 0 0 19 +1 0 0 19 +2 0 0 19 +3 0 0 19 +4 0 0 19 +5 0 0 19 +6 0 0 19 +7 0 0 19 +8 0 0 19 +9 0 0 19 +10 0 0 19 +11 0 0 19 +12 0 0 19 +13 0 0 19 +14 0 0 19 +15 0 0 19 +16 0 0 19 +17 0 0 19 +18 0 0 19 +19 0 0 19 +20 0 0 19 +21 0 0 19 +22 0 0 19 +23 0 0 19 +24 0 0 19 +25 0 0 19 +26 0 0 19 +27 0 0 19 +28 0 0 19 +29 0 0 19 +30 0 0 19 +31 0 0 19 +32 0 0 19 +33 0 0 19 +34 0 0 19 +35 0 0 19 +36 0 0 19 +37 0 0 19 +38 0 0 19 +39 0 0 19 +40 0 0 19 +41 0 0 19 +42 0 0 19 +43 0 0 19 +44 0 0 19 +45 0 0 19 +46 0 0 19 +47 0 0 19 +48 0 0 19 +49 0 0 19 +50 0 0 19 +51 0 0 19 +52 0 0 19 +53 0 0 19 +54 0 0 19 +55 0 0 19 +56 0 0 19 +57 0 0 19 +58 0 0 19 +59 0 0 19 +60 0 0 19 +61 0 0 19 +62 0 0 19 +63 0 0 19 +64 0 0 19 +65 0 0 19 +66 0 0 19 +67 0 0 19 +68 0 0 19 +69 0 0 19 +70 0 0 19 +71 0 0 19 +72 0 0 19 +73 0 0 19 +74 0 0 19 +75 0 0 19 +76 0 0 19 +77 0 0 19 +78 0 0 19 +79 0 0 19 +80 0 0 19 +81 0 0 19 +82 0 0 19 +83 0 0 19 +84 0 0 19 +85 0 0 19 +86 0 0 19 +87 5.3829 3.83483 19 +88 5.30538 3.98374 19 +89 5.23575 3.8814 19 +90 5.1642 3.94229 19 +91 5.11313 4.15749 19 +92 5.07403 4.50831 19 +93 5.03735 3.74033 19 +94 4.94559 3.25245 19 +95 4.83263 2.86124 19 +96 4.68673 2.68852 19 +97 4.59118 3.38719 19 +98 4.52973 3.22521 19 +99 4.42974 2.90757 19 diff --git a/example/rayleigh/out/swd.txt b/example/rayleigh/out/swd.txt index 450f900..2de4550 100644 --- a/example/rayleigh/out/swd.txt +++ b/example/rayleigh/out/swd.txt @@ -1,1289 +1,838 @@ -100 94.1275 88.5999 83.3969 78.4994 73.8895 69.5504 65.466 61.6215 58.0028 54.5966 51.3904 48.3725 45.5319 42.858 40.3412 37.9721 35.7422 33.6433 31.6676 29.8079 28.0574 26.4098 24.8588 23.399 22.0249 20.7315 19.514 18.3681 17.2894 16.2741 15.3184 14.4188 13.5721 12.7751 12.0249 11.3187 10.654 10.0283 9.43944 8.88511 8.36333 7.87219 7.4099 6.97475 6.56516 6.17962 5.81673 5.47514 5.15361 4.85097 4.56609 4.29795 4.04555 3.80798 3.58436 3.37386 3.17573 2.98924 2.8137 2.64846 2.49293 2.34653 2.20873 2.07903 1.95694 1.84202 1.73384 1.63202 1.53618 1.44597 1.36106 1.28113 1.20589 1.13508 1.06842 1.00568 0.94662 0.891029 0.838704 0.789451 0.743091 0.699453 0.658377 0.619714 0.583322 0.549066 0.516822 0.486472 0.457904 0.431013 0.405702 0.381877 0.359452 0.338343 0.318474 0.299771 0.282167 0.265597 0.25 -0 3.103517 3.039950 0 -1 3.097533 3.031250 0 -2 3.114690 3.023849 0 -3 3.096373 3.008251 0 -4 3.088602 2.995590 0 -5 3.081174 2.979278 0 -6 3.079392 2.962533 0 -7 3.066544 2.939431 0 -8 3.058352 2.917230 0 -9 3.059494 2.889960 0 -10 3.043988 2.856939 0 -11 3.031557 2.821676 0 -12 3.013507 2.780211 0 -13 2.997513 2.737450 0 -14 2.981124 2.691933 0 -15 2.958670 2.639883 0 -16 2.936237 2.589245 0 -17 2.912552 2.537740 0 -18 2.885044 2.488413 0 -19 2.855427 2.441703 0 -20 2.825830 2.400707 0 -21 2.795446 2.366031 0 -22 2.764748 2.337265 0 -23 2.734228 2.315001 0 -24 2.704854 2.298034 0 -25 2.676849 2.285717 0 -26 2.649399 2.277241 0 -27 2.624191 2.271292 0 -27 3.498304 3.376758 1 -28 2.599858 2.267212 0 -28 3.488560 3.302919 1 -29 2.577737 2.264714 0 -29 3.474905 3.232454 1 -30 2.556953 2.262859 0 -30 3.457287 3.165336 1 -31 2.537629 2.261513 0 -31 3.436372 3.098728 1 -32 2.519514 2.260492 0 -32 3.411912 3.030854 1 -33 2.502578 2.259629 0 -33 3.384397 2.962322 1 -34 2.486912 2.258874 0 -34 3.353646 2.895489 1 -35 2.472156 2.258271 0 -35 3.320469 2.833840 1 -36 2.458525 2.257498 0 -36 3.284995 2.779649 1 -37 2.445736 2.256807 0 -37 3.248398 2.735412 1 -38 2.433768 2.256041 0 -38 3.211484 2.700298 1 -39 2.422484 2.255289 0 -39 3.175009 2.673572 1 -40 2.411986 2.254499 0 -40 3.139565 2.652848 1 -40 3.492036 3.232292 2 -41 2.402090 2.253731 0 -41 3.105374 2.636842 1 -41 3.469967 3.078493 2 -42 2.392793 2.253000 0 -42 3.072807 2.623946 1 -42 3.439606 2.962299 2 -43 2.384076 2.252236 0 -43 3.041797 2.613038 1 -43 3.403624 2.872652 2 -44 2.375925 2.251563 0 -44 3.012386 2.603559 1 -44 3.364165 2.805206 2 -45 2.368201 2.251032 0 -45 2.984505 2.594978 1 -45 3.323083 2.756898 2 -46 2.360990 2.250675 0 -46 2.958137 2.587010 1 -46 3.281955 2.722564 2 -47 2.354190 2.250572 0 -47 2.933129 2.579624 1 -47 3.241737 2.698341 2 -47 3.486463 3.106802 3 -48 2.347836 2.250766 0 -48 2.909459 2.572703 1 -48 3.203051 2.680123 2 -48 3.454465 2.936111 3 -49 2.341919 2.251299 0 -49 2.887010 2.566159 1 -49 3.166151 2.665534 2 -49 3.414591 2.836753 3 -50 2.336427 2.252261 0 -50 2.865732 2.559982 1 -50 3.131086 2.653049 2 -50 3.371443 2.776016 3 -51 2.331369 2.253620 0 -51 2.845559 2.554178 1 -51 3.097846 2.641842 2 -51 3.327749 2.738031 3 -52 2.326697 2.255471 0 -52 2.826420 2.548727 1 -52 3.066336 2.631515 2 -52 3.285040 2.712855 3 -52 3.476217 2.979256 4 -53 2.322463 2.257759 0 -53 2.808266 2.543636 1 -53 3.036485 2.621873 2 -53 3.244024 2.694494 3 -53 3.436186 2.842353 4 -54 2.318647 2.260451 0 -54 2.791042 2.538903 1 -54 3.008192 2.612878 2 -54 3.205002 2.679649 3 -54 3.391336 2.774833 4 -55 2.315241 2.263480 0 -55 2.774697 2.534555 1 -55 2.981370 2.604515 2 -55 3.167965 2.666846 3 -55 3.345899 2.737822 4 -55 3.495130 3.112201 5 -56 2.312233 2.266774 0 -56 2.759206 2.530585 1 -56 2.955957 2.596847 2 -56 3.132923 2.655535 3 -56 3.301783 2.715586 4 -56 3.458874 2.871464 5 -57 2.309612 2.270240 0 -57 2.744515 2.526986 1 -57 2.931875 2.589974 2 -57 3.099787 2.645789 3 -57 3.259790 2.701170 4 -57 3.413791 2.790417 5 -58 2.307377 2.273745 0 -58 2.730600 2.523767 1 -58 2.909090 2.583951 2 -58 3.068532 2.637813 3 -58 3.220248 2.691884 4 -58 3.368023 2.759387 5 -58 3.495354 3.100633 6 -59 2.305476 2.277232 0 -59 2.717423 2.520904 1 -59 2.887555 2.578849 2 -59 3.039138 2.631811 3 -59 3.183305 2.686572 4 -59 3.324401 2.748671 5 -59 3.459087 2.886538 6 -60 2.303908 2.280580 0 -60 2.704948 2.518377 1 -60 2.867239 2.574644 2 -60 3.011594 2.627660 3 -60 3.149000 2.684005 4 -60 3.283827 2.744823 5 -60 3.416325 2.826334 6 -61 2.302601 2.283585 0 -61 2.693156 2.516128 1 -61 2.848101 2.571214 2 -61 2.985852 2.624800 3 -61 3.117205 2.682053 4 -61 3.246198 2.739328 5 -61 3.373401 2.789818 6 -61 3.487302 2.973414 7 -62 2.301554 2.286391 0 -62 2.681993 2.514015 1 -62 2.830100 2.568270 2 -62 2.961836 2.622176 3 -62 3.087652 2.677797 4 -62 3.210778 2.724189 5 -62 3.330450 2.738453 6 -62 3.441025 2.741037 7 -63 2.300733 2.288886 0 -63 2.671442 2.511967 1 -63 2.813150 2.565328 2 -63 2.939338 2.618347 3 -63 3.059803 2.667673 4 -63 3.176272 2.691997 5 -63 3.285626 2.667526 6 -63 3.386071 2.678373 7 -63 3.482551 2.917007 8 -64 2.300105 2.291032 0 -64 2.661453 2.509813 1 -64 2.797167 2.561825 2 -64 2.918105 2.611644 3 -64 3.032936 2.648369 4 -64 3.141153 2.643673 5 -64 3.239383 2.630262 6 -64 3.336253 2.728674 7 -64 3.440667 2.867407 8 -65 2.299624 2.292826 0 -65 2.651960 2.507383 1 -65 2.781998 2.557154 2 -65 2.897762 2.600788 3 -65 3.006233 2.619702 4 -65 3.105009 2.604600 5 -65 3.196790 2.658269 6 -65 3.295349 2.771209 7 -65 3.398536 2.803794 8 -65 3.487195 2.857565 9 -66 2.299293 2.294269 0 -66 2.642935 2.504482 1 -66 2.767500 2.550689 2 -66 2.877928 2.585432 3 -66 2.979223 2.590079 4 -66 3.070045 2.603080 5 -66 3.160969 2.697324 6 -66 3.258878 2.754037 7 -66 3.351757 2.690639 8 -66 3.433431 2.737155 9 -67 2.299036 2.295448 0 -67 2.634265 2.500978 1 -67 2.753456 2.542240 2 -67 2.858290 2.567848 3 -67 2.952421 2.573868 4 -67 3.038904 2.625747 5 -67 3.129894 2.703276 6 -67 3.221507 2.684785 7 -67 3.301915 2.666253 8 -67 3.386223 2.803400 9 -67 3.474274 2.864669 10 -68 2.298843 2.296360 0 -68 2.625902 2.496699 1 -68 2.739753 2.532253 2 -68 2.838855 2.553072 3 -68 2.927122 2.576014 4 -68 3.011808 2.641484 5 -68 3.100113 2.671848 6 -68 3.181618 2.636362 7 -68 3.258787 2.722646 8 -68 3.344589 2.765542 9 -68 3.422122 2.702254 10 -68 3.492278 2.977233 11 -69 2.298719 2.297068 0 -69 2.617789 2.491605 1 -69 2.726280 2.521949 2 -69 2.820006 2.546131 3 -69 2.904259 2.586316 4 -69 2.987139 2.635755 5 -69 3.069460 2.629882 6 -69 3.143825 2.652824 7 -69 3.222321 2.729083 8 -69 3.300082 2.683858 9 -69 3.371263 2.757153 10 -69 3.450596 2.827797 11 -70 2.298640 2.297559 0 -70 2.609843 2.485829 1 -70 2.713057 2.513378 2 -70 2.802324 2.547744 3 -70 2.883692 2.591450 4 -70 2.963150 2.613389 5 -70 3.038834 2.615934 6 -70 3.111078 2.673998 7 -70 3.186684 2.682719 8 -70 3.255979 2.693793 9 -70 3.329241 2.773747 10 -70 3.401277 2.731297 11 -70 3.468579 2.866868 12 -71 2.298586 2.297947 0 -71 2.602009 2.479622 1 -71 2.700257 2.508450 2 -71 2.786185 2.554039 3 -71 2.864546 2.584680 4 -71 2.939199 2.593242 5 -71 3.010617 2.626602 6 -71 3.081179 2.660970 7 -71 3.150736 2.663183 8 -71 3.218082 2.723384 9 -71 3.288454 2.724768 10 -71 3.353969 2.762805 11 -71 3.424308 2.803775 12 -71 3.486577 2.853085 13 -72 2.298540 2.298116 0 -72 2.594299 2.473462 1 -72 2.688149 2.508020 2 -72 2.771609 2.559491 3 -72 2.845877 2.567919 4 -72 2.916147 2.591193 5 -72 2.985236 2.629725 6 -72 3.051952 2.640153 7 -72 3.117829 2.678814 8 -72 3.183596 2.704627 9 -72 3.248315 2.716373 10 -72 3.312694 2.753649 11 -72 3.376217 2.718892 12 -72 3.436945 2.759558 13 -72 3.494002 2.847539 14 -73 2.298512 2.298288 0 -73 2.586686 2.467883 1 -73 2.676957 2.511504 2 -73 2.758229 2.559703 3 -73 2.827251 2.550720 4 -73 2.895210 2.602456 5 -73 2.961179 2.612880 6 -73 3.024222 2.643615 7 -73 3.088139 2.673190 8 -73 3.149773 2.682124 9 -73 3.211147 2.700701 10 -73 3.270430 2.678360 11 -73 3.327349 2.688660 12 -73 3.384723 2.710078 13 -73 3.442188 2.798499 14 -73 3.498304 3.009719 15 -74 2.298509 2.298379 0 -74 2.579245 2.463392 1 -74 2.666821 2.517465 2 -74 2.745511 2.552197 3 -74 2.809038 2.543704 4 -74 2.876543 2.609420 5 -74 2.937380 2.593086 6 -74 2.999403 2.655833 7 -74 3.058908 2.636805 8 -74 3.117462 2.670243 9 -74 3.173060 2.631538 10 -74 3.227490 2.670461 11 -74 3.281706 2.702024 12 -74 3.339021 2.777628 13 -74 3.396855 2.790560 14 -74 3.453610 2.789790 15 -75 2.298513 2.298431 0 -75 2.572033 2.460353 1 -75 2.657803 2.524149 2 -75 2.732875 2.537201 3 -75 2.792097 2.550315 4 -75 2.859095 2.598682 5 -75 2.914419 2.590652 6 -75 2.976413 2.638307 7 -75 3.029196 2.611283 8 -75 3.085487 2.623734 9 -75 3.134717 2.642147 10 -75 3.189561 2.691309 11 -75 3.242984 2.749948 12 -75 3.299005 2.730677 13 -75 3.350702 2.711805 14 -75 3.400040 2.692701 15 -75 3.451576 2.813987 16 -76 2.298493 2.298485 0 -76 2.565141 2.458817 1 -76 2.649752 2.530142 2 -76 2.719923 2.518407 3 -76 2.777152 2.565539 4 -76 2.841421 2.570108 5 -76 2.893678 2.605479 6 -76 2.952205 2.582393 7 -76 3.001261 2.623226 8 -76 3.052162 2.591279 9 -76 3.103624 2.706078 10 -76 3.154842 2.678460 11 -76 3.208696 2.713230 12 -76 3.254564 2.650369 13 -76 3.304109 2.711364 14 -76 3.353160 2.801056 15 -76 3.406175 2.766750 16 -76 3.454223 2.756135 17 -76 3.497109 2.883734 18 -77 2.298503 2.298524 0 -77 2.558635 2.458681 1 -77 2.642559 2.534139 2 -77 2.706581 2.501190 3 -77 2.764285 2.580045 4 -77 2.822719 2.537950 5 -77 2.875515 2.616961 6 -77 2.925694 2.541312 7 -77 2.976721 2.635010 8 -77 3.021574 2.623403 9 -77 3.076711 2.678589 10 -77 3.121733 2.669528 11 -77 3.169805 2.613788 12 -77 3.215503 2.749666 13 -77 3.263189 2.725208 14 -77 3.313927 2.737122 15 -77 3.355682 2.714586 16 -77 3.403897 2.781048 17 -77 3.452287 2.864875 18 -77 3.496361 2.843397 19 -78 2.298494 2.298567 0 -78 2.552560 2.459666 1 -78 2.635997 2.535174 2 -78 2.693168 2.489749 3 -78 2.752978 2.584646 4 -78 2.803440 2.519193 5 -78 2.858539 2.600311 6 -78 2.900242 2.559021 7 -78 2.953467 2.609540 8 -78 2.996827 2.671282 9 -78 3.046602 2.592118 10 -78 3.091285 2.676473 11 -78 3.132144 2.666744 12 -78 3.183746 2.713906 13 -78 3.225281 2.716842 14 -78 3.268511 2.668403 15 -78 3.315747 2.814133 16 -78 3.358491 2.733170 17 -78 3.402594 2.674918 18 -78 3.444235 2.831178 19 -78 3.487083 2.770791 20 -79 2.298513 2.298493 0 -79 2.546959 2.461474 1 -79 2.629775 2.532236 2 -79 2.680104 2.485429 3 -79 2.742201 2.572866 4 -79 2.784990 2.523405 5 -79 2.840541 2.559592 6 -79 2.879673 2.613486 7 -79 2.929374 2.573699 8 -79 2.975921 2.668773 9 -79 3.014575 2.588436 10 -79 3.062698 2.651461 11 -79 3.103461 2.732482 12 -79 3.146866 2.612896 13 -79 3.190692 2.718710 14 -79 3.229321 2.743078 15 -79 3.273867 2.618055 16 -79 3.313008 2.737683 17 -79 3.351222 2.738381 18 -79 3.394536 2.664101 19 -79 3.433700 2.848565 20 -79 3.474970 2.838577 21 -80 2.298477 2.298528 0 -80 2.541861 2.463842 1 -80 2.623612 2.524121 2 -80 2.667906 2.488719 3 -80 2.730758 2.544596 4 -80 2.768994 2.550791 5 -80 2.821128 2.529492 6 -80 2.863930 2.644328 7 -80 2.905024 2.559214 8 -80 2.953677 2.604320 9 -80 2.988820 2.672493 10 -80 3.033288 2.607704 11 -80 3.077569 2.674297 12 -80 3.110969 2.671950 13 -80 3.155046 2.621899 14 -80 3.194376 2.675018 15 -80 3.226929 2.698745 16 -80 3.270593 2.670674 17 -80 3.309609 2.773091 18 -80 3.345313 2.794478 19 -80 3.390286 2.711393 20 -80 3.426797 2.775564 21 -80 3.461869 2.769185 22 -81 2.298490 2.298527 0 -81 2.537225 2.466526 1 -81 2.617146 2.510304 2 -81 2.656983 2.499442 3 -81 2.717970 2.513766 4 -81 2.756359 2.584999 5 -81 2.801642 2.517685 6 -81 2.849439 2.617797 7 -81 2.882960 2.589000 8 -81 2.928779 2.563561 9 -81 2.969634 2.690709 10 -81 3.003774 2.601321 11 -81 3.046453 2.581640 12 -81 3.083895 2.704285 13 -81 3.115568 2.611136 14 -81 3.156244 2.643855 15 -81 3.195573 2.771803 16 -81 3.227892 2.703890 17 -81 3.270004 2.686132 18 -81 3.306869 2.721794 19 -81 3.336753 2.730470 20 -81 3.377071 2.705786 21 -81 3.415066 2.828046 22 -81 3.449098 2.867515 23 -81 3.488094 2.713035 24 -82 2.298489 2.298556 0 -82 2.533036 2.469356 1 -82 2.610053 2.492265 2 -82 2.647720 2.516147 3 -82 2.704357 2.495527 4 -82 2.746377 2.601730 5 -82 2.783142 2.518085 6 -82 2.832670 2.560900 7 -82 2.865913 2.643835 8 -82 2.903878 2.550647 9 -82 2.948484 2.594691 10 -82 2.979000 2.664851 11 -82 3.013335 2.564857 12 -82 3.054382 2.605653 13 -82 3.086934 2.753343 14 -82 3.120959 2.652101 15 -82 3.161591 2.634375 16 -82 3.195435 2.752168 17 -82 3.224568 2.654858 18 -82 3.262506 2.692488 19 -82 3.300993 2.804321 20 -82 3.330598 2.778992 21 -82 3.367819 2.661000 22 -82 3.402779 2.731785 23 -82 3.434223 2.893915 24 -82 3.469235 2.734531 25 -83 2.298532 2.298561 0 -83 2.529301 2.472127 1 -83 2.602234 2.474328 2 -83 2.640228 2.534583 3 -83 2.690868 2.489656 4 -83 2.737147 2.586535 5 -83 2.766578 2.536803 6 -83 2.813815 2.529727 7 -83 2.852240 2.639621 8 -83 2.880786 2.568094 9 -83 2.922216 2.533740 10 -83 2.958503 2.640162 11 -83 2.985544 2.654573 12 -83 3.023201 2.595852 13 -83 3.063110 2.664512 14 -83 3.090982 2.712980 15 -83 3.122245 2.601816 16 -83 3.160256 2.651116 17 -83 3.193153 2.814879 18 -83 3.222798 2.697180 19 -83 3.258054 2.618681 20 -83 3.292465 2.729648 21 -83 3.319811 2.817805 22 -83 3.353634 2.671481 23 -83 3.387262 2.629865 24 -83 3.417941 2.840234 25 -83 3.446186 2.804201 26 -83 3.482853 2.756410 27 -84 2.298483 2.298555 0 -84 2.525946 2.474832 1 -84 2.593875 2.460643 2 -84 2.634293 2.549999 3 -84 2.678154 2.489271 4 -84 2.726358 2.539667 5 -84 2.753354 2.580986 6 -84 2.794930 2.518878 7 -84 2.836102 2.557950 8 -84 2.862802 2.640551 9 -84 2.895847 2.532929 10 -84 2.935125 2.582458 11 -84 2.967136 2.716315 12 -84 2.994374 2.606625 13 -84 3.031684 2.567934 14 -84 3.065423 2.673443 15 -84 3.091370 2.748584 16 -84 3.124295 2.626245 17 -84 3.160302 2.604244 18 -84 3.188758 2.747607 19 -84 3.214355 2.714108 20 -84 3.248038 2.613900 21 -84 3.280785 2.652624 22 -84 3.307756 2.851676 23 -84 3.336760 2.761211 24 -84 3.371752 2.680828 25 -84 3.403798 2.777207 26 -84 3.429543 2.874729 27 -84 3.460841 2.706910 28 -84 3.491681 2.680186 29 -85 2.298520 2.298523 0 -85 2.522973 2.477406 1 -85 2.585357 2.452483 2 -85 2.629530 2.559748 3 -85 2.666294 2.489983 4 -85 2.713049 2.497271 5 -85 2.744030 2.619431 6 -85 2.776789 2.512312 7 -85 2.816139 2.516003 8 -85 2.849770 2.649601 9 -85 2.873004 2.578416 10 -85 2.911209 2.568667 11 -85 2.947319 2.596187 12 -85 2.971823 2.705417 13 -85 2.999982 2.582357 14 -85 3.036649 2.612086 15 -85 3.068583 2.666593 16 -85 3.090302 2.686988 17 -85 3.119460 2.597623 18 -85 3.154117 2.623155 19 -85 3.182799 2.720783 20 -85 3.205539 2.769956 21 -85 3.237624 2.686171 22 -85 3.271938 2.660354 23 -85 3.298658 2.784644 24 -85 3.322270 2.771268 25 -85 3.352585 2.639254 26 -85 3.383797 2.711291 27 -85 3.412775 2.929615 28 -85 3.438625 2.823039 29 -85 3.468558 2.678919 30 -85 3.499223 2.830439 31 -86 2.298493 2.298592 0 -86 2.520320 2.479769 1 -86 2.577021 2.449009 2 -86 2.625460 2.562764 3 -86 2.655263 2.490322 4 -86 2.698655 2.481109 5 -86 2.736559 2.616327 6 -86 2.759847 2.520933 7 -86 2.796648 2.522483 8 -86 2.834184 2.560392 9 -86 2.857375 2.675891 10 -86 2.887906 2.549774 11 -86 2.921588 2.552170 12 -86 2.954332 2.649768 13 -86 2.974933 2.682982 14 -86 3.005269 2.546836 15 -86 3.035756 2.576715 16 -86 3.066534 2.688776 17 -86 3.087342 2.731192 18 -86 3.115581 2.613956 19 -86 3.148803 2.668166 20 -86 3.178754 2.701267 21 -86 3.198963 2.750430 22 -86 3.225096 2.647486 23 -86 3.257360 2.659171 24 -86 3.286094 2.758048 25 -86 3.309639 2.888473 26 -86 3.336006 2.665631 27 -86 3.364534 2.619384 28 -86 3.393946 2.765096 29 -86 3.417820 2.859974 30 -86 3.440720 2.754631 31 -86 3.471415 2.686011 32 -86 3.498642 2.733176 33 -87 2.298512 2.298505 0 -87 2.517972 2.481944 1 -87 2.569121 2.448718 2 -87 2.621550 2.556298 3 -87 2.645020 2.493036 4 -87 2.684813 2.482816 5 -87 2.727419 2.552880 6 -87 2.746293 2.579424 7 -87 2.779345 2.532556 8 -87 2.814582 2.518417 9 -87 2.846751 2.668196 10 -87 2.865812 2.572871 11 -87 2.897425 2.561162 12 -87 2.929510 2.539300 13 -87 2.957860 2.672461 14 -87 2.975387 2.636617 15 -87 3.005785 2.602108 16 -87 3.036376 2.597382 17 -87 3.065997 2.703660 18 -87 3.084964 2.742322 19 -87 3.111653 2.573681 20 -87 3.139996 2.639831 21 -87 3.170183 2.689255 22 -87 3.191788 2.833171 23 -87 3.214353 2.658206 24 -87 3.243562 2.592408 25 -87 3.269548 2.652910 26 -87 3.295961 2.843974 27 -87 3.315595 2.758080 28 -87 3.341422 2.642099 29 -87 3.370473 2.689485 30 -87 3.396996 2.796229 31 -87 3.419466 2.969052 32 -87 3.444261 2.724659 33 -87 3.471107 2.657142 34 -87 3.498547 2.835510 35 -88 2.298505 2.298517 0 -88 2.515894 2.483911 1 -88 2.561764 2.450428 2 -88 2.617021 2.533789 3 -88 2.635957 2.507160 4 -88 2.672387 2.493327 5 -88 2.714151 2.492412 6 -88 2.738078 2.636472 7 -88 2.763467 2.528896 8 -88 2.795222 2.521968 9 -88 2.830750 2.532530 10 -88 2.851162 2.691297 11 -88 2.874685 2.545468 12 -88 2.903249 2.550856 13 -88 2.933711 2.555451 14 -88 2.959766 2.757832 15 -88 2.978451 2.612182 16 -88 3.006916 2.599785 17 -88 3.034946 2.567333 18 -88 3.062582 2.661287 19 -88 3.080155 2.789026 20 -88 3.105752 2.614121 21 -88 3.132161 2.595058 22 -88 3.158593 2.589406 23 -88 3.182355 2.794232 24 -88 3.199791 2.753409 25 -88 3.227126 2.627183 26 -88 3.252620 2.666143 27 -88 3.280574 2.735260 28 -88 3.301519 2.904574 29 -88 3.321967 2.702366 30 -88 3.348230 2.608488 31 -88 3.373300 2.724684 32 -88 3.400223 2.804389 33 -88 3.418514 2.878375 34 -88 3.440567 2.741156 35 -88 3.468811 2.744316 36 -88 3.495347 2.815363 37 -89 2.298496 2.298564 0 -89 2.514037 2.485730 1 -89 2.555048 2.453250 2 -89 2.610806 2.495162 3 -89 2.628965 2.537832 4 -89 2.661582 2.505761 5 -89 2.699268 2.474154 6 -89 2.731853 2.621051 7 -89 2.748571 2.539294 8 -89 2.778208 2.539876 9 -89 2.809362 2.492964 10 -89 2.840103 2.613756 11 -89 2.854858 2.631414 12 -89 2.881029 2.573913 13 -89 2.908553 2.564955 14 -89 2.939819 2.555772 15 -89 2.960069 2.757524 16 -89 2.978350 2.587452 17 -89 3.004416 2.608901 18 -89 3.031337 2.574933 19 -89 3.058290 2.583386 20 -89 3.074825 2.796227 21 -89 3.095170 2.629469 22 -89 3.121368 2.655429 23 -89 3.147586 2.612665 24 -89 3.173196 2.701294 25 -89 3.189924 2.865878 26 -89 3.212574 2.635235 27 -89 3.236314 2.624566 28 -89 3.260783 2.657923 29 -89 3.286641 2.789233 30 -89 3.303722 2.886998 31 -89 3.324855 2.649635 32 -89 3.350316 2.712657 33 -89 3.374658 2.621178 34 -89 3.397273 2.727618 35 -89 3.414693 2.940610 36 -89 3.435648 2.763393 37 -89 3.462009 2.673034 38 -89 3.484472 2.724081 39 -90 2.298506 2.298529 0 -90 2.512425 2.487313 1 -90 2.548946 2.456652 2 -90 2.602579 2.463065 3 -90 2.624378 2.565507 4 -90 2.652219 2.514292 5 -90 2.684779 2.471207 6 -90 2.722035 2.523644 7 -90 2.737867 2.621682 8 -90 2.763181 2.540840 9 -90 2.788832 2.506168 10 -90 2.821209 2.515974 11 -90 2.844769 2.707358 12 -90 2.860818 2.577505 13 -90 2.886681 2.581978 14 -90 2.911922 2.522275 15 -90 2.940931 2.565715 16 -90 2.959213 2.769217 17 -90 2.976737 2.577125 18 -90 3.000048 2.591100 19 -90 3.024046 2.593771 20 -90 3.052833 2.615488 21 -90 3.071146 2.826518 22 -90 3.087870 2.633547 23 -90 3.111790 2.645751 24 -90 3.135315 2.596702 25 -90 3.159523 2.602091 26 -90 3.181045 2.884891 27 -90 3.196562 2.720425 28 -90 3.219703 2.625400 29 -90 3.241428 2.627137 30 -90 3.265230 2.622694 31 -90 3.287709 2.757989 32 -90 3.302078 2.892054 33 -90 3.324662 2.708033 34 -90 3.347370 2.664598 35 -90 3.369774 2.694709 36 -90 3.394663 2.807074 37 -90 3.411773 2.966915 38 -90 3.429666 2.702740 39 -90 3.453589 2.703265 40 -90 3.474833 2.662759 41 -90 3.497816 2.813538 42 -91 2.298498 2.298561 0 -91 2.510970 2.488770 1 -91 2.543448 2.460289 2 -91 2.593368 2.447561 3 -91 2.621324 2.578748 4 -91 2.643783 2.515108 5 -91 2.671325 2.475552 6 -91 2.707560 2.478806 7 -91 2.732231 2.651017 8 -91 2.748450 2.525775 9 -91 2.771900 2.547323 10 -91 2.800761 2.505751 11 -91 2.831006 2.543831 12 -91 2.846924 2.712337 13 -91 2.865818 2.550230 14 -91 2.887666 2.579164 15 -91 2.913387 2.517658 16 -91 2.939936 2.557232 17 -91 2.957462 2.786661 18 -91 2.973730 2.619347 19 -91 2.997209 2.632365 20 -91 3.019383 2.557905 21 -91 3.045341 2.570423 22 -91 3.066012 2.768583 23 -91 3.078473 2.690528 24 -91 3.100346 2.651140 25 -91 3.122325 2.623604 26 -91 3.143957 2.539678 27 -91 3.167959 2.671091 28 -91 3.183420 2.893786 29 -91 3.200299 2.677200 30 -91 3.222689 2.700085 31 -91 3.244476 2.641786 32 -91 3.266956 2.642919 33 -91 3.289304 2.885185 34 -91 3.302461 2.791628 35 -91 3.321679 2.626112 36 -91 3.342616 2.717053 37 -91 3.364883 2.701359 38 -91 3.388377 2.744494 39 -91 3.406535 2.984986 40 -91 3.420855 2.689511 41 -91 3.441510 2.722833 42 -91 3.463543 2.712599 43 -91 3.483874 2.637630 44 -92 2.298489 2.298601 0 -92 2.509707 2.490049 1 -92 2.538528 2.463967 2 -92 2.584109 2.442339 3 -92 2.618877 2.579471 4 -92 2.635645 2.507593 5 -92 2.659356 2.489021 6 -92 2.692756 2.475934 7 -92 2.724816 2.548147 8 -92 2.736066 2.605089 9 -92 2.758617 2.568541 10 -92 2.781520 2.509081 11 -92 2.810194 2.501500 12 -92 2.836266 2.575381 13 -92 2.847642 2.679455 14 -92 2.868354 2.581619 15 -92 2.887936 2.566008 16 -92 2.913647 2.547588 17 -92 2.940052 2.568400 18 -92 2.956348 2.781737 19 -92 2.970308 2.579877 20 -92 2.991040 2.634576 21 -92 3.011376 2.565889 22 -92 3.035921 2.561095 23 -92 3.058287 2.616182 24 -92 3.070610 2.812231 25 -92 3.087228 2.647366 26 -92 3.108758 2.697162 27 -92 3.129492 2.602597 28 -92 3.153147 2.597481 29 -92 3.173733 2.742700 30 -92 3.185384 2.830160 31 -92 3.204096 2.652435 32 -92 3.223322 2.648133 33 -92 3.242892 2.678010 34 -92 3.267553 2.649842 35 -92 3.286921 2.783276 36 -92 3.298357 2.814000 37 -92 3.315813 2.645786 38 -92 3.335651 2.728837 39 -92 3.356139 2.685243 40 -92 3.377253 2.673791 41 -92 3.398854 2.919635 42 -92 3.411345 2.886047 43 -92 3.428642 2.668838 44 -92 3.448683 2.771091 45 -92 3.469330 2.762770 46 -92 3.491480 2.729726 47 -93 2.298518 2.298550 0 -93 2.508582 2.491194 1 -93 2.534129 2.467500 2 -93 2.575304 2.442243 3 -93 2.616086 2.559402 4 -93 2.627593 2.506619 5 -93 2.649415 2.511400 6 -93 2.679180 2.481999 7 -93 2.710455 2.473339 8 -93 2.730755 2.666235 9 -93 2.745901 2.540622 10 -93 2.764997 2.546417 11 -93 2.789898 2.499999 12 -93 2.815467 2.502574 13 -93 2.839561 2.668036 14 -93 2.849251 2.615482 15 -93 2.869561 2.620196 16 -93 2.889012 2.545609 17 -93 2.912561 2.519328 18 -93 2.935767 2.543779 19 -93 2.953959 2.785788 20 -93 2.965317 2.597531 21 -93 2.984495 2.635669 22 -93 3.002388 2.580912 23 -93 3.025507 2.593844 24 -93 3.049403 2.600757 25 -93 3.065923 2.819396 26 -93 3.076781 2.645116 27 -93 3.096242 2.659021 28 -93 3.113556 2.631736 29 -93 3.134696 2.576899 30 -93 3.156370 2.621688 31 -93 3.175435 2.818198 32 -93 3.185766 2.733706 33 -93 3.202308 2.612505 34 -93 3.220720 2.739480 35 -93 3.240495 2.652917 36 -93 3.262702 2.643270 37 -93 3.282531 2.750857 38 -93 3.294343 2.940236 39 -93 3.310168 2.673957 40 -93 3.328197 2.709279 41 -93 3.346926 2.748444 42 -93 3.367638 2.583449 43 -93 3.386920 2.686290 44 -93 3.402450 3.012162 45 -93 3.415133 2.826753 46 -93 3.434805 2.746254 47 -93 3.452697 2.723469 48 -93 3.471548 2.678995 49 -93 3.490773 2.615135 50 -94 2.298523 2.298559 0 -94 2.507588 2.492209 1 -94 2.530234 2.470775 2 -94 2.567178 2.444488 3 -94 2.610806 2.494556 4 -94 2.621340 2.550334 5 -94 2.641625 2.532500 6 -94 2.666909 2.485880 7 -94 2.694850 2.465281 8 -94 2.724688 2.559479 9 -94 2.733690 2.602580 10 -94 2.752563 2.578137 11 -94 2.771184 2.509226 12 -94 2.795515 2.519607 13 -94 2.821135 2.502599 14 -94 2.840763 2.728209 15 -94 2.851248 2.564676 16 -94 2.868607 2.609443 17 -94 2.886526 2.539287 18 -94 2.909207 2.540878 19 -94 2.931078 2.530543 20 -94 2.951255 2.750479 21 -94 2.960310 2.665850 22 -94 2.978948 2.662436 23 -94 2.995366 2.579478 24 -94 3.015042 2.546537 25 -94 3.036372 2.575582 26 -94 3.056819 2.613014 27 -94 3.067713 2.860534 28 -94 3.082552 2.620706 29 -94 3.099019 2.673741 30 -94 3.115783 2.588739 31 -94 3.136535 2.640309 32 -94 3.158644 2.642052 33 -94 3.175315 2.820067 34 -94 3.184480 2.751087 35 -94 3.202145 2.669004 36 -94 3.218017 2.701026 37 -94 3.236107 2.618981 38 -94 3.256449 2.622520 39 -94 3.275308 2.643643 40 -94 3.289454 2.986935 41 -94 3.301352 2.777458 42 -94 3.319500 2.650308 43 -94 3.334229 2.680537 44 -94 3.352055 2.655180 45 -94 3.372561 2.683974 46 -94 3.391603 2.777808 47 -94 3.403848 3.038107 48 -94 3.417415 2.725883 49 -94 3.434692 2.766115 50 -94 3.452397 2.791513 51 -94 3.469853 2.608853 52 -94 3.489365 2.743425 53 -95 2.298502 2.298533 0 -95 2.506703 2.493105 1 -95 2.526749 2.473915 2 -95 2.559732 2.448216 3 -95 2.601991 2.451261 4 -95 2.618314 2.584260 5 -95 2.635334 2.541324 6 -95 2.655544 2.486061 7 -95 2.680424 2.474072 8 -95 2.710352 2.471826 9 -95 2.728869 2.670487 10 -95 2.740576 2.539331 11 -95 2.756077 2.568175 12 -95 2.777915 2.521868 13 -95 2.799710 2.497671 14 -95 2.824120 2.493152 15 -95 2.840413 2.740700 16 -95 2.850766 2.573143 17 -95 2.866868 2.631590 18 -95 2.884486 2.541457 19 -95 2.905432 2.564055 20 -95 2.927032 2.517125 21 -95 2.947329 2.609179 22 -95 2.955438 2.752418 23 -95 2.970966 2.631955 24 -95 2.985773 2.636525 25 -95 3.003752 2.553049 26 -95 3.023325 2.578643 27 -95 3.042947 2.566009 28 -95 3.061754 2.795596 29 -95 3.070012 2.752191 30 -95 3.086989 2.669814 31 -95 3.100816 2.625495 32 -95 3.117917 2.597300 33 -95 3.137576 2.596440 34 -95 3.156009 2.599317 35 -95 3.173433 2.796500 36 -95 3.181515 2.790989 37 -95 3.197550 2.677904 38 -95 3.212307 2.706355 39 -95 3.228116 2.588115 40 -95 3.246608 2.679260 41 -95 3.267241 2.690136 42 -95 3.284050 2.785836 43 -95 3.292761 2.904508 44 -95 3.308028 2.680173 45 -95 3.323352 2.757927 46 -95 3.338885 2.676024 47 -95 3.357200 2.634583 48 -95 3.375453 2.689436 49 -95 3.393307 2.754435 50 -95 3.403034 2.957047 51 -95 3.415226 2.753616 52 -95 3.433423 2.840270 53 -95 3.448731 2.729332 54 -95 3.465432 2.607066 55 -95 3.483065 2.655788 56 -96 2.298497 2.298572 0 -96 2.505931 2.493897 1 -96 2.523676 2.476665 2 -96 2.553027 2.452318 3 -96 2.592140 2.438880 4 -96 2.616576 2.590820 5 -96 2.629405 2.531362 6 -96 2.645080 2.492497 7 -96 2.667927 2.491088 8 -96 2.694748 2.465832 9 -96 2.721354 2.512077 10 -96 2.730165 2.650896 11 -96 2.745828 2.596401 12 -96 2.761014 2.515619 13 -96 2.780926 2.524851 14 -96 2.801852 2.490331 15 -96 2.825601 2.514787 16 -96 2.840152 2.757267 17 -96 2.850657 2.573077 18 -96 2.864731 2.635419 19 -96 2.881844 2.527201 20 -96 2.899577 2.545060 21 -96 2.919243 2.525377 22 -96 2.940581 2.547051 23 -96 2.952276 2.826352 24 -96 2.963051 2.609986 25 -96 2.977550 2.691984 26 -96 2.993245 2.584502 27 -96 3.011981 2.584494 28 -96 3.029089 2.523352 29 -96 3.048083 2.570331 30 -96 3.062968 2.879793 31 -96 3.071565 2.646902 32 -96 3.086234 2.684736 33 -96 3.099661 2.654009 34 -96 3.116833 2.583929 35 -96 3.134243 2.618812 36 -96 3.152234 2.613699 37 -96 3.170935 2.779221 38 -96 3.178881 2.880226 39 -96 3.192906 2.623906 40 -96 3.205689 2.720296 41 -96 3.220826 2.660964 42 -96 3.238170 2.607784 43 -96 3.255388 2.643016 44 -96 3.272704 2.628954 45 -96 3.286630 2.973937 46 -96 3.295030 2.739537 47 -96 3.310342 2.734844 48 -96 3.324067 2.749942 49 -96 3.338960 2.586052 50 -96 3.355418 2.709211 51 -96 3.374693 2.736919 52 -96 3.391343 2.743419 53 -96 3.401340 3.069582 54 -96 3.413236 2.709346 55 -96 3.428392 2.783859 56 -96 3.442098 2.752390 57 -96 3.458175 2.676756 58 -96 3.475752 2.688699 59 -96 3.492005 2.683974 60 -97 2.298472 2.298592 0 -97 2.505240 2.494617 1 -97 2.520953 2.479185 2 -97 2.547040 2.456583 3 -97 2.582520 2.437055 4 -97 2.614747 2.574010 5 -97 2.622664 2.509580 6 -97 2.636484 2.522793 7 -97 2.657404 2.506417 8 -97 2.680202 2.468229 9 -97 2.705711 2.464587 10 -97 2.726789 2.660439 11 -97 2.734457 2.538149 12 -97 2.747589 2.591966 13 -97 2.764728 2.525340 14 -97 2.782440 2.523044 15 -97 2.804342 2.495714 16 -97 2.825753 2.498062 17 -97 2.839403 2.758975 18 -97 2.848690 2.559149 19 -97 2.861100 2.643750 20 -97 2.877082 2.555053 21 -97 2.894106 2.565370 22 -97 2.912365 2.526517 23 -97 2.932951 2.538848 24 -97 2.949278 2.732013 25 -97 2.955526 2.650572 26 -97 2.969471 2.656481 27 -97 2.981160 2.616244 28 -97 2.998555 2.595848 29 -97 3.014482 2.567828 30 -97 3.031933 2.554542 31 -97 3.050997 2.586856 32 -97 3.062837 2.903753 33 -97 3.071799 2.663923 34 -97 3.085932 2.739511 35 -97 3.098603 2.604518 36 -97 3.114239 2.563018 37 -97 3.129598 2.635185 38 -97 3.147606 2.585598 39 -97 3.164447 2.597026 40 -97 3.175021 2.978334 41 -97 3.184816 2.677022 42 -97 3.198293 2.731488 43 -97 3.210623 2.685677 44 -97 3.226503 2.621621 45 -97 3.242614 2.674054 46 -97 3.259377 2.671670 47 -97 3.277609 2.677160 48 -97 3.287200 2.983582 49 -97 3.296091 2.651007 50 -97 3.310297 2.801574 51 -97 3.323087 2.721992 52 -97 3.337716 2.652558 53 -97 3.354249 2.661168 54 -97 3.369802 2.668446 55 -97 3.386159 2.665399 56 -97 3.398145 3.069360 57 -97 3.406595 2.755260 58 -97 3.420842 2.776663 59 -97 3.433827 2.808526 60 -97 3.447529 2.592396 61 -97 3.462504 2.745549 62 -97 3.480558 2.776880 63 -97 3.496519 2.738573 64 -98 2.298494 2.298617 0 -98 2.504632 2.495256 1 -98 2.518524 2.481509 2 -98 2.541657 2.460788 3 -98 2.573570 2.439225 4 -98 2.609635 2.479253 5 -98 2.617178 2.568367 6 -98 2.630605 2.553106 7 -98 2.648233 2.509519 8 -98 2.666916 2.474132 9 -98 2.690337 2.469492 10 -98 2.715499 2.471496 11 -98 2.727498 2.685004 12 -98 2.738513 2.579315 13 -98 2.749571 2.549645 14 -98 2.767010 2.550653 15 -98 2.783868 2.494330 16 -98 2.803659 2.496249 17 -98 2.823808 2.497856 18 -98 2.838500 2.766714 19 -98 2.846669 2.578267 20 -98 2.858177 2.652919 21 -98 2.872624 2.553268 22 -98 2.888048 2.568720 23 -98 2.904261 2.501861 24 -98 2.922409 2.533993 25 -98 2.941048 2.554738 26 -98 2.950999 2.850434 27 -98 2.960930 2.601744 28 -98 2.971919 2.701741 29 -98 2.986202 2.596394 30 -98 3.001569 2.606461 31 -98 3.016797 2.547855 32 -98 3.033640 2.515820 33 -98 3.050114 2.586330 34 -98 3.062116 2.922481 35 -98 3.070282 2.644488 36 -98 3.082727 2.724494 37 -98 3.093775 2.617727 38 -98 3.109501 2.641211 39 -98 3.124057 2.617259 40 -98 3.139984 2.603647 41 -98 3.157596 2.605274 42 -98 3.171700 2.835748 43 -98 3.177820 2.783462 44 -98 3.190179 2.641123 45 -98 3.200725 2.750703 46 -98 3.214513 2.669955 47 -98 3.230384 2.650684 48 -98 3.243894 2.607154 49 -98 3.260162 2.627597 50 -98 3.276009 2.630382 51 -98 3.285853 3.045526 52 -98 3.294596 2.720306 53 -98 3.307435 2.767044 54 -98 3.318726 2.761349 55 -98 3.333150 2.676355 56 -98 3.348724 2.737817 57 -98 3.364199 2.696053 58 -98 3.379402 2.542616 59 -98 3.392834 2.820142 60 -98 3.400080 3.055243 61 -98 3.412608 2.727229 62 -98 3.424335 2.812905 63 -98 3.436663 2.754382 64 -98 3.451079 2.671474 65 -98 3.466248 2.706311 66 -98 3.480705 2.695013 67 -98 3.496109 2.685673 68 -99 2.298515 2.298569 0 -99 2.504090 2.495784 1 -99 2.516390 2.483591 2 -99 2.536891 2.464747 3 -99 2.565393 2.443163 4 -99 2.599922 2.440075 5 -99 2.615359 2.595651 6 -99 2.626204 2.558132 7 -99 2.639356 2.499207 8 -99 2.655326 2.493633 9 -99 2.676698 2.481662 10 -99 2.699119 2.457584 11 -99 2.722142 2.523482 12 -99 2.728104 2.648580 13 -99 2.740123 2.622332 14 -99 2.752291 2.519618 15 -99 2.766706 2.548061 16 -99 2.783934 2.504236 17 -99 2.802391 2.505761 18 -99 2.822348 2.485199 19 -99 2.837432 2.738325 20 -99 2.843330 2.575170 21 -99 2.854424 2.665223 22 -99 2.866442 2.550076 23 -99 2.880860 2.602447 24 -99 2.896423 2.530314 25 -99 2.913345 2.534110 26 -99 2.930623 2.526240 27 -99 2.947211 2.659455 28 -99 2.952089 2.720862 29 -99 2.963717 2.669138 30 -99 2.973256 2.632741 31 -99 2.987598 2.608025 32 -99 3.001307 2.616578 33 -99 3.016508 2.532303 34 -99 3.032451 2.577064 35 -99 3.049263 2.578581 36 -99 3.061138 2.906048 37 -99 3.067626 2.638631 38 -99 3.079401 2.756984 39 -99 3.089709 2.600915 40 -99 3.102925 2.602633 41 -99 3.116284 2.651555 42 -99 3.131285 2.603098 43 -99 3.147351 2.556107 44 -99 3.161627 2.604300 45 -99 3.172962 2.996697 46 -99 3.180131 2.695680 47 -99 3.192091 2.767148 48 -99 3.201949 2.704823 49 -99 3.216576 2.674056 50 -99 3.229906 2.670243 51 -99 3.244039 2.619349 52 -99 3.258617 2.544566 53 -99 3.272978 2.628519 54 -99 3.284186 3.023726 55 -99 3.290946 2.798956 56 -99 3.303985 2.784491 57 -99 3.313551 2.710902 58 -99 3.326015 2.671623 59 -99 3.340732 2.711065 60 -99 3.353448 2.640245 61 -99 3.368278 2.657306 62 -99 3.383107 2.645491 63 -99 3.395152 3.026779 64 -99 3.401450 2.859331 65 -99 3.413646 2.786802 66 -99 3.424723 2.882987 67 -99 3.437109 2.742530 68 -99 3.451811 2.694031 69 -99 3.464318 2.607137 70 -99 3.477051 2.704039 71 -99 3.493579 2.724321 72 +100 96.1255 92.4011 88.8211 85.3797 82.0717 78.8918 75.8352 72.897 70.0726 67.3576 64.7479 62.2392 59.8278 57.5098 55.2816 53.1397 51.0808 49.1017 47.1992 45.3705 43.6126 41.9229 40.2986 38.7372 37.2364 35.7936 34.4068 33.0737 31.7923 30.5605 29.3764 28.2383 27.1442 26.0925 25.0815 24.1098 23.1756 22.2777 21.4145 20.5848 19.7873 19.0206 18.2837 17.5753 16.8943 16.2398 15.6106 15.0057 14.4243 13.8655 13.3282 12.8118 12.3155 11.8383 11.3796 10.9387 10.5149 10.1075 9.71589 9.33945 8.97759 8.62976 8.2954 7.974 7.66504 7.36806 7.08259 6.80818 6.54439 6.29083 6.0471 5.8128 5.58759 5.3711 5.16299 4.96295 4.77066 4.58583 4.40815 4.23736 4.07318 3.91537 3.76367 3.61784 3.47767 3.34293 3.21341 3.0889 2.96923 2.85418 2.7436 2.6373 2.53512 2.43689 2.34248 2.25172 2.16448 2.08061 2 +0 4.35647 3.66126 0 +1 4.32098 3.56341 0 +2 4.28215 3.45288 0 +3 4.24024 3.33302 0 +4 4.19161 3.20323 0 +5 4.13755 3.07014 0 +6 4.07747 2.93385 0 +7 4.01132 2.80091 0 +8 3.94048 2.67593 0 +9 3.86495 2.56384 0 +10 3.78579 2.46893 0 +11 3.70579 2.39045 0 +12 3.6259 2.33065 0 +12 5.39017 4.61213 1 +13 3.54716 2.28662 0 +13 5.33735 4.12257 1 +14 3.4721 2.25646 0 +14 5.27195 3.98885 1 +15 3.39943 2.23926 0 +15 5.2057 3.94629 1 +16 3.33266 2.23044 0 +16 5.14141 3.93042 1 +17 3.26992 2.22976 0 +17 5.08008 3.92006 1 +18 3.21219 2.23581 0 +18 5.02197 3.90384 1 +19 3.15898 2.24746 0 +19 4.96648 3.87978 1 +20 3.11064 2.2633 0 +20 4.91193 3.84648 1 +21 3.06693 2.28278 0 +21 4.8588 3.80381 1 +22 3.02727 2.30536 0 +22 4.80545 3.75246 1 +23 2.99182 2.33011 0 +23 4.75195 3.69496 1 +24 2.96008 2.35631 0 +24 4.69793 3.63377 1 +24 5.39995 5.30923 2 +25 2.93186 2.38361 0 +25 4.64317 3.57119 1 +25 5.38964 5.02489 2 +26 2.90668 2.4114 0 +26 4.58794 3.51069 1 +26 5.37135 4.89769 2 +27 2.88454 2.43902 0 +27 4.53211 3.45501 1 +27 5.34938 4.82165 2 +28 2.865 2.46621 0 +28 4.47626 3.40612 1 +28 5.32536 4.76429 2 +29 2.84782 2.49263 0 +29 4.42114 3.3662 1 +29 5.29987 4.71312 2 +30 2.83284 2.51789 0 +30 4.36698 3.33571 1 +30 5.27315 4.66093 2 +31 2.81981 2.54177 0 +31 4.31456 3.31351 1 +31 5.24507 4.60358 2 +32 2.80846 2.56443 0 +32 4.26401 3.29879 1 +32 5.21523 4.53809 2 +33 2.79856 2.58567 0 +33 4.21603 3.28861 1 +33 5.18344 4.46252 2 +34 2.79014 2.60505 0 +34 4.17021 3.28129 1 +34 5.1489 4.37541 2 +35 2.78287 2.62295 0 +35 4.12667 3.2739 1 +35 5.11128 4.27614 2 +36 2.77669 2.63919 0 +36 4.08508 3.26393 1 +36 5.06987 4.16331 2 +37 2.77139 2.65399 0 +37 4.04523 3.24843 1 +37 5.02385 4.03493 2 +38 2.76695 2.66722 0 +38 4.00649 3.22476 1 +38 4.97213 3.88762 2 +38 5.39292 4.97312 3 +39 2.76319 2.67909 0 +39 3.96825 3.19027 1 +39 4.91366 3.71843 2 +39 5.37066 4.80953 3 +40 2.76004 2.68959 0 +40 3.92973 3.14246 1 +40 4.84674 3.5278 2 +40 5.34503 4.75724 3 +41 2.75746 2.69881 0 +41 3.89011 3.07913 1 +41 4.76996 3.32383 2 +41 5.31886 4.72901 3 +42 2.75531 2.70687 0 +42 3.84847 3.00034 1 +42 4.68294 3.12892 2 +42 5.2926 4.69956 3 +43 2.75354 2.71384 0 +43 3.80386 2.90862 1 +43 4.58741 2.97515 2 +43 5.26587 4.65918 3 +44 2.7521 2.71986 0 +44 3.75583 2.811 1 +44 4.48872 2.89082 2 +44 5.23806 4.59978 3 +45 2.75096 2.72494 0 +45 3.70426 2.71852 1 +45 4.39368 2.88318 2 +45 5.20804 4.51437 3 +46 2.75002 2.72932 0 +46 3.65009 2.64203 1 +46 4.30819 2.93551 2 +46 5.17424 4.39421 3 +47 2.74928 2.73296 0 +47 3.59479 2.58847 1 +47 4.23479 3.02036 2 +47 5.13464 4.23052 3 +47 5.39677 4.25488 4 +48 2.74871 2.73589 0 +48 3.54022 2.55899 1 +48 4.17314 3.11011 2 +48 5.08655 4.02031 3 +48 5.32935 4.06718 4 +49 2.74825 2.73838 0 +49 3.48797 2.55002 1 +49 4.12127 3.18633 2 +49 5.0271 3.77544 3 +49 5.26821 4.13321 4 +50 2.74791 2.74033 0 +50 3.43911 2.55641 1 +50 4.07674 3.23882 2 +50 4.95456 3.52613 3 +50 5.21405 4.16836 4 +51 2.74766 2.74194 0 +51 3.39422 2.57306 1 +51 4.03717 3.26382 2 +51 4.86911 3.30459 3 +51 5.16382 4.15738 4 +51 5.38566 4.38947 5 +52 2.74745 2.74316 0 +52 3.3535 2.59602 1 +52 4.00048 3.2593 2 +52 4.77349 3.12448 3 +52 5.11426 4.09468 4 +52 5.33396 4.29476 5 +53 2.7473 2.74418 0 +53 3.31684 2.6224 1 +53 3.96465 3.22412 2 +53 4.67123 2.98394 3 +53 5.06209 3.97918 4 +53 5.28561 4.33683 5 +54 2.7472 2.74492 0 +54 3.28399 2.65011 1 +54 3.92787 3.15747 2 +54 4.56595 2.88132 3 +54 5.00442 3.82214 4 +54 5.24221 4.36897 5 +55 2.74713 2.74548 0 +55 3.25464 2.678 1 +55 3.88831 3.06082 2 +55 4.46166 2.82344 3 +55 4.9395 3.65625 4 +55 5.20239 4.3815 5 +56 2.74707 2.74595 0 +56 3.22848 2.70501 1 +56 3.84433 2.94167 2 +56 4.36298 2.82045 3 +56 4.86823 3.5246 4 +56 5.16466 4.37191 5 +57 2.74704 2.74625 0 +57 3.20517 2.73082 1 +57 3.79493 2.81629 2 +57 4.27443 2.87298 3 +57 4.79429 3.44871 4 +57 5.12776 4.32996 5 +57 5.39815 4.89108 6 +58 2.747 2.74649 0 +58 3.18438 2.75509 1 +58 3.74046 2.70598 2 +58 4.19862 2.96274 3 +58 4.72163 3.42025 4 +58 5.08908 4.23067 5 +58 5.35853 4.41449 6 +59 2.74699 2.74663 0 +59 3.16587 2.77769 1 +59 3.6827 2.62603 2 +59 4.13547 3.05857 3 +59 4.65278 3.41512 4 +59 5.04427 4.03843 5 +59 5.31352 4.389 6 +60 2.74697 2.74673 0 +60 3.14935 2.79851 1 +60 3.62423 2.57963 2 +60 4.08249 3.13113 3 +60 4.5882 3.40853 4 +60 4.9868 3.72009 5 +60 5.27004 4.36714 6 +61 2.74697 2.74681 0 +61 3.13459 2.81766 1 +61 3.56741 2.56101 2 +61 4.03626 3.1631 3 +61 4.52658 3.37629 4 +61 4.90719 3.31833 5 +61 5.22691 4.32034 6 +62 2.74697 2.74685 0 +62 3.12141 2.83514 1 +62 3.51384 2.56184 2 +62 3.99331 3.14774 3 +62 4.46507 3.29257 4 +62 4.80292 3.01147 5 +62 5.18311 4.26128 6 +62 5.326 3.73586 7 +63 2.74696 2.7469 0 +63 3.10963 2.85108 1 +63 3.46438 2.57502 2 +63 3.95045 3.08436 3 +63 4.3993 3.1435 4 +63 4.68937 2.94346 5 +63 5.13781 4.16899 6 +63 5.24874 3.97569 7 +64 2.74695 2.74694 0 +64 3.09907 2.86551 1 +64 3.41931 2.59531 2 +64 3.90475 2.97851 3 +64 4.32568 2.97869 4 +64 4.58973 3.09432 5 +64 5.08638 3.96006 6 +64 5.19038 4.14854 7 +65 2.74696 2.74698 0 +65 3.08963 2.87855 1 +65 3.37853 2.61941 2 +65 3.85391 2.84771 3 +65 4.24722 2.90001 4 +65 4.51451 3.32686 5 +65 5.02052 3.63733 6 +65 5.14427 4.27113 7 +65 5.3448 4.01992 8 +66 2.74695 2.74694 0 +66 3.08112 2.89039 1 +66 3.34182 2.64507 2 +66 3.79724 2.7215 3 +66 4.17269 2.92722 4 +66 4.4596 3.51196 5 +66 4.93481 3.30989 6 +66 5.10474 4.27857 7 +66 5.27678 4.01112 8 +67 2.74694 2.74695 0 +67 3.07352 2.90107 1 +67 3.30884 2.67101 2 +67 3.73614 2.62675 3 +67 4.10759 2.99673 4 +67 4.41706 3.61876 5 +67 4.82974 3.0242 6 +67 5.06278 4.10093 7 +67 5.21384 4.04703 8 +68 2.74695 2.74697 0 +68 3.06667 2.91069 1 +68 3.27926 2.69634 2 +68 3.67362 2.57207 3 +68 4.0514 3.04586 4 +68 4.38088 3.65003 5 +68 4.70889 2.80558 6 +68 5.00737 3.77344 7 +68 5.15976 4.17406 8 +69 2.74695 2.74699 0 +69 3.0605 2.91937 1 +69 3.25271 2.72054 2 +69 3.61264 2.55061 3 +69 4.00042 3.04107 4 +69 4.34579 3.57729 5 +69 4.58196 2.71631 6 +69 4.93467 3.51236 7 +69 5.11731 4.30939 8 +69 5.35873 4.1436 9 +70 2.74695 2.747 0 +70 3.05495 2.92719 1 +70 3.22887 2.74349 2 +70 3.5552 2.55145 3 +70 3.95022 2.97472 4 +70 4.3032 3.31272 5 +70 4.46823 2.86682 6 +70 4.8535 3.40004 7 +70 5.08045 4.27535 8 +70 5.29599 4.07526 9 +71 2.74696 2.74698 0 +71 3.04994 2.93422 1 +71 3.20746 2.76498 2 +71 3.50229 2.56554 3 +71 3.89691 2.85962 4 +71 4.24093 2.96198 5 +71 4.39085 3.31186 6 +71 4.77228 3.34773 7 +71 5.03609 3.95074 8 +71 5.23283 3.99859 9 +71 5.36321 3.79767 10 +72 2.74696 2.74696 0 +72 3.04542 2.94054 1 +72 3.18822 2.78491 2 +72 3.45415 2.58688 3 +72 3.83813 2.72957 4 +72 4.16574 2.86789 5 +72 4.34856 3.66845 6 +72 4.6921 3.26468 7 +72 4.96272 3.34551 8 +72 5.17088 4.03503 9 +72 5.28024 3.8525 10 +73 2.74696 2.74696 0 +73 3.04134 2.94625 1 +73 3.1709 2.80337 2 +73 3.41069 2.61171 3 +73 3.7744 2.62462 4 +73 4.0956 2.91687 5 +73 4.32194 3.8093 6 +73 4.60728 3.07841 7 +73 4.85099 2.96784 8 +73 5.12045 4.1969 9 +73 5.20868 3.93892 10 +73 5.35899 4.08843 11 +74 2.74694 2.74698 0 +74 3.03766 2.95137 1 +74 3.15531 2.82037 2 +74 3.37159 2.63792 3 +74 3.70869 2.56311 4 +74 4.0342 2.95555 5 +74 4.30025 3.81752 6 +74 4.5087 2.82409 7 +74 4.73527 3.04098 8 +74 5.07432 4.01176 9 +74 5.14773 4.06756 10 +74 5.2965 4.11712 11 +75 2.74695 2.74697 0 +75 3.03431 2.95601 1 +75 3.14123 2.836 2 +75 3.33644 2.66411 3 +75 3.6444 2.53945 4 +75 3.9774 2.92783 5 +75 4.27549 3.60818 6 +75 4.40161 2.78182 7 +75 4.64576 3.28421 8 +75 5.00557 3.49212 9 +75 5.10308 4.3127 10 +75 5.23671 4.04847 11 +76 2.74697 2.74696 0 +76 3.03128 2.96016 1 +76 3.12853 2.85036 2 +76 3.3049 2.68957 3 +76 3.58391 2.54058 4 +76 3.91985 2.83274 5 +76 4.22709 2.99673 6 +76 4.32308 3.33509 7 +76 4.57876 3.43749 8 +76 4.90395 3.06099 9 +76 5.06636 4.20479 10 +76 5.17452 3.96696 11 +76 5.38384 4.13167 12 +77 2.74697 2.74696 0 +77 3.02854 2.9639 1 +77 3.11706 2.86346 2 +77 3.27657 2.71385 3 +77 3.5283 2.55579 4 +77 3.85777 2.70803 5 +77 4.14991 2.80555 6 +77 4.29103 3.82564 7 +77 4.5218 3.44575 8 +77 4.77504 2.75619 9 +77 5.0118 3.69829 10 +77 5.11914 4.18198 11 +77 5.31677 4.04791 12 +77 5.39779 3.94148 13 +78 2.74696 2.74696 0 +78 3.02606 2.96727 1 +78 3.10668 2.87545 2 +78 3.25109 2.73675 3 +78 3.4778 2.57833 4 +78 3.79101 2.60452 5 +78 4.07602 2.85529 6 +78 4.27433 3.93765 7 +78 4.462 3.22766 8 +78 4.63807 2.72799 9 +78 4.93079 3.40599 10 +78 5.08157 4.34813 11 +78 5.2512 3.96646 12 +78 5.31093 3.91078 13 +79 2.74696 2.74698 0 +79 3.0238 2.97033 1 +79 3.09728 2.88642 2 +79 3.22818 2.75812 3 +79 3.4323 2.60419 4 +79 3.72261 2.54659 5 +79 4.01093 2.87822 6 +79 4.25947 3.86586 7 +79 4.38065 2.83956 8 +79 4.53252 3.13268 9 +79 4.84246 3.30634 10 +79 5.04088 3.95362 11 +79 5.18028 3.82497 12 +79 5.2457 4.10085 13 +79 5.39128 3.89683 14 +80 2.74694 2.74697 0 +80 3.02175 2.97307 1 +80 3.08876 2.8964 2 +80 3.20754 2.778 3 +80 3.39142 2.63113 4 +80 3.65619 2.5276 5 +80 3.94901 2.82018 6 +80 4.22903 3.17687 7 +80 4.2946 3.16453 8 +80 4.47126 3.51735 9 +80 4.75119 3.14622 10 +80 4.95715 3.14195 11 +80 5.1181 4.1407 12 +80 5.19005 4.08588 13 +80 5.30621 3.88662 14 +81 2.74696 2.74695 0 +81 3.01988 2.97554 1 +81 3.08104 2.90551 2 +81 3.18891 2.79644 3 +81 3.35471 2.65789 4 +81 3.5941 2.53282 5 +81 3.88457 2.70722 6 +81 4.15223 2.74604 7 +81 4.26302 3.90278 8 +81 4.42894 3.61577 9 +81 4.64531 2.82909 10 +81 4.83488 2.98305 11 +81 5.07717 4.18771 12 +81 5.13361 4.03384 13 +81 5.23974 4.08869 14 +82 2.74695 2.74697 0 +82 3.01818 2.97779 1 +82 3.07402 2.91383 2 +82 3.17209 2.81343 3 +82 3.32176 2.68375 4 +82 3.53732 2.55106 5 +82 3.81572 2.60056 6 +82 4.07298 2.79362 7 +82 4.25118 4.00939 8 +82 4.38666 3.40788 9 +82 4.52168 2.70232 10 +82 4.73247 3.23311 11 +82 5.01377 3.46759 12 +82 5.08911 4.36157 13 +82 5.18443 4.0863 14 +82 5.36232 3.69856 15 +83 2.74696 2.74697 0 +83 3.01664 2.97981 1 +83 3.06766 2.92138 2 +83 3.15688 2.82908 3 +83 3.29217 2.7083 4 +83 3.48598 2.57561 5 +83 3.74498 2.53836 6 +83 4.00338 2.81521 7 +83 4.23956 3.86282 8 +83 4.31775 2.86248 9 +83 4.42769 3.26188 10 +83 4.65561 3.36885 11 +83 4.90327 2.92804 12 +83 5.05369 4.10224 13 +83 5.12716 4.01482 14 +83 5.271 3.78869 15 +83 5.35909 3.73835 16 +84 2.74696 2.74697 0 +84 3.01522 2.98164 1 +84 3.06187 2.92826 2 +84 3.14313 2.84347 3 +84 3.26555 2.7314 4 +84 3.43982 2.60274 5 +84 3.67618 2.51811 6 +84 3.93691 2.74921 7 +84 4.19388 2.79556 8 +84 4.25384 3.69824 9 +84 4.38394 3.68926 10 +84 4.58514 3.24252 11 +84 4.76077 2.68135 12 +84 4.98489 3.45983 13 +84 5.08385 4.38549 14 +84 5.2029 4.06044 15 +84 5.2731 3.80735 16 +85 2.74694 2.74698 0 +85 3.01394 2.98329 1 +85 3.0566 2.93454 2 +85 3.13066 2.85667 3 +85 3.24159 2.75298 4 +85 3.39839 2.63049 5 +85 3.61192 2.5238 6 +85 3.86777 2.63924 7 +85 4.10694 2.71259 8 +85 4.24072 4.04369 9 +85 4.35383 3.69392 10 +85 4.49485 2.79808 11 +85 4.63389 3.00463 12 +85 4.89299 3.28708 13 +85 5.04841 4.04303 14 +85 5.14478 3.95032 15 +85 5.20006 3.98196 16 +85 5.32486 3.84604 17 +86 2.74696 2.74698 0 +86 3.01278 2.98478 1 +86 3.0518 2.94025 2 +86 3.11936 2.86877 3 +86 3.22 2.77299 4 +86 3.36126 2.65764 5 +86 3.55327 2.54303 6 +86 3.79538 2.55314 7 +86 4.02936 2.76571 8 +86 4.23275 4.00339 9 +86 4.31044 3.09804 10 +86 4.39073 3.00161 11 +86 4.5584 3.43232 12 +86 4.79387 3.05962 13 +86 4.96132 3.05905 14 +86 5.09356 4.31767 15 +86 5.14659 4.14251 16 +86 5.24546 3.84998 17 +87 2.74695 2.74698 0 +87 3.01172 2.98613 1 +87 3.04744 2.94543 2 +87 3.10909 2.87988 3 +87 3.20049 2.79153 4 +87 3.32792 2.6837 5 +87 3.50032 2.56859 6 +87 3.72322 2.51433 7 +87 3.95863 2.73375 8 +87 4.20011 2.8372 9 +87 4.24302 3.61719 10 +87 4.34311 3.7321 11 +87 4.50434 3.46354 12 +87 4.67122 2.6856 13 +87 4.83836 3.0653 14 +87 5.05563 3.95248 15 +87 5.09728 4.20788 16 +87 5.17902 4.0434 17 +87 5.33289 3.72444 18 +87 5.38286 3.82261 19 +88 2.74695 2.74698 0 +88 3.01074 2.98737 1 +88 3.04345 2.95017 2 +88 3.09977 2.89005 3 +88 3.18287 2.80862 4 +88 3.29798 2.70832 5 +88 3.45278 2.59659 6 +88 3.6548 2.51064 7 +88 3.88728 2.6354 8 +88 4.10977 2.66629 9 +88 4.23113 4.07858 10 +88 4.31917 3.79757 11 +88 4.43834 2.96357 12 +88 4.54342 2.89609 13 +88 4.74402 3.29625 14 +88 4.96542 3.07443 15 +88 5.06548 4.37104 16 +88 5.12458 4.03124 17 +88 5.23661 3.6091 18 +88 5.30538 3.98441 19 +89 2.74691 2.74699 0 +89 3.00985 2.98848 1 +89 3.03982 2.95448 2 +89 3.09129 2.89934 3 +89 3.1669 2.8244 4 +89 3.27105 2.73137 5 +89 3.41017 2.62499 6 +89 3.59191 2.52599 7 +89 3.81307 2.54773 8 +89 4.02822 2.72288 9 +89 4.2247 4.00926 10 +89 4.28241 3.09386 11 +89 4.3445 3.07339 12 +89 4.47398 3.52143 13 +89 4.66402 3.21098 14 +89 4.82415 2.68071 15 +89 5.00776 3.49418 16 +89 5.07965 4.4196 17 +89 5.16358 4.08147 18 +89 5.23577 3.88151 19 +89 5.33654 3.93033 20 +90 2.74694 2.74695 0 +90 3.00904 2.98949 1 +90 3.03649 2.95843 2 +90 3.08356 2.90785 3 +90 3.15245 2.83887 4 +90 3.2468 2.75282 5 +90 3.372 2.65269 6 +90 3.53502 2.55038 7 +90 3.73902 2.50687 8 +90 3.95412 2.69128 9 +90 4.17723 2.64903 10 +90 4.22935 3.94551 11 +90 4.30749 3.84683 12 +90 4.43134 3.55844 13 +90 4.56275 2.72492 14 +90 4.69044 3.01302 15 +90 4.91313 3.24863 16 +90 5.04584 3.95865 17 +90 5.113 4.08033 18 +90 5.1642 3.94167 19 +90 5.26687 3.96274 20 +90 5.39856 3.73644 21 +91 2.74696 2.74697 0 +91 3.00829 2.9904 1 +91 3.03348 2.96199 2 +91 3.07654 2.91562 3 +91 3.13935 2.85221 4 +91 3.22492 2.77273 5 +91 3.33775 2.67917 6 +91 3.48393 2.5785 7 +91 3.66879 2.50296 8 +91 3.87975 2.59765 9 +91 4.08377 2.65062 10 +91 4.22304 4.10902 11 +91 4.28846 3.79008 12 +91 4.37014 2.87976 13 +91 4.45218 3.10381 14 +91 4.61128 3.40485 15 +91 4.80441 2.90863 16 +91 4.94486 2.97298 17 +91 5.07567 4.47781 18 +91 5.11314 4.1588 19 +91 5.19473 3.83492 20 +91 5.29824 3.85552 21 +91 5.3772 3.67826 22 +92 2.74696 2.74697 0 +92 3.00761 2.99125 1 +92 3.03071 2.96525 2 +92 3.07013 2.92274 3 +92 3.12744 2.86445 4 +92 3.20515 2.79113 5 +92 3.30701 2.70411 6 +92 3.43815 2.60761 7 +92 3.6043 2.51896 8 +92 3.80344 2.52317 9 +92 4.00228 2.68801 10 +92 4.21313 3.47019 11 +92 4.23826 3.02019 12 +92 4.29745 3.62913 13 +92 4.40385 3.67934 14 +92 4.54642 3.22327 15 +92 4.66505 2.63914 16 +92 4.82842 3.18503 17 +92 5.02447 3.42396 18 +92 5.07406 4.51548 19 +92 5.13162 4.05998 20 +92 5.22623 3.80233 21 +92 5.2812 3.76354 22 +92 5.39996 4.59865 23 +93 2.74696 2.74697 0 +93 3.00699 2.992 1 +93 3.02818 2.96823 2 +93 3.06428 2.92924 3 +93 3.11661 2.8757 4 +93 3.18727 2.80812 5 +93 3.27935 2.72745 6 +93 3.39719 2.63625 7 +93 3.54606 2.54419 8 +93 3.72862 2.4954 9 +93 3.92595 2.62945 10 +93 4.1247 2.58706 11 +93 4.22025 4.11655 12 +93 4.27871 3.93621 13 +93 4.3677 3.4239 14 +93 4.44773 2.72319 15 +93 4.55881 3.29508 16 +93 4.73921 3.23859 17 +93 4.89757 2.73662 18 +93 5.03738 3.73797 19 +93 5.08202 4.30677 20 +93 5.14996 3.98549 21 +93 5.21376 4.04259 22 +93 5.31192 3.76739 23 +94 2.74693 2.74698 0 +94 3.00642 2.99269 1 +94 3.02587 2.97093 2 +94 3.05895 2.93519 3 +94 3.10677 2.88598 4 +94 3.17109 2.82375 5 +94 3.25446 2.74913 6 +94 3.36049 2.66374 7 +94 3.49381 2.57307 8 +94 3.6586 2.49988 9 +94 3.84851 2.54288 10 +94 4.03511 2.65219 11 +94 4.21577 4.02132 12 +94 4.2525 3.12272 13 +94 4.29337 3.12818 14 +94 4.37699 3.63078 15 +94 4.50344 3.50148 16 +94 4.63682 2.74617 17 +94 4.75181 2.91243 18 +94 4.9456 3.25253 19 +94 5.05295 4.15944 20 +94 5.10172 4.15338 21 +94 5.14969 3.91552 22 +94 5.23756 3.98758 23 +94 5.33602 3.41545 24 +94 5.39633 3.96349 25 +95 2.74695 2.74697 0 +95 3.0059 2.99331 1 +95 3.02376 2.97339 2 +95 3.05408 2.94063 3 +95 3.09781 2.89542 4 +95 3.1564 2.83815 5 +95 3.23199 2.76924 6 +95 3.32757 2.68972 7 +95 3.44708 2.60278 8 +95 3.59482 2.52051 9 +95 3.77103 2.49545 10 +95 3.95513 2.63339 11 +95 4.14852 2.55207 12 +95 4.21751 4.11088 13 +95 4.26782 3.97291 14 +95 4.34776 3.69167 15 +95 4.43523 2.83794 16 +95 4.51519 3.02931 17 +95 4.66257 3.3544 18 +95 4.83263 2.86181 19 +95 4.95601 2.97327 20 +95 5.0696 4.56822 21 +95 5.09931 4.1856 22 +95 5.17067 3.83124 23 +95 5.23563 3.87938 24 +95 5.31438 3.78577 25 +96 2.74693 2.74696 0 +96 3.00542 2.99388 1 +96 3.02182 2.97564 2 +96 3.04963 2.9456 3 +96 3.08963 2.90408 4 +96 3.14307 2.85136 5 +96 3.21169 2.78784 6 +96 3.29799 2.71405 7 +96 3.40525 2.63195 8 +96 3.53743 2.54813 9 +96 3.69729 2.48895 10 +96 3.87626 2.55214 11 +96 4.05302 2.61473 12 +96 4.21399 4.09485 13 +96 4.25087 3.47351 14 +96 4.28868 2.90207 15 +96 4.35248 3.53887 16 +96 4.45883 3.60035 17 +96 4.58716 3.04218 18 +96 4.68673 2.68464 19 +96 4.84114 3.21043 20 +96 5.01071 3.21376 21 +96 5.06608 4.60409 22 +96 5.10887 4.06102 23 +96 5.17327 3.90326 24 +96 5.22634 3.76003 25 +96 5.33609 3.84476 26 +97 2.74692 2.74698 0 +97 3.00498 2.9944 1 +97 3.02005 2.9777 2 +97 3.04556 2.95014 3 +97 3.08218 2.91201 4 +97 3.13094 2.86354 5 +97 3.19332 2.80497 6 +97 3.27137 2.73667 7 +97 3.36782 2.65985 8 +97 3.48609 2.57817 9 +97 3.62959 2.50505 10 +97 3.79704 2.4951 11 +97 3.96948 2.61965 12 +97 4.1548 2.52896 13 +97 4.2148 4.11825 14 +97 4.25745 3.99898 15 +97 4.32592 3.7891 16 +97 4.40771 3.04328 17 +97 4.47447 2.86775 18 +97 4.59118 3.3902 19 +97 4.7472 3.0809 20 +97 4.86757 2.67239 21 +97 5.01541 3.42472 22 +97 5.06774 4.57248 23 +97 5.11368 4.2026 24 +97 5.16428 4.05527 25 +97 5.25134 3.75732 26 +97 5.32335 3.85944 27 +97 5.39407 3.63512 28 +98 2.74696 2.74697 0 +98 3.00458 2.99488 1 +98 3.01843 2.97957 2 +98 3.04184 2.95429 3 +98 3.07538 2.91928 4 +98 3.11993 2.87469 5 +98 3.17668 2.82074 6 +98 3.24737 2.75766 7 +98 3.33425 2.68617 8 +98 3.44022 2.60834 9 +98 3.56854 2.53133 10 +98 3.72095 2.48194 11 +98 3.88882 2.54755 12 +98 4.05615 2.58834 13 +98 4.21173 4.09977 14 +98 4.24278 3.48784 15 +98 4.27481 2.9159 16 +98 4.3285 3.56079 17 +98 4.41789 3.66348 18 +98 4.52973 3.23043 19 +98 4.62036 2.63339 20 +98 4.74076 3.18645 21 +98 4.91154 3.07916 22 +98 5.02102 3.27201 23 +98 5.07426 4.51783 24 +98 5.10879 4.18374 25 +98 5.18078 3.97892 26 +98 5.23378 3.58664 27 +98 5.29709 3.91299 28 +99 2.74696 2.74698 0 +99 3.00421 2.9953 1 +99 3.01694 2.98128 2 +99 3.03843 2.9581 3 +99 3.06917 2.92594 4 +99 3.10989 2.88495 5 +99 3.16159 2.83527 6 +99 3.22571 2.77707 7 +99 3.3041 2.71077 8 +99 3.39919 2.63759 9 +99 3.51387 2.56136 10 +99 3.65079 2.49545 11 +99 3.80822 2.49019 12 +99 3.97024 2.59829 13 +99 4.14466 2.50644 14 +99 4.21223 4.14316 15 +99 4.24794 4.03303 16 +99 4.30538 3.82106 17 +99 4.37367 3.07029 18 +99 4.42975 2.90165 19 +99 4.52707 3.45121 20 +99 4.66038 3.21609 21 +99 4.77192 2.60072 22 +99 4.89803 3.11381 23 +99 5.04463 3.67845 24 +99 5.06934 4.53166 25 +99 5.11641 3.99193 26 +99 5.16405 4.10501 27 +99 5.223 3.73272 28 +99 5.31843 3.8213 29 +99 5.39104 3.41782 30 diff --git a/example/rayleigh/phase.jpg b/example/rayleigh/phase.jpg deleted file mode 100644 index 4ca53f2..0000000 Binary files a/example/rayleigh/phase.jpg and /dev/null differ diff --git a/example/rayleigh/run.sh b/example/rayleigh/run.sh index 264c55b..5b192be 100644 --- a/example/rayleigh/run.sh +++ b/example/rayleigh/run.sh @@ -8,10 +8,10 @@ mkdir -p out sourcedir=`pwd`/../../ echo $sourcedir -wavetp=2 # run sem -time $sourcedir/bin/surfvti model.txt $wavetp 0.01 4 100 +time $sourcedir/bin/surfrayl model.txt 0.01 0.5 100 0 + # convert database to h5file python $sourcedir/scripts/binary2h5.py out/database.bin out/swd.txt out/kernels.h5 @@ -21,12 +21,12 @@ python $sourcedir/scripts/binary2h5.py out/database.bin out/swd.txt out/kernels. ln -s $sourcedir/lib/cps* . \cp $sourcedir/scripts/bench_cps.py . -python bench_cps.py $wavetp +python bench_cps.py model.txt.cps 2 # plot displ python $sourcedir/scripts/plot_disp.py # plot_kernel.py file period_id mode -python plot_kernels.py out/kernels.h5 20 0 +# python plot_kernels.py out/kernels.h5 20 0 \rm -f *.so bench_cps.py diff --git a/example/love/run.sh b/example/rayleigh/run_att.sh similarity index 77% rename from example/love/run.sh rename to example/rayleigh/run_att.sh index 9b12bef..1c7fdad 100644 --- a/example/love/run.sh +++ b/example/rayleigh/run_att.sh @@ -7,10 +7,11 @@ mkdir -p out sourcedir=`pwd`/../../ echo $sourcedir -wavetp=1 + # run sem -time $sourcedir/bin/surfvti model.txt $wavetp 0.01 1 120 +time $sourcedir/bin/surfrayl model.txt 0.01 0.5 100 0 + # convert database to h5file python $sourcedir/scripts/binary2h5.py out/database.bin out/swd.txt out/kernels.h5 @@ -20,12 +21,13 @@ python $sourcedir/scripts/binary2h5.py out/database.bin out/swd.txt out/kernels. ln -s $sourcedir/lib/cps* . \cp $sourcedir/scripts/bench_cps.py . -python bench_cps.py $wavetp +python bench_cps.py model.txt.cps 2 # plot displ python $sourcedir/scripts/plot_disp.py # plot_kernel.py file period_id mode -python plot_kernels.py out/kernels.h5 119 0 +# python plot_kernels.py out/kernels.h5 20 0 \rm -f *.so bench_cps.py + diff --git a/example/rayleigh/test.jpg b/example/rayleigh/test.jpg new file mode 100644 index 0000000..2c17808 Binary files /dev/null and b/example/rayleigh/test.jpg differ diff --git a/include/swdlayer.hpp b/include/swdlayer.hpp deleted file mode 100644 index 5ba4ff7..0000000 --- a/include/swdlayer.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SWDLAYER_MODEL -#define SWDLAYER_MODEL - -#include -#include -#include - -class LayerModel { - -protected: - // GLL/GRL nodes and weights - static const int NGLL = 7, NGRL = 20; - std::array xgll,wgll; - std::array xgrl,wgrl; - std::array hprimeT,hprime; // hprimeT(i,j) = l'_i(xi_j) - std::array hprimeT_grl,hprime_grl; - -public: - std::vector ilayer_flag; // shape(nspec + 1), return layer flag - -public: - // SEM Mesh - int nspec,nspec_grl; // # of elements for gll/grl layer - int nglob; // # of unique points - std::vector ibool; // connectivity matrix, shape(nspec * NGLL + NGRL) - std::vector skel; // skeleton, shape(nspec * 2 + 2) - std::vector znodes; // shape(nspec * NGLL + NGRL) - std::vector jaco; // jacobian for GLL, shape(nspec + 1) dz / dxi - std::vector zstore; // shape(nglob) - -public: - bool IS_DICON_MODEL; - double PHASE_VELOC_MIN,PHASE_VELOC_MAX; - -//functions -private: - void initialize_nodes(); - -public: - LayerModel(){}; - void initialize(); - void interp_model(const float *z,const float *param,std::vector &md) const; - void create_mesh(const int *nel, const float *thk,const float *zlist,int nlayer,double scale); - void project_kl(const float *z, const double *param_kl, double *kl_out) const; -}; - -#endif \ No newline at end of file diff --git a/lib/cps330.cpython-311-darwin.so b/lib/cps330.cpython-311-darwin.so index e7e293d..a55e793 100755 Binary files a/lib/cps330.cpython-311-darwin.so and b/lib/cps330.cpython-311-darwin.so differ diff --git a/lib/libswd.cpython-311-darwin.so b/lib/libswd.cpython-311-darwin.so index 8b112a6..1e7d847 100755 Binary files a/lib/libswd.cpython-311-darwin.so and b/lib/libswd.cpython-311-darwin.so differ diff --git a/misc/doxygen/doxygen.cfg b/misc/doxygen/doxygen.cfg new file mode 100644 index 0000000..9841426 --- /dev/null +++ b/misc/doxygen/doxygen.cfg @@ -0,0 +1,10 @@ +PROJECT_NAME = SpecSWD +INPUT = ./src/mesh ./src/vti ./src/shared ./src/libswd +GENERATE_HTML = YES +HTML_FILE_EXTENSION = .html +FULL_PATH_NAMES = NO + +OUTPUT_DIRECTORY = ./misc/doxygen +GENERATE_HTML = YES +GENERATE_LATEX = YES +#GENERATE_XML = YES \ No newline at end of file diff --git a/misc/source/conf.py b/misc/source/conf.py new file mode 100644 index 0000000..a5644d0 --- /dev/null +++ b/misc/source/conf.py @@ -0,0 +1,47 @@ +# conf.py + +project = 'SpecSWD' +author = 'Nanqiao Du' + +import os +import sys +sys.path.insert(0, os.path.abspath('../')) +sys.path.insert(0, os.path.abspath('../../../')) +sys.path.insert(0, os.path.abspath('../../')) + +latex_engine = 'pdflatex' +# Set up LaTeX formatting elements +latex_elements = { + 'preamble': r''' + \usepackage{amsmath} + \usepackage{amssymb} + ''' +} + +# Add myst-parser to the extensions list +extensions = [ + 'myst_parser', # Markdown parser + 'sphinx.ext.mathjax', # for math rendering in HTML + 'sphinx.ext.autodoc', # For generating Python API docs + 'sphinx.ext.napoleon', # For Google and NumPy docstring styles (optional) + 'sphinx.ext.viewcode', # To link source code in the API docs (optional) +] + +# You might have: +autodoc_default_options = { + 'members': True, + 'undoc-members': True, # <--- include this to document all functions + 'private-members': False, + 'special-members': False, + 'show-inheritance': True, +} + +# Add .md as a valid source suffix +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown', # Enable Markdown support +} + +# Optional: Set up the master document +master_doc = 'index' # Default is 'index.rst', which you can change as needed +html_theme = 'sphinx_rtd_theme' \ No newline at end of file diff --git a/misc/source/index.rst b/misc/source/index.rst new file mode 100644 index 0000000..7082ea6 --- /dev/null +++ b/misc/source/index.rst @@ -0,0 +1,11 @@ +Welcome to My Project +===================== + +.. toctree:: + :maxdepth: 4 + :caption: Contents: + + markdown/readme.md + markdown/Tutorial.md + markdown/gallery.md + python/index diff --git a/misc/source/markdown/Tutorial.md b/misc/source/markdown/Tutorial.md new file mode 100644 index 0000000..a8a8743 --- /dev/null +++ b/misc/source/markdown/Tutorial.md @@ -0,0 +1,49 @@ +# Tutorial + +## SpecSWD Models +**SpecSWD** use a mixture 1-D model (linear variation model with discontinuities). The discontinuities is marked by two group of quantities defined at the same depth. **SpecSWD** currently support 3 type of different models: VTI-Love wave model, VTI-Rayleigh wave model, full-anisotropic model. The format is as below: + +### Love wave model +In VTI media (or radial anisotropy), only 2 velocities `Vsv,Vsh` and corresponding quality factor `Ql,Qn` are related to love wave. + +### Rayleigh (Scholte) wave model +For Rayleigh wave, generally we need 3 velocities `Vph,Vpv,Vsv`, their corresponding quality factor `Qa,Qc,Ql`, and a ratio factor `eta`. If this model also involves acoutic regions, you should set the `Vsv = 0` and `Vpv=Vph, Qa=Qc` in these regions to make the program know it's acoutic. Also at elastic-acoustic boundary, a discontinuty is required. + +### Fully anisotropic wave model +For fully-anisotropic model, we need 21 parameters. It should be flattened like: +```python +id = 0 +for i in range(6): + for j in range(i,6): + c21_flat[id] = c66[i,j] + id += 1 +``` +The quality factors in anisotropic media is user defined. The default implementation is only focus on the isotropic part of the media, and thus requires $Q_{\kappa}$ and $Q_{\mu}$ ([Carcione 1990](https://academic.oup.com/gji/article/101/3/739/602971)). High-level users can go to `src/shared/attenuation.cpp` to define their own quality factors. If anisotropic media also includes acoustic layer, it should be set like a isotropic `c21` with zero out corresponding elements. + +## Q model +This program use standard linear solids to model attenuation effects. The correction method ([van Driel et al, 2014](https://academic.oup.com/gji/article/199/2/1078/624157?login=true)) make us only do one non-linear inversion to get coefficients that can be used for many Qs. The current coefficients in this program only be valid for 0.01-100 Hz (see figure below). If your application requires Q at different frequency domain, you can use `scripts/attenuation.py` to compute your coefficients, and paste to `src/attenuation.cpp`. + +![](../static/Qmodel.jpg) +*Q model estimated by SLS model* + +## Example +```python +#!/bin/python3 +import numpy as np +from specd import SpecWorkSpace + +# set a model for Love wave, discontinuities is at 35 km +model = np.array([ + [0.0000000, 2.800000, 3.300000, 3.000000, 220., 200.], + [35.000000, 2.800000, 3.300000, 3.000000, 220., 200.], + [35.000000, 3.200000, 5.500000, 5.000000, 330., 300.] +]) +z,rho,vsh,vsv,_,_ = (model[:, i].reshape(3) for i in range(6)) + +# create work space +ws = SpecWorkSpace('love',z,rho,vsh=vsh,vsv=vsv,disp=True) + +# compute phase velocity +c = ws.compute_egn(1.,-1,False) +print(c) +``` \ No newline at end of file diff --git a/misc/source/markdown/gallery.md b/misc/source/markdown/gallery.md new file mode 100644 index 0000000..114e60d --- /dev/null +++ b/misc/source/markdown/gallery.md @@ -0,0 +1,28 @@ +# Gallery +## Two layer Love wave Model +| Layer Number | h | $\rho$ | $\beta_{v}$| $\beta_{h}$ | $Q_L$ | $Q_N$ | +| -------- | ------- |---- |--| --| -- | --| +| 1 | 35 | 2.8 | 3.0 | 3.3 | 220 | 200 | +| 2 | $\infty$ | 3.2 | 5.0 | 5.5 |330 |300| + +![image](../../../example/love/eigenvalues_att.jpg) +*Benchmark of phase/group/group Q ith Analytical Solution* + +![image](../../../example/love/phase_deriv_veloc_att.jpg) +*Benchmark of phase velocity sensitivity kernels ith Analytical Solution* + + +![image](../../../example/love/group_deriv_veloc_att.jpg) +*Benchmark of group velocity sensitivity kernels ith Analytical Solution* + + + \ No newline at end of file diff --git a/misc/source/markdown/readme.md b/misc/source/markdown/readme.md new file mode 100644 index 0000000..d9b6f95 --- /dev/null +++ b/misc/source/markdown/readme.md @@ -0,0 +1,40 @@ +# SpecSWD +**SpecSWD** is a software to compute surface wave dispersions and do sensitivity analysis for 1-D fully anisotropic, wealy anelastic media. It utilizes spectral element method and quadratic eigenvalue solver to handle multiphysics (elastic-acoustic coupling), strong anisotropy and discontinuities inside the study region. + +**SpecSWD** also provides high-level sensitivity analysis framework (adjoint methods) for any user-defined quantities. + + +# Installation + +1. **Compilers:** C++/Fortran compilers which support c++17 (tested on `GCC >=7.5`), `cmake >= 3.12` + +2. packages: +* [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page) >= 3.4.0 +* [MKL](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl-download.html) or [OpenBLAS](http://www.openmathlib.org/OpenBLAS/) +* [doxygen](https://www.doxygen.nl/) for api document generation + +3. Python environments +```bash +conda create -n specswd python=3.10 +conda activate specswd +conda install numpy scipy matplotlib pybind11 +``` + +4. Install +```bash +mkdir -p build +cd build +cmake .. -DCXX=g++ -DFC=gfortran -DEIGEN_INC=/path/to/eigen/ -DBUILD_LIBS=ON -DPython3_EXECUTABLE=`which python` +make -j4 +make install +``` + +5. Install low-level C++ API docs +```bash +doxygen misc/doxygen/doxygen.cfg +``` + +6. Python libraries +```bash +pip install . +``` \ No newline at end of file diff --git a/misc/source/python/index.rst b/misc/source/python/index.rst new file mode 100644 index 0000000..c6b6194 --- /dev/null +++ b/misc/source/python/index.rst @@ -0,0 +1,11 @@ + +Python Library API Reference +============================== + +This is the main page for Specd project + + +.. toctree:: + :maxdepth: 4 + + modules diff --git a/misc/source/static/Qmodel.jpg b/misc/source/static/Qmodel.jpg new file mode 100644 index 0000000..211657f Binary files /dev/null and b/misc/source/static/Qmodel.jpg differ diff --git a/scripts/bench_cps.py b/scripts/bench_cps.py index d0f875b..fe05265 100644 --- a/scripts/bench_cps.py +++ b/scripts/bench_cps.py @@ -14,12 +14,14 @@ def get_disp(thk,vp,vs,rho,T,mode,wavetype,sphere=False): def main(): - if len(sys.argv) != 2: - print("Usage: python bench_cps.py wavetype") + if len(sys.argv) != 3: + print("Usage: python bench_cps.py modfile wavetype") exit(1) - wavetype = int(sys.argv[1]) + + modfile = sys.argv[1] + wavetype = int(sys.argv[2]) - data = np.loadtxt("model.txt",skiprows=1,dtype=np.float32) + data = np.loadtxt(modfile,dtype=np.float32) thk = data[:,0] rho = data[:,1] vs = data[:,4] @@ -38,7 +40,7 @@ def main(): wtp = 'R' else: wtp = 'L' - for i in range(0,6): + for i in range(20): c = np.zeros(len(T)) u = np.zeros(len(T)) for it in range(len(T)): diff --git a/scripts/binary2h5.py b/scripts/binary2h5.py index 248c83d..2e7122d 100644 --- a/scripts/binary2h5.py +++ b/scripts/binary2h5.py @@ -13,62 +13,95 @@ def main(): swdfile = sys.argv[2] outfile = sys.argv[3] - # open outfile - fout:h5py.File = h5py.File(outfile,"w") + # read attributes + fin:FortranFile = FortranFile(binfile,"r") + SWD_TYPE = fin.read_ints('i4')[0] + HAS_ATT = fin.read_ints('?')[0] + nz = int(fin.read_ints('i4')[0]) + nkers = fin.read_ints('i4')[0] + ncomps = fin.read_ints('i4')[0] # open swd file to read T and swd T = np.loadtxt(swdfile,max_rows=1,ndmin=1) data = np.loadtxt(swdfile,skiprows=1) + Tid = np.int32(data[:,0]) + modeid = np.int32(data[:,-1]) max_modes = int(np.max(data[:,-1])) + 1 + + # open outfile + fout:h5py.File = h5py.File(outfile,"w") fout.create_group("swd") for imode in range(max_modes): gname = f"swd/mode{imode}/" fout.create_group(f"{gname}") - idx = data[:,-1] == imode + idx = modeid == imode data1 = data[idx,:] nt1 = data1.shape[0] fout.create_dataset(f"{gname}/T",shape = (nt1),dtype='f4') fout.create_dataset(f"{gname}/c",shape = (nt1),dtype='f4') fout.create_dataset(f"{gname}/u",shape = (nt1),dtype='f4') - fout[f'{gname}/T'][:] = T[np.int32(data[idx,0])] - fout[f'{gname}/c'][:] = data1[:,1] - fout[f'{gname}/u'][:] = data1[:,2] + fout[f'{gname}/T'][:] = T[Tid[idx]] + if HAS_ATT: + fout.create_dataset(f"{gname}/cQ",shape = (nt1),dtype='f4') + fout.create_dataset(f"{gname}/uQ",shape = (nt1),dtype='f4') + fout[f'{gname}/c'][:] = data1[:,1] + fout[f'{gname}/u'][:] = data1[:,2] + fout[f'{gname}/cQ'][:] = 0.5 * data1[:,1] / data1[:,3] + fout[f'{gname}/uQ'][:] = 0.5 * data1[:,2] / data1[:,4] + else: + fout[f'{gname}/c'][:] = data1[:,1] + fout[f'{gname}/u'][:] = data1[:,2] # write kernels - fin:FortranFile = FortranFile(binfile,"r") - nkers = fin.read_ints('i4')[0] - ncomps = fin.read_ints('i4')[0] - assert(nkers in [3,5,8]) - assert(ncomps in [1,2,3]) - if nkers == 3: - kl_name = ['rho_kl','vsv_kl','vsh_kl'] + # fin:FortranFile = FortranFile(binfile,"r") + # SWD_TYPE = fin.read_ints('i4')[0] + # HAS_ATT = fin.read_ints('?')[0] + # nz = int(fin.read_ints('i4')[0]) + # nkers = fin.read_ints('i4')[0] + # ncomps = fin.read_ints('i4')[0] + fout.attrs['HAS_ATT'] = HAS_ATT + if SWD_TYPE == 0: comp_name = ['W'] fout.attrs['WaveType'] = 'Love' fout.attrs['ModelType'] = 'VTI' - displ_type = 'f8' - elif nkers == 5: + PTYPE = 'f4' + if HAS_ATT: + dname = ['C','Q'] + kl_name = ['vsh','vsv','Qvsh','Qvsv','rho'] + PTYPE = 'c8' + else: + dname = ['C'] + kl_name = ['vsh','vsv','rho'] + + elif SWD_TYPE == 1: comp_name = ['U','V'] - kl_name = ['rho_kl','vpv_kl','vph_kl','vsv_kl','eta_kl'] fout.attrs['WaveType'] = 'Rayleigh' fout.attrs['ModelType'] = 'VTI' - displ_type = 'f8' + PTYPE = 'f4' + + if HAS_ATT: + dname = ['C','Q'] + kl_name = ['vph','vpv','vsv','eta','Qvph','Qvpv','Qvsv','vp','Qvp','rho'] + PTYPE = 'c8' + else: + dname = ['C'] + kl_name = ['vph','vpv','vsv','eta','vp','rho'] else: comp_name = ['U','W','V'] kl_name = ['rho_kl','vpv_kl','vph_kl','vsv_kl','vsh_kl','eta_kl','theta_kl','phi_kl'] fout.attrs['WaveType'] = 'Full' fout.attrs['ModelType'] = 'TTI' - displ_type = 'c16' + PTYPE = 'c8' fout.create_group("kernels") for it in range(len(T)): - idx = data[:,0] == it - data1 = data[idx,:] - max_mode = int(np.max(data1[:,-1])) + 1 + idx = Tid == it + max_mode = np.max(modeid[idx]) + 1 #fout.attrs[f"kernels/{it}/T"] = T[it] # read coordinates - zcords = fin.read_reals('f8') + zcords = fin.read_reals('f4') npts = zcords.size fout.create_dataset(f"kernels/{it}/zcords",dtype='f4',shape =(npts)) fout[f'kernels/{it}/zcords'][:] = zcords[:] @@ -77,18 +110,21 @@ def main(): fout.create_group(gname) # read eigenfuncs - displ = fin.read_reals(displ_type) + displ = fin.read_record(PTYPE) displ = displ.reshape((ncomps,npts)) for icomp in range(ncomps): - fout.create_dataset(f"{gname}/{comp_name[icomp]}",dtype=displ_type,shape=(npts)) + fout.create_dataset(f"{gname}/{comp_name[icomp]}",dtype=PTYPE,shape=(npts)) fout[f"{gname}/{comp_name[icomp]}"][:] = displ[icomp,:] # read kernels - kernel = fin.read_reals('f8').reshape((nkers,npts)) - for iker in range(nkers): - fout.create_dataset(f"{gname}/{kl_name[iker]}",dtype='f8',shape=(npts)) - fout[f"{gname}/{kl_name[iker]}"][:] = kernel[iker,:] - + for iname in range(len(dname)): + prefix = dname[iname] + kernel = fin.read_reals('f4').reshape((nkers,nz)) + for iker in range(nkers): + #print(f"{gname}/{prefix}_{kl_name[iker]}") + fout.create_dataset(f"{gname}/{prefix}_{kl_name[iker]}",dtype='f4',shape=(nz)) + fout[f"{gname}/{prefix}_{kl_name[iker]}"][:] = kernel[iker,:] + #print(f"{gname}/{prefix}_{kl_name[iker]}") # close fin.close() diff --git a/scripts/plot_disp.py b/scripts/plot_disp.py index 4a9814b..496f07c 100644 --- a/scripts/plot_disp.py +++ b/scripts/plot_disp.py @@ -2,6 +2,16 @@ import matplotlib.pyplot as plt import sys +import matplotlib as mpl +mpl.rcParams['lines.linewidth'] = 1.5 +mpl.rcParams['font.size'] = 10 +mpl.rcParams['xtick.labelsize']=15 +mpl.rcParams['ytick.labelsize']=15 +mpl.rcParams['axes.labelsize']=15 +mpl.rcParams['legend.fontsize'] = 20 +mpl.rcParams['legend.fontsize'] = 20 +mpl.rcParams['savefig.bbox'] = 'tight' + def fetch_data(T,data,nc,col_id): nt = len(T) c_all = np.zeros((nt,nc)) - 1 @@ -10,7 +20,7 @@ def fetch_data(T,data,nc,col_id): idx = data[:,0] == it c = data[idx,col_id] for i in range(len(c)): - if i >= c_all.shape[1] : break + if i >=nc: continue c_all[it,i] = c[i] return c_all @@ -28,7 +38,7 @@ def main(): # load swd data data = np.loadtxt("out/swd.txt",skiprows=1) - data1 = np.loadtxt("out/swd.cps.txt",skiprows=1) + data_cps = np.loadtxt("out/swd.cps.txt",skiprows=1) # find unique T T = np.loadtxt("out/swd.txt",max_rows=1) @@ -37,49 +47,58 @@ def main(): # plot phase nc = int(np.max(data[:,-1])) + 1 - plt.figure(1,figsize=(14,5)) + ncplot = min(ncplot,nc) + + # plotting maps + cmap = plt.get_cmap("viridis",ncplot) + norm = mpl.colors.Normalize(vmin=0, vmax=ncplot-1) # Normalize the color range + fig,ax = plt.subplots(1,2,figsize=(15,6)) + #plt.scatter(1./data[:,0],data[:,1],s=10,color='k') c_all = fetch_data(T,data,nc,1) - - ncplot = min(ncplot,c_all.shape[1]) for i in range(ncplot): idx = c_all[:,i] > 0 if np.sum(idx) != 0: - plt.plot(1./T[idx],c_all[idx,i]) + ax[0].plot(1./T[idx],c_all[idx,i],color=cmap(i)) - c1_all = fetch_data(T1,data1,nc,1) + c1_all = fetch_data(T1,data_cps,nc,1) for i in range(ncplot): idx = c1_all[:,i] > 0 + label = None + if i == 0: + label = 'T-H' if np.sum(idx) != 0: - plt.plot(1./T1[idx],c1_all[idx,i],color='k',ls='--',label=f'cps_{i}') + ax[0].scatter(1./T1[idx],c1_all[idx,i],s=10,color='k',label=label) - plt.legend() - plt.xlabel("Frequency,Hz") - plt.ylabel("Phase Velocity, km/s") - plt.savefig("phase.jpg") - plt.clf() + ax[0].legend() + ax[0].set_xlabel("Frequency,Hz") + ax[0].set_ylabel("Phase Velocity, km/s") # plot group - plt.figure(1,figsize=(14,5)) - #plt.scatter(1./data[:,0],data[:,2],s=10,color='k') c_all = fetch_data(T,data,nc,2) # plot for i in range(ncplot): idx = c_all[:,i] > 0 if np.sum(idx) != 0: - plt.plot(1./T[idx],c_all[idx,i]) + ax[1].plot(1./T[idx],c_all[idx,i],color=cmap(i)) - c1_all = fetch_data(T1,data1,nc,2) + c1_all = fetch_data(T1,data_cps,nc,2) for i in range(ncplot): idx = c1_all[:,i] > 0 + label = None + if i == 0: + label = 'T-H' if np.sum(idx) != 0: - plt.plot(1./T1[idx],c1_all[idx,i],color='k',ls='--',label=f'cps_{i}') - plt.legend() - plt.xlabel("Frequency,Hz") - plt.ylabel("Group Velocity, km/s") - plt.savefig("group.jpg") + ax[1].scatter(1./T1[idx],c1_all[idx,i],color='k',s=10,label=label) + ax[1].legend() + ax[1].set_xlabel("Frequency,Hz") + ax[1].set_ylabel("Group Velocity, km/s") + sm = plt.cm.ScalarMappable(cmap=cmap,norm=norm) + fig.colorbar(sm,ax=ax.ravel().tolist(),label='order',location='bottom',pad=0.075,shrink=0.4,format='%d') + fig.savefig("eigenvalues.jpg",dpi=300) + fig.savefig("eigenvalues.pdf",dpi=300) main() \ No newline at end of file diff --git a/scripts/plot_disp_att.py b/scripts/plot_disp_att.py new file mode 100644 index 0000000..4a9814b --- /dev/null +++ b/scripts/plot_disp_att.py @@ -0,0 +1,85 @@ +import numpy as np +import matplotlib.pyplot as plt +import sys + +def fetch_data(T,data,nc,col_id): + nt = len(T) + c_all = np.zeros((nt,nc)) - 1 + + for it in range(len(T)): + idx = data[:,0] == it + c = data[idx,col_id] + for i in range(len(c)): + if i >= c_all.shape[1] : break + c_all[it,i] = c[i] + + return c_all + +def main(): + + if len(sys.argv) != 2 and len(sys.argv) != 1: + print("usage: python plot_disp.py max_order") + exit(1) + + if len(sys.argv) == 2: + ncplot = int(sys.argv[1]) + else: + ncplot = 100 + + # load swd data + data = np.loadtxt("out/swd.txt",skiprows=1) + data1 = np.loadtxt("out/swd.cps.txt",skiprows=1) + + # find unique T + T = np.loadtxt("out/swd.txt",max_rows=1) + T1 = np.loadtxt("out/swd.cps.txt",max_rows=1) + nt = len(T) + + # plot phase + nc = int(np.max(data[:,-1])) + 1 + plt.figure(1,figsize=(14,5)) + #plt.scatter(1./data[:,0],data[:,1],s=10,color='k') + c_all = fetch_data(T,data,nc,1) + + ncplot = min(ncplot,c_all.shape[1]) + for i in range(ncplot): + idx = c_all[:,i] > 0 + if np.sum(idx) != 0: + plt.plot(1./T[idx],c_all[idx,i]) + + c1_all = fetch_data(T1,data1,nc,1) + for i in range(ncplot): + idx = c1_all[:,i] > 0 + if np.sum(idx) != 0: + plt.plot(1./T1[idx],c1_all[idx,i],color='k',ls='--',label=f'cps_{i}') + + plt.legend() + plt.xlabel("Frequency,Hz") + plt.ylabel("Phase Velocity, km/s") + plt.savefig("phase.jpg") + plt.clf() + + # plot group + plt.figure(1,figsize=(14,5)) + #plt.scatter(1./data[:,0],data[:,2],s=10,color='k') + c_all = fetch_data(T,data,nc,2) + + # plot + for i in range(ncplot): + idx = c_all[:,i] > 0 + if np.sum(idx) != 0: + plt.plot(1./T[idx],c_all[idx,i]) + + c1_all = fetch_data(T1,data1,nc,2) + + for i in range(ncplot): + idx = c1_all[:,i] > 0 + if np.sum(idx) != 0: + plt.plot(1./T1[idx],c1_all[idx,i],color='k',ls='--',label=f'cps_{i}') + plt.legend() + plt.xlabel("Frequency,Hz") + plt.ylabel("Group Velocity, km/s") + plt.savefig("group.jpg") + +main() + \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..72163b9 --- /dev/null +++ b/setup.py @@ -0,0 +1,55 @@ +from setuptools import setup, find_packages +import os +import shutil +from distutils.command.clean import clean as Clean + +class CleanCommand(Clean): + def run(self): + Clean.run(self) + for path in [ 'dist', '*.egg-info']: + if os.path.isdir(path): + print(f"Removing {path}") + shutil.rmtree(path) + else: + # Glob match for *.egg-info (in case of project_name.egg-info) + for p in [p for p in os.listdir('.') if p.endswith('.egg-info')]: + print(f"Removing {p}") + shutil.rmtree(p) + +setup( + name="specd", + version="0.1.0", + author="Nanqiao Du", + author_email="nqdu@foxmail.com", + description="Surface wave dispersion and sensitivity analysis in anisotropic, wealy anelastic medium", + long_description=open("README.md").read(), + long_description_content_type="text/markdown", + url="https://github.com/yourusername/your-repo", + packages=find_packages(exclude=["tests", "docs"]), + package_data={'': ['lib/*.so']}, + install_requires=[ + # List your dependencies here + "numpy>=1.20", + "scipy", + "requests", + ], + python_requires=">=3.7", + entry_points={ + "console_scripts": [ + "your-cli-name = your_module.cli:main", # Adjust this path + ], + }, + classifiers=[ + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", + "License :: OSI Approved :: MIT License", + ], + license="MIT", + include_package_data=True, + zip_safe=False, + + # your existing setup() config... + cmdclass={ + 'clean': CleanCommand, + }, +) diff --git a/specd/THSolver.py b/specd/THSolver.py new file mode 100644 index 0000000..17384d1 --- /dev/null +++ b/specd/THSolver.py @@ -0,0 +1,54 @@ +from .lib import cps330 +import numpy as np + +class THSolver: + def __init__(self,thick:np.ndarray,vp:np.ndarray, + vs:np.ndarray,rho:np.ndarray,spherical:bool=False + ): + """ + Initialize Thompson-Haskell Matrix Dispersion Solver + + Parameters + ------------ + thick: np.ndarray + thickness of layered model,in km + vp: np.ndarray + P wave velocity, km/s + vs: np.ndarray + S wave velocity, km/s + rho: np.ndarray + density + """ + # backup input params + self._thick = thick + self._vp = vp + self._vs = vs + self._rho = rho + self._spherical = spherical + + def compute_swd(self,wavetype:str,mode:int,T:np.ndarray) -> np.ndarray: + """ + compute dispersion (phase/group) for a give wavetype + + Parameters + ------------ + wavetype: str + wave type, one of ['Rc','Rg','Lc','Lg'] + mode: int + which mode it will return, >=0 + T: np.ndarray + period, in s + + Returns + ----------- + cg: np.ndarray + phase velocity (for Rc,Lc) or group velocity (Rg,Lg) + """ + # check input args + assert wavetype in ['Rc','Rg','Lc','Lg'], "check wave type!" + c,_ = cps330.forward( + self._thick,self._vp,self._vs, + self._rho,T,wavetype,mode, + self._spherical) + + return c \ No newline at end of file diff --git a/specd/__init__.py b/specd/__init__.py new file mode 100644 index 0000000..5ede28d --- /dev/null +++ b/specd/__init__.py @@ -0,0 +1,2 @@ +from specd.specd import SpecWorkSpace +from specd.THSolver import THSolver \ No newline at end of file diff --git a/specd/__pycache__/THMatrixSolver.cpython-311.pyc b/specd/__pycache__/THMatrixSolver.cpython-311.pyc new file mode 100644 index 0000000..888e108 Binary files /dev/null and b/specd/__pycache__/THMatrixSolver.cpython-311.pyc differ diff --git a/specd/__pycache__/THSolver.cpython-311.pyc b/specd/__pycache__/THSolver.cpython-311.pyc new file mode 100644 index 0000000..083eb77 Binary files /dev/null and b/specd/__pycache__/THSolver.cpython-311.pyc differ diff --git a/specd/__pycache__/__init__.cpython-311.pyc b/specd/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..1717fd1 Binary files /dev/null and b/specd/__pycache__/__init__.cpython-311.pyc differ diff --git a/specd/__pycache__/attenuation.cpython-311.pyc b/specd/__pycache__/attenuation.cpython-311.pyc new file mode 100644 index 0000000..812fd22 Binary files /dev/null and b/specd/__pycache__/attenuation.cpython-311.pyc differ diff --git a/specd/__pycache__/specd.cpython-311.pyc b/specd/__pycache__/specd.cpython-311.pyc new file mode 100644 index 0000000..56d5685 Binary files /dev/null and b/specd/__pycache__/specd.cpython-311.pyc differ diff --git a/specd/attenuation.py b/specd/attenuation.py new file mode 100644 index 0000000..6239ebb --- /dev/null +++ b/specd/attenuation.py @@ -0,0 +1,330 @@ +import numpy as np +import matplotlib.pyplot as plt +from scipy.optimize import dual_annealing + +def compute_q_sls_model(y_sls,w_sls,om,exact=False): + """ + compute Q model by a given SLS coefficients: + Q^{-1}(om) = D(om) / N(om) + where N(om) = \sum_p y[p] * om^2 / (om^2 + w[p]^2) and + D(om) = y[p] * om^2 / (om^2 + w[p]^2) + + Parameters + ---------- + y_sls: np.ndarray + y coefficients, shape(NSLS) + w_sls: np.ndarray + w coefficients, shape(NSLS) + om: np.ndarray + current angular frequency + exact: bool + if True, N(om) and D(om) are all computed. Else set N =1. + + """ + Q_ls = 1. + nsls = len(y_sls) + if exact: + for p in range(nsls): + Q_ls += y_sls[p] * om**2 / (om**2 + w_sls[p]**2) + + # denom + Q_demon = 0. + for p in range(nsls): + Q_demon += y_sls[p] * om * w_sls[p] / (om**2 + w_sls[p]**2) + + return Q_ls / Q_demon + +def _compute_q_model(Q0:float,om,alpha = 0.,om_ref=1.): + """ + User defined power law Q model: Q = Q0 (om/om_ref)**alpha + + Parameters + ---------- + Q0: float + target constant Q + om: np.ndarray + angular frequency used + alpha: float + power factor + om_ref: float + reference angular frequency + + Returns + -------- + q: np.ndarray + target q model + """ + q = Q0 * (om / om_ref) ** alpha + + return q + +def _misfit_func(x,om,q_target,weights = 1): + """ + misfit function of targeted and synthetic Q model = 1/2 \int d\om log[(Q_sls / Q_target)]**2 * weights + + Parameter + ------------ + x: np.ndarray + sls coefs [y,w] with shape(NSLS * 2) + om: np.ndarray + angular frequency used + q_target: np.ndarray + target Q model at om + weights: np.darray or float + weights + + Returns + ----------- + f: float + misfit = 1/2 \int d\om log[(Q_sls / Q_target)]**2 * weights + """ + NSLS = len(x) // 2 + y_sls = x[:NSLS] * 1. + w_sls = x[NSLS:] * 1. + q_sls = compute_q_sls_model(y_sls,w_sls,om,False) + + return np.sum(np.log(q_sls/q_target)**2 * weights) * 0.5 + +def y_corrector(y_sls,Q_ref:float,Q:float): + """ + correction from reference y to target y + + Parameters + -------------- + y_sls: np.ndarray + y factor for refernce sls model + Q_ref: float + refernce Q + Q: float + target Q + """ + # note y_sls is fitted + y = y_sls / Q * Q_ref + dy = y * 0. + + # corrector + dy[0] = 1 + 0.5 * y[0] + for i in range(1,len(y)): + dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i] + + # corrected y_sls + return dy * y + +def compute_sls_coefs(freqmin:float,freqmax:float, NSLS=5, nfsamp=100, + weight_by_freq = True,method='dual', + Q_ref = 1.,random_seed=10): + """ + compute SLS coefs for reference model, by nonlinear inversion + + Parameter + ------------ + freqmin: float + minimum frequency + freqmax: float + maximum frequency + NSLS: int + no. of SLS solids, default = 5 + nfsamp: int + no. of sampling points in [freqmin,freqmax], default = 100 + weight_by_freq: bool + if apply frequency weighting in misfit function ,default = True + method: str + one of ['dual','simulated'], dual or regular simulated annealling + Q_ref: float + reference Q value, default is 1. Donnot change it unless you know what you're doning + random_seed: int + random seed, default 10 + + Returns + ------------ + y: np.ndarray + SLS factor + w: np.ndarray + SLS angular frequency + """ + + # get min/max freq, with a bigger range + min_freq = 0.5 * freqmin + max_freq = 2 * freqmax + + # check OPT_METHOD + assert(method in ['dual','simulated']) + + # get om vector + om = np.logspace(np.log10(min_freq),np.log10(max_freq),nfsamp) * np.pi * 2 + + # initial y_sls and w_sls + w_sls = np.logspace(np.log10(min_freq),np.log10(max_freq),NSLS) * np.pi * 2 + y_sls = 1.5 * np.ones((NSLS)) / Q_ref + x = np.append(y_sls,w_sls) + + # weight factor + weights = om * 0 + 1. + if weight_by_freq: + weights = om / np.sum(om) + + # target Q model + q_target = _compute_q_model(Q_ref,om,0.,1.) + + if method == 'simulated': + # set random seed + np.random.seed(random_seed) + + # now call a simulated annealing optimizer + Tw = 0.1 + Ty = 0.1 + chi = _misfit_func(x,om,q_target,weights) + + x_test = x * 1. + for it in range(100000): + for i in range(NSLS): + x_test[i] = x[i] * (1.0 + (0.5 - np.random.rand()) * Ty) + x_test[i+NSLS] = x[i+NSLS] * (1.0 + (0.5 - np.random.rand()) * Tw) + + # compute Q + chi_test = _misfit_func(x_test,om,q_target,weights) + Ty *= 0.995 + Tw *= 0.995 + + # check if accept this parameter + if chi_test < chi: + x[:] = x_test[:] * 1. + chi = chi_test * 1. + + # return taget model + print('final misift = ',chi) + y_opt = x[:NSLS] + w_opt = x[NSLS:] + else : # dual annealing + # set search boundary for w_sls and y_sls + bounds = [] + for i in range(NSLS): + y_min = y_sls[i] * 0.8 + y_max = y_sls[i] * 1.5 + bounds.append((y_min,y_max)) + for i in range(NSLS): + w_min = w_sls[i] * 0.8 + w_max = w_sls[i] * 1.5 + bounds.append((w_min,w_max)) + res = dual_annealing(_misfit_func,bounds=bounds,args=(om,q_target,weights), \ + x0=x,maxiter=1000,seed=random_seed) + y_opt = res.x[:NSLS] + w_opt = res.x[NSLS:] + + return y_opt,w_opt + +def test(): + # set your parameters here + ##### target Q power law model Q(w) = Q (w / w_ref)^alpha + alpha = 0. # + om_ref = 1. + Q = 20 + + # SLS q model + NSLS = 5 + min_freq = 0.5 * 1.0e-2 + max_freq = 2 * 100 + nfsamp = 100 # no. of frequency points in om to fit Q model + weight_by_freq = True + + # optimization method + OPT_METHOD = 'dual' # 1 for simulated annealing and 2 for dual anneling + rand_seed = 10 + + #### STOP HERE ##### + + # reference Q to fitting + Q_ref = 1. + + # check OPT_METHOD + assert(OPT_METHOD in ['dual','simulated']) + + # get om vector + om = np.logspace(np.log10(min_freq),np.log10(max_freq),nfsamp) * np.pi * 2 + + # initial y_sls and w_sls + w_sls = np.logspace(np.log10(min_freq),np.log10(max_freq),NSLS) * np.pi * 2 + y_sls = 1.5 * np.ones((NSLS)) / Q_ref + x = np.append(y_sls,w_sls) + + # weight factor + weights = om * 0 + 1. + if weight_by_freq: + weights = om / np.sum(om) + + # target Q model + q_target = _compute_q_model(Q_ref,om,alpha,om_ref) + + if OPT_METHOD == 'simulated': + # set random seed + np.random.seed(rand_seed) + + # now call a simulated annealing optimizer + Tw = 0.1 + Ty = 0.1 + chi = _misfit_func(x,om,q_target,weights) + + x_test = x * 1. + for it in range(100000): + for i in range(NSLS): + x_test[i] = x[i] * (1.0 + (0.5 - np.random.rand()) * Ty) + x_test[i+NSLS] = x[i+NSLS] * (1.0 + (0.5 - np.random.rand()) * Tw) + + # compute Q + chi_test = _misfit_func(x_test,om,q_target,weights) + Ty *= 0.995 + Tw *= 0.995 + + # check if accept this parameter + if chi_test < chi: + x[:] = x_test[:] * 1. + chi = chi_test * 1. + + # return taget model + print('final misift = ',chi) + y_opt = x[:NSLS] + w_opt = x[NSLS:] + else : # dual annealing + # set search boundary for w_sls and y_sls + bounds = [] + for i in range(NSLS): + y_min = y_sls[i] * 0.8 + y_max = y_sls[i] * 1.5 + bounds.append((y_min,y_max)) + for i in range(NSLS): + w_min = w_sls[i] * 0.8 + w_max = w_sls[i] * 1.5 + bounds.append((w_min,w_max)) + res = dual_annealing(_misfit_func,bounds=bounds,args=(om,q_target,weights), \ + x0=x,maxiter=1000,seed=10) + print(res) + y_opt = res.x[:NSLS] + w_opt = res.x[NSLS:] + pass + + # # save optimized y_sls and w_sls + # fio = open("include/atteunuation_table.hpp","w") + # fio.write("#include \n") + # fio.write("const int NSLS = 5;\n") + # y_opt_str = ",".join([str(y_opt[i]) for i in range(len(y_opt))]) + # w_opt_str = ",".join([str(w_opt[i]) for i in range(len(y_opt))]) + # fio.write("const std::array y_sls_ref = {%s};\n" % (y_opt_str)) + # fio.write("const std::array w_sls_ref = {%s};\n" % (w_opt_str)) + # fio.close() + + # plot Q model + om_plot = np.logspace(np.log10(min_freq*0.01),np.log10(max_freq*100),500) * np.pi * 2 + print('optimized y_sls_ref = ',y_opt) + print('optimized w_sls_ref = ',w_opt) + y_opt = y_corrector(y_opt,Q_ref,Q) + Q_opt = compute_q_sls_model(y_opt,w_opt,om_plot,True) + Q_pow = _compute_q_model(Q,om_plot,alpha,om_ref) + + plt.semilogx(om_plot/(2*np.pi),1./Q_opt,label='1/Q_opt') + plt.semilogx(om_plot/(2*np.pi),1./Q_pow,label='1/Q_target') + plt.xlabel("Frequency,Hz") + plt.ylabel("$Q^{-1}$") + plt.axvline(min_freq) + plt.axvline(max_freq) + plt.legend() + plt.savefig("Qmodel.jpg") diff --git a/specd/lib/cps330.cpython-311-darwin.so b/specd/lib/cps330.cpython-311-darwin.so new file mode 100755 index 0000000..a55e793 Binary files /dev/null and b/specd/lib/cps330.cpython-311-darwin.so differ diff --git a/specd/lib/libswd.cpython-311-darwin.so b/specd/lib/libswd.cpython-311-darwin.so new file mode 100755 index 0000000..1e7d847 Binary files /dev/null and b/specd/lib/libswd.cpython-311-darwin.so differ diff --git a/specd/specd.py b/specd/specd.py new file mode 100644 index 0000000..6579544 --- /dev/null +++ b/specd/specd.py @@ -0,0 +1,198 @@ +from .lib import libswd +import numpy as np + +def _model_sanity_check(wavetype:str,vph=None,vpv=None,vsh=None,vsv=None, + Qa=None,Qc=None,Qn=None,Ql=None, + c21=None,nQani=None,Qani=None): + if wavetype == "love": + if (vsh is None) or (vsv is None): + print("love wave model mustn't have None vsh/vsv!") + exit(1) + elif wavetype == "rayl": + if (vsv is None) or (vpv is None) or (vph is None): + print("rayleigh wave model mustn't have None vph/vpv/vsv!") + + pass + +class SpecWorkSpace: + + def __init__(self): + self._max_mode = 0 + self._has_att = None + self._use_qz = None + self._wavetype = None + + pass + + def initialize(self,wavetype:str,z:np.ndarray,rho:np.ndarray, + vph=None,vpv=None,vsh=None,vsv=None, + eta=None,Qa=None,Qc=None,Qn=None,Ql=None, + c21=None,nQani=None,Qani=None, + disp=False): + """ + initialize working space for SEM + + Parameters + ---------- + wavetype: str + wavetype, one of ['love','rayl','aniso'] + z: np.ndarray + depth vector, should include discontinuities at half sapce + rho: np.ndarray + density, shape_like(z) + vph/vpv/vsh/vsv: np.ndarray + VTI parameters, shape_like(z) + Qa/Qc/Qn/Ql: np.ndarray + VTI quality factors, shape_like(z) + c21: np.ndarray + 21 elastic tensor, shape(21,nz) + nQani: int + no. of Q models for fully anisotropy + Qnai: np.ndarray + quality factors, shape(nQnai,nz) + disp: bool + if True print model information + + Note + ------------ + The input parameters should be carefully chose by user. For + Love wave, only vsh/vsv/Qsh/Qsv can be enabled, and for + Rayleigh wave, only vph/vpv/vsv can ve enabled, and + other params are for full anisotropy + """ + + self._wavetype = wavetype.lower() + self._use_qz = False + self._nz = len(z) + assert(self._wavetype in ['love','rayl','aniso']) + + _model_sanity_check(wavetype,vph,vpv,vsh,vsv,Qa, + Qc,Qn,Ql,c21,nQani,Qani) + + # init work space by calling libswd + self._has_att = False + if self._wavetype == "love": + if (Qn is not None) and (Ql is not None): + self._has_att = True + libswd.init_love(z,rho,vsh,vsv,Qn,Ql,self._has_att,disp) + + elif self._wavetype == 'rayl': + if (Qn is not None) and (Qa is not None) and (Qc is not None): + self._has_att = True + libswd.init_rayl(z,rho,vph,vpv,vsv,eta,Qa,Qc,Ql, + self._has_att,disp) + else: + print("not implemented!") + assert(0 == 1) + + def compute_egn(self,freq:float,max_order:int = -1,use_qz=True) -> np.ndarray: + """ + compute eigenvalues/eigenvectors + + Parameters + --------- + freq: float + current frequency + max_order: int + no. of orders returns + use_qz: bool + if False, only compute eigenvalues (phase velocities) + if True, phase velocities and eigenfunctions will be computed + + Returns + -------- + c: np.ndarray + phase velocities + """ + + # save use_qz + self._use_qz = use_qz + + if self._has_att: + c = libswd.compute_egn_att(freq,max_order,use_qz) + else: + c = libswd.compute_egn(freq,max_order,use_qz) + + # save current mode number + self._max_mode = len(c) + + return c + + def group_velocity(self,max_order:int = -1) -> np.ndarray: + """ + compute group velocites + + Parameters + ---------- + max_order: int + no. of orders returns + + Returns + -------- + u: np.ndarray + group velocities at current frequency + + Note + ---------- + before calling this routine, use_qz should be True in self.compute_egn + """ + assert self._use_qz ,"please enable use_qz in self.compute_egn" + + if self._has_att: + u = libswd.group_vel(max_order) + else: + u = libswd.group_vel_att(max_order) + + return u + + def get_phase_kl(self,imode:int): + """ + compute phase velocity sensitivity kernels for mode {imode} + + Parameters + ------------- + imode : int + compute kernels at imode, imode \belong [0,max_mode) + + Returns + ----------- + frekl_c: np.ndarray + phase velocity kernels, shape(nkers,self._nz) + frekl_q: np.ndarray + phase velocity Q kernels,shape(nkers,self._nz), only returns when + self._has_att = True + """ + if(imode >= self._max_mode): + print(f"imode should inside [0,{self._max_mode})") + frekl_c,frekl_q = libswd.phase_kl(imode,self._has_att) + + if self._has_att: + return frekl_c,frekl_q + else: + return frekl_c + + def get_group_kl(self,imode:int): + """ + compute group velocity sensitivity kernels for mode {imode} + + Parameters + ------------- + imode : int + compute kernels at imode, imode \belong [0,max_mode) + + Returns + ----------- + frekl_c: np.ndarray + group velocity kernels, shape(nkers,self._nz) + frekl_q: np.ndarray + group velocity Q kernels,shape(nkers,self._nz), only returns when + self._has_att = True + """ + if(imode >= self._max_mode): + print(f"imode should inside [0,{self._max_mode})") + frekl_c,frekl_q = libswd.group_kl(imode,self._has_att) + + if self._has_att: + return frekl_c,frekl_q + else: + return frekl_c \ No newline at end of file diff --git a/src/aniso/CMakeLists.txt b/src/aniso/CMakeLists.txt new file mode 100644 index 0000000..bd66e64 --- /dev/null +++ b/src/aniso/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB SOURCE "*.cpp" ) +list(FILTER SOURCE EXCLUDE REGEX "main*.cpp") + +add_library(aniso ${SOURCE}) + +add_executable(surfani main.cpp) +target_link_libraries(surfani aniso mesh shared LAPACK::LAPACK -llapacke) \ No newline at end of file diff --git a/src/aniso/aniso.hpp b/src/aniso/aniso.hpp new file mode 100644 index 0000000..40aa0d1 --- /dev/null +++ b/src/aniso/aniso.hpp @@ -0,0 +1,70 @@ +#ifndef SPECSWD_ANI_SOLVER_H_ +#define SPECSWD_ANI_SOLVER_H_ + +#include "mesh/mesh.hpp" + +#include +#include + +namespace specswd +{ + +typedef std::complex scmplx; + +class SolverAni { + +private: + // solver matrices + std::vector Mmat,Emat,Kmat,Hmat; + std::vector CMmat,CEmat,CKmat,CHmat; + + // QZ matrix all are column major + std::vector Qmat_,Zmat_,Smat_,Spmat_; // column major! + std::vector cQmat_,cZmat_,cSmat_,cSpmat_; + +public: + + // eigenfunctions/values + void prepare_matrices(const Mesh &M); + void compute_egn(const Mesh &M, + std::vector &c, + std::vector &egn, + bool use_qz=false); + void compute_egn_att(const Mesh &M, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz=false); + + // group velocity + float group_vel(const Mesh &M, + float c,const scmplx *egn) const; + scmplx group_vel_att(const Mesh &M, + scmplx c, const scmplx *ur, + const scmplx *ul) const ; + + // phase velocity kernels + void compute_phase_kl(const Mesh &M, + float c,const float *egn, + std::vector &frekl) const; + void compute_phase_kl_att(const Mesh &M, + scmplx c, const scmplx *egn, + std::vector &frekl_c, + std::vector &frekl_q) const; + + // tranforms + void egn2displ(const Mesh &M, + float c, + const scmplx *egn, + scmplx * __restrict displ) const; + void egn2displ_att(const Mesh &M, + scmplx c,const scmplx *egn, + scmplx * __restrict displ) const; + void transform_kernels(std::vector &frekl) const; +}; + + +} // namespace specswd + + +#endif \ No newline at end of file diff --git a/src/aniso/eigenvalues.cpp b/src/aniso/eigenvalues.cpp new file mode 100644 index 0000000..e166450 --- /dev/null +++ b/src/aniso/eigenvalues.cpp @@ -0,0 +1,216 @@ +#include "aniso/aniso.hpp" +#include "shared/schur.hpp" + +#include +#include + +namespace specswd +{ + +/** + * @brief compute Love wave dispersion and eigenfunctions, elastic case + * + * @param mesh Mesh class + * @param c dispersion, shape(nc) + * @param egn eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if true, save QZ matrix + */ +void SolverAni:: +compute_egn(const Mesh &mesh, + std::vector &c, + std::vector &egn, + bool use_qz) +{ + typedef Eigen::MatrixX crmat2; + using Eigen::indexing::all; + using Eigen::indexing::seq; + + // mapping M,K,E to matrix + int ng = mesh.nglob_el*3 + mesh.nglob_ac; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map> E(Emat.data(),ng,ng); + Eigen::Map> H(Hmat.data(),ng,ng); + + // construct A = (om^2 M - E), B = K + float freq = mesh.freq; + const crealw imag_i{0.,1.}; + realw om = 2. * M_PI * freq; + realw omega2 = std::pow(om,2); + crmat2 A(ng*2,ng*2), B(ng*2,ng*2); + auto idx1 = seq(0,ng-1), idx2 = seq(ng,ng*2-1); + A.setZero(); B.setZero(); + A(idx1,idx2).setIdentity(); + A(idx2,idx1) = omega2 * crmat2(M.cast().asDiagonal()) - E.cast(); + A(idx2,idx2) = H.cast() *imag_i; + B(idx1,idx1).setIdentity(); + B(idx2,idx2) = K.cast(); + + // allocate eigenvalues/eigenvectors + Eigen::ArrayX k_all(ng*2); + Eigen::MatrixX vsr; + + if(!use_qz) { + LAPACKE_CMPLX(hegvd)( + LAPACK_COL_MAJOR,1,'V','U',ng*2, + (LCREALW*)A.data(),ng*2, + (LCREALW*)B.data(),ng*2,k_all.data() + ); + + k_all = k_all.cast().sqrt().real(); + } + else { + Eigen::ArrayX k2_all(ng*2); + vsr.resize(ng*2,ng*2); + schur_qz( + A,B,k2_all,vsr.data(),nullptr, + cQmat_,cZmat_,cSmat_,cSpmat_, + false + ); + k_all = k2_all.sqrt().real(); + } + + Eigen::ArrayX c_all = om / k_all; + auto mask = ((c_all >= mesh.PHASE_VELOC_MIN)&& + (c_all <= mesh.PHASE_VELOC_MAX) && + k_all.real().abs() >= 10 *k_all.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort according to ascending order + int nc = idx0.size(); + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c/displ + c.resize(nc); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + } + + if(use_qz) { + egn.resize(nc * ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + for(int i = 0; i < ng; i ++) { + egn[ic * ng + i] = vsr(i,id); + } + } + } +} + +/** + * @brief compute Love wave dispersion and eigenfunctions, elastic case + * + * @param mesh Mesh class + * @param c dispersion, shape(nc) + * @param ur,ul left/right eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if true, save QZ matrix + */ +void SolverAni:: +compute_egn_att(const Mesh &mesh, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::MatrixX crmat2; + using Eigen::indexing::all; + using Eigen::indexing::seq; + + // mapping M,K,E to matrix + int ng = mesh.nglob_el*3 + mesh.nglob_ac; + Eigen::Map M(CMmat.data(),ng); + Eigen::Map K(CKmat.data(),ng); + Eigen::Map> E(CEmat.data(),ng,ng); + Eigen::Map> H(CHmat.data(),ng,ng); + + // construct A = (om^2 M - E), B = K + float freq = mesh.freq; + const crealw imag_i{0.,1.}; + realw om = 2. * M_PI * freq; + realw omega2 = std::pow(om,2); + crmat2 A(ng*2,ng*2), B(ng*2,ng*2); + auto idx1 = seq(0,ng-1), idx2 = seq(ng,ng*2-1); + A.setZero(); B.setZero(); + A(idx1,idx2).setIdentity(); + A(idx2,idx1) = omega2 * crmat2(M.cast().asDiagonal()) - E.cast(); + A(idx2,idx2) = H.cast() *imag_i; + B(idx1,idx1).setIdentity(); + B(idx2,idx2) = K.cast(); + + // allocate eigenvalues/eigenvectors + Eigen::ArrayX k_all(ng*2); + Eigen::MatrixX vsr,vsl; + + if(!use_qz) { // only compute phase velocity + Eigen::ArrayX beta(ng); + LAPACKE_CMPLX(ggev)( + LAPACK_COL_MAJOR,'N','N',ng,(LCREALW*)A.data(), + ng,(LCREALW*)B.data(),ng, + (LCREALW*)k_all.data(),(LCREALW*)beta.data(), + nullptr,ng,nullptr,ng + ); + k_all = k_all / beta; + } + else { + vsr.resize(ng*2,ng*2); + vsl.resize(ng*2,ng*2); + schur_qz( + A,B,k_all,vsr.data(),nullptr, + cQmat_,cZmat_,cSmat_,cSpmat_, + true + ); + } + k_all = k_all.sqrt(); + + Eigen::ArrayX c_all = om / k_all; + auto mask = ((c_all >= mesh.PHASE_VELOC_MIN)&& + (c_all <= mesh.PHASE_VELOC_MAX) && + k_all.real().abs() >= k_all.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort according to ascending order + int nc = idx0.size(); + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) + {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c/displ + c.resize(nc); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + } + + if(use_qz) { + ur.resize(nc * ng); ul.resize(nc * ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + for(int i = 0; i < ng; i ++) { + ul[ic * ng + i] = vsl(i,id); + ur[ic * ng + i] = vsr(i,id); + } + } + } +} + +} // namespace specswd diff --git a/src/aniso/group_velocity.cpp b/src/aniso/group_velocity.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/aniso/sem.cpp b/src/aniso/sem.cpp new file mode 100644 index 0000000..f295c5a --- /dev/null +++ b/src/aniso/sem.cpp @@ -0,0 +1,262 @@ +#include "shared/GQTable.hpp" +#include "aniso/aniso.hpp" + +namespace specswd +{ + + +using std::vector; + +/** + * @brief preparing anisotropic matrix M/H/K/E, note we don't multiply I to H + * + * @tparam T data type, default float + * @param freq input data type, float or complex + * @param nspec_el no. of elastic GLL elements + * @param nspec_ac no. of acoustic GLL elements + * @param nspec_el_grl no. of elastic GRL elements + * @param nspec_ac_grl no. of acoustic GRL elements + * @param nglob_el unique points in elastic domain + * @param nglob_ac unique points in acoustic domain + * @param el_elmnts mapping from el elements to global index + * @param ac_elmnts mapping from ac elements to global index + * @param xrho_el density in elastic domain + * @param xrho_ac density in acoustic domain + * @param ibool_el connectivity matrix,in el shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param ibool_ac connectivity matrix,in ac shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param jaco jacobians, shape(nspec_ac+nspec_el+1) + * @param xc21 21 elastic tensor, shape(21,size_el) + * @param nQmodel no. of quality factors used + * @param xQani Quality factors in el domain, shape(nQmodel, size_el) + * @param xkappa_ac kappa in ac domain + * @param xQk_ac Qkappa, in ac domain + * @param nfaces_bdry no. of el-ac interfaces + * @param ispec_bdry element index on each side, (ispec_ac,ispec_el) = ispec_bdry[i,:], shape(nfaces_bdry,2) + * @param bdry_norm_direc if the ac-> el normal vector is downward + * @param Mmat,Kmat,Hmat,Emat M/K/H/E matrices + */ +template +void +prepare_aniso_(float freq,int nspec_el,int nspec_ac,int nspec_el_grl, + int nspec_ac_grl,int nglob_el,int nglob_ac,int nQmodel, + const int *el_elmnts,const int *ac_elmnts, + const float *xrho_el,const float *xrho_ac, + const int* ibool_el, const int* ibool_ac, + const float *jaco,const float *xc21, + const float *xQani,const float *xkappa_ac, + const float *xQk_ac,int nfaces_bdry, + const int* ispec_bdry,const char *bdry_norm_direc, + float phi,vector &Mmat, + vector &Kmat,vector &Hmat,vector &Emat) +{ + // allocate space and set zero + int ng = nglob_ac + nglob_el * 3; + Mmat.resize(ng); + Emat.resize(ng * ng); + Kmat.resize(ng); Hmat.resize(ng*ng); + std::fill(Mmat.begin(),Mmat.end(),(T)0.); + std::fill(Emat.begin(),Emat.end(),(T)0.); + std::fill(Kmat.begin(),Kmat.end(),(T)0.); + std::fill(Hmat.begin(),Hmat.end(),(T)0.); + + // direction + float k[2] = {std::cos(phi),std::sin(phi)}; + + // temp arrays to save elastic tensor + using namespace GQTable; + const int size_el = nspec_el*NGLL + nspec_el_grl * NGRL; + std::array sumC21; + #define C21(i,j,p,q,a) sumC21[a*NGRL + Index(i,j,p,q)] + + // compute M/K/H/E for gll/grl layer, elastic + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id = ispec * NGLL; + float J = jaco[iel]; + + // get const arrays + const bool is_gll = (ispec != nspec_el); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hpT = is_gll? hprimeT.data(): hprimeT_grl.data(); + const float *hp = is_gll? hprime.data(): hprime_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + for(int idx = 0; idx < 21; idx ++) { + sumC21[i*NGRL+idx] = xc21[idx*size_el+i]; + } + + // apply Q model to C21 if required + if constexpr (std::is_same_v) { + std::array Qm; + for(int q = 0; q < nQmodel; q ++) { + Qm[q] = xQani[q*size_el+i]; + } + set_C21_att_model(freq,Qm.data(),nQmodel, + &sumC21[i*NGRL]); + } + + + // add other terms + for(int idx = 0; idx < 21; idx ++) { + sumC21[i*NGRL+idx] *= J * weight[i]; + } + } + + // assemble H/E + for(int a = 0; a < NGL; a ++) { + int iglob = ibool_el[id + a]; + for(int b = 0; b < NGL; b ++) { + int iglob1 = ibool_el[id+b]; + + // loop each component + for(int i = 0; i < 3; i ++) { + for(int p = 0; p < 3; p ++) { + int idx = (i*nglob_el+iglob)*ng+(p*nglob_el+iglob1); + + // E + T sx{}; + for(int s = 0; s < NGL; s ++) { + sx += C21(i,2,p,2,s) * hpT[a*NGL+s] * hpT[b*NGL+s]; + } + Emat[idx] += sx / (J * J); + + // H + T temp1 = C21(i,0,p,2,a) * k[0] + + C21(i,1,p,2,a) * k[1]; + T temp2 = C21(i,2,p,0,b) * k[0] + + C21(i,2,p,1,b) * k[1]; + Hmat[idx] += temp1 * hp[a*NGL+b] - + temp2 * hpT[a*NGL+b]; + }} + } + } + + // compute M/K + for(int a = 0; a < NGL; a ++) { + int iglob = ibool_el[id + a]; + + // compute mass matrix + T M0 = weight[a] * J * xrho_el[id + a]; + for(int i = 0; i < 3; i ++) { + Mmat[iglob + nglob_el * i] += M0; + for(int p = 0; p < 3; p ++) { + T temp = C21(i,0,p,0,a) * k[0] * k[0] + + C21(i,0,p,1,a) * k[0] * k[1] + + C21(i,1,p,0,a) * k[0] * k[1] + + C21(i,1,p,1,a) * k[1] * k[1]; + int idx = (i*nglob_el+iglob) * ng + (p*nglob_el+iglob); + Kmat[idx] += temp; + } + } + } + } + + // acoustic case + std::array sumL; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { + int iel = ac_elmnts[ispec]; + int id = ispec * NGLL; + + // get const arrays + const bool is_gll = (ispec != nspec_el); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hpT = is_gll? hprimeT.data(): hprimeT_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + sumL[i] = weight[i] / jaco[iel] / xrho_ac[id+i]; + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int ig0 = ibool_ac[id + i]; + if(ig0 == -1) continue; + int iglob = ig0 + nglob_el * 3; + T temp = weight[i] * jaco[iel]; + + // assemble M and K + T sk = 1.; + if constexpr (std::is_same_v) { + sk = get_sls_modulus_factor(freq,xQk_ac[id+i]); + } + Mmat[iglob] += temp / (sk * xkappa_ac[id + i]); + Kmat[iglob * ng + iglob] += temp / xrho_ac[id + i]; + + // assemble E + for(int j = 0; j < NGL; j ++) { + int ig1 = ibool_ac[id + j]; + if(ig1 == -1) continue; + int iglob1 = ig1 + nglob_el * 3; + T s{}; + for(int m = 0; m < NGL; m ++) { + s += sumL[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * ng + iglob1] += s; + } + } + } + + // acoustic-elastic boundary + float om = M_PI * 2 * freq; + for(int iface = 0; iface < nfaces_bdry; iface ++) { + int ispec_ac = ispec_bdry[iface * 2 + 0]; + int ispec_el = ispec_bdry[iface * 2 + 1]; + T norm = -1.; + int igll_el = 0; + int igll_ac = NGLL - 1; + if(!bdry_norm_direc[iface]) { + norm = 1.; + igll_ac = 0; + igll_el = NGLL - 1; + } + + // get ac/el global loc + int iglob_el = ibool_el[ispec_el * NGLL + igll_el]; + int iglob_ac = ibool_ac[ispec_ac * NGLL + igll_ac]; + + // add contribution to E mat, elastic case + // E(nglob_el + iglob_el, nglob_el*2 + iglob_ac) += + int id = (nglob_el*2 + iglob_el) * ng + (nglob_el * 3 + iglob_ac); + Emat[id] += (T)(om * om * norm); + + // acoustic case + // E(nglob_el*2 + iglob_ac, nglob_el + iglob_el) += norm + id = (nglob_el*3 + iglob_ac) * ng + (nglob_el*2 + iglob_el); + Emat[id] += (T)norm; + } + + #undef C21 +} + +void SolverAni:: +prepare_matrices(const Mesh &M) +{ + if(!M.HAS_ATT) { + prepare_aniso_( + M.freq,M.nspec_el,M.nspec_ac,M.nspec_el_grl,M.nspec_ac_grl, + M.nglob_el,M.nglob_ac,M.nQmodel_ani,M.el_elmnts.data(), + M.ac_elmnts.data(),M.xrho_el.data(),M.xrho_ac.data(), + M.ibool_el.data(),M.ibool_ac.data(),M.jaco.data(), + M.xC21.data(),M.xQani.data(),M.xkappa_ac.data(), + M.xQk_ac.data(),M.nfaces_bdry,M.ispec_bdry.data(), + M.bdry_norm_direc.data(),M.phi,Mmat,Kmat,Hmat,Emat + ); + } + else { + prepare_aniso_( + M.freq,M.nspec_el,M.nspec_ac,M.nspec_el_grl,M.nspec_ac_grl, + M.nglob_el,M.nglob_ac,M.nQmodel_ani,M.el_elmnts.data(), + M.ac_elmnts.data(),M.xrho_el.data(),M.xrho_ac.data(), + M.ibool_el.data(),M.ibool_ac.data(),M.jaco.data(), + M.xC21.data(),M.xQani.data(),M.xkappa_ac.data(), + M.xQk_ac.data(),M.nfaces_bdry,M.ispec_bdry.data(), + M.bdry_norm_direc.data(),M.phi,CMmat,CKmat,CHmat,CEmat + ); + } +} + + +} // namespace specswd \ No newline at end of file diff --git a/src/aniso/transform.cpp b/src/aniso/transform.cpp new file mode 100644 index 0000000..62c2e26 --- /dev/null +++ b/src/aniso/transform.cpp @@ -0,0 +1,133 @@ +#include "aniso/aniso.hpp" +#include "shared/GQTable.hpp" + +namespace specswd +{ + +void +egn2displ_aniso(int nspec_el,int nspec_ac,int nspec_el_grl,int nspec_ac_grl, + int nglob_el,int nglob_ac,const float* jaco, + const int *ibool_el,const int *ibool_ac, const int *el_elmnts, + const int *ac_elmnts,const float *xrho_ac, + const scmplx *egn, float freq,scmplx c, + float phi,scmplx * __restrict displ) +{ + + // get wave number and it's direction + scmplx wvnm = (scmplx)(M_PI * 2.) * freq / c; + scmplx khat[2] = {std::cos(phi),std::sin(phi)}; + const scmplx I = scmplx{0.,1.}; + + // size + using namespace GQTable; + int npts = (nspec_el + nspec_ac) * NGLL + (nspec_ac_grl + nspec_el_grl) * NGRL; + + // loop elastic elements + for(int ispec = 0; ispec < nspec_el+nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + int NGL = NGLL; + + // grl case + if(ispec == nspec_el) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id0+i]; + for(int j = 0; j < 3; j ++) { + displ[j*npts + id1+i] = egn[iglob + nglob_el * j]; + } + } + } + + // loop each acoustic element + std::array chi; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec += 1) { + int iel = ac_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + const float *hp = &hprime[0]; + const float J = jaco[iel]; + + // GRL layer + if(ispec == nspec_ac) { + NGL = NGRL; + hp = &hprime_grl[0]; + } + + // cache chi in an element + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int iglob = ibool_ac[id]; + chi[i] = (iglob == -1) ? (scmplx)0.: egn[nglob_el * 2 + iglob]; + } + + + // compute derivative dchi / dz + for(int i = 0; i < NGL; i ++) { + scmplx dchi{}; + for(int j = 0; j < NGL; j ++) { + dchi += chi[j] * hp[i * NGL + j]; + } + dchi /= J; + + // set value to displ + displ[0*npts + id1+i] = -I * chi[i] * khat[0] / xrho_ac[id0 + i]; + displ[1*npts + id1+i] = -I * chi[i] * khat[1] / xrho_ac[id0 + i]; + displ[2*npts + id1+i] = dchi / xrho_ac[id0 + i]; + } + } +} + +/** + * @brief convert right eigenfunction to displacement, elastic case + * + * @param M Mesh class + * @param c current phase velocity + * @param egn eigenfunction,shape(nglob_el*2+nglob_ac) + * @param displ displacement, shape(2,npts) + */ +void SolverAni:: +egn2displ(const Mesh &M, + float c, + const scmplx *egn, + scmplx * __restrict displ) const +{ + egn2displ_aniso( + M.nspec_el,M.nspec_ac,M.nspec_el_grl, + M.nspec_ac_grl,M.nglob_el,M.nglob_ac, + M.jaco.data(),M.ibool_el.data(), + M.ibool_ac.data(),M.el_elmnts.data(), + M.ac_elmnts.data(),M.xrho_ac.data(), + egn,M.freq,(scmplx)c,M.phi,displ + ); +} + +/** + * @brief convert right eigenfunction to displacement, elastic case + * + * @param M Mesh class + * @param c current phase velocity + * @param egn eigenfunction,shape(nglob_el*2+nglob_ac) + * @param displ displacement, shape(2,npts) + */ +void SolverAni:: +egn2displ_att(const Mesh &M, + scmplx c, + const scmplx *egn, + scmplx * __restrict displ) const +{ + egn2displ_aniso( + M.nspec_el,M.nspec_ac,M.nspec_el_grl, + M.nspec_ac_grl,M.nglob_el,M.nglob_ac, + M.jaco.data(),M.ibool_el.data(), + M.ibool_ac.data(),M.el_elmnts.data(), + M.ac_elmnts.data(),M.xrho_ac.data(), + egn,M.freq,c,M.phi,displ + ); +} + +} // namespace specswd diff --git a/src/cps330/CMakeLists.txt b/src/cps330/CMakeLists.txt index 61f972a..0212472 100644 --- a/src/cps330/CMakeLists.txt +++ b/src/cps330/CMakeLists.txt @@ -8,4 +8,9 @@ install(TARGETS cps330 COMPONENT python LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/lib ) + +install(TARGETS cps330 + COMPONENT python + LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/specd/lib +) # add_library(libcps330 ${SOURCE}) \ No newline at end of file diff --git a/src/cps330/main.cpp b/src/cps330/main.cpp index 1d311e0..3e003d4 100644 --- a/src/cps330/main.cpp +++ b/src/cps330/main.cpp @@ -6,10 +6,12 @@ namespace py = pybind11; using py::arg; -typedef py::array_t ftensor; -typedef py::array_t dtensor; -typedef std::tuple tupledt6; -typedef std::tuple tuple2; +namespace py = pybind11; + +const auto FCST = (py::array::c_style | py::array::forcecast) ; +typedef py::array_t fvec; +typedef py::array_t dvec; +typedef std::tuple tuple2; /** * calculates the dispersion values for any layered model, any frequency, and any mode. @@ -59,8 +61,8 @@ int _surfdisp(float *thk,float *vp,float *vs,float *rho, return ierr; } -tuple2 forward(ftensor &thk,ftensor &vp,ftensor &vs,ftensor &rho, - dtensor &t,std::string wavetype, +tuple2 forward(fvec &thk,fvec &vp,fvec &vs,fvec &rho, + dvec &t,const std::string &wavetype, int mode=0,bool sphere=false) { // check input parameters @@ -74,7 +76,7 @@ tuple2 forward(ftensor &thk,ftensor &vp,ftensor &vs,ftensor &rho, // allocate space int nt = t.size(), n = thk.size(); - dtensor cg(nt); + dvec cg(nt); int ierr; ierr = _surfdisp(thk.mutable_data(),vp.mutable_data(),vs.mutable_data(), rho.mutable_data(),n,t.mutable_data(),cg.mutable_data(), diff --git a/src/libswd/CMakeLists.txt b/src/libswd/CMakeLists.txt index b790f4c..2d7e37f 100644 --- a/src/libswd/CMakeLists.txt +++ b/src/libswd/CMakeLists.txt @@ -1,13 +1,24 @@ -#file(GLOB SOURCE "*.f") -#list(FILTER SOURCE EXCLUDE REGEX "main.cpp") -#message("myfile = ${SOURCE}") -pybind11_add_module(libswd main.cpp utils.cpp) -target_link_libraries(libswd PRIVATE libvti libtti shared ) -set_target_properties(libvti libtti shared PROPERTIES POSITION_INDEPENDENT_CODE ON) +# pylib +pybind11_add_module(libswd main.cpp pack.cpp init.cpp) +target_link_libraries(libswd PRIVATE vti mesh shared ${LAPACKE_LIBRARIES} ) +set_target_properties(vti mesh shared PROPERTIES POSITION_INDEPENDENT_CODE ON) #target_include_directories(libswd PUBLIC ${PROJECT_SOURCE_DIR}/src) +install(TARGETS libswd + COMPONENT python + LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/specd/lib/ +) install(TARGETS libswd COMPONENT python LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/lib ) + +# # .so +# add_library(specswd SHARED pack.cpp) +# set_target_properties(specswd PROPERTIES PUBLIC_HEADER specswd.hpp ) +# target_link_libraries(specswd PRIVATE vti mesh shared LAPACK::LAPACK -llapacke ) +# install(TARGETS specswd +# LIBRARY DESTINATION ${PROJECT_SOURCE_DIR}/lib +# PUBLIC_HEADER DESTINATION ${PROJECT_SOURCE_DIR}/include +# ) # add_library(libcps330 ${SOURCE}) \ No newline at end of file diff --git a/src/libswd/global.hpp b/src/libswd/global.hpp new file mode 100644 index 0000000..51f3dc8 --- /dev/null +++ b/src/libswd/global.hpp @@ -0,0 +1,27 @@ +#ifndef SPECSWD_LIB_GLOB_H_ +#define SPECSWD_LIB_GLOB_H_ + +#include "mesh/mesh.hpp" +#include "vti/vti.hpp" + +#include +#include + +#define CNAME(a) extern "C" void a + +// global vars for solver/mesh + +namespace specswd_pylib +{ + +extern std::unique_ptr M_; +extern std::unique_ptr LoveSol_; +extern std::unique_ptr RaylSol_; + +// global vars for eigenvalues/eigenvectors +extern std::vector egnr_,egnl_,c_,u_; +extern std::vector cegnr_,cegnl_,cc_,cu_; + +} // namespace specswd_pylib + +#endif \ No newline at end of file diff --git a/src/libswd/init.cpp b/src/libswd/init.cpp new file mode 100644 index 0000000..c0e5bdd --- /dev/null +++ b/src/libswd/init.cpp @@ -0,0 +1,51 @@ +#include "shared/GQTable.hpp" +#include "shared/attenuation.hpp" +#include "libswd/global.hpp" + +extern "C" void +specswd_init_GQTable() { + GQTable::initialize(); +} + +extern "C" void +specswd_reset_Qmodel(const double *w,const double *y) +{ + specswd::reset_ref_Q_model(w,y); +} + +/** + * @brief compute kernel size (nker,nz) + * @param nkers no. of kernels + * @param nz size of input tomo model + */ +extern "C" void +specswd_kernel_size(int *nkers,int *nz) +{ + using namespace specswd_pylib; + bool HAS_ATT = M_ -> HAS_ATT; + int SWD_TYPE = M_ -> SWD_TYPE; + *nz = M_ -> nz_tomo; + int nker{}; + + if(SWD_TYPE == 0) { + nker = 3; + if (HAS_ATT) { + nker = 5; + } + } + else if (SWD_TYPE == 1) { + nker = 5; + if (HAS_ATT) { + nker = 10; + } + } + else { + nker = 22; + if(HAS_ATT) { + nker += M_ -> nQmodel_ani; + } + } + + // copy to output + *nkers = nker; +} \ No newline at end of file diff --git a/src/libswd/main.cpp b/src/libswd/main.cpp index 0b0aa11..e1430da 100644 --- a/src/libswd/main.cpp +++ b/src/libswd/main.cpp @@ -1,149 +1,248 @@ + +#include "libswd/specswd.hpp" +#include "libswd/global.hpp" + #include #include #include -#include "libswd/utils.hpp" - namespace py = pybind11; +using namespace py::literals; using py::arg; -typedef py::array_t ftensor; -typedef py::array_t dtensor; -typedef std::tuple tupledt6; -typedef std::tuple tuple2; +const auto FCST = (py::array::c_style | py::array::forcecast) ; +typedef py::array_t vec; +typedef py::array_t,FCST> cvec; -static int -check_wavetype(const std::string &wavetype) +void init_love(const vec &z,const vec &rho, + const vec &vsh, const vec &vsv, + const vec &QN, const vec &QL, + bool HAS_ATT,bool print_info) { - // check input parameters - bool flag = wavetype == "Rc" || wavetype == "L"; - if(flag == false){ - std::cout << "parameter wavetp should be in one of [R,L]\n "; - exit(0); + // init GQtable + specswd_init_GQTable(); + + // get pointer + const float *qn = nullptr, *ql = nullptr; + if(HAS_ATT) { + qn = QN.data(); + ql = QL.data(); } - int iwave = 1; - if(wavetype[0] == 'R') { - iwave = 2; + + // init mesh + int nz = z.size(); + specswd_init_mesh_love( + nz,z.data(),rho.data(),vsh.data(),vsv.data(), + qn,ql,HAS_ATT,print_info + ); +} + +void init_rayl(const vec &z,const vec &rho, + const vec &vph, const vec &vpv, + const vec &vsv,const vec &eta, + const vec &QA,const vec &QC, + const vec &QL,bool HAS_ATT, + bool print_info) +{ + // init GQtable + specswd_init_GQTable(); + + // get pointer + const float *qa = nullptr, + *ql = nullptr, + *qc = nullptr; + if(HAS_ATT) { + qa = QA.data(); + ql = QL.data(); + qc = QC.data(); } - return iwave; + int nz = z.size(); + specswd_init_mesh_rayl( + nz,z.data(),rho.data(),vph.data(),vpv.data(), + vsv.data(),eta.data(),qa,qc,ql,HAS_ATT,print_info + ); } -auto -swdvti(const ftensor &thk,const ftensor &vpv,const ftensor &vph, - const ftensor &vsv,const ftensor &vsh,const ftensor &eta,const ftensor &rho, - const dtensor &t,const std::string &wavetype, bool only_phase, - int mode=0) +template py::array_t +compute_swd(float freq,int max_order,bool use_qz) { - int iwave = check_wavetype(wavetype); + using namespace specswd_pylib; + py::array_t c_out; + const int SWD_TYPE = M_->SWD_TYPE; + const bool HAS_ATT = M_->HAS_ATT; + + // get phase velocities + switch (SWD_TYPE) + { + case 0: + specswd_egn_love(freq,use_qz); + break; + case 1: + specswd_egn_rayl(freq,use_qz); + break; + default: + break; + } // allocate space - int nt = t.size(), n = thk.size(); - dtensor cg(nt),cp(nt); + int nc = (HAS_ATT) ? cc_.size() : c_.size(); + const T *c_glob = nullptr; + if constexpr (std::is_same_v) { + c_glob = c_.data(); + } + else { + c_glob = cc_.data(); + } + if (max_order < 0 || max_order > nc ) { + max_order = nc; + } + c_out.resize({max_order}); - __surfvti(thk.data(),vph.data(),vpv.data(),vsh.data(),vsv.data(),eta.data(), - rho.data(),n,nt,mode,iwave,only_phase,t.data(),cp.mutable_data(), - cg.mutable_data()); - if(only_phase) cg = cp; + // copy phase velocity to c_out + auto c = c_out.template mutable_unchecked<1>(); + for(int ic = 0; ic < max_order; ic ++) { + c(ic) = c_glob[ic]; + } - return std::make_tuple(cp,cg); + return c_out; } -auto -vti_kl(const ftensor &thk,const ftensor &vpv,const ftensor &vph, - const ftensor &vsv,const ftensor &vsh,const ftensor &eta, - const ftensor &rho,const dtensor &t, - const std::string &wavetype,int mode=0) +template py::array_t +compute_group_vel(int max_order) { - int iwave = check_wavetype(wavetype); - int nt = t.size(), n = thk.size(); - dtensor cg(nt),cp(nt); - - auto frekl = __surfvti_kl(thk.data(),vph.data(),vpv.data(),vsh.data(),vsv.data(), - eta.data(),rho.data(),n,nt,mode,iwave, - t.data(),cp.mutable_data(),cg.mutable_data()); - int nker = frekl.size() / (n * nt); - dtensor frekl_out({nt,nker,n}); - memcpy(frekl_out.mutable_data(),frekl.data(),frekl.size() * sizeof(double)); - - return std::make_tuple(cp,cg,frekl_out); -} + using namespace specswd_pylib; + py::array_t u_out; + const int SWD_TYPE = M_->SWD_TYPE; + const bool HAS_ATT = M_->HAS_ATT; + + // get phase velocities + switch (SWD_TYPE) + { + case 0: + specswd_group_love(); + break; + case 1: + specswd_group_rayl(); + break; + default: + break; + } + + // allocate space + int nc = (HAS_ATT) ? cu_.size() : u_.size(); + const T *u_glob = nullptr; + if constexpr (std::is_same_v) { + u_glob = u_.data(); + } + else { + u_glob = cu_.data(); + } + if (max_order < 0 || max_order > nc ) { + max_order = nc; + } + u_out.resize({max_order}); + // copy phase velocity to c_out + auto u = u_out.template mutable_unchecked<1>(); + for(int ic = 0; ic < max_order; ic ++) { + u(ic) = u_glob[ic]; + } + return u_out; +} -// -auto -swdiso(const ftensor &thk,const ftensor &vp,const ftensor &vs,const ftensor &rho, - const dtensor &t,const std::string &wavetype, bool only_phase, - int mode=0) +std::tuple +compute_phase_kl(int imode,bool HAS_ATT) { - ftensor eta(thk.size()); - for(size_t i = 0; i < thk.size(); i++ ) eta.mutable_data()[i] = 1.; - return swdvti(thk,vp,vp,vs,vs,eta,rho,t,wavetype,only_phase,mode); + int nkers,nz; + specswd_kernel_size(&nkers,&nz); + vec frekl_c({nkers,nz}),frekl_q; + if(HAS_ATT) { + frekl_q.reshape({nkers,nz}); + } + else { + frekl_q.resize({0,0}); + } + + // compute kernels + specswd_phase_kl( + imode, + frekl_c.mutable_data(), + frekl_q.mutable_data() + ); + + return std::make_tuple(frekl_c,frekl_q); } -auto -iso_kl(const ftensor &thk,const ftensor &vp,const ftensor &vs,const ftensor &rho, - const dtensor &t,const std::string wavetype,int mode=0) +std::tuple +compute_group_kl(int imode,bool HAS_ATT) { - dtensor cp,cg,frekl; - ftensor eta(thk.size()); - for(size_t i = 0; i < thk.size(); i++ ) eta.mutable_data()[i] = 1.; - std::tie(cp,cg,frekl) = vti_kl(thk,vp,vp,vs,vs,eta,rho,t,wavetype,mode); - - int iwave = check_wavetype(wavetype); - auto kl = frekl.unchecked<3>(); - - // convert to iso type - auto shape = frekl.shape(); - int nker = shape[1], n = shape[2], nt = shape[0]; - dtensor frekl_out; - if(iwave == 1) { // love wave - frekl_out.resize({nt,2,n}); - auto data = frekl_out.mutable_unchecked<3>(); - - for(int it = 0; it < nt; it ++) { - for(int i = 0; i < n; i ++) { - data(it,0,i) = kl(it,0,i) + kl(it,1,i); - data(it,1,i) = kl(it,2,i); - } - } + int nkers,nz; + specswd_kernel_size(&nkers,&nz); + vec frekl_c({nkers,nz}),frekl_q; + if(HAS_ATT) { + frekl_q.reshape({nkers,nz}); } else { - frekl_out.resize({nt,3,n}); - auto data = frekl_out.mutable_unchecked<3>(); - for(int it = 0; it < nt; it ++) { - for(int i = 0; i < n; i ++) { - data(it,0,i) = kl(it,0,i) + kl(it,1,i); // vp - data(it,1,i) = kl(it,2,i); // vs - data(it,2,i) = kl(it,4,i); // rho - } - } + frekl_q.resize({0,0}); } - - return std::make_tuple(cp,cg,frekl_out); -} + // compute kernels + specswd_group_kl( + imode, + frekl_c.mutable_data(), + frekl_q.mutable_data() + ); + + return std::make_tuple(frekl_c,frekl_q); +} PYBIND11_MODULE(libswd,m){ m.doc() = "Surface wave dispersion and sensivity kernel\n"; - m.def("swdiso",&swdiso,arg("thk"),arg("vp"),arg("vs"), - arg("rho"),arg("period"),arg("wavetype"),arg("only_phase"), - arg("mode")=0, - "ISO surface wave dispersion c++ wrapper"); - - m.def("iso_kl",&iso_kl,arg("thk"),arg("vp"),arg("vs"), - arg("rho"),arg("period"),arg("wavetype"),arg("mode")=0, - "ISO surface wave kernel c++ wrapper"); - - m.def("swdvti",&swdvti,arg("thk"),arg("vpv"),arg("vph"),arg("vsv"), - arg("vsh"),arg("eta"),arg("rho"),arg("period"),arg("wavetype"),arg("only_phase"), - arg("mode")=0, - "VTI surface wave dispersion c++ wrapper"); - - m.def("vti_kl",&vti_kl,arg("thk"),arg("vpv"),arg("vph"),arg("vsv"), - arg("vsh"),arg("eta"),arg("rho"),arg("period"),arg("wavetype"),arg("mode")=0, - "VTI surface wave kernel c++ wrapper"); + m.def( + "init_love",&init_love,arg("z"),arg("rho"), + arg("vsh"),arg("vsv"),arg("QN"),arg("QL"), + arg("HAS_ATT") = false, + arg("print_info") = false, + "initialize global vars for love wave" + ); + + m.def("init_rayl",&init_rayl,arg("z"), + arg("rho"),arg("vph"), + arg("vpv"),arg("vsv"), arg("eta"), + arg("QA"),arg("QC"), + arg("QL"),arg("HAS_ATT") = false, + arg("print_info") = false, + "initialize global vars for rayleigh wave"); + + m.def("compute_egn",&compute_swd, + arg("freq"),arg("max_order"), + arg("use_qz")=true, + "compute dispersions for elastic wave"); + + m.def("compute_egn_att",&compute_swd>, + arg("freq"),arg("max_order"),arg("use_qz")=true, + "compute dispersions for visco-elastic wave"); + + m.def("group_vel",&compute_group_vel, + arg("max_order"), + "compute group velocity for elastic wave"); + + m.def("group_vel_att",&compute_group_vel>, + arg("max_order"), + "compute group velocity for visco-elastic wave"); + m.def( + "phase_kl",&compute_phase_kl, + arg("imode"),arg("HAS_ATT"), + "compute phase velocity sensitivity kernels" + ); + + m.def( + "group_kl",&compute_group_kl, + arg("imode"),arg("HAS_ATT"), + "compute groupvelocity sensitivity kernels" + ); } \ No newline at end of file diff --git a/src/libswd/pack.cpp b/src/libswd/pack.cpp new file mode 100644 index 0000000..4dd3a1d --- /dev/null +++ b/src/libswd/pack.cpp @@ -0,0 +1,341 @@ +#include "mesh/mesh.hpp" +#include "vti/vti.hpp" +#include "libswd/specswd.hpp" + +#include + +#include +#include + +// global vars + +// global vars for solver/mesh +namespace specswd_pylib +{ +std::unique_ptr M_; +std::unique_ptr LoveSol_; +std::unique_ptr RaylSol_; + +// global vars for eigenvalues/eigenvectors +std::vector egnr_,egnl_,c_,u_; +std::vector cegnr_,cegnl_,cc_,cu_; +} + +extern "C" void +specswd_init_mesh_love( + int nz, const float *z,const float *rho,const float *vsh, + const float *vsv,const float *QN, const float *QL, + bool HAS_ATT,bool print_tomo_info = false +) +{ + using namespace specswd_pylib; + + // allocate memory + auto &M = M_; + M.reset(new specswd::Mesh); + + // allocate space for tomo, and set model + M -> allocate_1D_model(nz,0,HAS_ATT); + for(int i = 0; i < nz; i ++) { + M -> rho_tomo[i] = rho[i]; + M -> vsv_tomo[i] = vsv[i]; + M -> vsh_tomo[i] = vsh[i]; + M -> depth_tomo[i] = z[i]; + if (HAS_ATT) { + M -> QN_tomo[i] = QN[i]; + M -> QL_tomo[i] = QL[i]; + } + } + + // create attributes + M -> create_model_attributes(); + if (print_tomo_info) { + M -> print_model(); + } + + // initialize solver + LoveSol_.reset(new specswd::SolverLove); +} + +extern "C" void +specswd_init_mesh_rayl( + int nz, const float *z,const float *rho, + const float *vph,const float* vpv,const float *vsv, + const float *eta,const float *QA, const float *QC, + const float *QL, bool HAS_ATT,bool print_tomo_info +) +{ + using namespace specswd_pylib; + + // allocate memory + auto &M = M_; + M.reset(new specswd::Mesh); + + // allocate space for tomo, and set model + M -> allocate_1D_model(nz,1,HAS_ATT); + for(int i = 0; i < nz; i ++) { + M -> rho_tomo[i] = rho[i]; + M -> vsv_tomo[i] = vsv[i]; + M -> vph_tomo[i] = vph[i]; + M -> vpv_tomo[i] = vpv[i]; + M -> depth_tomo[i] = z[i]; + M -> eta_tomo[i] = eta[i]; + if (HAS_ATT) { + M -> QA_tomo[i] = QA[i]; + M -> QC_tomo[i] = QC[i]; + M -> QL_tomo[i] = QL[i]; + } + } + + // create attributes + M -> create_model_attributes(); + if (print_tomo_info) { + M -> print_model(); + } + + // initialize solver + RaylSol_.reset(new specswd::SolverRayl); +} + +extern "C" void +specswd_egn_love(float freq,bool use_qz) +{ + using namespace specswd_pylib; + + // get contants + bool HAS_ATT = M_->HAS_ATT; + + // create database + M_ -> create_database(freq,0.); + + // prepare all matrices + LoveSol_ -> prepare_matrices(*M_); + + // compute + if(!HAS_ATT) { + LoveSol_ -> compute_egn(*M_,c_,egnr_,use_qz); + } + else { + LoveSol_ -> compute_egn_att(*M_,cc_,cegnr_,use_qz); + } +} + +extern "C" void +specswd_egn_rayl(float freq,bool use_qz) +{ + using namespace specswd_pylib; + + // get contants + bool HAS_ATT = M_->HAS_ATT; + + // create database + M_ -> create_database(freq,0.); + + // prepare all matrices + RaylSol_ -> prepare_matrices(*M_); + + if(!HAS_ATT) { + RaylSol_ -> compute_egn(*M_,c_,egnr_,egnl_,use_qz); + } + else { + RaylSol_ -> compute_egn_att(*M_,cc_,cegnr_,cegnl_,use_qz); + } +} + +extern "C" void +specswd_group_love() +{ + using namespace specswd_pylib; + + // get contants + bool HAS_ATT = M_->HAS_ATT; + int ng = M_ -> nglob_el; + + int nc = 0; + if(HAS_ATT) { + nc = c_.size(); + cu_.resize(nc); + + for(int ic = 0; ic < nc; ic ++ ) { + cu_[ic] = LoveSol_ -> group_vel_att(*M_,cc_[ic],&cegnr_[ic*ng]); + } + } + else { + nc = cc_.size(); + u_.resize(nc); + for(int ic = 0; ic < nc; ic ++ ) { + u_[ic] = LoveSol_ -> group_vel(*M_,c_[ic],&egnr_[ic*ng]); + } + } +} + +extern "C" void +specswd_group_rayl() +{ + using namespace specswd_pylib; + + // get contants + bool HAS_ATT = M_->HAS_ATT; + int ng = M_->nglob_el * 2 + M_-> nglob_ac; + + + int nc = 0; + if(HAS_ATT) { + nc = c_.size(); + cu_.resize(nc); + + for(int ic = 0; ic < nc; ic ++ ) { + cu_[ic] = RaylSol_ -> group_vel_att(*M_,cc_[ic],&cegnr_[ic*ng],&cegnl_[ic*ng]); + } + } + else { + nc = cc_.size(); + u_.resize(nc); + + for(int ic = 0; ic < nc; ic ++ ) { + u_[ic] = RaylSol_ -> group_vel(*M_,c_[ic],&egnr_[ic*ng],&egnl_[ic*ng]); + } + } +} + +/** + * @brief compute phase kernels + * @param imode which mode return, =0 is fundamental + * @param frekl_c frechet kernels for phase velocity, size = (nker,nz), user memory management + * @param frekl_q frechet kernels for phase velocity, size = (nker,nz), user memory management. + * it will not be used for elastic case + * @note nker dependents on : 1.elastic love, nker = 3 vsh/vsv/rho + * 2. visco-elastic love, nker = 5 vsh/vsv/QNi/QLi/rho + * 3. elastic rayleigh nker = 6 vph/vpv/vsv/eta/vp/rho + * 4. visco-elastic rayleigh nker = 10 vph/vpv/vsv/eta/Qai/Qci/Qli/vp/Qki/rho + */ +extern "C" void +specswd_phase_kl(int imode,float *frekl_c,float *frekl_q) +{ + using namespace specswd_pylib; + bool HAS_ATT = M_ -> HAS_ATT; + int SWD_TYPE = M_ -> SWD_TYPE; + + // frekl + std::vector f,fq; + int nker,nz; + specswd_kernel_size(&nker,&nz); + int npts = M_ -> ibool.size(); + + if(SWD_TYPE == 0) { + int ng = M_ -> nglob_el; + npts = M_ -> ibool_el.size(); + if (!HAS_ATT) { + LoveSol_ -> compute_phase_kl( + *M_,c_[imode],&egnr_[imode*ng],f + ); + } + else { + LoveSol_ -> compute_phase_kl_att( + *M_,cc_[imode], + &cegnr_[imode*ng],f,fq + ); + } + } + else if (SWD_TYPE == 1) { + int ng = M_ -> nglob_el * 2 + M_ -> nglob_ac; + if (!HAS_ATT) { + RaylSol_ -> compute_phase_kl( + *M_,c_[imode],&egnr_[imode*ng], + &egnl_[imode*ng],f + ); + } + else { + RaylSol_ -> compute_phase_kl_att( + *M_,cc_[imode],&cegnr_[imode*ng], + &cegnl_[imode*ng],f,fq + ); + } + } + else { + printf("not implemented!\n"); + exit(1); + } + + // project to tomo kernels + for(int iker = 0; iker < nker; iker ++) { + M_ -> project_kl(&f[iker*npts],&frekl_c[iker*npts]); + if(HAS_ATT) { + M_ -> project_kl(&fq[iker*npts],&frekl_q[iker*npts]); + } + } +} + +/** + * @brief compute group kernels + * @param imode which mode return, =0 is fundamental + * @param frekl_c frechet kernels for group velocity, size = (nker,nz), user memory management + * @param frekl_q frechet kernels for group velocity, size = (nker,nz), user memory management. + * it will not be used for elastic case + * @note nker dependents on : 1.elastic love, nker = 3 vsh/vsv/rho + * 2. visco-elastic love, nker = 5 vsh/vsv/QNi/QLi/rho + * 3. elastic rayleigh nker = 6 vph/vpv/vsv/eta/vp/rho + * 4. visco-elastic rayleigh nker = 10 vph/vpv/vsv/eta/Qai/Qci/Qli/vp/Qki/rho + */ +extern "C" void +specswd_group_kl(int imode,float *frekl_c,float *frekl_q) +{ + using namespace specswd_pylib; + bool HAS_ATT = M_ -> HAS_ATT; + int SWD_TYPE = M_ -> SWD_TYPE; + + // frekl + std::vector f,fq; + int nker,nz; + specswd_kernel_size(&nker,&nz); + int npts = M_ -> ibool.size(); + + if(SWD_TYPE == 0) { + int ng = M_ -> nglob_el; + npts = M_ -> ibool_el.size(); + if (HAS_ATT) { + nker = 3; + LoveSol_ -> compute_group_kl( + *M_,c_[imode],&egnr_[imode*ng],f + ); + } + else { + nker = 5; + LoveSol_ -> compute_group_kl_att( + *M_,cc_[imode],cu_[imode], + &cegnr_[imode*ng],f,fq + ); + } + } + else if (SWD_TYPE == 1) { + int ng = M_ -> nglob_el * 2 + M_ -> nglob_ac; + if (HAS_ATT) { + nker = 5; + RaylSol_ -> compute_group_kl( + *M_,c_[imode],&egnr_[imode*ng], + &egnl_[imode*ng],f + ); + } + else { + nker = 10; + RaylSol_ -> compute_group_kl_att( + *M_,cc_[imode],cu_[imode], + &cegnr_[imode*ng], + &cegnl_[imode*ng],f,fq + ); + } + } + else { + printf("not implemented!\n"); + exit(1); + } + + // project to tomo kernels + for(int iker = 0; iker < nker; iker ++) { + M_ -> project_kl(&f[iker*npts],&frekl_c[iker*npts]); + if(HAS_ATT) { + M_ -> project_kl(&fq[iker*npts],&frekl_q[iker*npts]); + } + } +} + \ No newline at end of file diff --git a/src/libswd/specswd.hpp b/src/libswd/specswd.hpp new file mode 100644 index 0000000..8f570c7 --- /dev/null +++ b/src/libswd/specswd.hpp @@ -0,0 +1,51 @@ +#ifndef SPECSWD_LIB_UTILS_H_ +#define SPECSWD_LIB_UTILS_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void +specswd_init_GQTable(); + +void specswd_reset_Qmodel(const double *w,const double *y); + +void specswd_kernel_size(int *nkers,int *nz); + +void +specswd_init_mesh_love( + int nz, const float *z,const float *rho,const float *vsh, + const float *vsv,const float *QN, const float *QL, + bool HAS_ATT,bool print_tomo_info +); + +void +specswd_init_mesh_rayl( + int nz, const float *z,const float *rho, + const float *vph,const float* vpv,const float *vsv, + const float *eta,const float *QA, const float *QC, + const float *QL, bool HAS_ATT,bool print_tomo_info = false +); + +void +specswd_egn_love(float freq,bool use_qz); + +void +specswd_egn_rayl(float freq,bool use_qz); + +void +specswd_group_love(); + +void +specswd_group_rayl(); + +void specswd_phase_kl(int imode,float *frekl_c,float *frekl_q); +void specswd_group_kl(int imode,float *frekl_c,float *frekl_q); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/src/libswd/utils.cpp b/src/libswd/utils.cpp deleted file mode 100644 index f01d6bf..0000000 --- a/src/libswd/utils.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "tti/swdlayertti.hpp" -#include "vti/swdlayervti.hpp" - -#include -#include - -/** - * @brief compute vti surface wave dispersion - * - * @param thkm thickness of each layer, shape(nlayer) - * @param vphm/vpvm/vshm/vsvm/etam vti 5 parameters, shape(nlayer) - * @param rhom density, shape(nlayer) - * @param nlayer no. of layers - * @param nt no. of period points used - * @param mode which mode you want, start from 0 = fundamental - * @param wavetype =1 for love and =2 for rayleigh - * @param only_phase = false only for phase, or for both phase/group - * @param t period vector - * @param cp/cg output dispersion,phase/group - */ -void -__surfvti(const float *thkm,const float *vphm,const float *vpvm, - const float *vshm,const float *vsvm,const float *etam, - const float *rhom,int nlayer,int nt,int mode, int wavetype, - bool only_phase,const double *t,double *cp,double *cg) -{ - LayerModelVTI model; - model.initialize(); - int nglob = model.nglob; - - // allocate space for displ/velocity - std::vector c,displ,u,frekl; - int eig_size = nglob * wavetype; - - // loop every period - for(int it = 0; it < nt; it ++) { - double freq = 1. / t[it]; - model.create_database(freq,nlayer,vphm,vpvm, - vshm,vsvm,etam,rhom,thkm, - true); - model.prepare_matrices(wavetype); - switch (wavetype) - { - case 1: - model.compute_slegn(freq,c,displ); - break; - - default: - model.compute_sregn(freq,c,displ); - break; - } - - // cache the one you want - cp[it] = c[mode]; - if(!only_phase) return; - - // compute group velocity - if(wavetype == 1) { - cg[it] = model.compute_love_kl(freq,c[mode],&displ[mode * eig_size],frekl); - } - else { - cg[it] = model.compute_rayl_kl(freq,c[mode],&displ[mode * eig_size],frekl); - } - } -} - -/** - * @brief compute vti surface wave dispersion - * - * @param thkm thickness of each layer, shape(nlayer) - * @param vphm/vpvm/vshm/vsvm/etam vti 5 parameters, shape(nlayer) - * @param rhom density, shape(nlayer) - * @param nlayer no. of layers - * @param nt no. of period points used - * @param mode which mode you want, start from 0 = fundamental - * @param wavetype =1 for love and =2 for rayleigh - * @param t period vector - * @param cp/cg output dispersion,phase/group - * @returns kernels: shape(nt,nker,nlayer) sensitivity kernels - */ -std::vector -__surfvti_kl(const float *thkm,const float *vphm,const float *vpvm, - const float *vshm,const float *vsvm,const float *etam, - const float *rhom,int nlayer,int nt,int mode, int wavetype, - const double *t,double *cp,double *cg) -{ - LayerModelVTI model; - model.initialize(); - int nglob = model.nglob; - - // allocate space for displ/velocity - std::vector c,displ,u,frekl; - int eig_size = nglob * wavetype; - - // allocate kernels - int size = model.ibool.size(); - int nker = frekl.size() / (model.ibool.size()); - std::vector kernels(nker * nlayer * nt); - - // z coordinates - std::vector zlist(nlayer); - zlist[0] = 0.; - for(int i = 0; i < nlayer - 1; i ++) { - zlist[i + 1] = zlist[i] + thkm[i]; - } - - // loop every period - for(int it = 0; it < nt; it ++) { - double freq = 1. / t[it]; - model.create_database(freq,nlayer,vphm,vpvm, - vshm,vsvm,etam,rhom,thkm, - true); - model.prepare_matrices(wavetype); - switch (wavetype) - { - case 1: - model.compute_slegn(freq,c,displ); - break; - - default: - model.compute_sregn(freq,c,displ); - break; - } - - // cache the one you want - cp[it] = c[mode]; - - // compute group velocity - if(wavetype == 1) { - cg[it] = model.compute_love_kl(freq,c[mode],&displ[mode * eig_size],frekl); - } - else { - cg[it] = model.compute_rayl_kl(freq,c[mode],&displ[mode * eig_size],frekl); - } - model.transform_kernels(frekl); - - // project back to original model - for(int iker = 0; iker < nker; iker ++) { - model.project_kl(zlist.data(),&frekl[iker * size],&kernels[it * nlayer * nker + iker * nlayer]); - } - } - - return kernels; - -} \ No newline at end of file diff --git a/src/libswd/utils.hpp b/src/libswd/utils.hpp deleted file mode 100644 index 6927e7b..0000000 --- a/src/libswd/utils.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#include - -// interface -void -__surfvti(const float *thkm,const float *vphm,const float *vpvm, - const float *vshm,const float *vsvm,const float *etam, - const float *rhom,int nlayer,int nt,int mode, int wavetype, - bool only_phase,const double *t,double *cp,double *cg); -std::vector -__surfvti_kl(const float *thkm,const float *vphm,const float *vpvm, - const float *vshm,const float *vsvm,const float *etam, - const float *rhom,int nlayer,int nt,int mode, int wavetype, - const double *t,double *cp,double *cg); \ No newline at end of file diff --git a/src/mesh/CMakeLists.txt b/src/mesh/CMakeLists.txt new file mode 100644 index 0000000..5ceea28 --- /dev/null +++ b/src/mesh/CMakeLists.txt @@ -0,0 +1,3 @@ +file(GLOB SOURCE "*.cpp" ) + +add_library(mesh ${SOURCE}) \ No newline at end of file diff --git a/src/mesh/christoffel.cpp b/src/mesh/christoffel.cpp new file mode 100644 index 0000000..6f95b42 --- /dev/null +++ b/src/mesh/christoffel.cpp @@ -0,0 +1,70 @@ +#include + +// Fast Voigt index lookup table +const int voigt_lookup[3][3] = { + {0, 5, 4}, + {5, 1, 3}, + {4, 3, 2} +}; + +static int inline +Voigt_index(int i, int j) +{ + return voigt_lookup[i][j]; +} + +namespace specswd +{ + + +/** + * @brief find the min/max phase velocity by solving Christoffel equations G_{ik} g_k = v^2 g_i + * @param phi direction angle, in rad + * @param c21 c21 tensor, shape(21) + * @param cmin/cmax min/max phase velocity + */ +void solve_christoffel(float phi, const float *c21,float &cmin,float &cmax) +{ + // direction + double direc[3] = {std::cos(phi),std::sin(phi),0.}; + + // allocate Chirstoffel matrix + Eigen::Matrix G; G.setZero(); + using Eigen::dcomplex; + + // set value + for(int i = 0; i < 3; i ++) { + for(int j = 0; j < 3; j ++) { + int m = Voigt_index(i,j); + for(int p = 0; p < 3; p ++) { + for(int q = 0; q < 3; q ++) { + int n = Voigt_index(p,q); + + // get c21 index + int m1 = m; + int n1 = n; + if(m1 > n1) std::swap(m1,n1); + int idx = m * 6 + n - (m * (m + 1)) / 2; + + // sum G_{ik} = c_{ijkl} n_j n_l + G(i,p) += c21[idx] * direc[j] * direc[q]; + }} + }} + + // find eigenvalues + Eigen::Array3d vr,vi; + LAPACKE_dgeev( + LAPACK_ROW_MAJOR,'N','N',3,G.data(),3, + vr.data(),vi.data(),nullptr,3,nullptr,3 + ); + Eigen::Array3d v = (vr + Eigen::dcomplex{0,1.} * vi).array().sqrt().real().cast(); + + // sort + std::sort(v.data(),v.data() + 3); + + // find the min/max + cmin = v[0]; + cmax = v[1]; // we need S wave +} + +} // namespace specswd \ No newline at end of file diff --git a/src/mesh/database.cpp b/src/mesh/database.cpp new file mode 100644 index 0000000..245d5f2 --- /dev/null +++ b/src/mesh/database.cpp @@ -0,0 +1,329 @@ +#include "mesh/mesh.hpp" +#include "shared/GQTable.hpp" + +namespace specswd +{ + +void solve_christoffel(float phi, const float *c21,float &cmin,float &cmax); + + +void Mesh:: +compute_minmax_veloc_(float phi,std::vector &vmin,std::vector &vmax) +{ + vmin.resize(nregions); + vmax.resize(nregions); + + for(int ig = 0; ig < nregions; ig ++ ) { + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + float v0 = 1.0e20, v1 = -1.0e20; + + for(int i = istart; i <= iend; i ++) { + if(SWD_TYPE == 0) { // love wave + float vsh = vsh_tomo[i]; + v0 = std::min(v0,vsh); + // if(HAS_ATT) { + // vsh *= 1. + 0.125 / std::pow(QN_[i],2); // correction to second order + // } + v1 = std::max(v1,vsh); + } + else if (SWD_TYPE == 1) { // rayleigh + if(is_el_reg[ig]) { + v0 = std::min(v0,vsv_tomo[i]); + v1 = std::max(v1,vsv_tomo[i]); + } + else { + v0 = std::min(v0,vpv_tomo[i]); + v1 = std::max(v1,vpv_tomo[i]); + } + } + else { // aniso + float temp[21],cmin,cmax; + for(int j = 0; j < 21; j ++) { + temp[j] = c21_tomo[j*21+i]; + } + solve_christoffel(phi,temp,cmin,cmax); + v0 = std::min(cmin,v0); + v1 = std::max(cmax,v1); + } + } + + // set value + vmin[ig] = v0; + vmax[ig] = v1; + } +} + + +/** + * @brief Create SEM database by using input model info + * + * @param freq0 current frequency, in Hz + * @param phi0 directional angle,in deg + */ +void Mesh:: +create_database(float freq0,float phi0) +{ + // copy constants + this -> freq = freq0; + this -> phi = phi0 * M_PI / 180.; + + using namespace GQTable; + + std::vector vmin,vmax; + this -> compute_minmax_veloc_(phi,vmin,vmax); + + // find min/max vs + PHASE_VELOC_MAX = -1.; + PHASE_VELOC_MIN = 1.0e20; + for(int i = 0; i < nregions; i ++) { + PHASE_VELOC_MAX = std::max(vmax[i],PHASE_VELOC_MAX); + PHASE_VELOC_MIN = std::min(vmin[i],PHASE_VELOC_MIN); + } + PHASE_VELOC_MIN *= 0.85; + + // loop every region to find best element size + nspec = 0; + std::vector nel(nregions - 1); + for(int ig = 0; ig < nregions - 1; ig ++) { + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + + float maxdepth = depth_tomo[iend] - depth_tomo[istart]; + nel[ig] = 1.5 * (maxdepth * freq) / vmin[ig] + 1; + if(nel[ig] <=0) nel[ig] = 1; + nspec += nel[ig]; + } + nspec_grl = 1; + + // allocate space + size_t size = nspec * NGLL + NGRL; + ibool.resize(size); znodes.resize(size); + jaco.resize(nspec+1); iregion_flag.resize(nspec+1); + skel.resize(nspec*2+2); + + // connectivity matrix + int idx = 0; + for(int ispec = 0; ispec < nspec; ispec ++) { + for(int igll = 0; igll < NGLL; igll ++) { + ibool[ispec * NGLL + igll] = idx; + idx += 1; + } + idx -= 1; + } + for(int i = 0; i < NGRL; i ++) { + ibool[nspec * NGLL + i] = idx; + idx += 1; + } + nglob = ibool[nspec * NGLL + NGRL - 1] + 1; + + // skeleton and nspec/ac/el + int id = 0; + nspec_ac = 0; nspec_el = 0; + is_elastic.resize(nspec+1); + is_acoustic.resize(nspec+1); + for(int ig = 0; ig < nregions - 1; ig ++) { + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + float h = (depth_tomo[iend] - depth_tomo[istart]) / nel[ig]; + for(int j = 0; j < nel[ig]; j ++) { + skel[id * 2 + 0] = depth_tomo[istart] + h * j; + skel[id * 2 + 1] = depth_tomo[istart] + h * (j + 1.); + is_elastic[id] = is_el_reg[ig]; + is_acoustic[id] = is_ac_reg[ig]; + if(is_elastic[id]) nspec_el += 1; + if(is_acoustic[id]) nspec_ac += 1; + + // set iregion flag + iregion_flag[id] = ig; + + id += 1; + } + } + + // half space skeleton + nspec_el_grl = 0; nspec_ac_grl = 0; + float scale = PHASE_VELOC_MAX / freq / xgrl[NGRL-1] * 20; // up to 50 wavelength + skel[nspec * 2 + 0] = depth_tomo[nz_tomo-1]; + skel[nspec * 2 + 1] = depth_tomo[nz_tomo-1] + xgrl[NGRL-1] * scale; + iregion_flag[nspec] = nregions - 1; + + // half space material type + is_elastic[nspec] = is_el_reg[nregions-1]; + is_acoustic[nspec] = is_ac_reg[nregions-1]; + if(is_acoustic[nspec]) nspec_ac_grl = 1; + if(is_elastic[nspec]) nspec_el_grl = 1; + + // jacobians and coordinates + for(int ispec = 0; ispec < nspec; ispec ++) { + float h = skel[ispec*2+1] - skel[ispec*2+0]; + jaco[ispec] = h / 2.; + for(int i = 0; i < NGLL; i ++) { + float xi = xgll[i]; + znodes[ispec * NGLL + i] = skel[ispec*2] + h * 0.5 * (xi + 1); + } + } + // compute coordinates and jaco in GRL layer + for(int ispec = nspec; ispec < nspec + 1; ispec ++) { + jaco[ispec] = scale; + for(int i = 0; i < NGRL; i ++) { + float xi = xgrl[i]; + znodes[ispec*NGLL+i] = skel[ispec*2] + xi * scale; + } + } + + // UNIQUE coordinates + zstore.resize(nglob); + for(int i = 0; i < nspec * NGLL + NGRL; i ++) { + int iglob = ibool[i]; + zstore[iglob] = znodes[i]; + } + + // create connectivity matrix for each material + this -> create_material_info_(); + + // interpolate model + switch (SWD_TYPE) + { + case 0: + this -> create_db_love_(); + break; + case 1: + this -> create_db_rayl_(); + break; + default: + this -> create_db_aniso_(); + break; + } +} + + +/** + * @brief create database for Love wave + */ +void Mesh:: +create_db_love_() +{ + size_t size = ibool_el.size(); + + // interpolate base model + xrho_el.resize(size); + xL.resize(size); + xN.resize(size); + this -> interp_model(rho_tomo.data(),el_elmnts,xrho_el); + this -> interp_model(vsh_tomo.data(),el_elmnts,xN); + this -> interp_model(vsv_tomo.data(),el_elmnts,xL); + for(size_t i = 0; i < size; i ++) { + float r = xrho_el[i]; + xN[i] = std::pow(xN[i],2) * r; + xL[i] = std::pow(xL[i],2) * r; + } + + // Q model + nQmodel_ani = 0; + if(HAS_ATT) { + // interpolate Q model + xQL.resize(size); xQN.resize(size); + this -> interp_model(QL_tomo.data(),el_elmnts,xQL); + this -> interp_model(QN_tomo.data(),el_elmnts,xQN); + nQmodel_ani = 2; + } +} + + +/** + * @brief create database for Love wave + */ +void Mesh:: +create_db_rayl_() +{ + size_t size_el = ibool_el.size(); + size_t size_ac = ibool_ac.size(); + + // allocate space for density + xrho_el.resize(size_el); + xrho_ac.resize(size_ac); + + // interpolate xrho + this -> interp_model(rho_tomo.data(),el_elmnts,xrho_el); + this -> interp_model(rho_tomo.data(),ac_elmnts,xrho_ac); + + // temp arrays + xA.resize(size_el); xL.resize(size_el); + xC.resize(size_el); xeta.resize(size_el); + xkappa_ac.resize(size_ac); + + // interpolate parameters in elastic domain + this -> interp_model(vph_tomo.data(),el_elmnts,xA); + this -> interp_model(vpv_tomo.data(),el_elmnts,xC); + this -> interp_model(vsv_tomo.data(),el_elmnts,xL); + this -> interp_model(eta_tomo.data(),el_elmnts,xeta); + for(size_t i = 0; i < size_el; i ++) { + double r = xrho_el[i]; + xA[i] = xA[i] * xA[i] * r; + xC[i] = xC[i] * xC[i] * r; + xL[i] = xL[i] * xL[i] * r; + } + + // acoustic domain + this -> interp_model(&vph_tomo[0],ac_elmnts,xkappa_ac); + for(size_t i = 0; i < size_ac; i ++) { + xkappa_ac[i] = xkappa_ac[i] * xkappa_ac[i] * xrho_ac[i]; + } + + nQmodel_ani = 0; + if(HAS_ATT) { + // allocate space for Q + xQL.resize(size_el); xQA.resize(size_el); + xQC.resize(size_el); xQk_ac.resize(size_ac); + this -> interp_model(QL_tomo.data(),el_elmnts,xQL); + this -> interp_model(QC_tomo.data(),el_elmnts,xQC); + this -> interp_model(QA_tomo.data(),el_elmnts,xQA); + this -> interp_model(QC_tomo.data(),ac_elmnts,xQk_ac); + + nQmodel_ani = 3; + } +} + +/** + * @brief create database for Love wave + */ +void Mesh:: +create_db_aniso_() +{ + size_t size_el = ibool_el.size(); + size_t size_ac = ibool_ac.size(); + + // allocate space for density + xrho_el.resize(size_el); + xrho_ac.resize(size_ac); + + // interpolate xrho + this -> interp_model(rho_tomo.data(),el_elmnts,xrho_el); + this -> interp_model(rho_tomo.data(),ac_elmnts,xrho_ac); + + // allocate elastic model + std::vector xtemp_el(size_el); + xC21.resize(21*size_el); + xkappa_ac.resize(size_ac); + for(int i = 0; i < 21; i ++) { + this -> interp_model(&c21_tomo[21*nz_tomo],el_elmnts,xtemp_el); + for(size_t j = 0; j < size_el;j ++) { + xC21[i*size_el+j] = xtemp_el[j]; + } + } + + // acoustic domain + this -> interp_model(&c21_tomo[0],ac_elmnts,xkappa_ac); + if(HAS_ATT) { + for(int iq = 0; iq < nQmodel_ani; iq ++) { + this -> interp_model(&Qani_tomo[iq*nz_tomo],el_elmnts,xtemp_el); + for(size_t j = 0; j < size_el;j ++) { + xQani[iq*size_el+j] = xtemp_el[j]; + } + } + this -> interp_model(&Qani_tomo[0],ac_elmnts,xQk_ac); + } +} + +} // namespace specswd diff --git a/src/mesh/initialize.cpp b/src/mesh/initialize.cpp new file mode 100644 index 0000000..b1d2e9d --- /dev/null +++ b/src/mesh/initialize.cpp @@ -0,0 +1,110 @@ +#include "mesh/mesh.hpp" +#include "shared/GQTable.hpp" + +#include + +namespace specswd +{ + +void Mesh:: +create_material_info_() +{ + using namespace GQTable; + ac_elmnts.resize(0); el_elmnts.resize(0); + ac_elmnts.reserve(nspec_ac + nspec_ac_grl); + el_elmnts.reserve(nspec_el + nspec_el_grl); + is_elastic.resize(nspec + nspec_grl); + is_acoustic.resize(nspec + nspec_grl); + for(int ispec = 0; ispec < nspec + nspec_grl; ispec ++) { + if(is_elastic[ispec]) { + el_elmnts.push_back(ispec); + } + if(is_acoustic[ispec]) { + ac_elmnts.push_back(ispec); + } + } + + // get nglob_el for elastic + ibool_el.resize(nspec_el * NGLL + nspec_el_grl * NGRL); + nglob_el = 0; + int idx = -1; + for(int i = 0; i < nspec_el + nspec_el_grl; i += 1) { + int ispec = el_elmnts[i]; + if(idx == ibool[ispec * NGLL]) nglob_el -= 1; + + int NGL = NGLL; + if(i == nspec_el) NGL = NGRL; + for(int igll = 0; igll < NGL; igll ++) { + ibool_el[i * NGLL + igll] = nglob_el; + nglob_el += 1; + } + idx = ibool[ispec * NGLL + NGLL-1]; + } + + // regular boundary condition at infinity + // if(nspec_el_grl == 1) { + // nglob_el -= 1; + // ibool_el[nspec_el*NGLL + NGRL-1] = -1; + // } + + // get nglob_ac for acoustic + ibool_ac.resize(nspec_ac * NGLL + nspec_ac_grl * NGRL); + idx = -10; + nglob_ac = 0; + if(is_acoustic[0]) nglob_ac = -1; // the top point of acoustic wave is 0 + for(int i = 0; i < nspec_ac + nspec_ac_grl; i += 1) { + int ispec = ac_elmnts[i]; + if(idx == ibool[ispec * NGLL]) nglob_ac -= 1; + + int NGL = NGLL; + if(i == nspec_ac) NGL = NGRL; + for(int igll = 0; igll < NGL; igll ++) { + ibool_ac[i * NGLL + igll] = nglob_ac; + nglob_ac += 1; + } + idx = ibool[ispec * NGLL + NGLL-1]; + } + + // elastic-acoustic boundary + nfaces_bdry = 0; + for(int i = 0; i < nspec; i ++) { + if(is_elastic[i] != is_elastic[i+1]) { + nfaces_bdry += 1; + } + } + ispec_bdry.resize(nfaces_bdry*2); + bdry_norm_direc.resize(nfaces_bdry); + idx = 0; + for(int i = 0; i < nspec; i ++) { + if(is_elastic[i] != is_elastic[i+1]) { + int iloc_el = i + 1, iloc_ac = i; + if(is_elastic[i]) { + bdry_norm_direc[i] = 0; + iloc_el = i; + iloc_ac = i + 1; + } + else { + bdry_norm_direc[idx] = 1; + } + auto it = std::find(el_elmnts.begin(),el_elmnts.end(),iloc_el); + int ispec_el = it - el_elmnts.begin(); + it = std::find(ac_elmnts.begin(),ac_elmnts.end(),iloc_ac); + int ispec_ac = it - ac_elmnts.begin(); + ispec_bdry[idx * 2 + 0] = ispec_ac; + ispec_bdry[idx * 2 + 1] = ispec_el; + idx += 1; + } + } + +#ifdef SPECSWD_DEBUG + // debug + for(int iface = 0; iface < nfaces_bdry; iface ++) { + printf("\nface %d, ispec_ac,ispec_el = %d %d\n",iface,ispec_bdry[iface*2],ispec_bdry[iface*2+1]); + printf("acoustic -> elastic = %d\n",bdry_norm_direc[iface]); + } +#endif +} + +} // namespace specswd + + diff --git a/src/mesh/interpolate.cpp b/src/mesh/interpolate.cpp new file mode 100644 index 0000000..8bab227 --- /dev/null +++ b/src/mesh/interpolate.cpp @@ -0,0 +1,147 @@ +#include "mesh/mesh.hpp" +#include "shared/GQTable.hpp" + +namespace specswd +{ + + +/** + * @brief find location of z0 in ascending list z + * + * @param z depth list, shape(nlayer) + * @param z0 current loc, must be inside z + * @param nz sizeof z + * @return int location of z0 in z, satisfies z0 >= z[i] && z0 < z[i + 1] + */ +static int +find_loc(const float *z,float z0,int nz) +{ + + int i = 0; + while(i < nz - 1) { + if(z0 >= z[i] && z0 < z[i + 1]) { + break; + } + i += 1; + } + + return i; +} + + +/** + * @brief interpolate elastic/acoustic model by using coordinates + * + * @param param input model parameter, shape(nz_tomo) + * @param elmnts all elements used, ispec = elmnts[i] + * @param md model required to interpolate, shape(nspec_el*NGLL + nspec_el_grl * NGRL) + */ +void Mesh:: +interp_model(const float *param,const std::vector &elmnts,std::vector &md) const +{ + using GQTable :: NGLL; using GQTable :: NGRL; + int nel = elmnts.size(); + + for(int ireg = 0; ireg < nregions; ireg ++) { + int istart = region_bdry[ireg*2]; + int iend = region_bdry[ireg*2+1]; + int npts = iend - istart + 1; + + for(int ispec_md = 0; ispec_md < nel; ispec_md ++) { + int ispec = elmnts[ispec_md]; + int NGL = NGLL; + if(ispec == nspec) { + NGL = NGRL; + } + + if(ireg != iregion_flag[ispec]) continue; + + // interpolate + for(int i = 0; i < NGL; i ++) { + int id = ispec_md * NGLL + i; + + float z0 = znodes[ispec * NGLL + i]; + + // find loc in this region + int j = find_loc(&depth_tomo[istart],z0,npts) + istart; + if(j < istart || j >= iend) { + j = j < istart ? istart : iend; + md[id] = param[j]; + } + else { + float dzinv = 1./ (depth_tomo[j + 1] - depth_tomo[j]); + md[id] = param[j] + (param[j+1]-param[j]) * dzinv * (z0-depth_tomo[j]); + } + + } + } + } +} + +/** + * @brief project kernels to original 1-D model + * @param frekl derivatives, shape(nspec*NGLL+NGRL) + * @param kl_out derivatives on original 1-Dmodel, shape(nz_) + */ +void Mesh:: +project_kl(const float *frekl, float *kl_out) const +{ + using GQTable :: NGLL; using GQTable :: NGRL; + + // zero out kl_out + for(int i = 0; i < nz_tomo; i ++) kl_out[i] = 0.; + + // loop every region + for(int ireg = 0; ireg < nregions; ireg ++) { + int istart = region_bdry[ireg*2]; + int iend = region_bdry[ireg*2+1]; + int npts = iend - istart + 1; + + // choose domain + const int *mat_elmnts = nullptr; + int nel = 0; + for(int im = 0; im < 2; im ++) { + if(im == 0) { + nel = nspec_el + nspec_el_grl; + mat_elmnts = el_elmnts.data(); + } + else { + nel = nspec_ac + nspec_ac_grl; + mat_elmnts = ac_elmnts.data(); + } + + // elastic region + for(int ispec_md = 0; ispec_md < nel; ispec_md ++) { + int ispec = mat_elmnts[ispec_md]; + if(ireg != iregion_flag[ispec]) continue; + + // check if GRL + int NGL = NGLL; + if(ispec == nspec) { + NGL = NGRL; + } + + // find interpolate points + for(int i = 0; i < NGL; i ++) { + double z0 = znodes[ispec * NGLL + i]; + int id = ispec * NGLL + i; + + // find loc in this region + int j = find_loc(&depth_tomo[istart],z0,npts) + istart; + if(j < istart || j >= iend) { + j = j < istart ? istart : iend; + kl_out[j] += frekl[id]; + } + else { + float dz = depth_tomo[j + 1] - depth_tomo[j]; + float coef = (z0 - depth_tomo[j]) / dz; + kl_out[j] += (1 - coef) * frekl[id]; + kl_out[j+1] += coef * frekl[id]; + } + } + } + } + } +} + +} // namespace specswd diff --git a/src/mesh/io.cpp b/src/mesh/io.cpp new file mode 100644 index 0000000..7076b4f --- /dev/null +++ b/src/mesh/io.cpp @@ -0,0 +1,462 @@ +#include "mesh/mesh.hpp" +#include +#include +#include + +namespace specswd +{ + +template +void +allocate(int n,T &vec1,Args& ...args) +{ + vec1.resize(n); + std::fill(vec1.begin(),vec1.end(),0); + if constexpr(sizeof...(args) > 0){ + allocate(n,args...); + } +} + +void Mesh:: +allocate_1D_model(int nz0,int swd_type,int has_att) +{ + // copy value to mesh type + SWD_TYPE = swd_type; + nz_tomo = nz0; + HAS_ATT = has_att; + + // allocate space + switch (SWD_TYPE) + { + case 0: + allocate(nz_tomo,vsv_tomo,vsh_tomo,rho_tomo); + if(HAS_ATT) { + allocate(nz_tomo,QN_tomo,QL_tomo); + } + break; + case 1: + allocate(nz_tomo,vpv_tomo,vph_tomo,vsv_tomo, + rho_tomo,eta_tomo); + if(HAS_ATT) allocate(nz_tomo,QC_tomo,QA_tomo,QL_tomo); + break; + + case 2: + allocate(nz_tomo*21,c21_tomo); + allocate(nz_tomo,rho_tomo); + if(HAS_ATT) allocate(nz_tomo*21,Qani_tomo); + + break; + default: + printf("SWD_TYPE should in [0,1,2]!\n"); + printf("current value is %d\n",SWD_TYPE); + exit(1); + break; + } + + // allocate depth + allocate(nz_tomo,depth_tomo); +} + + + +/** + * @brief read header of 1D model, including wave type, attenutation flag, + * attenuation model flag + * @param filename model filename + */ +void Mesh:: +read_model_header_(const char *filename) +{ + std::ifstream infile; infile.open(filename); + if(infile.fail()) { + printf("cannot open %s\n",filename); + exit(1); + } + + // read first line + std::string line; + std::getline(infile,line); + + // read SWD_TYPE and HAS_ATT + int dummy[2]; + { + std::istringstream info(line); + info >> dummy[0] >> dummy[1]; + } + + // find how many depth points in this file + int nz = 0; + while (std::getline(infile,line)) + { + nz += 1; + } + infile.close(); + + // allocate model + this -> allocate_1D_model(nz,dummy[0],dummy[1]); + + // allocate depth + float z = 0.; + + // read depth in file + infile.open(filename); + std::getline(infile,line); + for(int i = 0; i < nz; i ++) { + std::getline(infile,line); + std::istringstream info(line); + info >> depth_tomo[i]; + info.clear(); + + if(i >= 1) { + // make sure depth is no descreasing + if(depth_tomo[i] - z < 0) { + printf("depth should not decrease!\n"); + printf("current/previous depth = %f %f\n",depth_tomo[i],z); + exit(1); + } + z = depth_tomo[i]; + } + } +} + +/** + * @brief read 1D VTI model for Love wave + * @param filename 1D model file + */ +void Mesh:: +read_model_love_(const char *filename) +{ + std::string line; + std::ifstream infile; infile.open(filename); + + // skip header + std::getline(infile,line); + + float temp; + for(int i = 0; i < nz_tomo; i ++) { + std::getline(infile,line); + std::istringstream info(line); + info >> temp >> rho_tomo[i] >> vsh_tomo[i] >> vsv_tomo[i]; + if(HAS_ATT) { + info >> QN_tomo[i] >> QL_tomo[i]; + } + info.clear(); + } + infile.close(); +} + + +/** + * @brief read 1D VTI model for Rayleigh wave + * @param filename 1D model file + */ +void Mesh:: +read_model_rayl_(const char *filename) +{ + std::ifstream infile; infile.open(filename); + std::string line; + + // skip header + std::getline(infile,line); + + for(int i = 0; i < nz_tomo; i ++) { + std::getline(infile,line); + std::istringstream info(line); + float temp; + info >> temp >> rho_tomo[i] >> vph_tomo[i] + >> vpv_tomo[i] >> vsv_tomo[i] >> eta_tomo[i]; + if(HAS_ATT) { + info >> QA_tomo[i] >> QC_tomo[i] >> QL_tomo[i]; + } + info.clear(); + } + infile.close(); +} + +/** + * @brief read 1D full anisotropy model model for Rayleigh wave + * @param filename 1D model file + */ +void Mesh:: +read_model_full_aniso_(const char *filename) +{ + std::ifstream infile; infile.open(filename); + std::string line; + + // skip header + std::getline(infile,line); + + for(int i = 0; i < nz_tomo; i ++) { + float temp; + infile >> temp >> rho_tomo[i]; + for(int j = 0; j < 21; j ++ ) { + infile >> c21_tomo[j*nz_tomo+i]; + } + if(HAS_ATT) { + for(int j = 0; j < nQmodel_ani; j ++) { + infile >> Qani_tomo[j*nz_tomo+i]; + } + } + } + + // close + infile.close(); +} + + +/** + * @brief read 1D model + * @param filename 1D model file + */ +void Mesh:: +read_model(const char *filename) +{ + this -> read_model_header_(filename); + switch (SWD_TYPE) + { + case 0: + this -> read_model_love_(filename); + break; + case 1: + this -> read_model_rayl_(filename); + break; + case 2: + this -> read_model_full_aniso_(filename); + break; + default: + printf("SWD_TYPE should in [0,1,2]"); + printf("current SWD_TYPE = %d\n",SWD_TYPE); + exit(1); + } +} + +static bool +check_fluid_c21(const float *c21) +{ + bool flag = true; + float c0 = c21[0]; + flag = flag & (c0 > 0); + for(int i = 2; i < 21; i ++) { + if(i == 1 || i == 6 || i == 11 ) { + flag = flag && (c21[i] == c0); + } + else if(i == 2 || i == 7) { + flag = flag && (c21[i] == 2 * c0); + } + else { + flag = flag && (c21[i] == 0.); + } + } + + return flag; +} + +/** + * @brief create attributes for elastic/acoustic regions + */ +void Mesh:: +create_model_attributes() +{ + // first check discontinuities + region_bdry.resize(0); + region_bdry.reserve(10); + int ndis = 0; + int ipt0 = 0,ipt1 = 0; + for(int i = 1; i < nz_tomo; i ++) { + if(depth_tomo[i] == depth_tomo[i-1]) { + ndis = ndis + 1; + ipt1 = i-1; + + // add to region_bdry + region_bdry.push_back(ipt0); + region_bdry.push_back(ipt1); + ipt0 = ipt1 + 1; + } + } + + // check a discontinuity is add to half space + if(region_bdry[region_bdry.size() - 1] != nz_tomo - 2) { + printf("Please add a discontinuity at half space !\n"); + exit(1); + } + + // half space is another region + region_bdry.push_back(nz_tomo-1); + region_bdry.push_back(nz_tomo-1); + nregions = region_bdry.size() / 2; + + // now check where the fluid is + std::vector is_ac_pts; + is_ac_pts.resize(nz_tomo); + for(int i = 0; i < nz_tomo; i ++) { + is_ac_pts[i] = 0; + if(SWD_TYPE == 0) { // Love + if(vsh_tomo[i] < 1.0e-6 || vsv_tomo[i] < 1.0e-6) { + printf("Love wave cannot exist in fluid layers!\n"); + printf("current velocity vsv = %f vsh = %f\n",vsv_tomo[i],vsh_tomo[i]); + exit(1); + } + } + else if(SWD_TYPE == 1) { // Rayleigh + if(vsv_tomo[i] < 1.0e-6) { + is_ac_pts[i] = 1; + + // check if vpv == vph || Qvpv == Qvph + bool flag = vpv_tomo[i] == vph_tomo[i]; + if(HAS_ATT) flag = flag &(QC_tomo[i] == QA_tomo[i]); + if(!flag) { + printf("vpv and vph should be same in fluid layers\n"); + printf("current velocity vpv = %f vph = %f\n",vpv_tomo[i],vph_tomo[i]); + printf("current velocity Qvpv = %f Qvph = %f\n",QC_tomo[i],QA_tomo[i]); + exit(1); + } + } + } + else { // full aniso + float temp_c21[21], temp_Qc21[21]; + for(int j = 0; j < 21; j ++) { + temp_c21[j] = c21_tomo[j*21+i]; + } + bool flag = check_fluid_c21(temp_c21); + + if(HAS_ATT) { + for(int j = 0; j < nQmodel_ani; j ++) { + temp_Qc21[j] = Qani_tomo[j*nQmodel_ani+i]; + } + flag = flag && check_fluid_c21(temp_Qc21); + } + + if(flag) { + is_ac_pts[i] = 1; + } + } + } + + // allocate material flag + allocate(nregions,is_ac_reg,is_el_reg); + + // check if all points in a region is fluid/elastic only + for(int ig = 0; ig < nregions; ig ++) { + int startid = region_bdry[ig*2+0]; + int endid = region_bdry[ig*2+1]; + bool flag = is_ac_pts[startid]; + for(int i = startid+1; i <= endid; i ++) { + if(flag != is_ac_pts[i]) { + printf("in one region, you can only have one material !\n"); + printf("Problem region %d, index= %d - %d",ig,startid,endid); + exit(1); + } + } + + // set flag + is_ac_reg[ig] = is_ac_pts[startid]; + is_el_reg[ig] = !is_ac_pts[startid]; + } +} + +/** + * @brief print 1-D model information + */ +void Mesh:: +print_model() const +{ + printf("\n====================================\n"); + printf("========= Model Description ========\n"); + printf("====================================\n\n"); + + std::string outinfo = "elastic"; + if(HAS_ATT) { + outinfo = "visco-elastic"; + } + + if(SWD_TYPE == 0) { // love wave + printf("compute dispersions for %s Love wave\n",outinfo.c_str()); + } + else if(SWD_TYPE == 1) { // rayleigh wave + printf("compute dispersions for %s Rayleigh wave\n",outinfo.c_str()); + } + else { + printf("compute dispersions for %s fully anisotropic wave\n",outinfo.c_str()); + } + + for(int ig = 0; ig < nregions; ig ++) { + if(ig == nregions - 1) { + printf("\nhalf space begins at depth = %f\n", + depth_tomo[nz_tomo - 1]); + } + printf("\nregion %d:\n",ig + 1); + printf("=======================\n"); + int istart = region_bdry[ig*2+0]; + int iend = region_bdry[ig*2+1]; + + if(SWD_TYPE == 0) { + printf("depth\t rho\t vsh\t vsv (QN QL)\t \n"); + for(int i = istart; i <= iend; i ++) { + printf("%f %f %f %f", + depth_tomo[i],rho_tomo[i], + vsh_tomo[i],vsv_tomo[i]); + if(HAS_ATT) { + printf(" %f %f\n",QN_tomo[i],QL_tomo[i]); + } + else { + printf("\n"); + } + } + } + else if (SWD_TYPE == 1) { + printf("depth\t rho\t vph\t vpv\t vsv\t eta (Qvph Qvpv Qvsv)\n"); + for(int i = istart; i <= iend; i ++) { + printf("%f %f %f %f %f %f", + depth_tomo[i],rho_tomo[i], + vph_tomo[i],vpv_tomo[i],vsv_tomo[i], + eta_tomo[i]); + if(HAS_ATT) { + printf(" %f %f %f\n",QA_tomo[i],QC_tomo[i],QL_tomo[i]); + } + else { + printf("\n"); + } + } + } + else { + + } + } +} + +void Mesh:: +print_database() const +{ + // print SEM mesh information for debug + printf("\n====================================\n"); + printf("========= DATABASE Description ========\n"); + printf("====================================\n\n"); + + printf("elements:\n"); + printf("=========================\n"); + printf("no. of nelemnts = %d\n",nspec + nspec_grl); + printf("no. of elastic GLL/GRL nelemnts = %d %d\n",nspec_el,nspec_el_grl); + printf("no. of acoustic GLL/GRL nelemnts = %d %d\n",nspec_ac,nspec_ac_grl); + printf("no. of elastic wavefield points = %d\n",nglob_el); + printf("no. of acoustic wavefield points = %d\n",nglob_ac); + + printf("\nSimulation parameters:\n"); + printf("=========================\n"); + printf("phase velocity min/max = %f %f\n",PHASE_VELOC_MIN,PHASE_VELOC_MAX); + + printf("\nElastic-Acoustic Boundary:\n"); + printf("=========================\n"); + printf("no. of E-A boundaries = %d\n",nfaces_bdry); + for(int iface = 0; iface < nfaces_bdry; iface ++) { + int ispec_ac = ispec_bdry[iface * 2 + 0]; + int ispec_el = ispec_bdry[iface * 2 + 1]; + printf("boundary %d:\n",iface); + printf("\tispec_ac = %d ispec_el = %d\n",ispec_ac,ispec_el); + int top_is_fluid = bdry_norm_direc[iface]; + printf("top material is fluid = %d\n",top_is_fluid); + } + +} + +} // namespace specswd + diff --git a/src/mesh/mesh.hpp b/src/mesh/mesh.hpp new file mode 100644 index 0000000..72ae5c9 --- /dev/null +++ b/src/mesh/mesh.hpp @@ -0,0 +1,114 @@ +#ifndef SPECSWD_MESH_H_ +#define SPECSWD_MESH_H_ + +#include +#include +#include + +namespace specswd +{ + +/** + * @brief SEM mesh class + * + */ +struct Mesh { + + // SEM Mesh + int nspec,nspec_grl; // no. of elements for gll/grl layer + int nglob; // no. of unique points + std::vector ibool; // connectivity matrix, shape(nspec * NGLL + NGRL) + std::vector skel; // skeleton, shape(nspec * 2 + 2) + std::vector znodes; // shape(nspec * NGLL + NGRL) + std::vector jaco; // jacobian for GLL, shape(nspec + 1) dz / dxi + std::vector zstore; // shape(nglob) + + // element type for each medium + int nspec_ac,nspec_el; + int nspec_ac_grl,nspec_el_grl; + std::vector is_elastic, is_acoustic; + std::vector el_elmnts,ac_elmnts; // elements for each media, shape(nspec_? + nspec_?_grl) + + // unique array for acoustic/elastic + int nglob_ac, nglob_el; + std::vector ibool_el, ibool_ac; // connectivity matrix, shape shape(nspec_? + nspec_?_grl) + + // density and elastic parameters + std::vector xrho_ac; // shape(nspec_ac * NGLL + nspec_ac_grl * NGRL) + std::vector xrho_el; // shape (nsepc_el * NGLL + nspec_el_grl * NGRL) + + // attenuation/type flag + bool HAS_ATT; + int SWD_TYPE; // =0 Love wave, = 1 for Rayleigh = 2 full aniso + + // vti media + std::vector xA,xC,xL,xeta,xN; // shape(nspec_el * NGLL+ nspec_el_grl * NGRL) + std::vector xQA,xQC,xQL,xQN; // shape(nspec_el * NGLL+ nspec_el_grl * NGRL), Q model + + // full anisotropy + int nQmodel_ani; // no. of Q used for anisotropy + std::vector xC21; // shape(21,nspec_el * NGLL+ nspec_el_grl * NGRL) + std::vector xQani; // shape(nQmodel_ani,nspec_el * NGLL+ nspec_el_grl * NGRL) + + // fluid vti + std::vector xkappa_ac,xQk_ac; + + // fluid-elastic boundary + int nfaces_bdry; + std::vector ispec_bdry; // shape(nfaces_bdry,2) (i,:) = [ispec_ac,ispec_el] + std::vector bdry_norm_direc; // shape(nfaces_bdry), = 1 point from acoustic -> z direc elastic + + int nz_tomo, nregions; + std::vector rho_tomo; + std::vector vpv_tomo,vph_tomo,vsv_tomo,vsh_tomo,eta_tomo; + std::vector QC_tomo,QA_tomo,QL_tomo,QN_tomo; + std::vector c21_tomo,Qani_tomo; + std::vector depth_tomo; + std::vector region_bdry; // shape(nregions,2) + std::vector iregion_flag; // shape(nspec + 1), return region flag + + // interface with layered model + std::vector is_el_reg, is_ac_reg; // shape(nregions) + + float PHASE_VELOC_MIN,PHASE_VELOC_MAX; + + // constants + float freq; // current frequency + float phi; // current angle, in rad + + // public functions + void read_model(const char *filename); + void create_database(float freq,float phi); + void print_model() const; + void print_database() const; + void allocate_1D_model(int nz0,int swd_type,int has_att); + void create_model_attributes(); + + // interpolate model + void interp_model(const float *param,const std::vector &elmnts,std::vector &md) const; + void project_kl(const float *frekl, float *kl_out) const; + + // private functions below + // ============================== + // + void create_material_info_(); + + // 1-D model + void read_model_header_(const char *filename); + void read_model_love_(const char *filename); + void read_model_rayl_(const char *filename); + void read_model_full_aniso_(const char *filename); + + // create SEM database + void compute_minmax_veloc_(float phi,std::vector &vmin,std::vector &vmax); + void create_db_love_(); + void create_db_rayl_(); + void create_db_aniso_(); +}; + +} // namespace specswd + + + + +#endif \ No newline at end of file diff --git a/src/shared/GQTable.cpp b/src/shared/GQTable.cpp new file mode 100644 index 0000000..3a6d653 --- /dev/null +++ b/src/shared/GQTable.cpp @@ -0,0 +1,84 @@ +#include "shared/GQTable.hpp" + +#include + +//GLL +void gauss_legendre_lobatto(double* knots, double* weights, size_t length); +void lagrange_poly(double xi,size_t nctrl,const double *xctrl, + double *h,double* hprime); + +// GRL +void gauss_radau_laguerre(double *xgrl,double *wgrl,size_t length); +double laguerre_func(size_t n, double x); + + +namespace GQTable +{ + +std::array xgll,wgll; +std::array xgrl,wgrl; +std::array hprimeT,hprime; // hprimeT(i,j) = l'_i(xi_j) +std::array hprimeT_grl,hprime_grl; + +/** + * @brief initialize GLL/GRL nodes/weights + * + */ +void initialize() +{ + + // CHECK NGLL and NGRL range + static_assert(NGLL >=5 && NGLL <= 10,"Best NGLL range is [5,10]"); + static_assert(NGRL >=15 && NGLL <= 30,"Best NGRL range is [15,30]"); + + // GLL nodes/weights + std::array x_temp,w_temp; + gauss_legendre_lobatto(x_temp.data(),w_temp.data(),NGLL); + for(int i = 0; i < NGLL; i ++) { + xgll[i] = x_temp[i]; + wgll[i] = w_temp[i]; + } + + // compute hprime and hprimeT + double poly[NGLL],h_temp[NGLL]; + for(int i = 0; i < NGLL; i ++) { + double xi = x_temp[i]; + lagrange_poly(xi,NGLL,x_temp.data(),poly,h_temp); + for(int j = 0; j < NGLL; j ++) { + hprime[i*NGLL+j] = h_temp[j]; + } + } + for(int i = 0; i < NGLL; i ++) { + for(int j = 0; j < NGLL; j ++) { + hprimeT[i * NGLL + j] = hprime[j * NGLL + i]; + }} + + // GRL nodes/weights + gauss_radau_laguerre(x_temp.data(),w_temp.data(),NGRL); + for(int i = 0; i < NGRL; i ++) { + xgrl[i] = x_temp[i]; + wgrl[i] = w_temp[i]; + } + + // compute hprime_grl and hprimeT_grl + for(int i = 0; i < NGRL; i ++) { + for(int j = 0; j < NGRL; j ++) { + int id = i * NGRL + j; + if(i != j) { + hprimeT_grl[id] = laguerre_func(NGRL,xgrl[j]) / laguerre_func(NGRL,xgrl[i]) / (xgrl[j] - xgrl[i]); + } + else if(i == j && i == 0) { + hprimeT_grl[id] = -NGRL / 2.; + } + else { + hprimeT_grl[id] = 0.; + } + }} + for(int i = 0; i < NGRL; i ++) { + for(int j = 0; j < NGRL; j ++) { + int id = i * NGRL + j; + hprime_grl[j * NGRL + i] = hprimeT_grl[id]; + }} +} + +} // namespace GQTable diff --git a/src/shared/GQTable.hpp b/src/shared/GQTable.hpp new file mode 100644 index 0000000..e84413d --- /dev/null +++ b/src/shared/GQTable.hpp @@ -0,0 +1,20 @@ +#ifndef SPECSWD_GQTABLE_H_ +#define SPECSWD_GQTABLE_H_ + +#include + +namespace GQTable +{ + +const int NGLL = 7, NGRL = 20; +extern std::array xgll,wgll; +extern std::array xgrl,wgrl; +extern std::array hprimeT,hprime; // hprimeT(i,j) = l'_i(xi_j) +extern std::array hprimeT_grl,hprime_grl; + +void initialize(); + +} // GQTable + + +#endif \ No newline at end of file diff --git a/src/shared/attenuation.cpp b/src/shared/attenuation.cpp new file mode 100644 index 0000000..2d0de88 --- /dev/null +++ b/src/shared/attenuation.cpp @@ -0,0 +1,327 @@ +#include +#include + +typedef std::complex crealw; +typedef std::complex dcmplx; + +namespace specswd +{ + +// only valid for frequency range [0.01,100] +const int NSLS = 5; +std::array y_sls_ref = {1.93044501, 1.64217132, 1.73606189, 1.42826439, 1.66934129}; +std::array w_sls_ref = {4.71238898e-02, 6.63370885e-01, 9.42477796e+00, 1.14672436e+02,1.05597079e+03}; + + +/** + * @brief reset reference SLS model + * + * @param w_sls new refernce w_sls, shape(NSLS) + * @param y_sls new refernce y_sls, shape(NSLS) + */ +void +reset_ref_Q_model(const double *w_sls, const double *y_sls) +{ + for(int i = 0; i < NSLS; i ++) { + w_sls_ref[i] = w_sls[i]; + y_sls_ref[i] = y_sls[i]; + } +} + +/** + * @brief correct y from reference model to target model + * @param Q target Q + * @param y_sls reference y_sls parameters + * @param w_sls reference w_sls + */ +static void +get_Q_sls_model(float Q,double *y_sls,double *w_sls) +{ + double dy[NSLS]; + double y[NSLS]; + for(int i = 0; i < NSLS; i ++) { + y[i] = y_sls_ref[i] / Q; + } + dy[0] = 1. + 0.5 * y[0]; + for(int i = 1; i < NSLS; i ++) { + dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i]; + } + + // copy to y_sls/w_sls + for(int i = 0; i < NSLS; i ++) { + w_sls[i] = w_sls_ref[i]; + y_sls[i] = dy[i] * y[i]; + } +} + +/** + * @brief get SLS Q terms on the elastic modulus + * + * @param freq current frequency + * @param Q Q value + * @return s modulus factor mu = mu * s + */ +crealw get_sls_modulus_factor(float freq,float Q) +{ + double y_sls[NSLS], w_sls[NSLS]; + double om = 2 * M_PI * freq; + const dcmplx I = {0.,1.}; + + get_Q_sls_model(Q,y_sls,w_sls); + dcmplx s {}; + for(int j = 0; j < NSLS; j ++) { + s += I * om * y_sls[j] / (w_sls[j] + I * om); + } + + return (crealw)(s + 1.); +} + +/** + * @brief Get the Q factor and derivative for SLS model + * + * @param freq frequency + * @param Q current Q + * @param s modulus factor mu = mu * s + * @param dsdqi Q^{-1} derivative ds / dQi + */ +void +get_sls_Q_derivative(float freq,float Q,crealw &s,crealw &dsdqi) +{ + double dy[NSLS],dd_dqi[NSLS]; + double y[NSLS]; + const dcmplx I = {0.,1.}; + double om = 2 * M_PI * freq; + + // compute corrector + for(int i = 0; i < NSLS; i ++) { + y[i] = y_sls_ref[i] / Q; + } + dy[0] = 1. + 0.5 * y[0]; + for(int i = 1; i < NSLS; i ++) { + dy[i] = dy[i-1] + (dy[i-1] - 0.5) * y[i-1] + 0.5 * y[i]; + } + + dd_dqi[0] = 0.5 * y_sls_ref[0]; + for(int i = 1; i < NSLS; i ++) { + dd_dqi[i] = dd_dqi[i-1] + (dy[i-1] - 0.5) * y_sls_ref[i-1] + dd_dqi[i-1] * y[i-1] + 0.5 * y_sls_ref[i]; + } + + // sum together + dcmplx s1{},dsdqi1{}; + s1 = 0.; dsdqi1 = 0.; + for(int i = 0; i < NSLS; i ++) { + s1 += I * om * y[i] * dy[i]/ (w_sls_ref[i] + I * om); + + // y' = delta * y + // dy'/dqi = d delta /dqi * y + delta * dy/dqi + double dyp_dqi = dd_dqi[i] * y[i] + dy[i] * y_sls_ref[i]; + dsdqi1 += I * om * dyp_dqi / (w_sls_ref[i] + I * om); + } + + s = (crealw)(s1 + 1.); + dsdqi = dsdqi1; +} + +static int Index(int m,int n) +{ + if(m > n) { + std::swap(m,n); + } + int idx = m * 6 + n - (m * (m + 1)) / 2; + + return idx; +} + +/** + * @brief only set Qkappa and Qmu to C21 + * @see Carcione and Cavallini (1995d), delta = 2, M3 = M4 = M2 -> Qmu + */ +static void +C21_iso_(crealw Qk_fac,crealw Qmu_fac,crealw __restrict *c21) +{ + // get kappa and mu by using average + #define C(p,q) c21[Index(p,q)] + crealw eps = (1.0f/3.0f) * (C(0,0) + C(1,1) + C(2,2)); + crealw mu = (1.0f/3.0f) * (C(3,3) + C(4,4) + C(5,5)); + crealw kappa = eps - (float)(4. / 3.) * mu; + + // add back to c21 + for(int i = 0; i < 3; i ++) { + C(i,i) = C(i,i) - eps + kappa * Qk_fac + (float)(4./3.) * mu * Qmu_fac; + } + for(int i = 0; i < 3; i ++) { + for(int j = i + 1; j < 3; j ++) { + C(i,j) = C(i,j) - eps + kappa * Qk_fac + 2.0f* mu * (1.0f - 1.0f/3.0f * Qmu_fac); + } + } + + for(int i = 3; i < 6; i ++) C(i,i) *= Qmu_fac; + + #undef C +} + +static void +C21_iso_deriv_(const crealw *Qfac, const crealw *dQfac, + const float *c21, + crealw *__restrict dCC21_dc, + crealw *__restrict dCC21_dQi) +{ + // set derivatives to zero + for(int i = 0; i < 21 * 2; i ++) { + dCC21_dc[i] = 0.; + dCC21_dQi[i] = 0.; + } + + // get kappa and mu fac/dfac + dcmplx Qk_fac = Qfac[0], Qmu_fac = Qfac[1]; + dcmplx dQk_fac = dQfac[0], dQmu_fac = dQfac[1]; + + // compute derivatives + // auto generated by sympy + #define SETDC(i,j,a) dCC21_dc[i*21+j] = (crealw) (a) + #define SETDQ(i,j,b) dCC21_dQi[i*2+j] = (crealw) (b) + #define C(p,q) c21[Index(p,q)] + SETDC(0,0,(1.0/3.0)*Qk_fac + 2.0/3.0); + SETDC(0,6,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(0,11,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(0,15,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(0,18,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(0,20,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(1,0,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(1,1,1); + SETDC(1,6,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(1,11,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(1,15,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(1,18,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(1,20,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(2,0,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(2,2,1); + SETDC(2,6,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(2,11,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(2,15,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(2,18,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(2,20,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(3,3,1); + SETDC(4,4,1); + SETDC(5,5,1); + SETDC(6,0,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(6,6,(1.0/3.0)*Qk_fac + 2.0/3.0); + SETDC(6,11,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(6,15,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(6,18,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(6,20,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(7,0,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(7,6,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(7,7,1); + SETDC(7,11,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(7,15,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(7,18,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(7,20,-4.0/9.0*Qk_fac - 2.0/9.0*Qmu_fac + 2.0/3.0); + SETDC(8,8,1); + SETDC(9,9,1); + SETDC(10,10,1); + SETDC(11,0,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(11,6,(1.0/3.0)*Qk_fac - 1.0/3.0); + SETDC(11,11,(1.0/3.0)*Qk_fac + 2.0/3.0); + SETDC(11,15,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(11,18,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(11,20,-4.0/9.0*Qk_fac + (4.0/9.0)*Qmu_fac); + SETDC(12,12,1); + SETDC(13,13,1); + SETDC(14,14,1); + SETDC(15,15,Qmu_fac); + SETDC(16,16,1); + SETDC(17,17,1); + SETDC(18,18,Qmu_fac); + SETDC(19,19,1); + SETDC(20,20,Qmu_fac); + + SETDQ(0,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac); + SETDQ(0,1,((4.0/9.0)*C(3,3)*1. + (4.0/9.0)*C(4,4)*1. + (4.0/9.0)*C(5,5)*1.) * dQmu_fac); + SETDQ(1,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac); + SETDQ(1,1,(-2.0/9.0*C(3,3)*1. - 2.0/9.0*C(4,4)*1. - 2.0/9.0*C(5,5)*1.) * dQmu_fac); + SETDQ(2,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac); + SETDQ(2,1,(-2.0/9.0*C(3,3)*1. - 2.0/9.0*C(4,4)*1. - 2.0/9.0*C(5,5)*1.) * dQmu_fac); + SETDQ(6,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac); + SETDQ(6,1,((4.0/9.0)*C(3,3)*1. + (4.0/9.0)*C(4,4)*1. + (4.0/9.0)*C(5,5)*1.) * dQmu_fac); + SETDQ(7,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac); + SETDQ(7,1,(-2.0/9.0*C(3,3)*1. - 2.0/9.0*C(4,4)*1. - 2.0/9.0*C(5,5)*1.) * dQmu_fac); + SETDQ(11,0,((1.0/3.0)*C(0,0)*1. + (1.0/3.0)*C(1,1)*1. + (1.0/3.0)*C(2,2)*1. - 4.0/9.0*C(3,3)*1. - 4.0/9.0*C(4,4)*1. - 4.0/9.0*C(5,5)*1.) * dQk_fac); + SETDQ(11,1,((4.0/9.0)*C(3,3)*1. + (4.0/9.0)*C(4,4)*1. + (4.0/9.0)*C(5,5)*1.) * dQmu_fac); + SETDQ(15,1,(C(3,3)*1.) * dQmu_fac); + SETDQ(18,1,(C(4,4)*1.) * dQmu_fac); + SETDQ(20,1,(C(5,5)*1.) * dQmu_fac); + + #undef C + #undef SETDC + #undef SETDQ +} + +/** + * @brief set C21 attenuation model + * @param freq frequency + * @param Qm Q values + * @param nQmodel number of Q values + * @param[inout] c21 real C21 modulus shape(21), return complex modulus + * @param funcid function id, default 1 + */ +void get_C21_att(float freq,const float *Qm,int nQmodel, + crealw __restrict *c21,int funcid) +{ + // get all sls factor + std::array Qfac; + for(int im = 0; im < nQmodel; im ++) { + Qfac[im] = get_sls_modulus_factor(freq,Qm[im]); + } + + // choose sls factor + switch (funcid) + { + case 1: + C21_iso_(Qfac[0],Qfac[1],c21); + break; + + default: + printf("not implemented!\n"); + exit(1); + break; + } +} + +/** + * @brief compute derivatives of C21 att model + * @param freq frequency + * @param Qm Q values + * @param C21 C21 model + * @param nQmodel number of Q values + * @param dCC21_dc derivative of complex c21 to real c21, shape (21,21) + * @param dCC21_dQi derivative of complex c21 to Qi, shape (21,nQmodel) + * @param funcid function id, default 1 + */ +void get_C21_deriv(float freq,const float *Qm,int nQmodel, + const float *C21, + crealw *__restrict dCC21_dc, + crealw *__restrict dCC21_dQi, + int funcid) +{ + // get all sls factor + std::array Qfac,dQfac; + for(int im = 0; im < nQmodel; im ++) { + get_sls_Q_derivative(freq,Qm[im],Qfac[im],dQfac[im]); + } + + switch (funcid) + { + case 1: + C21_iso_deriv_(Qfac.data(),dQfac.data(),C21,dCC21_dc,dCC21_dQi); + break; + + default: + printf("not implemented!\n"); + exit(1); + break; + } +} + +} // namespace specswd + diff --git a/src/shared/attenuation.hpp b/src/shared/attenuation.hpp new file mode 100644 index 0000000..6f818e2 --- /dev/null +++ b/src/shared/attenuation.hpp @@ -0,0 +1,26 @@ + +#ifndef SPECSWD_ATT_TABLE_H_ +#define SPECSWD_ATT_TABLE_H_ + +#include + +namespace specswd +{ + +const int NSLS = 5; + +std::complex get_sls_modulus_factor(float freq,float Q); +void +get_sls_Q_derivative(float freq,float Qm,std::complex &s, + std::complex &dsdqi); + +void get_C21_att(float freq,const float *Qm,int nQmodel, + std::complex * c21, + int funcid=1); + +void +reset_ref_Q_model(const double *w_sls, const double *y_sls); + +} + +#endif \ No newline at end of file diff --git a/src/shared/filter_swd.cpp b/src/shared/filter_swd.cpp deleted file mode 100644 index 7e88afb..0000000 --- a/src/shared/filter_swd.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include - -typedef std::complex dcmplx; - -/** - * @brief filter swd in the [ vmin,vmax] and Rek >= Imk - * - * @param vmin/vmax min/max velocity in this region - * @param om angular frequency - * @param displ_all eigen functions, shape(size,nc_all) - * @param k eigenvalues, wavenumber - * @param c filtered phase velocity, shape(nc) - * @param displ filtered eigen function, shape(nc,size) - */ -void -filter_swd(double vmin, double vmax,double om, const Eigen::MatrixXcd &displ_all, - const Eigen::Array,-1,1> &k,std::vector &c, - std::vector &displ) -{ - Eigen::Array c_all = (om / k).real(); - //std::cout << c_all.transpose() << "\n"; - - // filter swd in [vmin * 0.85,vmax] region - Eigen::Array c_filt; - Eigen::MatrixXd displ_filt; - using Eigen::all; - //auto mask = ((c_all >= 0.85 * vmin) && (c_all <= vmax)) && (k.real().abs() >= k.imag().abs()); - auto mask = ((c_all >= vmin)&& (c_all <= vmax)) && (k.real().abs() > 5 * k.imag().abs()); - // std::cout << mask << "\n"; - std::vector idx0; idx0.reserve(mask.cast().sum()); - for(int i = 0; i < c_all.size(); i ++) { - if(mask[i]) { - idx0.push_back(i); - } - } - - int nc = idx0.size(); - int size = displ_all.rows(); - c_filt.resize(nc); displ_filt.resize(size,nc); - for(int i = 0; i < nc; i ++) { - c_filt[i] = c_all[idx0[i]]; - displ_filt(all,i) = displ_all(all,idx0[i]).real(); - } - //printf("%g %g\n",c_filt.minCoeff(),c_filt.maxCoeff()); - - // sort according to ascending order - std::vector idx; - idx.resize(nc); - for(int i = 0; i < nc; i ++ ) idx[i] = i; - std::stable_sort(idx.begin(), idx.end(), - [&c_filt](size_t i1, size_t i2) {return c_filt[i1] < c_filt[i2];}); - - // copy to c/displ - c.resize(nc); displ.resize(nc * size); - for(int ic = 0; ic < nc; ic ++) { - c[ic] = c_filt[idx[ic]]; - for(int i = 0; i < size; i ++) { - displ[ic * size + i] = displ_filt(i,idx[ic]); - } - } -} diff --git a/src/shared/initialize.cpp b/src/shared/initialize.cpp deleted file mode 100644 index e12c818..0000000 --- a/src/shared/initialize.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "swdlayer.hpp" -#include "shared/quadrature.hpp" - -/** - * @brief initialize GLL/GRL nodes/weights - * - */ -void LayerModel:: initialize() -{ - // GLL nodes/weights - gauss_legendre_lobatto(xgll.data(),wgll.data(),NGLL); - - // compute hprime and hprimeT - double poly[NGLL]; - for(int i = 0; i < NGLL; i ++) { - double xi = xgll[i]; - lagrange_poly(xi,NGLL,xgll.data(),poly,&hprime[i*NGLL]); - } - for(int i = 0; i < NGLL; i ++) { - for(int j = 0; j < NGLL; j ++) { - hprimeT[i * NGLL + j] = hprime[j * NGLL + i]; - }} - - - // GRL nodes/weights - gauss_radau_laguerre(xgrl.data(),wgrl.data(),NGRL); - - // compute hprime_grl and hprimeT_grl - for(int i = 0; i < NGRL; i ++) { - for(int j = 0; j < NGRL; j ++) { - int id = i * NGRL + j; - if(i != j) { - hprimeT_grl[id] = laguerre_func(NGRL,xgrl[j]) / laguerre_func(NGRL,xgrl[i]) / (xgrl[j] - xgrl[i]); - } - else if(i == j && i == 0) { - hprimeT_grl[id] = -NGRL / 2.; - } - else { - hprimeT_grl[id] = 0.; - } - }} - for(int i = 0; i < NGRL; i ++) { - for(int j = 0; j < NGRL; j ++) { - int id = i * NGRL + j; - hprime_grl[j * NGRL + i] = hprimeT_grl[id]; - }} -} - -/** - * @brief find location of z0 in ascending list z - * - * @param z depth list, shape(nlayer) - * @param z0 current loc, must be inside z - * @param nlayer - * @return int location of z0 in z, satisfies z0 >= z[i] && z0 < z[i + 1] - */ -static int -find_loc(const float *z,float z0,int nz) -{ - - int i = 0; - while(i < nz) { - if(z0 >= z[i] && z0 < z[i + 1]) { - break; - } - i += 1; - } - - return i; -} - - -/** - * @brief interpolate a model by using coordinates - * - * @param z input model z coordinates, shape(nlayer) - * @param param input model parameter, shape(nlayer) - * @param md model required to interpolate, shape(nspec*NGLL + NGRL) - */ -void LayerModel:: -interp_model(const float *z,const float *param,std::vector &md) const -{ - // get ilayer - int nlay = ilayer_flag[nspec] + 1; - - for(int ispec = 0; ispec < nspec + 1; ispec ++) { - int NGL = NGLL; - if(ispec == nspec) { - NGL = NGRL; - } - - // get layer index - int ilay = ilayer_flag[ispec]; - - for(int i = 0; i < NGL; i ++) { - int id = ispec * NGLL + i; - double z0 = znodes[id]; - - // set model - if(IS_DICON_MODEL) { - md[id] = param[ilay]; - } - else { - if(z0 >= z[nlay - 1]) { - md[id] = param[nlay - 1]; - } - else if (z0 <= z[0]) { - md[id] = param[0]; - } - else { - // find location - int ilay = find_loc(z,z0,nlay); - float dz = z[ilay + 1] - z[ilay]; - md[id] = param[ilay] + (param[ilay + 1] - param[ilay]) / dz * (z0 - z[ilay]); - } - } - } - } -} - -/** - * @brief Create SEM mesh by using input model info - * - * @param nel no. of elements for each layer, shape(nlayer - 1) for layered model, and shape(1) for continous model - * @param thk thickness of each layer, shape(nlayer) - * @param zlist cumsum(thk), shape(nlayer) - * @param nlayer no. of layers - * @param scale scale factor for GRL layer, zbot = sum(thk) + xgrl[-1] * scale - */ -void LayerModel:: -create_mesh(const int *nel, const float *thk,const float *zlist,int nlayer,double scale) -{ - // count # of elements - int nelsize = nlayer - 1; - if(!IS_DICON_MODEL) nelsize = 1; - nspec = 0; - for(int i = 0; i < nelsize; i ++) { - nspec += nel[i]; - } - nspec_grl = 1; - - // allocate space - size_t size = nspec * NGLL + NGRL; - ibool.resize(size); znodes.resize(size); - jaco.resize(nspec + 1); skel.resize(nspec * 2 + 2); - ilayer_flag.resize(nspec + 1); - - // connectivity matrix - int idx = 0; - for(int ispec = 0; ispec < nspec; ispec ++) { - for(int igll = 0; igll < NGLL; igll ++) { - ibool[ispec * NGLL + igll] = idx; - idx += 1; - } - idx -= 1; - } - for(int i = 0; i < NGRL; i ++) { - ibool[nspec * NGLL + i] = idx; - idx += 1; - } - nglob = ibool[nspec * NGLL + NGRL - 1] + 1; - - // compute skeleton coordinates in GLL layer - if(this -> IS_DICON_MODEL) { - int id = 0; - for(int i = 0; i < nelsize; i ++) { - float h = thk[i] / nel[i]; - for(int j = 0; j < nel[i]; j ++ ) { - skel[id * 2 + 0] = zlist[i] + h * j; - skel[id * 2 + 1] = zlist[i] + h * (j+1); - ilayer_flag[id] = i; - id += 1; - } - } - ilayer_flag[nspec] = nlayer - 1; - } - else { - int id = 0; - float h = (zlist[nlayer - 1] - zlist[0]) / nel[0]; - for(int j = 0; j < nel[0]; j ++ ) { - skel[id * 2 + 0] = zlist[0] + h * j; - skel[id * 2 + 1] = zlist[0] + h * (j+1); - ilayer_flag[id] = -1; // will not be used - id += 1; - } - ilayer_flag[nspec] = nlayer - 1; - } - - // compute coordinates and jaco in GLL layer - for(int ispec = 0; ispec < nspec; ispec ++) { - double h = skel[ispec * 2 + 1] - skel[ispec * 2 + 0]; - jaco[ispec] = h / 2.; - for(int i = 0; i < NGLL; i ++) { - double xi = xgll[i]; - znodes[ispec * NGLL + i] = skel[ispec * 2] + h * 0.5 * (xi + 1); - } - } - - // min/max z for GRL layer - float zmax = zlist[nlayer - 1]; - skel[nspec * 2 + 0] = zmax; - skel[nspec * 2 + 1] = zmax + xgrl[NGRL-1] * scale; - - // GRL layer - for(int ispec = nspec; ispec < nspec + 1; ispec ++) { - jaco[ispec] = scale; - for(int i = 0; i < NGRL; i ++) { - double xi = xgrl[i]; - znodes[ispec * NGLL + i] = skel[ispec * 2] + xi * scale; - } - } - - // UNIQUE coordinates - zstore.resize(nglob); - for(int i = 0; i < nspec * NGLL + NGRL; i ++) { - int iglob = ibool[i]; - zstore[iglob] = znodes[i]; - } -} - -/** - * @brief project SEM-type kernels to original model - * - * @param z z coordiantes of previous model, shape(nlayer) - * @param param_kl SEM typed kernel, shape(nspec * NGLL + NGRL) - * @param kl_out kernels in original model, shape(nlayer) - */ -void LayerModel :: -project_kl(const float *z, const double *param_kl, double *kl_out) const -{ - // zero out kl_out - int nlayer = ilayer_flag[nspec] + 1; - for(int i = 0; i < nlayer; i ++) kl_out[i] = 0.; - - for(int ispec = 0; ispec < nspec + 1; ispec ++) { - int NGL = NGLL; - if(ispec == nspec) { - NGL = NGRL; - } - - // get layer index - int ilay = ilayer_flag[ispec]; - - for(int i = 0; i < NGL; i ++) { - int id = ispec * NGLL + i; - double z0 = znodes[id]; - - // interp - if(IS_DICON_MODEL) { - kl_out[ilay] += param_kl[id]; - } - else { - if(z0 >= z[nlayer - 1]) { - kl_out[nlayer - 1] += param_kl[id]; - } - else if (z0 <= z[0]) { - kl_out[0] += param_kl[id]; - } - else { - int ilay = find_loc(z,z0,nlayer); - double dz = z[ilay + 1] - z[ilay]; - double coef = (z0 - z[ilay]) / dz; - kl_out[ilay] += (1 - coef) * param_kl[id]; - kl_out[ilay + 1] += coef * param_kl[id]; - } - } - } - } -} \ No newline at end of file diff --git a/include/swdio.hpp b/src/shared/iofunc.hpp similarity index 77% rename from include/swdio.hpp rename to src/shared/iofunc.hpp index 8a749e9..fad63f7 100644 --- a/include/swdio.hpp +++ b/src/shared/iofunc.hpp @@ -1,10 +1,17 @@ +#ifndef SPECSWD_IOFUNC_H_ +#define SPECSWD_IOFUNC_H_ + #include +namespace specswd +{ + + inline void __myfwrite(const void *__ptr, size_t __size, size_t __nitems, FILE *__stream) { size_t size = fwrite(__ptr,__size,__nitems,__stream); if(size != __nitems) { - fprintf(stderr,"cannot write to binary!\n"); + printf("cannot write to binary!\n"); exit(1); } } @@ -25,4 +32,9 @@ write_binary_f(FILE *fp, const T *data, size_t n) // integer back __myfwrite(&size,sizeof(int),1,fp); -} \ No newline at end of file +} + +} // namespace specswd + + +#endif \ No newline at end of file diff --git a/src/shared/libgll.cpp b/src/shared/libgll.cpp index 3d49d9c..9e47a5b 100644 --- a/src/shared/libgll.cpp +++ b/src/shared/libgll.cpp @@ -15,15 +15,16 @@ * @brief compute the Lagrange interpolants based upon the interpolation points * * @param xi current location, - * @param nctrl no. of control points + * @param NCTRL no. of control points * @param xctrl control nodes, shape (nctrl) * @param h polynomial value, shape (nctrl) * @param hprime derivative, shape (nctrl) */ -void lagrange_poly(double xi,int nctrl,const double *xctrl, +void lagrange_poly(double xi,size_t NCTRL,const double *xctrl, double * h,double* hprime) { //! note: this routine is hit pretty hard by the mesher, optimizing the loops here will be beneficial + int nctrl = NCTRL; for(int dgr = 0;dgr - -//GLL -void gauss_legendre_lobatto(double* knots, double* weights, int length); -void lagrange_poly(double xi,int nctrl,const double *xctrl, - double *h,double* hprime); - -// GRL -void gauss_radau_laguerre(double *xgrl,double *wgrl,size_t length); -double laguerre_func(size_t n, double x); - -#endif \ No newline at end of file diff --git a/src/shared/schur.hpp b/src/shared/schur.hpp new file mode 100644 index 0000000..8eae861 --- /dev/null +++ b/src/shared/schur.hpp @@ -0,0 +1,144 @@ +#ifndef SPECSWD_SCHUR_H_ +#define SPECSWD_SCHUR_H_ + +#include +#include + +#ifdef SPECSWD_EGN_DOUBLE +typedef double realw; +#define LAPACKE_REAL(name) LAPACKE_d ## name +#define LAPACKE_CMPLX(name) LAPACKE_z ## name +#define LCREALW lapack_complex_double +#else +typedef float realw; +#define LAPACKE_REAL(name) LAPACKE_s ## name +#define LAPACKE_CMPLX(name) LAPACKE_c ## name +#define LCREALW lapack_complex_float + +#endif + +typedef std::complex crealw; + + +namespace specswd { + +/** + * @brief compute generalized eigenvalues/eigenvectors and schur decomposition for A x = w B x + * @note all matrices used are column major + * + * @tparam COMMTP compute type, double/complex + * @tparam SAVETP save type, float/complex + * @param A,B two matrices, type = COMMTP, shape(n,n) + * @param w eigenvalues, shape(n) + * @param vr left eigenvectors, shape(n,n) + * @param vl right eigenvectors shape(n,n) + * @param Qmat,Zmat,Smat,Spmat QZ matrix, where A = Q @ S @ Z.H, B = Q @ S' @ Z.H + * @param compute_left_egn if true also compute left eigenvectors + */ +template void +schur_qz( + Eigen::MatrixX &A, + Eigen::MatrixX &B, + Eigen::ArrayX &w, + COMMTP *__restrict vr, + COMMTP *__restrict vl, + std::vector &Qmat, + std::vector &Zmat, + std::vector &Smat, + std::vector &Spmat, + bool compute_left_egn = false +) +{ + static_assert(std::is_same_v || + std::is_same_v>); + + // allocate Q,Z matrix to compute + int ng = A.rows(); + Eigen::MatrixX Q(ng,ng),Z(ng,ng); + + // resize all matrices + Qmat.resize(ng*ng); Zmat.resize(ng*ng); + Smat.resize(ng*ng); Spmat.resize(ng*ng); + + // eigenvalues/vectors for compute + Eigen::VectorX alpha(ng),beta(ng); + char side = 'R'; + if(compute_left_egn) side = 'B'; + + // run Qz + int sdim = 0,mm = ng; + if constexpr (std::is_same_v) { // save type is float + // allocate eigenvectors + Eigen::VectorX alphai(ng); + + // ?gges to compute + LAPACKE_REAL(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,A.data(),ng,B.data(),ng,&sdim,alpha.data(), + alphai.data(),beta.data(),Q.data(),ng, + Z.data(),ng + ); + + LAPACKE_REAL(tgevc)( + LAPACK_COL_MAJOR,side,'A',nullptr, + ng,A.data(),ng,B.data(),ng, + vl,ng,vr,ng,ng,&mm + ); + } + else { + LAPACKE_CMPLX(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(), + ng,&sdim,(LCREALW*)alpha.data(),(LCREALW*)beta.data(), + (LCREALW*)Q.data(),ng, + (LCREALW*)Z.data(),ng + ); + + LAPACKE_CMPLX(tgevc)( + LAPACK_COL_MAJOR,side,'A',nullptr, + ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(), + ng,(LCREALW*)vl,ng,(LCREALW*)vr,ng,ng,&mm + ); + } + + // note in surface wave dispersion, eigenvalues are always real numbers if A,B are real + alpha = alpha.array() / beta.array(); + + // compute right eigenvector + using Eigen::indexing::all; + Eigen::Map> VR(vr,ng,ng); + VR = Z * VR; + for(int i = 0; i < ng; i ++) { // normalize + COMMTP s = VR(all,i).norm(); + VR(all,i) /= s; + } + + // left eigenvector if required + if(compute_left_egn) { + Eigen::Map> VL(vl,ng,ng); + VL = Q * VL; + + for(int i = 0; i < ng; i ++) { // normalize + COMMTP s = VL(all,i).norm(); + VL(all,i) /= s; + } + } + + // save Q,Z,S,Sp matrix + for(int j = 0; j < ng; j ++) { + for(int i = 0; i < ng; i ++) { + int idx = j * ng + i; + Smat[idx] = A(i,j); + Spmat[idx] = B(i,j); + Qmat[idx] = Q(i,j); + Zmat[idx] = Z(i,j); + }} + + // save eigenvalues + w = alpha; +} + +} // namespace specswd + + +#endif \ No newline at end of file diff --git a/src/shared/schur.hpp.bak b/src/shared/schur.hpp.bak new file mode 100644 index 0000000..3ce58e1 --- /dev/null +++ b/src/shared/schur.hpp.bak @@ -0,0 +1,322 @@ +#ifndef SPECSWD_SCHUR_H_ +#define SPECSWD_SCHUR_H_ + +#include +#include + +#ifdef SPECSWD_EGN_DOUBLE +typedef double realw; +#define LAPACKE_REAL(name) LAPACKE_d ## name +#define LAPACKE_CMPLX(name) LAPACKE_z ## name +#define LCREALW lapack_complex_double + +#else +typedef float realw; +#define LAPACKE_REAL(name) LAPACKE_s ## name +#define LAPACKE_CMPLX(name) LAPACKE_c ## name +#define LCREALW lapack_complex_float +#endif + +typedef std::complex crealw; + + +namespace specswd { + +/** + * @brief solve eigenvectors from Hessenburg form (A - w[i] B) (Z.H @ x_i) = 0 + * + * @tparam T data type, default is float + * @param A triangular matrix A + * @param B triangular matrix A + * @param Z Z matrix, unitary + * @param w eigenvalues w[i] = A(i,i) / B(i,i) + * @param v right eigenvectors + */ +template void +solve_regn_triangular( + const Eigen::MatrixX &A, + const Eigen::MatrixX &B, + const Eigen::MatrixX &Z, + const Eigen::VectorX &w, + Eigen::MatrixX &v +) +{ + using Eigen::indexing::seq; + using Eigen::indexing::all; + int n = A.rows(); + for (int i = 0; i < n; i ++) { + T e = w[i]; + + // set constants + v(seq(i+1,n-1),i).setZero(); + v(i,i) = 1.; + + // backward substitution + for(int j = i-1; j >=0; j --) { + auto idx = seq(j+1,i); + T s = (A(j,idx) - e * B(j,idx)) * v(idx,i); + T diag = A(j,j) - e * B(j,j); + v(j,i) = std::abs(diag) < 1.0e-12 ? 0. : -s / diag; + } + } + v = Z * v; + + // normalize + for(int i = 0; i < n; i ++) { + T s = v(all,i).norm(); + v(all,i) /= s; + } +} + +/** + * @brief solve left eigenvectors from Hessenburg form (A - w[i] B).H (Q.H @ y_i) = 0 + * + * @tparam T data type, default is float + * @param A triangular matrix A + * @param B triangular matrix A + * @param Q Q matrix, unitary + * @param w eigenvalues w[i] = A(i,i) / B(i,i) + * @param v left eigenvectors + */ +template void +solve_legn_triangular( + const Eigen::MatrixX &A, + const Eigen::MatrixX &B, + const Eigen::MatrixX &Q, + const Eigen::VectorX &w, + Eigen::MatrixX &v +) +{ + using Eigen::indexing::seq; + using Eigen::indexing::all; + int n = A.rows(); + for (int i = 0; i < n; i ++) { + T e = w[i]; + + // set constants + v(seq(0,i-1),i).setZero(); + v(i,i) = 1.; + + // forward substitution + for(int j = i + 1; j < n; j ++) { + auto idx = seq(i,j-1); + T diag{}, s{}; + if constexpr(std::is_same_v ||std::is_same_v ) { + diag = A(j,j) - e * B(j,j); + s = ((A(idx,j) - e * B(idx,j)).array() + * v(idx,i).array()).sum(); + } + else { + diag = std::conj(A(j,j) - e * B(j,j)); + s = ((A(idx,j) - e * B(idx,j)) * v(idx,i)).array().conjugate().sum(); + } + v(j,i) = std::abs(diag) < 1.0e-12 ? 0 : -s / diag; + } + } + v = Q * v; + + // normalize + for(int i = 0; i < n; i ++) { + T s = v(all,i).norm(); + v(all,i) /= s; + } +} + +/** + * @brief compute generalized eigenvalues/eigenvectors and schur decomposition for A x = w B x + * @note all matrices used are column major + * + * @tparam COMMTP compute type, double/complex + * @tparam SAVETP save type, float/complex + * @param A,B two matrices, type = COMMTP, shape(n,n) + * @param w eigenvalues, shape(n) + * @param vr left eigenvectors, shape(n,n) + * @param vl right eigenvectors shape(n,n) + * @param Qmat,Zmat,Smat,Spmat QZ matrix, where A = Q @ S @ Z.H, B = Q @ S' @ Z.H + * @param compute_left_egn if true also compute left eigenvectors + */ +template void +schur_qz( + Eigen::MatrixX &A, + Eigen::MatrixX &B, + Eigen::ArrayX &w, + COMMTP *__restrict vr, + COMMTP *__restrict vl, + std::vector &Qmat, + std::vector &Zmat, + std::vector &Smat, + std::vector &Spmat, + bool compute_left_egn = false +) +{ + static_assert(std::is_same_v || + std::is_same_v>); + + // allocate Q,Z matrix to compute + int ng = A.rows(); + Eigen::MatrixX Q(ng,ng),Z(ng,ng); + + // resize all matrices + Qmat.resize(ng*ng); Zmat.resize(ng*ng); + Smat.resize(ng*ng); Spmat.resize(ng*ng); + + // eigenvalues/vectors for compute + Eigen::VectorX alpha(ng),beta(ng); + char side = 'R'; + if(compute_left_egn) side = 'B'; + + // run Qz + int sdim = 0,mm = ng; + if constexpr (std::is_same_v) { // save type is float + // allocate eigenvectors + Eigen::VectorX alphai(ng); + + // ?gges to compute + LAPACKE_REAL(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,A.data(),ng,B.data(),ng,&sdim,alpha.data(), + alphai.data(),beta.data(),Q.data(),ng, + Z.data(),ng + ); + + LAPACKE_REAL(tgevc)( + LAPACK_COL_MAJOR,side,'A',nullptr, + ng,A.data(),ng,B.data(),ng, + vl,ng,vr,ng,ng,&mm + ); + } + else { + LAPACKE_CMPLX(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(), + ng,&sdim,(LCREALW*)alpha.data(),(LCREALW*)beta.data(), + (LCREALW*)Q.data(),ng, + (LCREALW*)Z.data(),ng + ); + + LAPACKE_CMPLX(tgevc)( + LAPACK_COL_MAJOR,side,'A',nullptr, + ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(), + ng,(LCREALW*)vl,ng,(LCREALW*)vr,ng,ng,&mm + ); + } + + // note in surface wave dispersion, eigenvalues are always real numbers if A,B are real + alpha = alpha.array() / beta.array(); + + // compute right eigenvector + Eigen::Map> VR(vr,ng,ng); + VR = Z * VR; + + // left eigenvector if required + if(compute_left_egn) { + Eigen::Map> VL(vl,ng,ng); + VL = Q * VL; + } + + // save Q,Z,S,Sp matrix + for(int j = 0; j < ng; j ++) { + for(int i = 0; i < ng; i ++) { + int idx = j * ng + i; + Smat[idx] = A(i,j); + Spmat[idx] = B(i,j); + Qmat[idx] = Q(i,j); + Zmat[idx] = Z(i,j); + }} + w = alpha; +} + +/** + * @brief QZ decomposition of matrix A and B + * @param ng rows/cols of A, B + * @param A,B two matrices, type = COMMTP + * @param Qmat,Zmat,Smat,Spmat QZ matrix, where A = Q @ S @ Z.H, B = Q @ S' @ Z.H + */ +template void +schur_qz1(int ng, + Eigen::MatrixX &A, + Eigen::MatrixX &B, + std::vector &Qmat,std::vector &Zmat, + std::vector &Smat,std::vector &Spmat +) +{ + static_assert(std::is_same_v || + std::is_same_v>); + // resize all matrices + Qmat.resize(ng*ng); Zmat.resize(ng*ng); + Smat.resize(ng*ng); Spmat.resize(ng*ng); + + // run QZ + int sdim = 0; + if constexpr (std::is_same_v){ + Eigen::VectorX alphar(ng),alphai(ng),beta(ng); + if constexpr (std::is_same_v) { + LAPACKE_REAL(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,A.data(),ng,B.data(),ng,&sdim,alphar.data(), + alphai.data(),beta.data(),Qmat.data(),ng, + Zmat.data(),ng + ); + memcpy(Smat.data(),A.data(),A.size()*sizeof(A(0,0))); + memcpy(Spmat.data(),B.data(),B.size()*sizeof(B(0,0))); + } + else { + Eigen::MatrixX Q1(ng,ng),Z1(ng,ng); + LAPACKE_REAL(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,A.data(),ng,B.data(),ng,&sdim,alphar.data(), + alphai.data(),beta.data(),Q1.data(),ng, + Z1.data(),ng + ); + + // copy to Smat/Spmat + for(int j = 0; j < ng; j ++) { + for(int i = 0; i < ng; i ++) { + int idx = j * ng + i; + Smat[idx] = A(i,j); + Spmat[idx] = B(i,j); + Qmat[idx] = Q1(i,j); + Zmat[idx] = Z1(i,j); + }} + } + } + else { // save type is scmplex + Eigen::VectorX alpha(ng),beta(ng); + + if constexpr (std::is_same_v) { + LAPACKE_CMPLX(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(), + ng,&sdim,(LCREALW*)alpha.data(),(LCREALW*)beta.data(), + (LCREALW*)Qmat.data(),ng, + (LCREALW*)Zmat.data(),ng + ); + memcpy(Smat.data(),A.data(),A.size()*sizeof(A(0,0))); + memcpy(Spmat.data(),B.data(),B.size()*sizeof(B(0,0))); + } + else { + Eigen::MatrixX Q1(ng,ng),Z1(ng,ng); + LAPACKE_CMPLX(gges)( + LAPACK_COL_MAJOR,'V','V','N',nullptr, + ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(), + ng,&sdim,(LCREALW*)alpha.data(),(LCREALW*)beta.data(), + (LCREALW*)Q1.data(),ng, + (LCREALW*)Z1.data(),ng + ); + + // copy to Smat/Spmat + for(int j = 0; j < ng; j ++) { + for(int i = 0; i < ng; i ++) { + int idx = j * ng + i; + Smat[idx] = A(i,j); + Spmat[idx] = B(i,j); + Qmat[idx] = Q1(i,j); + Zmat[idx] = Z1(i,j); + }} + } + } +} + +} + +#endif \ No newline at end of file diff --git a/src/tti/CMakeLists.txt b/src/tti/CMakeLists.txt deleted file mode 100644 index 7603fd4..0000000 --- a/src/tti/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -file(GLOB SOURCE "*.cpp" "*.f90") -list(FILTER SOURCE EXCLUDE REGEX "main_tti.cpp") - -add_library(libtti ${SOURCE}) - - -add_executable(surftti ${PROJECT_SOURCE_DIR}/src/tti/main_tti.cpp) -target_link_libraries(surftti libtti shared ${LAPACK_LIBRARIES}) \ No newline at end of file diff --git a/src/tti/main_tti.cpp b/src/tti/main_tti.cpp deleted file mode 100644 index b86bd5b..0000000 --- a/src/tti/main_tti.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "tti/swdlayertti.hpp" -#include "swdio.hpp" - -#include -#include - -int main (int argc, char **argv){ - // read model name - if(argc != 6 & argc != 7) { - printf("Usage: ./surfvti modelfile phi f1 f2 nt [is_layered=1]\n"); - printf("freqs = logspace(log10(f1),log10(f2),nt)\n"); - exit(1); - } - - // read flag if required - bool is_layer = true; - if(argc == 7) { - int flag; - sscanf(argv[6],"%d",&flag); - is_layer = (flag == 1); - } - - // read model - std::ifstream infile; infile.open(argv[1]); - if(is_layer) { - printf("reading layered velocity model:\n"); - } - else { - printf("reading continuous velocity model:\n"); - } - printf("layer number\t thick\t rho\t vpv\t vph\t vsv\t vsh\t eta\t theta\t phi \n"); - std::vector thk,vpv,vph,vsv,vsh,rho,theta0,phi0,eta; - int nz; - infile >> nz; - thk.resize(nz); vsv.resize(nz); vsh.resize(nz); rho.resize(nz); - vpv.resize(nz); vph.resize(nz); eta.resize(nz); theta0.resize(nz); - phi0.resize(nz); - for(int i = 0; i < nz; i ++) { - infile >> thk[i] >> rho[i] >> vpv[i] >> - vph[i] >> vsv[i] >> vsh[i] >> - eta[i] >> theta0[i] >> phi0[i]; - printf("layer %d\t %g\t %g\t %g\t %g\t %g\t %g\t %g\t %g\t %g\n", - i + 1,thk[i],rho[i],vpv[i], - vph[i],vsv[i],vsh[i],eta[i], - theta0[i],phi0[i]); - theta0[i] *= M_PI / 180.; - phi0[i] *= M_PI / 180.; - } - infile.close(); - - // Period - int nt; - float f1,f2; - sscanf(argv[3],"%g",&f1); sscanf(argv[4],"%g",&f2); - sscanf(argv[5],"%d",&nt); - f1 = std::log10(f1); f2 = std::log10(f2); - if(f1 > f2) std::swap(f1,f2); - std::vector freq(nt); - for(int it = 0; it < nt; it ++) { - double coef = (nt - 1); - if(coef == 0.) coef = 1.; - coef = 1. / coef; - double f = f1 + (f2 - f1) * coef * it; - freq[it] = std::pow(10,f); - } - - // angle - float phi; - sscanf(argv[2],"%f",&phi); - - // create database - printf("\ncomputing dispersions for TTI model, angle = %f ...\n",phi); - LayerModelTTI model; - model.initialize(); - - FILE *fp = fopen("out/swd.txt","w"); - FILE *fio = fopen("out/database.bin","wb"); - - // write period vector into fp - for(int it = 0; it < nt; it ++) { - fprintf(fp,"%g ",1. / freq[it]); - } - fprintf(fp,"\n"); - - // write meta info into database - int nkers = 8, ncomp = 3; - write_binary_f(fio,&nkers,1); - write_binary_f(fio,&ncomp,1); - - for(int it = 0; it < nt; it ++) { - std::vector c; - std::vector> displ; - - // phase velocity/eigenfunctions - model.create_database( - freq[it],nz,rho.data(),vpv.data(),vph.data(),vsv.data(), - vsh.data(),eta.data(),theta0.data(),phi0.data(), - thk.data(),is_layer); - model.prepare_matrices(phi); - model.compute_egnfun(freq[it],phi,c,displ); - - // get some consts - int nglob = model.nglob; - int npts = model.ibool.size(); - - // write coordinates - write_binary_f(fio,model.znodes.data(),npts); - - // group - std::vector frekl; - int nc = c.size(); - double u,uphi; - for(int ic = 0; ic < nc; ic ++) { - auto out = model.compute_kernels(freq[it],c[ic],phi,&displ[ic*nglob*3],frekl); - u = out[0]; uphi = out[1]; - model.transform_kernels(frekl); - - // write swd - fprintf(fp,"%d %g %g %g %g %d\n",it,c[ic],u,phi,uphi,ic); - - // write displ - std::vector> temp(npts*ncomp); - for(int i = 0; i < npts; i ++) { - int iglob = model.ibool[i]; - for(int j = 0; j < ncomp; j ++) { - temp[j * npts + i] = displ[ic * nglob * ncomp + j * nglob + iglob]; - } - } - write_binary_f(fio,temp.data(),npts*ncomp); - - // write kernels - write_binary_f(fio,&frekl[0],npts*nkers); - } - } - fclose(fio); - fclose(fp); - -} \ No newline at end of file diff --git a/src/tti/sem_tti.cpp b/src/tti/sem_tti.cpp deleted file mode 100644 index e9c13d7..0000000 --- a/src/tti/sem_tti.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include "tti/swdlayertti.hpp" - -#include -#include - -#include -#include - -/** - * @brief compute phase velocity and eigen displacements for a given direction - * - * @param freq current frequency - * @param phi current direction, in deg - * @param c phase velocity - * @param displ displacement - */ -void LayerModelTTI:: -compute_egnfun(double freq, double phi, std::vector &c, std::vector &displ) const -{ - typedef Eigen::Matrix dcmat; - typedef std::complex scmplx; - - // angular frequency - double om = 2. * M_PI * freq; - double omega2 = std::pow(om,2); - - // mapping memory - Eigen::Map M(Mmat.data(),nglob*3); - Eigen::Map E(Emat.data(),nglob*3,nglob*3); - Eigen::Map K1(K1mat.data(),nglob*3,nglob*3); - Eigen::Map K2(K2mat.data(),nglob*3,nglob*3); - - // initialize auxiliary matrices A,B - Eigen::MatrixXcf A(nglob * 6,nglob * 6), B(nglob * 6,nglob * 6); - A.setZero(); B.setZero(); - - // construct auxiliary matrices A,B - using Eigen::seq; - auto idx1 = seq(0,nglob*3-1), idx2 = seq(nglob*3,nglob*6-1); - A(idx1,idx2).setIdentity(); // A[:nglob*3,nglob*3:] = I; - A(idx2,idx1) = (omega2 * dcmat(M.asDiagonal()) - E).cast(); // A[nglob*3:,:nglob*3] = om^2 * M - E - A(idx2,idx2) = (-K1).cast(); - - // solve generatlized matrix problem based on lapacke/mkl/eigen -#ifdef EIGEN_USE_LAPACKE - typedef lapack_complex_float lscmplx; - Eigen::VectorXcf alpha(nglob*6),beta(nglob*6); - Eigen::MatrixXcf displ_all(nglob * 6,nglob * 6); - - B(idx1,idx1).setIdentity(); - B(idx2,idx2) = K2.cast(); // B = [[I 0],[0,M]] - LAPACKE_cggev(LAPACK_COL_MAJOR,'N','V',nglob*6,(lscmplx*)A.data(),nglob*6, - (lscmplx*)B.data(),nglob*6,(lscmplx*)alpha.data(),(lscmplx*)beta.data(), - NULL,nglob*6,(lscmplx*)displ_all.data(),nglob*6); - - // eigenvalues - Eigen::ArrayXcf k = alpha.array() / beta.array(); -#else - B(idx1,idx1).setIdentity(); - B(idx2,idx2) = (K2.inverse()).cast(); // B = [[I 0],[0,M]] - A = B * A; - - // get eigen values/eigen vector - Eigen::ComplexEigenSolver sol(A); - Eigen::MatrixXcf displ_all = sol.eigenvectors();; - Eigen::ArrayXcf k = sol.eigenvalues().array(); -#endif - - // filter swd in [vmin * 0.85,vmax] region - double vmin = PHASE_VELOC_MIN, vmax = PHASE_VELOC_MAX; - Eigen::ArrayXf c_filt; - Eigen::MatrixXcf displ_filt; - Eigen::ArrayXf c_all = ((float)om / k).real(); - auto mask = ((c_all >= vmin)&& (c_all <= vmax)) && (k.real().abs() > k.imag().abs()); - std::vector fidx; fidx.reserve(mask.cast().sum()); // filterd indexes - int nc_all = c_all.size(); - for(int i = 0; i < nc_all; i ++) { - if(mask[i]) { - fidx.push_back(i); - } - } - - // copy filtered eigenvalues/funcs to a temporary array - using Eigen::all; - int nc = fidx.size(); - c_filt.resize(nc); displ_filt.resize(nglob*3,nc); - for(int i = 0; i < nc; i ++) { - c_filt[i] = c_all[fidx[i]]; - displ_filt(all,i) = displ_all(idx1,fidx[i]); - } - - // sort according to ascending order - std::vector sidx; - sidx.resize(nc); - for(int i = 0; i < nc; i ++ ) sidx[i] = i; - std::stable_sort(sidx.begin(), sidx.end(), - [&c_filt](size_t i1, size_t i2) {return c_filt[i1] < c_filt[i2];}); - - // copy to c/displ - int size = nglob * 3; - c.resize(nc); displ.resize(nc * size); - for(int ic = 0; ic < nc; ic ++) { - c[ic] = c_filt[sidx[ic]]; - for(int i = 0; i < size; i ++) { - displ[ic * size + i] = displ_filt(i,sidx[ic]); - } - } -} diff --git a/src/tti/swdlayertti.cpp b/src/tti/swdlayertti.cpp deleted file mode 100644 index 1d273df..0000000 --- a/src/tti/swdlayertti.cpp +++ /dev/null @@ -1,234 +0,0 @@ -#include "tti/swdlayertti.hpp" -typedef std::complex dcmplx; - -/** - * @brief initalize SEM mesh and create a TTI database from a layered model - * - * @param freq current frequency - * @param nlayer # of nlayers - * @param vpv/vph/vsv/vsh/eta/rho layer model vti parameters, shape(nlayer) - * @param theta0/phi0 axis direction - */ -void LayerModelTTI:: -create_database(double freq,int nlayer, const float *rho, - const float *vpv, const float* vph, - const float *vsv, const float *vsh, const float *eta, - const float *theta0, const float *phi0, - const float *thk,bool is_layer) -{ - // find min/max thickness, min veloc and create depth list - std::vector zlist(nlayer); - zlist[0] = 0.; - for(int i = 0; i < nlayer - 1; i ++) { - zlist[i + 1] = zlist[i] + thk[i]; - } - - // find min/max vs - PHASE_VELOC_MAX = -1.; - PHASE_VELOC_MIN = 1.0e20; - for(int i = 0; i < nlayer; i ++) { - double vmin = std::min(vsv[i],vsh[i]); - double vmax = std::max(vsv[i],vsh[i]); - PHASE_VELOC_MAX = std::max(vmax,PHASE_VELOC_MAX); - PHASE_VELOC_MIN = std::min(vmin,PHASE_VELOC_MIN); - } - PHASE_VELOC_MIN *= 0.85; - - // copy is_layer - IS_DICON_MODEL = is_layer; - - //double scale = Tmin /(2.0 * M_PI * std::sqrt(1. / (4.99 * 4.99) - 1 / (vmax * vmax))); - double scale = PHASE_VELOC_MAX / freq / xgrl[NGRL-1] * 10; - - // determine no. elements in each layer - std::vector nel; - if(this -> IS_DICON_MODEL) { - nel.resize(nlayer - 1); - for(int i = 0; i < nlayer - 1; i ++) { - float v0 = std::min(vsv[i],vsh[i]) * 0.85; - nel[i] = (int)(thk[i] * freq / v0 * 1.5 ) + 1; - } - } - else { // continuous model, constructed with min velocity - nel.resize(1); - float maxdepth = zlist[nlayer - 1] - zlist[0]; - nel[0] = 1.5 * (maxdepth * freq / PHASE_VELOC_MIN) + 1; - } - - // create mesh - this -> create_mesh(nel.data(),thk,zlist.data(),nlayer,scale); - - // allocate space - size_t size = nspec * NGLL + NGRL; - - // set value to modulus - xrho.resize(size); xA.resize(size); xC.resize(size); - xL.resize(size); xN.resize(size); xF.resize(size); - xT.resize(size); xP.resize(size); - - // interpolate - std::vector temp_eta(size); - this -> interp_model(zlist.data(),rho,xrho); - this -> interp_model(zlist.data(),vph,xA); - this -> interp_model(zlist.data(),vpv,xC); - this -> interp_model(zlist.data(),vsh,xN); - this -> interp_model(zlist.data(),vsv,xL); - this -> interp_model(zlist.data(),eta,temp_eta); - this -> interp_model(zlist.data(),theta0,xT); - this -> interp_model(zlist.data(),phi0,xP); - - // convert to elastic parameters - for(int i = 0; i < nspec * NGLL + NGRL; i ++) { - xA[i] = xA[i] * xA[i] * xrho[i]; - xC[i] = xC[i] * xC[i] * xrho[i]; - xN[i] = xN[i] * xN[i] * xrho[i]; - xL[i] = xL[i] * xL[i] * xrho[i]; - xF[i] = temp_eta[i] * (xA[i] - 2. * xL[i]); - } -} - - - -// fortran functions -extern "C" { - -void get_comp1_(int NGL,const double *A,const double *C,const double *F, - const double *L,const double *N,const double *theta0, - const double *dphi,double jaco, const double *weight, - const double *hp,const double *hpT, dcmplx *K0U,dcmplx *K0V, - dcmplx *K0W,dcmplx *K1U,dcmplx *K1V,dcmplx *K1W,dcmplx *K2U, - dcmplx *K2V,dcmplx *K2W); -void get_comp2_(int NGL,const double *A,const double *C,const double *F, - const double *L,const double *N,const double *theta0, - const double *dphi,double jaco, const double *weight, - const double *hp,const double *hpT, dcmplx *K0U,dcmplx *K0V, - dcmplx *K0W,dcmplx *K1U,dcmplx *K1V,dcmplx *K1W,dcmplx *K2U, - dcmplx *K2V,dcmplx *K2W); -void get_comp3_(int NGL,const double *A,const double *C,const double *F, - const double *L,const double *N,const double *theta0, - const double *dphi,double jaco, const double *weight, - const double *hp,const double *hpT, dcmplx *K0U,dcmplx *K0V, - dcmplx *K0W,dcmplx *K1U,dcmplx *K1V,dcmplx *K1W,dcmplx *K2U, - dcmplx *K2V,dcmplx *K2W); -} - -/** - * @brief wrapper function to compute weak form matrices in one element - * - * @param comp = 1,2,3 - * @param NGL - * @param A,C,F,L,N,theta0,dphi parameters, shape(NGL) - * @param jaco jacobian for this element - * @param weight GLL/GRL weights, shape (NGL) - * @param hp,hpT GLL/GRL derivatives, shape(NGL,NGL), note it's column major! - * @param K(0/1/2)/(U/V/W) matrices related to k^p (p=0,1,2) - */ -static void -get_comp_wrapper(int comp, - int NGL,const double *A,const double *C,const double *F, - const double *L,const double *N,const double *theta0, - const double *dphi,double jaco, const double *weight, - const double *hp,const double *hpT, dcmplx *K0U,dcmplx *K0V, - dcmplx *K0W,dcmplx *K1U,dcmplx *K1V,dcmplx *K1W,dcmplx *K2U, - dcmplx *K2V,dcmplx *K2W -) -{ - switch (comp + 1) - { - case 1: - get_comp1_(NGL,A,C,F,L,N,theta0,dphi,jaco,weight,hp,hpT, - K0U,K0V,K0W,K1U,K1V,K1W,K2U,K2V,K2W); - break; - case 2: - get_comp2_(NGL,A,C,F,L,N,theta0,dphi,jaco,weight,hp,hpT, - K0U,K0V,K0W,K1U,K1V,K1W,K2U,K2V,K2W); - break; - case 3: - get_comp3_(NGL,A,C,F,L,N,theta0,dphi,jaco,weight,hp,hpT, - K0U,K0V,K0W,K1U,K1V,K1W,K2U,K2V,K2W); - break; - default: - printf("comp should be one of [1,2,3]!\n"); - exit(1); - break; - } -} - -/** - * @brief prepare M/K1/K2/E matrices for TTI model - * - * @param phi polar angle of k vector, in deg - */ -void LayerModelTTI :: -prepare_matrices(double phi) -{ - // allocate matrices - size_t msize = nglob * 3; - Mmat.resize(msize); - K1mat.resize(msize * msize); - K2mat.resize(msize * msize); - Emat.resize(msize * msize); - const dcmplx ZERO{0.,0.}; - std::fill(Mmat.begin(),Mmat.end(),ZERO); - std::fill(K1mat.begin(),K1mat.end(),ZERO); - std::fill(K2mat.begin(),K2mat.end(),ZERO); - std::fill(Emat.begin(),Emat.end(),ZERO); - - // compute M/K/E for gll/grl layer - std::array dphi; - std::array EU,EV,EW,K1U,K1V,K1W,K2U,K2V,K2W; - for(int ispec = 0; ispec < nspec + 1; ispec ++) { - int id = ispec * NGLL; - const double *weight = wgll.data(); - const double *hpT = hprimeT.data(); - const double *hp = hprime.data(); - int NGL = NGLL; - - // grl case - if(ispec == nspec) { - weight = wgrl.data(); - hpT = hprimeT_grl.data(); - hp = hprime_grl.data(); - NGL = NGRL; - } - - // compute temporary polar angle - for(int i = 0; i < NGL; i ++) { - dphi[i] = xP[id + i] - M_PI / 180. * phi; - } - - // get K1/K2/E matrix - for(int ic = 0; ic < 3; ic ++ ) { - get_comp_wrapper(ic,NGL,&xA[id],&xC[id],&xF[id],&xL[id],&xN[id],&xT[id], - dphi.data(),jaco[ispec],weight,hpT,hp,EU.data(),EV.data(), - EW.data(),K1U.data(),K1V.data(),K1W.data(),K2U.data(), - K2V.data(),K2W.data()); - - for(int i = 0; i < NGL; i ++) { - int iglob = ibool[id + i]; - - // mass matrix - double M0 = weight[i] * jaco[ispec] * xrho[id + i]; - - // assemble - Mmat[ic * nglob + iglob] += M0; - - for(int j = 0; j < NGL; j ++) { - int iglob1 = ibool[id + j]; - - size_t row = (ic * nglob + iglob) * msize; - Emat[row + nglob * 0 + iglob1] += EU[i * NGL + j]; - Emat[row + nglob * 1 + iglob1] += EW[i * NGL + j]; - Emat[row + nglob * 2 + iglob1] += EV[i * NGL + j]; - K1mat[row + nglob * 0 + iglob1] += K1U[i * NGL + j]; - K1mat[row + nglob * 1 + iglob1] += K1W[i * NGL + j]; - K1mat[row + nglob * 2 + iglob1] += K1V[i * NGL + j]; - K2mat[row + nglob * 0 + iglob1] += K2U[i * NGL + j]; - K2mat[row + nglob * 1 + iglob1] += K2W[i * NGL + j]; - K2mat[row + nglob * 2 + iglob1] += K2V[i * NGL + j]; - } - - } - } - } -} \ No newline at end of file diff --git a/src/tti/swdlayertti.hpp b/src/tti/swdlayertti.hpp deleted file mode 100644 index 6f13c18..0000000 --- a/src/tti/swdlayertti.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef SWD_LAYER_TTI_MODEL -#define SWD_LAYER_TTI_MODEL - -#include -#include -#include - -#include "swdlayer.hpp" - -class LayerModelTTI : public LayerModel{ - -typedef std::complex dcmplx; -public: - - LayerModelTTI(){}; - -private: - std::vector Mmat,Emat,K1mat,K2mat; // matrices for SEM,shape(3*nglob,3*nglob) om^2 M = k^2 K_2 + k K_1 + E - -public: - - // density - std::vector xrho; - - // tti Love parameters A,C,L,F,N, theta,phi - std::vector xA,xC,xL,xF,xN; // shape(nspec * NGLL + NGRL) - std::vector xT,xP; // theta/phi, shape(nspec *NGLL + NGRL), in rad - - - // TTI model - void create_database(double freq,int nlayer, const float *rho, - const float *vpv, const float* vph, - const float *vsv, const float *vsh, const float *eta, - const float *theta0, const float *phi0, - const float *thk,bool is_layer); - - void prepare_matrices(double phi); - - void compute_egnfun(double freq, double phi, std::vector &c, std::vector &displ) const; - std::array - compute_kernels(double freq, double c,double phi, - const dcmplx *displ, - std::vector &frekl) const; - - void transform_kernels(std::vector &frekl) const; -}; - -#endif \ No newline at end of file diff --git a/src/tti/tti_kernels.cpp b/src/tti/tti_kernels.cpp deleted file mode 100644 index 00ceb75..0000000 --- a/src/tti/tti_kernels.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include "tti/swdlayertti.hpp" -typedef std::complex dcmplx; - -extern "C" { -/** - * @brief compute tti sensitivity kernels - * - * @param NGL shape of input parameters - * @param k wavenumber - * @param A,C,F,L,N,theta0,dphi TTI parameters, shape (NGL) - * @param U,V,W,dU,dV,dW displacements and their z derivative, shape (NGL) - * @param Kwvnm dL/dk shape (NGL) - * @param KA,KC,KF,KL,KN,KT,KP dL/dparam, shape(NGL) - * @param dL_dkv dL/ d(kx,ky), shape(NGL) - */ -void get_kernels_(int NGL,double k,const double *A,const double *C,const double *F, - const double *L,const double *N,const double *theta0, - const double *dphi, const dcmplx *U,const dcmplx *V,const dcmplx *W, - const dcmplx *dU, const dcmplx *dV, const dcmplx *dW, - double *Kwvnm, double *KA, double *KC, double *KF, double *KL, - double *KN, double *KT, double *KP, double *dL_dkv); -} - -/** - * @brief compute group velocity and kernels for tti model - * - * @param freq current frequency - * @param c phase velocity at this frequency - * @param phi azimuthal angle of c - * @param displ eigen function, shape(nglob * 3) - * @param frekl Frechet kernels A/C/F/L/N/T/P/rho_kl kernels for elastic parameters, shape(8,nspec*NGLL + NGRL) - * @return double u group velocity and it's azimthual angle - */ -std::array LayerModelTTI :: -compute_kernels(double freq, double c,double phi, - const dcmplx *displ, - std::vector &frekl) const -{ - // first allocate element wise displ - std::array U,dU,V,dV,W,dW; - std::array dphi,Kwvnm; - std::array dL_dkv; - - // resize - size_t size = xrho.size(); - frekl.resize(8 * size); - double *rho_kl = &frekl[7 * size]; - - // consts - double om = 2 * M_PI * freq; - double k = om / c; - - // loop every element - double I1{}, I2{}; - double I3x{},I3y{}; - for(int ispec = 0; ispec < nspec + 1; ispec += 1) { - const double *hp = &hprime[0]; - const double *w = &wgll[0]; - int NGL = NGLL; - int id = ispec * NGLL; - - // GRL layer - if(ispec == nspec) { - hp = &hprime_grl[0]; - w = &wgrl[0]; - NGL = NGRL; - } - - // cache displ in a element - for(int i = 0; i < NGL; i ++) { - int iglob = ibool[id + i]; - U[i] = displ[iglob + 0 * nglob]; - W[i] = displ[iglob + 1 * nglob]; - V[i] = displ[iglob + 2 * nglob]; - dphi[i] = xP[id + i] - M_PI / 180. * phi; - } - - // compute derivative - for(int i = 0; i < NGL; i ++) { - dcmplx sx{},sy{},sz{}; - for(int j = 0; j < NGL; j ++) { - sx += U[j] * hp[i * NGL + j]; - sy += W[j] * hp[i * NGL + j]; - sz += V[j] * hp[i * NGL + j]; - } - dU[i] = sx / jaco[ispec]; - dW[i] = sy / jaco[ispec]; - dV[i] = sz / jaco[ispec]; - } - - // compute A/C/F/L/N/T/P kernels - get_kernels_(NGL,k,&xA[id],&xC[id],&xF[id],&xL[id],&xN[id],&xT[id],dphi.data(), - U.data(),V.data(),W.data(),dU.data(),dV.data(),dW.data(),Kwvnm.data(), - &frekl[id],&frekl[id+size],&frekl[id+ 2*size],&frekl[id+3*size], - &frekl[id+4*size],&frekl[id+5*size],&frekl[id+6*size],dL_dkv.data()); - - // compute kernel/energy integral - // I1 = int dL/dk dz - // I2 = int dL/dom dz - // I3x = int dL/d_kx dz I3y = int dL/d_ky dz - for(int i = 0; i < NGL; i ++) { - // rho kernel - double rho = xrho[id + i]; - double disp_sq = std::pow(std::abs(U[i]),2) + - std::pow(std::abs(V[i]),2) + - std::pow(std::abs(W[i]),2); - rho_kl[id + i] = om * om * disp_sq; - - // accumulate I1/I2/I3x/I3y - I1 += Kwvnm[i] * w[i] * jaco[ispec]; - I2 += 2 * om * rho * w[i] * disp_sq * jaco[ispec]; - I3x += dL_dkv[i] * w[i] * jaco[ispec]; - I3y += dL_dkv[i + NGL] * w[i] * jaco[ispec]; - } - } - - // compute group velocity - std::array cg; - double ux = -I3x / I2; - double uy = -I3y / I2; - cg[0] = std::hypot(ux,uy); - cg[1] = std::atan2(uy,ux) * 180. / M_PI + phi; - - // rescale kernels with I1 - double coef1 = c / k / I1; - for(int iker = 0; iker < 8; iker ++) { - for(int i = 0; i < nspec * NGLL + NGRL; i ++) { - frekl[iker * size + i] *= coef1; - } - } - - return cg; -} - -/** - * @brief transform kernels from base to rho/vpv/vph/vsv/vsh/eta/T/P - * - * @param frekl base Frechet kernels, shape(8,nspec*NGLL+NGRL) - */ -void LayerModelTTI:: -transform_kernels(std::vector &frekl) const -{ - // get # of kernels - int npts = nspec * NGLL + NGRL; - int nker = frekl.size() / npts; - - // loop every point to transform kernels - for(int ipt = 0; ipt < npts; ipt ++) { - // set zero of all base kernels - double A_kl{},C_kl{},F_kl{}, L_kl{}, N_kl{}, rho_kl{}; - double T_kl{}, P_kl{}; - - // fetch kernels from global array - A_kl = frekl[0 * npts + ipt]; - C_kl = frekl[1 * npts + ipt]; - F_kl = frekl[2 * npts + ipt]; - L_kl = frekl[3 * npts + ipt]; - N_kl = frekl[4 * npts + ipt]; - T_kl = frekl[5 * npts + ipt]; - P_kl = frekl[6 * npts + ipt]; - rho_kl = frekl[7 * npts + ipt]; - - // get variables - double A = xA[ipt], C = xC[ipt], L = xL[ipt]; - double F = xF[ipt], N = xN[ipt], rho = xrho[ipt]; - - // compute vph/vpv/vsh/vsv/eta - double vph = std::sqrt(A / rho), vpv = std::sqrt(C / rho); - double vsh = std::sqrt(N / rho), vsv = std::sqrt(L / rho); - double eta = F / (A - 2. * L); - - // transform kernels - double vph_kl = 2. * rho * vph * A_kl, vpv_kl = 2. * rho * vpv * C_kl; - double vsh_kl = 2. * rho * vsh * N_kl, vsv_kl = 2. * rho * vsv * L_kl; - double eta_kl = (A - 2. * L) * F_kl; - double r_kl = vph * vph * A_kl + vpv * vpv * C_kl + - vsh * vsh * N_kl + vsv * vsv * L_kl + - rho_kl; - - // copy back to frekl array - frekl[0 * npts + ipt] = r_kl; - frekl[1 * npts + ipt] = vpv_kl; - frekl[2 * npts + ipt] = vph_kl; - frekl[3 * npts + ipt] = vsv_kl; - frekl[4 * npts + ipt] = vsh_kl; - frekl[5 * npts + ipt] = eta_kl; - frekl[6 * npts + ipt] = T_kl; - frekl[7 * npts + ipt] = P_kl; - } -} \ No newline at end of file diff --git a/src/tti/tti_subs.f90 b/src/tti/tti_subs.f90 deleted file mode 100644 index 9c7ede0..0000000 --- a/src/tti/tti_subs.f90 +++ /dev/null @@ -1,1115 +0,0 @@ -!=========================================================================== -!============================= AUTO CODE FROM SYMPY ======================== -!=========================================================================== - -subroutine get_comp1 (NGL,A,C,F,L,N,theta0,dphi,jaco, & - weight,hp,hpT, K0U,K0V,K0W,K1U,K1V,K1W,& - K2U,K2V,K2W) bind(c,name='get_comp1_') - use iso_c_binding,only: c_int,dp => c_double ,dcp => c_double_complex - implicit none - - integer(c_int),value,intent(in) :: NGL - real(dp),dimension(NGL),intent(in) :: A,C,F,L,N,theta0,dphi,weight - real(dp),dimension(NGL,NGL),intent(in) :: hp,hpT - real(dp),value :: jaco - complex(dcp),dimension(NGL,NGL),intent(out) :: K1U,K1V,K1W,K2U,K2V,K2W,K0U,K0V,K0W - - !local vars - integer(c_int) :: i,j - complex(dcp),dimension(NGL) :: temp - real(dp),dimension(NGL) :: costh0, sinth0,cosphi,sinphi - complex(dcp),parameter :: imag_i = cmplx(0.0,1.0,kind=dcp) - - !init matrices - K0U(:,:) = (0.0,0.0); K0V(:,:) = (0.0,0.0); K0W(:,:) = (0.0,0.0); - K1U(:,:) = (0.0,0.0); K1V(:,:) = (0.0,0.0); K1W(:,:) = (0.0,0.0); - K2U(:,:) = (0.0,0.0); K2V(:,:) = (0.0,0.0); K2W(:,:) = (0.0,0.0); - costh0 = cos(theta0); sinth0 = sin(theta0); - cosphi = cos(dphi); sinphi = sin(dphi); - - ! k^0, Udot psidot - temp(:) = A*sinth0**2*cosphi**2*costh0**2 + C*sinth0**2*cosphi**2*costh0**2 & - - 2*F*sinth0**2*cosphi**2*costh0**2 & - - 4*L*sinth0**2*cosphi**2*costh0**2 + L*sinth0**2*cosphi**2 & - + L*costh0**2 - N*sinth0**2*cosphi**2 - N*costh0**2 & - + N - do j=1,NGL; do i=1,NGL; - K0U(i,j) = K0U(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^0, Wdot psidot - temp(:) = A*sinphi*sinth0**2*cosphi*costh0**2 & - + C*sinphi*sinth0**2*cosphi*costh0**2 - 2*F*sinphi*sinth0**2*cosphi*costh0**2 & - - 4*L*sinphi*sinth0**2*cosphi*costh0**2 & - + L*sinphi*sinth0**2*cosphi & - - N*sinphi*sinth0**2*cosphi - do j=1,NGL; do i=1,NGL; - K0W(i,j) = K0W(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^0, Vdot psidot - temp(:) = A*sinth0*cosphi*costh0**3 - A*sinth0*cosphi*costh0 & - + C*sinth0*cosphi*costh0**3 - 2*F*sinth0*cosphi*costh0**3 & - + F*sinth0*cosphi*costh0 & - - 4*L*sinth0*cosphi*costh0**3 + 2*L*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K0V(i,j) = K0V(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^1, U psidot - temp(:) = - imag_i*A*sinth0**3*cosphi**3*costh0 & - + imag_i*A*sinth0*cosphi*costh0 - imag_i*C*sinth0**3*cosphi**3*costh0 & - + 2*imag_i*F*sinth0**3*cosphi**3*costh0 & - - imag_i*F*sinth0*cosphi*costh0 & - + 4*imag_i*L*sinth0**3*cosphi**3*costh0 & - - 2*imag_i*L*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K1U(i,j) = K1U(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Udot psi - temp(:) = imag_i*A*sinth0**3*cosphi**3*costh0 & - - imag_i*A*sinth0*cosphi*costh0 + imag_i*C*sinth0**3*cosphi**3*costh0 & - - 2*imag_i*F*sinth0**3*cosphi**3*costh0 & - + imag_i*F*sinth0*cosphi*costh0 & - - 4*imag_i*L*sinth0**3*cosphi**3*costh0 & - + 2*imag_i*L*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K1U(i,j) = K1U(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^1, W psidot - temp(:) = - imag_i*A*sinphi*sinth0**3*cosphi**2*costh0 & - - imag_i*C*sinphi*sinth0**3*cosphi**2*costh0 & - + 2*imag_i*F*sinphi*sinth0**3*cosphi**2*costh0 & - + 4*imag_i*L*sinphi*sinth0**3*cosphi**2*costh0 & - - imag_i*L*sinphi*sinth0*costh0 & - + imag_i*N*sinphi*sinth0*costh0 - do j=1,NGL; do i=1,NGL; - K1W(i,j) = K1W(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Wdot psi - temp(:) = imag_i*A*sinphi*sinth0**3*cosphi**2*costh0 & - - imag_i*A*sinphi*sinth0*costh0 & - + imag_i*C*sinphi*sinth0**3*cosphi**2*costh0 - 2*imag_i*F*sinphi*sinth0**3*cosphi**2*costh0 & - + imag_i*F*sinphi*sinth0*costh0 & - - 4*imag_i*L*sinphi*sinth0**3*cosphi**2*costh0 & - + 2*imag_i*N*sinphi*sinth0*costh0 - do j=1,NGL; do i=1,NGL; - K1W(i,j) = K1W(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^1, V psidot - temp(:) = - imag_i*A*sinth0**2*cosphi**2*costh0**2 & - - imag_i*C*sinth0**2*cosphi**2*costh0**2 & - + 2*imag_i*F*sinth0**2*cosphi**2*costh0**2 + 4*imag_i*L*sinth0**2*cosphi**2*costh0**2 & - - imag_i*L*sinth0**2*cosphi**2 & - - imag_i*L*costh0**2 + imag_i*N*sinth0**2*cosphi**2 & - + imag_i*N*costh0**2 - imag_i*N - do j=1,NGL; do i=1,NGL; - K1V(i,j) = K1V(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Vdot psi - temp(:) = imag_i*A*sinth0**2*cosphi**2*costh0**2 & - - imag_i*A*sinth0**2*cosphi**2 - imag_i*A*costh0**2 + imag_i*A & - + imag_i*C*sinth0**2*cosphi**2*costh0**2 & - - 2*imag_i*F*sinth0**2*cosphi**2*costh0**2 + imag_i*F*sinth0**2*cosphi**2 & - + imag_i*F*costh0**2 & - - 4*imag_i*L*sinth0**2*cosphi**2*costh0**2 + 2*imag_i*N*sinth0**2*cosphi**2 & - + 2*imag_i*N*costh0**2 - 2*imag_i*N - do j=1,NGL; do i=1,NGL; - K1V(i,j) = K1V(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^2, U psi - temp(:) = A*sinth0**4*cosphi**4 - 2*A*sinth0**2*cosphi**2 + A & - + C*sinth0**4*cosphi**4 - 2*F*sinth0**4*cosphi**4 & - + 2*F*sinth0**2*cosphi**2 - 4*L*sinth0**4*cosphi**4 & - + 4*L*sinth0**2*cosphi**2 - do i=1,NGL; K2U(i,i) = K2U(i,i) + temp(i) * weight(i) * jaco; enddo - - ! k^2, W psi - temp(:) = A*sinphi*sinth0**4*cosphi**3 - A*sinphi*sinth0**2*cosphi & - + C*sinphi*sinth0**4*cosphi**3 & - - 2*F*sinphi*sinth0**4*cosphi**3 + F*sinphi*sinth0**2*cosphi & - - 4*L*sinphi*sinth0**4*cosphi**3 & - + 2*L*sinphi*sinth0**2*cosphi - do i=1,NGL; K2W(i,i) = K2W(i,i) + temp(i) * weight(i) * jaco; enddo - - ! k^2, V psi - temp(:) = A*sinth0**3*cosphi**3*costh0 - A*sinth0*cosphi*costh0 & - + C*sinth0**3*cosphi**3*costh0 & - - 2*F*sinth0**3*cosphi**3*costh0 + F*sinth0*cosphi*costh0 & - - 4*L*sinth0**3*cosphi**3*costh0 & - + 2*L*sinth0*cosphi*costh0 - do i=1,NGL; K2V(i,i) = K2V(i,i) + temp(i) * weight(i) * jaco; enddo - - !transpose - K0U = transpose(K0U); K0V = transpose(K0V); K0W = transpose(K0W); - K1U = transpose(K1U); K1V = transpose(K1V); K1W = transpose(K1W); - K2U = transpose(K2U); K2V = transpose(K2V); K2W = transpose(K2W); - -end subroutine get_comp1 - -subroutine get_comp2 (NGL,A,C,F,L,N,theta0,dphi,jaco, & - weight,hp,hpT, K0U,K0V,K0W,K1U,K1V,K1W,& - K2U,K2V,K2W) bind(c,name='get_comp2_') - use iso_c_binding,only: c_int,dp => c_double ,dcp => c_double_complex - implicit none - - integer(c_int),value,intent(in) :: NGL - real(dp),dimension(NGL),intent(in) :: A,C,F,L,N,theta0,dphi,weight - real(dp),dimension(NGL,NGL),intent(in) :: hp,hpT - real(dp),value :: jaco - complex(dcp),dimension(NGL,NGL),intent(out) :: K1U,K1V,K1W,K2U,K2V,K2W,K0U,K0V,K0W - - !local vars - integer(c_int) :: i,j - complex(dcp),dimension(NGL) :: temp - real(dp),dimension(NGL) :: costh0, sinth0,cosphi,sinphi - complex(dcp),parameter :: imag_i = cmplx(0.0,1.0,kind=dcp) - - !init matrices - K0U(:,:) = (0.0,0.0); K0V(:,:) = (0.0,0.0); K0W(:,:) = (0.0,0.0); - K1U(:,:) = (0.0,0.0); K1V(:,:) = (0.0,0.0); K1W(:,:) = (0.0,0.0); - K2U(:,:) = (0.0,0.0); K2V(:,:) = (0.0,0.0); K2W(:,:) = (0.0,0.0); - costh0 = cos(theta0); sinth0 = sin(theta0); - cosphi = cos(dphi); sinphi = sin(dphi); - - ! k^0, Udot psidot - temp(:) = A*sinphi*sinth0**2*cosphi*costh0**2 & - + C*sinphi*sinth0**2*cosphi*costh0**2 - 2*F*sinphi*sinth0**2*cosphi*costh0**2 & - - 4*L*sinphi*sinth0**2*cosphi*costh0**2 & - + L*sinphi*sinth0**2*cosphi & - - N*sinphi*sinth0**2*cosphi - do j=1,NGL; do i=1,NGL; - K0U(i,j) = K0U(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^0, Wdot psidot - temp(:) = A*sinphi**2*sinth0**2*costh0**2 + C*sinphi**2*sinth0**2*costh0**2 & - - 2*F*sinphi**2*sinth0**2*costh0**2 & - - 4*L*sinphi**2*sinth0**2*costh0**2 + L*sinphi**2*sinth0**2 & - + L*costh0**2 - N*sinphi**2*sinth0**2 - N*costh0**2 & - + N - do j=1,NGL; do i=1,NGL; - K0W(i,j) = K0W(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^0, Vdot psidot - temp(:) = A*sinphi*sinth0*costh0**3 - A*sinphi*sinth0*costh0 & - + C*sinphi*sinth0*costh0**3 - 2*F*sinphi*sinth0*costh0**3 & - + F*sinphi*sinth0*costh0 & - - 4*L*sinphi*sinth0*costh0**3 + 2*L*sinphi*sinth0*costh0 - do j=1,NGL; do i=1,NGL; - K0V(i,j) = K0V(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^1, U psidot - temp(:) = - imag_i*A*sinphi*sinth0**3*cosphi**2*costh0 & - + imag_i*A*sinphi*sinth0*costh0 & - - imag_i*C*sinphi*sinth0**3*cosphi**2*costh0 + 2*imag_i*F*sinphi*sinth0**3*cosphi**2*costh0 & - - imag_i*F*sinphi*sinth0*costh0 & - + 4*imag_i*L*sinphi*sinth0**3*cosphi**2*costh0 & - - 2*imag_i*N*sinphi*sinth0*costh0 - do j=1,NGL; do i=1,NGL; - K1U(i,j) = K1U(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Udot psi - temp(:) = imag_i*A*sinphi*sinth0**3*cosphi**2*costh0 & - + imag_i*C*sinphi*sinth0**3*cosphi**2*costh0 & - - 2*imag_i*F*sinphi*sinth0**3*cosphi**2*costh0 & - - 4*imag_i*L*sinphi*sinth0**3*cosphi**2*costh0 & - + imag_i*L*sinphi*sinth0*costh0 & - - imag_i*N*sinphi*sinth0*costh0 - do j=1,NGL; do i=1,NGL; - K1U(i,j) = K1U(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^1, W psidot - temp(:) = - imag_i*A*sinphi**2*sinth0**3*cosphi*costh0 & - - imag_i*C*sinphi**2*sinth0**3*cosphi*costh0 & - + 2*imag_i*F*sinphi**2*sinth0**3*cosphi*costh0 & - + 4*imag_i*L*sinphi**2*sinth0**3*cosphi*costh0 & - - imag_i*L*sinth0*cosphi*costh0 & - + imag_i*N*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K1W(i,j) = K1W(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Wdot psi - temp(:) = imag_i*A*sinphi**2*sinth0**3*cosphi*costh0 & - + imag_i*C*sinphi**2*sinth0**3*cosphi*costh0 & - - 2*imag_i*F*sinphi**2*sinth0**3*cosphi*costh0 & - - 4*imag_i*L*sinphi**2*sinth0**3*cosphi*costh0 & - + imag_i*L*sinth0*cosphi*costh0 & - - imag_i*N*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K1W(i,j) = K1W(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^1, V psidot - temp(:) = - imag_i*A*sinphi*sinth0**2*cosphi*costh0**2 & - - imag_i*C*sinphi*sinth0**2*cosphi*costh0**2 & - + 2*imag_i*F*sinphi*sinth0**2*cosphi*costh0**2 & - + 4*imag_i*L*sinphi*sinth0**2*cosphi*costh0**2 & - - imag_i*L*sinphi*sinth0**2*cosphi & - + imag_i*N*sinphi*sinth0**2*cosphi - do j=1,NGL; do i=1,NGL; - K1V(i,j) = K1V(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Vdot psi - temp(:) = imag_i*A*sinphi*sinth0**2*cosphi*costh0**2 & - - imag_i*A*sinphi*sinth0**2*cosphi & - + imag_i*C*sinphi*sinth0**2*cosphi*costh0**2 - 2*imag_i*F*sinphi*sinth0**2*cosphi*costh0**2 & - + imag_i*F*sinphi*sinth0**2*cosphi & - - 4*imag_i*L*sinphi*sinth0**2*cosphi*costh0**2 & - + 2*imag_i*N*sinphi*sinth0**2*cosphi - do j=1,NGL; do i=1,NGL; - K1V(i,j) = K1V(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^2, U psi - temp(:) = A*sinphi*sinth0**4*cosphi**3 - A*sinphi*sinth0**2*cosphi & - + C*sinphi*sinth0**4*cosphi**3 & - - 2*F*sinphi*sinth0**4*cosphi**3 + F*sinphi*sinth0**2*cosphi & - - 4*L*sinphi*sinth0**4*cosphi**3 & - + 2*L*sinphi*sinth0**2*cosphi - do i=1,NGL; K2U(i,i) = K2U(i,i) + temp(i) * weight(i) * jaco; enddo - - ! k^2, W psi - temp(:) = A*sinphi**2*sinth0**4*cosphi**2 + C*sinphi**2*sinth0**4*cosphi**2 & - - 2*F*sinphi**2*sinth0**4*cosphi**2 & - - 4*L*sinphi**2*sinth0**4*cosphi**2 + L*sinphi**2*sinth0**2 & - + L*sinth0**2*cosphi**2 - N*sinphi**2*sinth0**2 & - - N*sinth0**2*cosphi**2 + N - do i=1,NGL; K2W(i,i) = K2W(i,i) + temp(i) * weight(i) * jaco; enddo - - ! k^2, V psi - temp(:) = A*sinphi*sinth0**3*cosphi**2*costh0 & - + C*sinphi*sinth0**3*cosphi**2*costh0 - 2*F*sinphi*sinth0**3*cosphi**2*costh0 & - - 4*L*sinphi*sinth0**3*cosphi**2*costh0 & - + L*sinphi*sinth0*costh0 & - - N*sinphi*sinth0*costh0 - do i=1,NGL; K2V(i,i) = K2V(i,i) + temp(i) * weight(i) * jaco; enddo - - !transpose - K0U = transpose(K0U); K0V = transpose(K0V); K0W = transpose(K0W); - K1U = transpose(K1U); K1V = transpose(K1V); K1W = transpose(K1W); - K2U = transpose(K2U); K2V = transpose(K2V); K2W = transpose(K2W); - -end subroutine get_comp2 - -subroutine get_comp3 (NGL,A,C,F,L,N,theta0,dphi,jaco, & - weight,hp,hpT, K0U,K0V,K0W,K1U,K1V,K1W,& - K2U,K2V,K2W) bind(c,name='get_comp3_') - use iso_c_binding,only: c_int,dp => c_double ,dcp => c_double_complex - implicit none - - integer(c_int),value,intent(in) :: NGL - real(dp),dimension(NGL),intent(in) :: A,C,F,L,N,theta0,dphi,weight - real(dp),dimension(NGL,NGL),intent(in) :: hp,hpT - real(dp),value :: jaco - complex(dcp),dimension(NGL,NGL),intent(out) :: K1U,K1V,K1W,K2U,K2V,K2W,K0U,K0V,K0W - - !local vars - integer(c_int) :: i,j - complex(dcp),dimension(NGL) :: temp - real(dp),dimension(NGL) :: costh0, sinth0,cosphi,sinphi - complex(dcp),parameter :: imag_i = cmplx(0.0,1.0,kind=dcp) - - !init matrices - K0U(:,:) = (0.0,0.0); K0V(:,:) = (0.0,0.0); K0W(:,:) = (0.0,0.0); - K1U(:,:) = (0.0,0.0); K1V(:,:) = (0.0,0.0); K1W(:,:) = (0.0,0.0); - K2U(:,:) = (0.0,0.0); K2V(:,:) = (0.0,0.0); K2W(:,:) = (0.0,0.0); - costh0 = cos(theta0); sinth0 = sin(theta0); - cosphi = cos(dphi); sinphi = sin(dphi); - - ! k^0, Udot psidot - temp(:) = A*sinth0*cosphi*costh0**3 - A*sinth0*cosphi*costh0 & - + C*sinth0*cosphi*costh0**3 - 2*F*sinth0*cosphi*costh0**3 & - + F*sinth0*cosphi*costh0 & - - 4*L*sinth0*cosphi*costh0**3 + 2*L*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K0U(i,j) = K0U(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^0, Wdot psidot - temp(:) = A*sinphi*sinth0*costh0**3 - A*sinphi*sinth0*costh0 & - + C*sinphi*sinth0*costh0**3 - 2*F*sinphi*sinth0*costh0**3 & - + F*sinphi*sinth0*costh0 & - - 4*L*sinphi*sinth0*costh0**3 + 2*L*sinphi*sinth0*costh0 - do j=1,NGL; do i=1,NGL; - K0W(i,j) = K0W(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^0, Vdot psidot - temp(:) = A*costh0**4 - 2*A*costh0**2 + A + C*costh0**4 & - - 2*F*costh0**4 + 2*F*costh0**2 - 4*L*costh0**4 & - + 4*L*costh0**2 - do j=1,NGL; do i=1,NGL; - K0V(i,j) = K0V(i,j) + sum(weight * temp / jaco * hp(:,j) * hp(:,i)) - enddo; enddo; - - ! k^1, U psidot - temp(:) = - imag_i*A*sinth0**2*cosphi**2*costh0**2 & - + imag_i*A*sinth0**2*cosphi**2 + imag_i*A*costh0**2 - imag_i*A & - - imag_i*C*sinth0**2*cosphi**2*costh0**2 & - + 2*imag_i*F*sinth0**2*cosphi**2*costh0**2 & - - imag_i*F*sinth0**2*cosphi**2 - imag_i*F*costh0**2 & - + 4*imag_i*L*sinth0**2*cosphi**2*costh0**2 - 2*imag_i*N*sinth0**2*cosphi**2 & - - 2*imag_i*N*costh0**2 + 2*imag_i*N - do j=1,NGL; do i=1,NGL; - K1U(i,j) = K1U(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Udot psi - temp(:) = imag_i*A*sinth0**2*cosphi**2*costh0**2 & - + imag_i*C*sinth0**2*cosphi**2*costh0**2 & - - 2*imag_i*F*sinth0**2*cosphi**2*costh0**2 - 4*imag_i*L*sinth0**2*cosphi**2*costh0**2 & - + imag_i*L*sinth0**2*cosphi**2 & - + imag_i*L*costh0**2 - imag_i*N*sinth0**2*cosphi**2 & - - imag_i*N*costh0**2 + imag_i*N - do j=1,NGL; do i=1,NGL; - K1U(i,j) = K1U(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^1, W psidot - temp(:) = - imag_i*A*sinphi*sinth0**2*cosphi*costh0**2 & - + imag_i*A*sinphi*sinth0**2*cosphi & - - imag_i*C*sinphi*sinth0**2*cosphi*costh0**2 + 2*imag_i*F*sinphi*sinth0**2*cosphi*costh0**2 & - - imag_i*F*sinphi*sinth0**2*cosphi & - + 4*imag_i*L*sinphi*sinth0**2*cosphi*costh0**2 & - - 2*imag_i*N*sinphi*sinth0**2*cosphi - do j=1,NGL; do i=1,NGL; - K1W(i,j) = K1W(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Wdot psi - temp(:) = imag_i*A*sinphi*sinth0**2*cosphi*costh0**2 & - + imag_i*C*sinphi*sinth0**2*cosphi*costh0**2 & - - 2*imag_i*F*sinphi*sinth0**2*cosphi*costh0**2 & - - 4*imag_i*L*sinphi*sinth0**2*cosphi*costh0**2 & - + imag_i*L*sinphi*sinth0**2*cosphi & - - imag_i*N*sinphi*sinth0**2*cosphi - do j=1,NGL; do i=1,NGL; - K1W(i,j) = K1W(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^1, V psidot - temp(:) = - imag_i*A*sinth0*cosphi*costh0**3 & - + imag_i*A*sinth0*cosphi*costh0 - imag_i*C*sinth0*cosphi*costh0**3 & - + 2*imag_i*F*sinth0*cosphi*costh0**3 & - - imag_i*F*sinth0*cosphi*costh0 + 4*imag_i*L*sinth0*cosphi*costh0**3 & - - 2*imag_i*L*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K1V(i,j) = K1V(i,j) + temp(j) * weight(j) * hpT(i,j) - enddo; enddo; - - ! k^1, Vdot psi - temp(:) = imag_i*A*sinth0*cosphi*costh0**3 & - - imag_i*A*sinth0*cosphi*costh0 + imag_i*C*sinth0*cosphi*costh0**3 & - - 2*imag_i*F*sinth0*cosphi*costh0**3 & - + imag_i*F*sinth0*cosphi*costh0 - 4*imag_i*L*sinth0*cosphi*costh0**3 & - + 2*imag_i*L*sinth0*cosphi*costh0 - do j=1,NGL; do i=1,NGL; - K1V(i,j) = K1V(i,j) + temp(i) * weight(i) * hp(i,j) - enddo; enddo; - - ! k^2, U psi - temp(:) = A*sinth0**3*cosphi**3*costh0 - A*sinth0*cosphi*costh0 & - + C*sinth0**3*cosphi**3*costh0 & - - 2*F*sinth0**3*cosphi**3*costh0 + F*sinth0*cosphi*costh0 & - - 4*L*sinth0**3*cosphi**3*costh0 & - + 2*L*sinth0*cosphi*costh0 - do i=1,NGL; K2U(i,i) = K2U(i,i) + temp(i) * weight(i) * jaco; enddo - - ! k^2, W psi - temp(:) = A*sinphi*sinth0**3*cosphi**2*costh0 & - + C*sinphi*sinth0**3*cosphi**2*costh0 - 2*F*sinphi*sinth0**3*cosphi**2*costh0 & - - 4*L*sinphi*sinth0**3*cosphi**2*costh0 & - + L*sinphi*sinth0*costh0 & - - N*sinphi*sinth0*costh0 - do i=1,NGL; K2W(i,i) = K2W(i,i) + temp(i) * weight(i) * jaco; enddo - - ! k^2, V psi - temp(:) = A*sinth0**2*cosphi**2*costh0**2 + C*sinth0**2*cosphi**2*costh0**2 & - - 2*F*sinth0**2*cosphi**2*costh0**2 & - - 4*L*sinth0**2*cosphi**2*costh0**2 + L*sinth0**2*cosphi**2 & - + L*costh0**2 - N*sinth0**2*cosphi**2 - N*costh0**2 & - + N - do i=1,NGL; K2V(i,i) = K2V(i,i) + temp(i) * weight(i) * jaco; enddo - - !transpose - K0U = transpose(K0U); K0V = transpose(K0V); K0W = transpose(K0W); - K1U = transpose(K1U); K1V = transpose(K1V); K1W = transpose(K1W); - K2U = transpose(K2U); K2V = transpose(K2V); K2W = transpose(K2W); - -end subroutine get_comp3 - -subroutine get_kernels (NGL,k,A,C,F,L,N,theta0,dphi, & - U,V,W,Udot,Vdot,Wdot,Kwvnm,& - KA,KC,KF,KL,KN,Ktheta0,Kdphi,dL_dkv) bind(c,name='get_kernels_') - use iso_c_binding,only: c_int,dp => c_double ,dcp => c_double_complex - implicit none - - integer(c_int),value,intent(in) :: NGL - real(dp),value,intent(in) :: k - real(dp),dimension(NGL),intent(in) :: A,C,F,L,N,theta0,dphi - complex(dcp),dimension(NGL),intent(in) :: U,V,W,Udot,Vdot,Wdot - real(dcp),dimension(NGL),intent(out) :: Kwvnm,KA,KC,KF,KL,KN,Ktheta0,Kdphi - real(dcp),dimension(NGL,2),intent(out) :: dL_dkv - - !local vars - complex(dcp),dimension(NGL) :: temp - real(dp),dimension(NGL) :: costh0, sinth0,cosphi,sinphi - complex(dcp),parameter :: imag_i = cmplx(0.0,1.0,kind=dcp) - - !init matrices - costh0 = cos(theta0); sinth0 = sin(theta0); - cosphi = cos(dphi); sinphi = sin(dphi); - - temp(:) = - U*k**2*(sinphi*sinth0**4*cosphi**3 & - - sinphi*sinth0**2*cosphi)*conjg(W) - U*k**2*(sinth0**3*cosphi**3*costh0 & - - sinth0*cosphi*costh0)*conjg(V) - U*k**2*(sinth0**4*cosphi**4 & - - 2*sinth0**2*cosphi**2 + 1)*conjg(U) & - + imag_i*U*k*(sinth0**3*cosphi**3*costh0 & - - sinth0*cosphi*costh0)*conjg(Udot) + imag_i*U*k*(sinphi*sinth0**3*cosphi**2*costh0 & - - sinphi*sinth0*costh0)*conjg(Wdot) & - + imag_i*U*k*(sinth0**2*cosphi**2*costh0**2 & - - sinth0**2*cosphi**2 - costh0**2 + 1)*conjg(Vdot) & - - imag_i*Udot*k*(sinth0**3*cosphi**3*costh0 - sinth0*cosphi*costh0)*conjg(U) & - - imag_i*Udot*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(W) & - - imag_i*Udot*k*sinth0**2*cosphi**2*costh0**2*conjg(V) & - - Udot*(sinth0*cosphi*costh0**3 & - - sinth0*cosphi*costh0)*conjg(Vdot) & - - Udot*sinphi*sinth0**2*cosphi*costh0**2*conjg(Wdot) & - - Udot*sinth0**2*cosphi**2*costh0**2*conjg(Udot) - V*k**2*(sinth0**3*cosphi**3*costh0 & - - sinth0*cosphi*costh0)*conjg(U) & - - V*k**2*sinphi*sinth0**3*cosphi**2*costh0*conjg(W) & - - V*k**2*sinth0**2*cosphi**2*costh0**2*conjg(V) & - + imag_i*V*k*(sinth0*cosphi*costh0**3 - sinth0*cosphi*costh0)*conjg(Vdot) & - + imag_i*V*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(Wdot) & - + imag_i*V*k*sinth0**2*cosphi**2*costh0**2*conjg(Udot) & - - imag_i*Vdot*k*(sinth0*cosphi*costh0**3 & - - sinth0*cosphi*costh0)*conjg(V) & - - imag_i*Vdot*k*(sinphi*sinth0**2*cosphi*costh0**2 & - - sinphi*sinth0**2*cosphi)*conjg(W) - imag_i*Vdot*k*(sinth0**2*cosphi**2*costh0**2 & - - sinth0**2*cosphi**2 - costh0**2 & - + 1)*conjg(U) - Vdot*(sinphi*sinth0*costh0**3 & - - sinphi*sinth0*costh0)*conjg(Wdot) - Vdot*(sinth0*cosphi*costh0**3 & - - sinth0*cosphi*costh0)*conjg(Udot) & - - Vdot*(costh0**4 - 2*costh0**2 + 1)*conjg(Vdot) & - - W*k**2*(sinphi*sinth0**4*cosphi**3 - sinphi*sinth0**2*cosphi)*conjg(U) & - - W*k**2*sinphi**2*sinth0**4*cosphi**2*conjg(W) & - - W*k**2*sinphi*sinth0**3*cosphi**2*costh0*conjg(V) & - + imag_i*W*k*(sinphi*sinth0**2*cosphi*costh0**2 & - - sinphi*sinth0**2*cosphi)*conjg(Vdot) & - + imag_i*W*k*sinphi**2*sinth0**3*cosphi*costh0*conjg(Wdot) & - + imag_i*W*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(Udot) & - - imag_i*Wdot*k*(sinphi*sinth0**3*cosphi**2*costh0 & - - sinphi*sinth0*costh0)*conjg(U) - imag_i*Wdot*k*sinphi**2*sinth0**3*cosphi*costh0*conjg(W) & - - imag_i*Wdot*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(V) - Wdot*(sinphi*sinth0*costh0**3 & - - sinphi*sinth0*costh0)*conjg(Vdot) & - - Wdot*sinphi**2*sinth0**2*costh0**2*conjg(Wdot) & - - Wdot*sinphi*sinth0**2*cosphi*costh0**2*conjg(Udot) - KA(:) = real(temp(:),kind=dp) - - temp(:) = - U*k**2*sinphi*sinth0**4*cosphi**3*conjg(W) & - - U*k**2*sinth0**4*cosphi**4*conjg(U) - U*k**2*sinth0**3*cosphi**3*costh0*conjg(V) & - + imag_i*U*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(Wdot) & - + imag_i*U*k*sinth0**3*cosphi**3*costh0*conjg(Udot) & - + imag_i*U*k*sinth0**2*cosphi**2*costh0**2*conjg(Vdot) & - - imag_i*Udot*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(W) & - - imag_i*Udot*k*sinth0**3*cosphi**3*costh0*conjg(U) & - - imag_i*Udot*k*sinth0**2*cosphi**2*costh0**2*conjg(V) & - - Udot*sinphi*sinth0**2*cosphi*costh0**2*conjg(Wdot) & - - Udot*sinth0**2*cosphi**2*costh0**2*conjg(Udot) & - - Udot*sinth0*cosphi*costh0**3*conjg(Vdot) & - - V*k**2*sinphi*sinth0**3*cosphi**2*costh0*conjg(W) & - - V*k**2*sinth0**3*cosphi**3*costh0*conjg(U) & - - V*k**2*sinth0**2*cosphi**2*costh0**2*conjg(V) & - + imag_i*V*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(Wdot) & - + imag_i*V*k*sinth0**2*cosphi**2*costh0**2*conjg(Udot) & - + imag_i*V*k*sinth0*cosphi*costh0**3*conjg(Vdot) & - - imag_i*Vdot*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(W) & - - imag_i*Vdot*k*sinth0**2*cosphi**2*costh0**2*conjg(U) & - - imag_i*Vdot*k*sinth0*cosphi*costh0**3*conjg(V) & - - Vdot*sinphi*sinth0*costh0**3*conjg(Wdot) - Vdot*sinth0*cosphi*costh0**3*conjg(Udot) & - - Vdot*costh0**4*conjg(Vdot) & - - W*k**2*sinphi**2*sinth0**4*cosphi**2*conjg(W) & - - W*k**2*sinphi*sinth0**4*cosphi**3*conjg(U) - W*k**2*sinphi*sinth0**3*cosphi**2*costh0*conjg(V) & - + imag_i*W*k*sinphi**2*sinth0**3*cosphi*costh0*conjg(Wdot) & - + imag_i*W*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(Udot) & - + imag_i*W*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(Vdot) & - - imag_i*Wdot*k*sinphi**2*sinth0**3*cosphi*costh0*conjg(W) & - - imag_i*Wdot*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(U) & - - imag_i*Wdot*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(V) & - - Wdot*sinphi**2*sinth0**2*costh0**2*conjg(Wdot) & - - Wdot*sinphi*sinth0**2*cosphi*costh0**2*conjg(Udot) & - - Wdot*sinphi*sinth0*costh0**3*conjg(Vdot) - KC(:) = real(temp(:),kind=dp) - - temp(:) = - U*k**2*( - 2*sinth0**4*cosphi**4 + 2*sinth0**2*cosphi**2)*conjg(U) & - - U*k**2*( - 2*sinphi*sinth0**4*cosphi**3 & - + sinphi*sinth0**2*cosphi)*conjg(W) - U*k**2*( & - - 2*sinth0**3*cosphi**3*costh0 + sinth0*cosphi*costh0)*conjg(V) & - + imag_i*U*k*( - 2*sinth0**3*cosphi**3*costh0 & - + sinth0*cosphi*costh0)*conjg(Udot) + imag_i*U*k*( & - - 2*sinphi*sinth0**3*cosphi**2*costh0 + sinphi*sinth0*costh0)*conjg(Wdot) & - + imag_i*U*k*( - 2*sinth0**2*cosphi**2*costh0**2 & - + sinth0**2*cosphi**2 + costh0**2)*conjg(Vdot) & - - imag_i*Udot*k*( - 2*sinth0**3*cosphi**3*costh0 & - + sinth0*cosphi*costh0)*conjg(U) & - + 2*imag_i*Udot*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(W) & - + 2*imag_i*Udot*k*sinth0**2*cosphi**2*costh0**2*conjg(V) - Udot*( & - - 2*sinth0*cosphi*costh0**3 + sinth0*cosphi*costh0)*conjg(Vdot) & - + 2*Udot*sinphi*sinth0**2*cosphi*costh0**2*conjg(Wdot) & - + 2*Udot*sinth0**2*cosphi**2*costh0**2*conjg(Udot) & - - V*k**2*( - 2*sinth0**3*cosphi**3*costh0 & - + sinth0*cosphi*costh0)*conjg(U) + 2*V*k**2*sinphi*sinth0**3*cosphi**2*costh0*conjg(W) & - + 2*V*k**2*sinth0**2*cosphi**2*costh0**2*conjg(V) & - + imag_i*V*k*( - 2*sinth0*cosphi*costh0**3 & - + sinth0*cosphi*costh0)*conjg(Vdot) & - - 2*imag_i*V*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(Wdot) & - - 2*imag_i*V*k*sinth0**2*cosphi**2*costh0**2*conjg(Udot) & - - imag_i*Vdot*k*( - 2*sinth0*cosphi*costh0**3 & - + sinth0*cosphi*costh0)*conjg(V) - imag_i*Vdot*k*( & - - 2*sinphi*sinth0**2*cosphi*costh0**2 + sinphi*sinth0**2*cosphi)*conjg(W) & - - imag_i*Vdot*k*( - 2*sinth0**2*cosphi**2*costh0**2 & - + sinth0**2*cosphi**2 + costh0**2)*conjg(U) & - - Vdot*( - 2*sinphi*sinth0*costh0**3 & - + sinphi*sinth0*costh0)*conjg(Wdot) - Vdot*( - 2*sinth0*cosphi*costh0**3 & - + sinth0*cosphi*costh0)*conjg(Udot) - Vdot*( & - - 2*costh0**4 + 2*costh0**2)*conjg(Vdot) - W*k**2*( & - - 2*sinphi*sinth0**4*cosphi**3 + sinphi*sinth0**2*cosphi)*conjg(U) & - + 2*W*k**2*sinphi**2*sinth0**4*cosphi**2*conjg(W) & - + 2*W*k**2*sinphi*sinth0**3*cosphi**2*costh0*conjg(V) + imag_i*W*k*( & - - 2*sinphi*sinth0**2*cosphi*costh0**2 & - + sinphi*sinth0**2*cosphi)*conjg(Vdot) & - - 2*imag_i*W*k*sinphi**2*sinth0**3*cosphi*costh0*conjg(Wdot) & - - 2*imag_i*W*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(Udot) - imag_i*Wdot*k*( & - - 2*sinphi*sinth0**3*cosphi**2*costh0 & - + sinphi*sinth0*costh0)*conjg(U) & - + 2*imag_i*Wdot*k*sinphi**2*sinth0**3*cosphi*costh0*conjg(W) & - + 2*imag_i*Wdot*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(V) - Wdot*( & - - 2*sinphi*sinth0*costh0**3 + sinphi*sinth0*costh0)*conjg(Vdot) & - + 2*Wdot*sinphi**2*sinth0**2*costh0**2*conjg(Wdot) & - + 2*Wdot*sinphi*sinth0**2*cosphi*costh0**2*conjg(Udot) - KF(:) = real(temp(:),kind=dp) - - temp(:) = - U*k**2*( - 4*sinth0**4*cosphi**4 + 4*sinth0**2*cosphi**2)*conjg(U) & - - U*k**2*( - 4*sinphi*sinth0**4*cosphi**3 & - + 2*sinphi*sinth0**2*cosphi)*conjg(W) - U*k**2*( & - - 4*sinth0**3*cosphi**3*costh0 + 2*sinth0*cosphi*costh0)*conjg(V) & - + imag_i*U*k*( - 4*sinth0**3*cosphi**3*costh0 & - + 2*sinth0*cosphi*costh0)*conjg(Udot) & - - 4*imag_i*U*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(Wdot) & - - 4*imag_i*U*k*sinth0**2*cosphi**2*costh0**2*conjg(Vdot) - imag_i*Udot*k*( & - - 4*sinth0**3*cosphi**3*costh0 & - + 2*sinth0*cosphi*costh0)*conjg(U) - imag_i*Udot*k*( & - - 4*sinphi*sinth0**3*cosphi**2*costh0 + sinphi*sinth0*costh0)*conjg(W) & - - imag_i*Udot*k*( - 4*sinth0**2*cosphi**2*costh0**2 & - + sinth0**2*cosphi**2 + costh0**2)*conjg(V) - Udot*( & - - 4*sinth0*cosphi*costh0**3 + 2*sinth0*cosphi*costh0)*conjg(Vdot) & - - Udot*( - 4*sinphi*sinth0**2*cosphi*costh0**2 & - + sinphi*sinth0**2*cosphi)*conjg(Wdot) - Udot*( & - - 4*sinth0**2*cosphi**2*costh0**2 + sinth0**2*cosphi**2 & - + costh0**2)*conjg(Udot) - V*k**2*( & - - 4*sinth0**3*cosphi**3*costh0 + 2*sinth0*cosphi*costh0)*conjg(U) & - - V*k**2*( - 4*sinphi*sinth0**3*cosphi**2*costh0 & - + sinphi*sinth0*costh0)*conjg(W) - V*k**2*( & - - 4*sinth0**2*cosphi**2*costh0**2 + sinth0**2*cosphi**2 + costh0**2)*conjg(V) & - + imag_i*V*k*( - 4*sinth0*cosphi*costh0**3 & - + 2*sinth0*cosphi*costh0)*conjg(Vdot) + imag_i*V*k*( & - - 4*sinphi*sinth0**2*cosphi*costh0**2 & - + sinphi*sinth0**2*cosphi)*conjg(Wdot) + imag_i*V*k*( - 4*sinth0**2*cosphi**2*costh0**2 & - + sinth0**2*cosphi**2 + costh0**2)*conjg(Udot) & - - imag_i*Vdot*k*( - 4*sinth0*cosphi*costh0**3 & - + 2*sinth0*cosphi*costh0)*conjg(V) & - + 4*imag_i*Vdot*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(W) & - + 4*imag_i*Vdot*k*sinth0**2*cosphi**2*costh0**2*conjg(U) - Vdot*( & - - 4*sinphi*sinth0*costh0**3 + 2*sinphi*sinth0*costh0)*conjg(Wdot) & - - Vdot*( - 4*sinth0*cosphi*costh0**3 & - + 2*sinth0*cosphi*costh0)*conjg(Udot) - Vdot*( - 4*costh0**4 & - + 4*costh0**2)*conjg(Vdot) - W*k**2*( - 4*sinphi*sinth0**4*cosphi**3 & - + 2*sinphi*sinth0**2*cosphi)*conjg(U) & - - W*k**2*( - 4*sinphi*sinth0**3*cosphi**2*costh0 & - + sinphi*sinth0*costh0)*conjg(V) - W*k**2*( - 4*sinphi**2*sinth0**4*cosphi**2 & - + sinphi**2*sinth0**2 + sinth0**2*cosphi**2)*conjg(W) & - + imag_i*W*k*( - 4*sinphi*sinth0**3*cosphi**2*costh0 & - + sinphi*sinth0*costh0)*conjg(Udot) & - + imag_i*W*k*( - 4*sinphi**2*sinth0**3*cosphi*costh0 & - + sinth0*cosphi*costh0)*conjg(Wdot) & - - 4*imag_i*W*k*sinphi*sinth0**2*cosphi*costh0**2*conjg(Vdot) - imag_i*Wdot*k*( & - - 4*sinphi*sinth0**2*cosphi*costh0**2 & - + sinphi*sinth0**2*cosphi)*conjg(V) - imag_i*Wdot*k*( & - - 4*sinphi**2*sinth0**3*cosphi*costh0 + sinth0*cosphi*costh0)*conjg(W) & - + 4*imag_i*Wdot*k*sinphi*sinth0**3*cosphi**2*costh0*conjg(U) & - - Wdot*( - 4*sinphi*sinth0*costh0**3 & - + 2*sinphi*sinth0*costh0)*conjg(Vdot) - Wdot*( & - - 4*sinphi*sinth0**2*cosphi*costh0**2 & - + sinphi*sinth0**2*cosphi)*conjg(Udot) - Wdot*( - 4*sinphi**2*sinth0**2*costh0**2 & - + sinphi**2*sinth0**2 + costh0**2)*conjg(Wdot) - KL(:) = real(temp(:),kind=dp) - - temp(:) = imag_i*U*k*(2*sinth0**2*cosphi**2 + 2*costh0**2 & - - 2)*conjg(Vdot) + 2*imag_i*U*k*sinphi*sinth0*costh0*conjg(Wdot) & - - imag_i*Udot*k*( - sinth0**2*cosphi**2 - costh0**2 & - + 1)*conjg(V) + imag_i*Udot*k*sinphi*sinth0*costh0*conjg(W) & - - Udot*( - sinth0**2*cosphi**2 - costh0**2 & - + 1)*conjg(Udot) + Udot*sinphi*sinth0**2*cosphi*conjg(Wdot) & - - V*k**2*( - sinth0**2*cosphi**2 - costh0**2 + 1)*conjg(V) & - + V*k**2*sinphi*sinth0*costh0*conjg(W) + imag_i*V*k*( & - - sinth0**2*cosphi**2 - costh0**2 + 1)*conjg(Udot) & - - imag_i*V*k*sinphi*sinth0**2*cosphi*conjg(Wdot) & - - imag_i*Vdot*k*(2*sinth0**2*cosphi**2 + 2*costh0**2 - 2)*conjg(U) & - - 2*imag_i*Vdot*k*sinphi*sinth0**2*cosphi*conjg(W) - W*k**2*( & - - sinphi**2*sinth0**2 - sinth0**2*cosphi**2 + 1)*conjg(W) & - + W*k**2*sinphi*sinth0*costh0*conjg(V) & - + 2*imag_i*W*k*sinphi*sinth0**2*cosphi*conjg(Vdot) & - - imag_i*W*k*sinphi*sinth0*costh0*conjg(Udot) & - - imag_i*W*k*sinth0*cosphi*costh0*conjg(Wdot) + imag_i*Wdot*k*sinphi*sinth0**2*cosphi*conjg(V) & - - 2*imag_i*Wdot*k*sinphi*sinth0*costh0*conjg(U) & - + imag_i*Wdot*k*sinth0*cosphi*costh0*conjg(W) & - - Wdot*( - sinphi**2*sinth0**2 - costh0**2 & - + 1)*conjg(Wdot) + Wdot*sinphi*sinth0**2*cosphi*conjg(Udot) - KN(:) = real(temp(:),kind=dp) - - temp(:) = - U*k**2*(8*(L - N)*sinth0*cosphi**2*costh0 + 4*( - A + F & - + 2*N)*sinth0*cosphi**2*costh0 + 4*(A + C - 2*F & - - 4*L)*sinth0**3*cosphi**4*costh0)*conjg(U) - U*k**2*(4*(L & - - N)*sinphi*sinth0*cosphi*costh0 + 2*( - A + F & - + 2*N)*sinphi*sinth0*cosphi*costh0 + 4*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**3*costh0)*conjg(W) - U*k**2*( - 2*(L & - - N)*sinth0**2*cosphi + 2*(L - N)*cosphi*costh0**2 - ( & - - A + F + 2*N)*sinth0**2*cosphi + ( - A + F + 2*N)*cosphi*costh0**2 & - - (A + C - 2*F - 4*L)*sinth0**4*cosphi**3 + 3*(A & - + C - 2*F - 4*L)*sinth0**2*cosphi**3*costh0**2)*conjg(V) & - + imag_i*U*k*((2*sinth0*cosphi**2*costh0 & - - 2*sinth0*costh0)*( - A + F + 2*N) - 2*(A + C - 2*F & - - 4*L)*sinth0**3*cosphi**2*costh0 + 2*(A + C - 2*F & - - 4*L)*sinth0*cosphi**2*costh0**3)*conjg(Vdot) + imag_i*U*k*( - ( - A + F & - + 2*N)*sinphi*sinth0**2 + ( - A + F + 2*N)*sinphi*costh0**2 - (A & - + C - 2*F - 4*L)*sinphi*sinth0**4*cosphi**2 + 3*(A + C & - - 2*F - 4*L)*sinphi*sinth0**2*cosphi**2*costh0**2)*conjg(Wdot) & - + imag_i*U*k*( - 2*(L - N)*sinth0**2*cosphi + 2*(L & - - N)*cosphi*costh0**2 - ( - A + F + 2*N)*sinth0**2*cosphi & - + ( - A + F + 2*N)*cosphi*costh0**2 - (A + C - 2*F & - - 4*L)*sinth0**4*cosphi**3 + 3*(A + C - 2*F & - - 4*L)*sinth0**2*cosphi**3*costh0**2)*conjg(Udot) - imag_i*Udot*k*((L & - - N)*(2*sinth0*cosphi**2*costh0 - 2*sinth0*costh0) - 2*(A & - + C - 2*F - 4*L)*sinth0**3*cosphi**2*costh0 + 2*(A + C & - - 2*F - 4*L)*sinth0*cosphi**2*costh0**3)*conjg(V) & - - imag_i*Udot*k*( - (L - N)*sinphi*sinth0**2 + (L & - - N)*sinphi*costh0**2 - (A + C - 2*F - 4*L)*sinphi*sinth0**4*cosphi**2 & - + 3*(A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi**2*costh0**2)*conjg(W) & - - imag_i*Udot*k*( - 2*(L - N)*sinth0**2*cosphi & - + 2*(L - N)*cosphi*costh0**2 - ( - A + F & - + 2*N)*sinth0**2*cosphi + ( - A + F + 2*N)*cosphi*costh0**2 - (A & - + C - 2*F - 4*L)*sinth0**4*cosphi**3 + 3*(A + C - 2*F & - - 4*L)*sinth0**2*cosphi**3*costh0**2)*conjg(U) - Udot*((L & - - N)*(2*sinth0*cosphi**2*costh0 - 2*sinth0*costh0) & - - 2*(A + C - 2*F - 4*L)*sinth0**3*cosphi**2*costh0 + 2*(A & - + C - 2*F - 4*L)*sinth0*cosphi**2*costh0**3)*conjg(Udot) & - - Udot*(2*(L - N)*sinphi*sinth0*cosphi*costh0 - 2*(A & - + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi*costh0 + 2*(A & - + C - 2*F - 4*L)*sinphi*sinth0*cosphi*costh0**3)*conjg(Wdot) & - - Udot*( - 2*(L - N)*sinth0**2*cosphi + 2*(L & - - N)*cosphi*costh0**2 - ( - A + F + 2*N)*sinth0**2*cosphi + ( & - - A + F + 2*N)*cosphi*costh0**2 - 3*(A + C - 2*F & - - 4*L)*sinth0**2*cosphi*costh0**2 + (A + C - 2*F & - - 4*L)*cosphi*costh0**4)*conjg(Vdot) - V*k**2*((L - N)*(2*sinth0*cosphi**2*costh0 & - - 2*sinth0*costh0) - 2*(A + C - 2*F & - - 4*L)*sinth0**3*cosphi**2*costh0 + 2*(A + C - 2*F & - - 4*L)*sinth0*cosphi**2*costh0**3)*conjg(V) - V*k**2*( - (L & - - N)*sinphi*sinth0**2 + (L - N)*sinphi*costh0**2 - (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**2 + 3*(A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi**2*costh0**2)*conjg(W) - V*k**2*( & - - 2*(L - N)*sinth0**2*cosphi + 2*(L - N)*cosphi*costh0**2 & - - ( - A + F + 2*N)*sinth0**2*cosphi + ( - A + F & - + 2*N)*cosphi*costh0**2 - (A + C - 2*F - 4*L)*sinth0**4*cosphi**3 & - + 3*(A + C - 2*F - 4*L)*sinth0**2*cosphi**3*costh0**2)*conjg(U) & - + imag_i*V*k*((L - N)*(2*sinth0*cosphi**2*costh0 & - - 2*sinth0*costh0) - 2*(A + C - 2*F & - - 4*L)*sinth0**3*cosphi**2*costh0 + 2*(A + C - 2*F & - - 4*L)*sinth0*cosphi**2*costh0**3)*conjg(Udot) + imag_i*V*k*(2*(L & - - N)*sinphi*sinth0*cosphi*costh0 - 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi*costh0 + 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0*cosphi*costh0**3)*conjg(Wdot) + imag_i*V*k*( & - - 2*(L - N)*sinth0**2*cosphi + 2*(L - N)*cosphi*costh0**2 & - - ( - A + F + 2*N)*sinth0**2*cosphi + ( - A + F & - + 2*N)*cosphi*costh0**2 - 3*(A + C - 2*F - 4*L)*sinth0**2*cosphi*costh0**2 & - + (A + C - 2*F - 4*L)*cosphi*costh0**4)*conjg(Vdot) & - - imag_i*Vdot*k*((2*sinth0*cosphi**2*costh0 & - - 2*sinth0*costh0)*( - A + F + 2*N) - 2*(A + C - 2*F & - - 4*L)*sinth0**3*cosphi**2*costh0 + 2*(A + C - 2*F & - - 4*L)*sinth0*cosphi**2*costh0**3)*conjg(U) - imag_i*Vdot*k*(2*( - A & - + F + 2*N)*sinphi*sinth0*cosphi*costh0 - 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi*costh0 + 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0*cosphi*costh0**3)*conjg(W) & - - imag_i*Vdot*k*( - 2*(L - N)*sinth0**2*cosphi + 2*(L & - - N)*cosphi*costh0**2 - ( - A + F + 2*N)*sinth0**2*cosphi + ( & - - A + F + 2*N)*cosphi*costh0**2 - 3*(A + C - 2*F & - - 4*L)*sinth0**2*cosphi*costh0**2 + (A + C - 2*F - 4*L)*cosphi*costh0**4)*conjg(V) & - - Vdot*( - 8*(L - N)*sinth0*costh0 - 4*( & - - A + F + 2*N)*sinth0*costh0 - 4*(A + C - 2*F & - - 4*L)*sinth0*costh0**3)*conjg(Vdot) - Vdot*( - 2*(L - N)*sinphi*sinth0**2 & - + 2*(L - N)*sinphi*costh0**2 - ( - A + F & - + 2*N)*sinphi*sinth0**2 + ( - A + F + 2*N)*sinphi*costh0**2 - 3*(A & - + C - 2*F - 4*L)*sinphi*sinth0**2*costh0**2 + (A + C & - - 2*F - 4*L)*sinphi*costh0**4)*conjg(Wdot) - Vdot*( - 2*(L & - - N)*sinth0**2*cosphi + 2*(L - N)*cosphi*costh0**2 - ( & - - A + F + 2*N)*sinth0**2*cosphi + ( - A + F + 2*N)*cosphi*costh0**2 & - - 3*(A + C - 2*F - 4*L)*sinth0**2*cosphi*costh0**2 & - + (A + C - 2*F - 4*L)*cosphi*costh0**4)*conjg(Udot) & - - W*k**2*((L - N)*(2*sinphi**2*sinth0*costh0 & - + 2*sinth0*cosphi**2*costh0) + 4*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi**2*costh0)*conjg(W) - W*k**2*(4*(L & - - N)*sinphi*sinth0*cosphi*costh0 + 2*( - A + F & - + 2*N)*sinphi*sinth0*cosphi*costh0 + 4*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**3*costh0)*conjg(U) - W*k**2*( - (L & - - N)*sinphi*sinth0**2 + (L - N)*sinphi*costh0**2 - (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**2 + 3*(A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi**2*costh0**2)*conjg(V) & - + imag_i*W*k*(2*( - A + F + 2*N)*sinphi*sinth0*cosphi*costh0 & - - 2*(A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi*costh0 & - + 2*(A + C - 2*F - 4*L)*sinphi*sinth0*cosphi*costh0**3)*conjg(Vdot) & - + imag_i*W*k*( - (L - N)*sinphi*sinth0**2 + (L & - - N)*sinphi*costh0**2 - (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**2 + 3*(A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi**2*costh0**2)*conjg(Udot) + imag_i*W*k*( - (L & - - N)*sinth0**2*cosphi + (L - N)*cosphi*costh0**2 - (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi + 3*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**2*cosphi*costh0**2)*conjg(Wdot) & - - imag_i*Wdot*k*(2*(L - N)*sinphi*sinth0*cosphi*costh0 & - - 2*(A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi*costh0 & - + 2*(A + C - 2*F - 4*L)*sinphi*sinth0*cosphi*costh0**3)*conjg(V) & - - imag_i*Wdot*k*( - (L - N)*sinth0**2*cosphi & - + (L - N)*cosphi*costh0**2 - (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**4*cosphi + 3*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**2*cosphi*costh0**2)*conjg(W) - imag_i*Wdot*k*( & - - ( - A + F + 2*N)*sinphi*sinth0**2 + ( - A + F & - + 2*N)*sinphi*costh0**2 - (A + C - 2*F - 4*L)*sinphi*sinth0**4*cosphi**2 & - + 3*(A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi**2*costh0**2)*conjg(U) & - - Wdot*((L - N)*(2*sinphi**2*sinth0*costh0 & - - 2*sinth0*costh0) - 2*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*costh0 + 2*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0*costh0**3)*conjg(Wdot) - Wdot*(2*(L & - - N)*sinphi*sinth0*cosphi*costh0 - 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi*costh0 + 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0*cosphi*costh0**3)*conjg(Udot) - Wdot*( - 2*(L & - - N)*sinphi*sinth0**2 + 2*(L - N)*sinphi*costh0**2 - ( & - - A + F + 2*N)*sinphi*sinth0**2 + ( - A + F + 2*N)*sinphi*costh0**2 & - - 3*(A + C - 2*F - 4*L)*sinphi*sinth0**2*costh0**2 & - + (A + C - 2*F - 4*L)*sinphi*costh0**4)*conjg(Vdot) - Ktheta0(:) = real(temp(:),kind=dp) - - temp(:) = - U*k**2*( - 2*(L - N)*sinphi*sinth0*costh0 - ( - A + F & - + 2*N)*sinphi*sinth0*costh0 - 3*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(V) - U*k**2*( - 8*(L & - - N)*sinphi*sinth0**2*cosphi - 4*( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi - 4*(A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(U) - U*k**2*( - 2*(L - N)*sinphi**2*sinth0**2 & - + 2*(L - N)*sinth0**2*cosphi**2 - ( - A + F & - + 2*N)*sinphi**2*sinth0**2 + ( - A + F + 2*N)*sinth0**2*cosphi**2 & - - 3*(A + C - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2 & - + (A + C - 2*F - 4*L)*sinth0**4*cosphi**4)*conjg(W) & - + imag_i*U*k*( - 2*( - A + F + 2*N)*sinphi*sinth0**2*cosphi - 2*(A & - + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Vdot) & - + imag_i*U*k*( - 2*(L - N)*sinphi*sinth0*costh0 & - - ( - A + F + 2*N)*sinphi*sinth0*costh0 - 3*(A + C & - - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Udot) & - + imag_i*U*k*(( - A + F + 2*N)*sinth0*cosphi*costh0 & - - 2*(A + C - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(Wdot) & - - imag_i*Udot*k*( - 2*(L - N)*sinphi*sinth0**2*cosphi & - - 2*(A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(V) & - - imag_i*Udot*k*( - 2*(L & - - N)*sinphi*sinth0*costh0 - ( - A + F + 2*N)*sinphi*sinth0*costh0 & - - 3*(A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) & - - imag_i*Udot*k*((L - N)*sinth0*cosphi*costh0 & - - 2*(A + C - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(W) & - - Udot*( - 2*(L - N)*sinphi*sinth0**2*cosphi & - - 2*(A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Udot) & - - Udot*( - 2*(L - N)*sinphi*sinth0*costh0 & - - ( - A + F + 2*N)*sinphi*sinth0*costh0 - (A & - + C - 2*F - 4*L)*sinphi*sinth0*costh0**3)*conjg(Vdot) & - - Udot*( - (L - N)*sinphi**2*sinth0**2 + (L - N)*sinth0**2*cosphi**2 & - - (A + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2 & - + (A + C - 2*F - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Wdot) & - - V*k**2*( - 2*(L - N)*sinphi*sinth0**2*cosphi & - - 2*(A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(V) & - - V*k**2*( - 2*(L - N)*sinphi*sinth0*costh0 & - - ( - A + F + 2*N)*sinphi*sinth0*costh0 - 3*(A + C & - - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) & - - V*k**2*((L - N)*sinth0*cosphi*costh0 - 2*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0 + (A + C & - - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(W) & - + imag_i*V*k*( - 2*(L - N)*sinphi*sinth0**2*cosphi - 2*(A + C & - - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Udot) & - + imag_i*V*k*( - 2*(L - N)*sinphi*sinth0*costh0 & - - ( - A + F + 2*N)*sinphi*sinth0*costh0 - (A + C - 2*F & - - 4*L)*sinphi*sinth0*costh0**3)*conjg(Vdot) + imag_i*V*k*( & - - (L - N)*sinphi**2*sinth0**2 + (L - N)*sinth0**2*cosphi**2 & - - (A + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2 & - + (A + C - 2*F - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Wdot) & - - imag_i*Vdot*k*( - 2*( - A + F + 2*N)*sinphi*sinth0**2*cosphi & - - 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(U) - imag_i*Vdot*k*( - 2*(L & - - N)*sinphi*sinth0*costh0 - ( - A + F + 2*N)*sinphi*sinth0*costh0 & - - (A + C - 2*F - 4*L)*sinphi*sinth0*costh0**3)*conjg(V) & - - imag_i*Vdot*k*( - ( - A + F + 2*N)*sinphi**2*sinth0**2 & - + ( - A + F + 2*N)*sinth0**2*cosphi**2 - (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2 + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(W) - Vdot*( & - - 2*(L - N)*sinphi*sinth0*costh0 - ( - A + F & - + 2*N)*sinphi*sinth0*costh0 - (A + C - 2*F & - - 4*L)*sinphi*sinth0*costh0**3)*conjg(Udot) - Vdot*(2*(L - N)*sinth0*cosphi*costh0 & - + ( - A + F + 2*N)*sinth0*cosphi*costh0 + (A & - + C - 2*F - 4*L)*sinth0*cosphi*costh0**3)*conjg(Wdot) & - - W*k**2*( - 2*(A + C - 2*F - 4*L)*sinphi**3*sinth0**4*cosphi & - + 2*(A + C - 2*F - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(W) & - - W*k**2*((L - N)*sinth0*cosphi*costh0 - 2*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0 + (A + C & - - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(V) - W*k**2*( & - - 2*(L - N)*sinphi**2*sinth0**2 + 2*(L - N)*sinth0**2*cosphi**2 & - - ( - A + F + 2*N)*sinphi**2*sinth0**2 + ( - A + F & - + 2*N)*sinth0**2*cosphi**2 - 3*(A + C - 2*F & - - 4*L)*sinphi**2*sinth0**4*cosphi**2 + (A + C - 2*F - 4*L)*sinth0**4*cosphi**4)*conjg(U) & - + imag_i*W*k*( - (L - N)*sinphi*sinth0*costh0 & - - (A + C - 2*F - 4*L)*sinphi**3*sinth0**3*costh0 & - + 2*(A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Wdot) & - + imag_i*W*k*((L - N)*sinth0*cosphi*costh0 & - - 2*(A + C - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(Udot) & - + imag_i*W*k*( - ( - A + F + 2*N)*sinphi**2*sinth0**2 & - + ( - A + F + 2*N)*sinth0**2*cosphi**2 - (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2 + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Vdot) & - - imag_i*Wdot*k*( - (L - N)*sinphi*sinth0*costh0 - (A + C & - - 2*F - 4*L)*sinphi**3*sinth0**3*costh0 + 2*(A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(W) & - - imag_i*Wdot*k*(( - A + F + 2*N)*sinth0*cosphi*costh0 & - - 2*(A + C - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(U) & - - imag_i*Wdot*k*( - (L - N)*sinphi**2*sinth0**2 + (L & - - N)*sinth0**2*cosphi**2 - (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**2*costh0**2 + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(V) - Wdot*(2*(L - N)*sinphi*sinth0**2*cosphi & - + 2*(A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Wdot) & - - Wdot*(2*(L - N)*sinth0*cosphi*costh0 & - + ( - A + F + 2*N)*sinth0*cosphi*costh0 + (A & - + C - 2*F - 4*L)*sinth0*cosphi*costh0**3)*conjg(Vdot) & - - Wdot*( - (L - N)*sinphi**2*sinth0**2 + (L - N)*sinth0**2*cosphi**2 & - - (A + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2 & - + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Udot) - Kdphi(:) = real(temp(:),kind=dp) - - temp(:) = - 2*U*k*(2*(L - N)*sinphi*sinth0**2*cosphi + ( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(W) - 2*U*k*(2*(L & - - N)*sinth0*cosphi*costh0 + ( - A + F + 2*N)*sinth0*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(V) & - - 2*U*k*(A + 4*(L - N)*sinth0**2*cosphi**2 + 2*( - A + F & - + 2*N)*sinth0**2*cosphi**2 + (A + C - 2*F & - - 4*L)*sinth0**4*cosphi**4)*conjg(U) + imag_i*U*(( - A + F + 2*N)*sinphi*sinth0*costh0 & - + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Wdot) & - + imag_i*U*(2*(L & - - N)*sinth0*cosphi*costh0 + ( - A + F + 2*N)*sinth0*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(Udot) & - + imag_i*U*(A - 2*N + (sinth0**2*cosphi**2 & - + costh0**2)*( - A + F + 2*N) + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Vdot) - imag_i*Udot*((L & - - N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(W) - imag_i*Udot*(N + (L & - - N)*(sinth0**2*cosphi**2 + costh0**2) + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(V) - imag_i*Udot*(2*(L & - - N)*sinth0*cosphi*costh0 + ( - A + F & - + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(U) & - - 2*V*k*((L - N)*sinphi*sinth0*costh0 & - + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(W) & - - 2*V*k*(N + (L - N)*(sinth0**2*cosphi**2 & - + costh0**2) + (A + C - 2*F - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(V) & - - 2*V*k*(2*(L - N)*sinth0*cosphi*costh0 & - + ( - A + F + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(U) + imag_i*V*((L & - - N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Wdot) & - + imag_i*V*(N + (L - N)*(sinth0**2*cosphi**2 + costh0**2) + (A & - + C - 2*F - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Udot) & - + imag_i*V*(2*(L - N)*sinth0*cosphi*costh0 + ( - A & - + F + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinth0*cosphi*costh0**3)*conjg(Vdot) - imag_i*Vdot*(( & - - A + F + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(W) & - - imag_i*Vdot*(2*(L - N)*sinth0*cosphi*costh0 + ( - A + F & - + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinth0*cosphi*costh0**3)*conjg(V) - imag_i*Vdot*(A - 2*N & - + (sinth0**2*cosphi**2 + costh0**2)*( - A + F + 2*N) + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(U) - 2*W*k*((L & - - N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(V) - 2*W*k*(N + (L & - - N)*(sinphi**2*sinth0**2 + sinth0**2*cosphi**2) + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2)*conjg(W) & - - 2*W*k*(2*(L - N)*sinphi*sinth0**2*cosphi + ( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(U) + imag_i*W*((L & - - N)*sinphi*sinth0*costh0 + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Udot) & - + imag_i*W*((L & - - N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(Wdot) + imag_i*W*(( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Vdot) - imag_i*Wdot*((L & - - N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(V) - imag_i*Wdot*((L & - - N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(W) - imag_i*Wdot*(( & - - A + F + 2*N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) - Kwvnm(:) = real(temp(:),kind=dp) - - temp(:) = - 2*U*k*(2*(L - N)*sinphi*sinth0**2*cosphi + ( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(W) - 2*U*k*(2*(L & - - N)*sinth0*cosphi*costh0 + ( - A + F + 2*N)*sinth0*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(V) & - - 2*U*k*(A + 4*(L - N)*sinth0**2*cosphi**2 + 2*( - A + F & - + 2*N)*sinth0**2*cosphi**2 + (A + C - 2*F & - - 4*L)*sinth0**4*cosphi**4)*conjg(U) + imag_i*U*(( - A + F + 2*N)*sinphi*sinth0*costh0 & - + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Wdot) & - + imag_i*U*(2*(L & - - N)*sinth0*cosphi*costh0 + ( - A + F + 2*N)*sinth0*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(Udot) & - + imag_i*U*(A - 2*N + (sinth0**2*cosphi**2 & - + costh0**2)*( - A + F + 2*N) + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Vdot) - imag_i*Udot*((L & - - N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(W) - imag_i*Udot*(N + (L & - - N)*(sinth0**2*cosphi**2 + costh0**2) + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(V) - imag_i*Udot*(2*(L & - - N)*sinth0*cosphi*costh0 + ( - A + F & - + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(U) & - - 2*V*k*((L - N)*sinphi*sinth0*costh0 & - + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(W) & - - 2*V*k*(N + (L - N)*(sinth0**2*cosphi**2 & - + costh0**2) + (A + C - 2*F - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(V) & - - 2*V*k*(2*(L - N)*sinth0*cosphi*costh0 & - + ( - A + F + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinth0**3*cosphi**3*costh0)*conjg(U) + imag_i*V*((L & - - N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Wdot) & - + imag_i*V*(N + (L - N)*(sinth0**2*cosphi**2 + costh0**2) + (A & - + C - 2*F - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(Udot) & - + imag_i*V*(2*(L - N)*sinth0*cosphi*costh0 + ( - A & - + F + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinth0*cosphi*costh0**3)*conjg(Vdot) - imag_i*Vdot*(( & - - A + F + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(W) & - - imag_i*Vdot*(2*(L - N)*sinth0*cosphi*costh0 + ( - A + F & - + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinth0*cosphi*costh0**3)*conjg(V) - imag_i*Vdot*(A - 2*N & - + (sinth0**2*cosphi**2 + costh0**2)*( - A + F + 2*N) + (A + C - 2*F & - - 4*L)*sinth0**2*cosphi**2*costh0**2)*conjg(U) - 2*W*k*((L & - - N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(V) - 2*W*k*(N + (L & - - N)*(sinphi**2*sinth0**2 + sinth0**2*cosphi**2) + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2)*conjg(W) & - - 2*W*k*(2*(L - N)*sinphi*sinth0**2*cosphi + ( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(U) + imag_i*W*((L & - - N)*sinphi*sinth0*costh0 + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Udot) & - + imag_i*W*((L & - - N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(Wdot) + imag_i*W*(( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Vdot) - imag_i*Wdot*((L & - - N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(V) - imag_i*Wdot*((L & - - N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(W) - imag_i*Wdot*(( & - - A + F + 2*N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) - dL_dkv(:,1) = real(temp(:),kind=dp) - temp(:) = - U*k*((L - N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(V) - U*k*(( & - - A + F + 2*N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(V) - U*k*(N & - + (L - N)*(sinphi**2*sinth0**2 + sinth0**2*cosphi**2) & - + (A + C - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2)*conjg(W) & - - 2*U*k*(2*(L - N)*sinphi*sinth0**2*cosphi + ( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi*sinth0**4*cosphi**3)*conjg(U) - U*k*(A - 2*N & - + (sinphi**2*sinth0**2 + sinth0**2*cosphi**2)*( - A + F + 2*N) + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2)*conjg(W) & - + imag_i*U*((L - N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(Udot) & - + imag_i*U*((L - N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(Wdot) & - + imag_i*U*(( - A + F + 2*N)*sinphi*sinth0**2*cosphi + (A & - + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Vdot) & - - imag_i*Udot*((L - N)*sinphi*sinth0*costh0 & - + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) & - - imag_i*Udot*((L - N)*sinphi*sinth0**2*cosphi & - + (A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(V) & - - imag_i*Udot*(( - A + F + 2*N)*sinth0*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(W) & - - V*k*((L - N)*sinphi*sinth0*costh0 & - + (A + C - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) & - - 2*V*k*((L - N)*sinphi*sinth0**2*cosphi & - + (A + C - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(V) & - - V*k*((L - N)*sinth0*cosphi*costh0 + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(W) & - - V*k*(( - A + F + 2*N)*sinphi*sinth0*costh0 + (A + C & - - 2*F - 4*L)*sinphi*sinth0**3*cosphi**2*costh0)*conjg(U) & - - V*k*(( - A + F + 2*N)*sinth0*cosphi*costh0 + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(W) & - + imag_i*V*((L - N)*sinphi*sinth0**2*cosphi + (A + C & - - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(Udot) & - + imag_i*V*(N + (L - N)*(sinphi**2*sinth0**2 + costh0**2) & - + (A + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2)*conjg(Wdot) & - + imag_i*V*(2*(L - N)*sinphi*sinth0*costh0 & - + ( - A + F + 2*N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0*costh0**3)*conjg(Vdot) - imag_i*Vdot*(( & - - A + F + 2*N)*sinphi*sinth0**2*cosphi + (A + C & - - 2*F - 4*L)*sinphi*sinth0**2*cosphi*costh0**2)*conjg(U) & - - imag_i*Vdot*(2*(L - N)*sinphi*sinth0*costh0 + ( - A & - + F + 2*N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi*sinth0*costh0**3)*conjg(V) - imag_i*Vdot*(A - 2*N & - + (sinphi**2*sinth0**2 + costh0**2)*( - A + F + 2*N) + (A & - + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2)*conjg(W) & - - W*k*((L - N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(V) - W*k*(( & - - A + F + 2*N)*sinth0*cosphi*costh0 + (A + C - 2*F & - - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(V) - W*k*(N & - + (L - N)*(sinphi**2*sinth0**2 + sinth0**2*cosphi**2) & - + (A + C - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2)*conjg(U) & - - 2*W*k*(2*(L - N)*sinphi*sinth0**2*cosphi + ( - A + F & - + 2*N)*sinphi*sinth0**2*cosphi + (A + C - 2*F & - - 4*L)*sinphi**3*sinth0**4*cosphi)*conjg(W) - W*k*(A - 2*N & - + (sinphi**2*sinth0**2 + sinth0**2*cosphi**2)*( - A + F + 2*N) + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**4*cosphi**2)*conjg(U) & - + imag_i*W*(( - A + F + 2*N)*sinth0*cosphi*costh0 + (A + C & - - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(Udot) & - + imag_i*W*(2*(L - N)*sinphi*sinth0*costh0 + ( & - - A + F + 2*N)*sinphi*sinth0*costh0 + (A + C - 2*F & - - 4*L)*sinphi**3*sinth0**3*costh0)*conjg(Wdot) + imag_i*W*(A & - - 2*N + (sinphi**2*sinth0**2 + costh0**2)*( - A + F + 2*N) & - + (A + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2)*conjg(Vdot) & - - imag_i*Wdot*((L - N)*sinth0*cosphi*costh0 & - + (A + C - 2*F - 4*L)*sinphi**2*sinth0**3*cosphi*costh0)*conjg(U) & - - imag_i*Wdot*(N + (L - N)*(sinphi**2*sinth0**2 & - + costh0**2) + (A + C - 2*F - 4*L)*sinphi**2*sinth0**2*costh0**2)*conjg(V) & - - imag_i*Wdot*(2*(L - N)*sinphi*sinth0*costh0 & - + ( - A + F + 2*N)*sinphi*sinth0*costh0 + (A & - + C - 2*F - 4*L)*sinphi**3*sinth0**3*costh0)*conjg(W) - dL_dkv(:,2) = real(temp(:),kind=dp) - -end subroutine get_kernels - diff --git a/src/vti/CMakeLists.txt b/src/vti/CMakeLists.txt index cfc8366..0585327 100644 --- a/src/vti/CMakeLists.txt +++ b/src/vti/CMakeLists.txt @@ -1,8 +1,9 @@ -file(GLOB SOURCE "*.cpp") -list(FILTER SOURCE EXCLUDE REGEX "main_vti.cpp") +file(GLOB SOURCE "*.cpp" ) +list(FILTER SOURCE EXCLUDE REGEX "main*.cpp") -add_library(libvti ${SOURCE}) +add_library(vti ${SOURCE}) -# exe -add_executable(surfvti ${PROJECT_SOURCE_DIR}/src/vti/main_vti.cpp) -target_link_libraries(surfvti libvti shared ${LAPACK_LIBRARIES}) \ No newline at end of file +add_executable(surflove main_love.cpp) +add_executable(surfrayl main_rayl.cpp) +target_link_libraries(surflove vti mesh shared ${LAPACKE_LIBRARIES}) +target_link_libraries(surfrayl vti mesh shared ${LAPACKE_LIBRARIES}) \ No newline at end of file diff --git a/src/vti/eigenvalue.cpp b/src/vti/eigenvalue.cpp new file mode 100644 index 0000000..b514faf --- /dev/null +++ b/src/vti/eigenvalue.cpp @@ -0,0 +1,391 @@ +#include "vti/vti.hpp" +#include "shared/schur.hpp" + +#include +#include + +namespace specswd { + + +/** + * @brief compute Love wave dispersion and eigenfunctions, elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) + * @param egn eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if false, only compute phase velocities + */ +void SolverLove:: +compute_egn(const Mesh &mesh, + std::vector &c, + std::vector &egn, + bool use_qz) +{ + typedef Eigen::MatrixX rmat2; + using Eigen::indexing::all; + + // mapping M,K,E to matrix + int ng = mesh.nglob_el; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map> E(Emat.data(),ng,ng); + + // constants + float freq = mesh.freq; + realw om = 2. * M_PI * freq; + realw omega2 = std::pow(om,2); + + // allocate eigenvalues and eigenvectors + Eigen::ArrayX k2_all(ng); + Eigen::ArrayX k_all(ng); + rmat2 vsr; + + // A/B matrix + rmat2 A = -E.cast() + rmat2(M.cast().asDiagonal()* omega2); + rmat2 B = rmat2(K.cast().asDiagonal()); + + // compute eigenvalues/vectors + if(!use_qz) { // only compute phase velocities + // note A and B are symmetric, and definite-positive ?sygv is used + LAPACKE_REAL(sygv)( + LAPACK_COL_MAJOR,1,'N','U',ng, + A.data(),ng,B.data(),ng, + k2_all.data() + ); + } + else { + vsr.resize(ng,ng); + schur_qz( + A,B,k2_all,vsr.data(),nullptr, + Qmat_,Zmat_,Smat_,Spmat_, + false + ); + } + k_all = k2_all.cast().sqrt(); + + // filter swd + Eigen::ArrayX c_all = (om / k_all).real(); + auto mask = ((c_all.real() >= mesh.PHASE_VELOC_MIN)&& + (c_all.real() <= mesh.PHASE_VELOC_MAX) && + k_all.real().abs() >= 10 *k_all.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + for(int i = 0; i < c_all.size(); i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort to ascending order + int nc = idx0.size(); + std::vector idx(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c + c.resize(nc); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + } + + // copy eigenvectors + if (use_qz) { + egn.resize(nc*ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + for(int i = 0; i < ng; i ++) { + egn[ic * ng + i] = vsr(i,id); + } + } + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, visco-elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param egn eigenfunctions (displ at y direction), shape(nc,nglob_el) + * @param use_qz if true, save QZ matrix + */ +void SolverLove:: +compute_egn_att(const Mesh &mesh, + std::vector &c, + std::vector &egn, + bool use_qz) +{ + typedef Eigen::MatrixX crmat2; + + // construct matrix + int ng = mesh.nglob_el; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(CKmat.data(),ng); + Eigen::Map> E(CEmat.data(),ng,ng); + + // construct A = K^{-1}(om^2 M - E) + float freq = mesh.freq; + float om = 2. * M_PI * freq; + realw omega2 = std::pow(om,2); + crmat2 A = -E.cast() + crmat2(M.cast().asDiagonal()* omega2); + + // eigenvectors/values + Eigen::ArrayX k(ng); + crmat2 vsr; + + // compute eigenvalues/vectors + if(!use_qz) { // only compute phase velocities + A = (1.0f / K.array()).cast().matrix().asDiagonal() * A; + LAPACKE_CMPLX(geev)( + LAPACK_COL_MAJOR,'N','N',ng, + (LCREALW *)A.data(),ng,(LCREALW*)k.data(), + nullptr,ng,nullptr,ng + ); + } + else { + crmat2 B = crmat2(K.cast().asDiagonal()); + vsr.resize(ng,ng); + schur_qz ( + A,B,k,vsr.data(),nullptr, + cQmat_,cZmat_,cSmat_,cSpmat_, + false + ); + } + k = k.sqrt(); + + // filter SWD + using Eigen::indexing::all; + Eigen::ArrayX c_all = om / k; + auto mask = ((c_all.real() >= mesh.PHASE_VELOC_MIN)&& + (c_all.real() <= mesh.PHASE_VELOC_MAX) && + k.real().abs() >= k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + int nc = idx0.size(); + + // sort according to ascending order + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c + c.resize(nc); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + } + + // save eigenvectors if required + if (use_qz) { + egn.resize(nc*ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + for(int i = 0; i < ng; i ++) { + egn[ic * ng + i] = vsr(i,id); + } + } + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param ur/ul left/right eigenvectors, shape(nc,nglob_el*2+nglob_ac) + * @param use_qz if true, save QZ matrix + */ +void SolverRayl:: +compute_egn(const Mesh &mesh, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::MatrixX rmat2; + + // mapping M,K,E to matrix + int ng = mesh.nglob_ac + mesh.nglob_el * 2; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map> K(Kmat.data(),ng,ng); + Eigen::Map> E(Emat.data(),ng,ng); + + // prepare matrix A = om^2 M -E + float freq = mesh.freq; + realw om = 2. * M_PI * freq; + realw omega2 = om * om; + + // solve this system + rmat2 A = omega2 * rmat2(M.cast().asDiagonal()) - E.cast(); + rmat2 B = K.cast(); + Eigen::ArrayX k2_all(ng); + Eigen::ArrayX k_all(ng); + rmat2 vsl,vsr; + + // compute eigenvalues/vectors + if(!use_qz) { // only compute phase velocities + Eigen::ArrayX ki(ng),beta(ng); + LAPACKE_REAL(ggev)( + LAPACK_COL_MAJOR,'N','N',ng,A.data(),ng,B.data(),ng, + k2_all.data(),ki.data(),beta.data(),nullptr,ng, + nullptr,ng); + + k2_all = k2_all / beta; + } + else { + vsr.resize(ng,ng); + vsl.resize(ng,ng); + schur_qz ( + A,B,k2_all,vsr.data(),vsl.data(), + Qmat_,Zmat_,Smat_,Spmat_, + true + ); + } + + //eigenvalue + k_all = k2_all.cast().sqrt(); + + // filter SWD + using Eigen::indexing::all; + Eigen::ArrayX c_all = (om / k_all).real(); + auto mask = ((c_all >= mesh.PHASE_VELOC_MIN)&& + (c_all <= mesh.PHASE_VELOC_MAX) && + k_all.real().abs() >= 10 *k_all.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort according to ascending order + int nc = idx0.size(); + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c + c.resize(nc); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + } + + // save eigenvectors if required + if(use_qz) { + ur.resize(nc * ng); ul.resize(nc*ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + for(int i = 0; i < ng; i ++) { + ur[ic*ng+i] = vsr(i,id); + ul[ic*ng+i] = vsl(i,id); + } + } + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, visco-elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param ur/ul left/right eigenvectors, shape(nc,nglob_el*2+nglob_ac) + * @param use_qz if true, save QZ matrix + */ +void SolverRayl:: +compute_egn_att(const Mesh &mesh, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::MatrixX crmat2; + + // mapping M,K,E to matrix + int ng = mesh.nglob_ac + mesh.nglob_el * 2; + + Eigen::Map M(CMmat.data(),ng); + Eigen::Map> K(CKmat.data(),ng,ng); + Eigen::Map> E(CEmat.data(),ng,ng); + + // prepare matrix A = om^2 M -E + float freq = mesh.freq; + realw om = 2. * M_PI * freq; + realw omega2 = om * om; + + // matrices + crmat2 A = crmat2(M.cast().asDiagonal()) * omega2 - E.cast(); + crmat2 B = K.cast(); + Eigen::ArrayX k_all(ng); + crmat2 vsl,vsr; + + // compute eigenvalues/vectors + if(!use_qz) { // only compute phase velocities + Eigen::ArrayX beta(ng); + LAPACKE_CMPLX(ggev)( + LAPACK_COL_MAJOR,'N','N',ng,(LCREALW*)A.data(), + ng,(LCREALW*)B.data(),ng, + (LCREALW*)k_all.data(),(LCREALW*)beta.data(), + nullptr,ng,nullptr,ng + ); + k_all = k_all / beta; + } + else { + vsr.resize(ng,ng); + vsl.resize(ng,ng); + schur_qz ( + A,B,k_all,vsr.data(),vsl.data(), + cQmat_,cZmat_,cSmat_,cSpmat_, + true + ); + } + k_all = k_all.sqrt(); + + // filter SWD + using Eigen::indexing::all; + Eigen::ArrayX c_all = om / k_all; + auto mask = ((c_all.real() >= mesh.PHASE_VELOC_MIN)&& + (c_all.real() <= mesh.PHASE_VELOC_MAX) && + k_all.real().abs() >= k_all.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + int nc = idx0.size(); + + // sort according to ascending order + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c/displ + c.resize(nc); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + } + + if(use_qz) { + ur.resize(nc * ng); ul.resize(nc * ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + for(int i = 0; i < ng; i ++) { + ul[ic * ng + i] = vsl(i,id); + ur[ic * ng + i] = vsr(i,id); + } + } + } +} + +} // namespace specswd \ No newline at end of file diff --git a/src/vti/eigenvalues.cpp.bak b/src/vti/eigenvalues.cpp.bak new file mode 100644 index 0000000..e19acad --- /dev/null +++ b/src/vti/eigenvalues.cpp.bak @@ -0,0 +1,360 @@ +#ifdef DEBUG + +#include "vti/vti.hpp" + +#include "shared/schur.hpp" + +#include +#include + +namespace specswd { + +/** + * @brief compute Love wave dispersion and eigenfunctions, elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) + * @param egn eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if false, only compute phase velocities + */ +void SolverLove:: +compute_egn(const Mesh &mesh, + std::vector &c, + std::vector &egn, + bool use_qz) +{ + typedef Eigen::MatrixX rmat2; + using Eigen::indexing::all; + + // mapping M,K,E to matrix + int ng = mesh.nglob_el; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map> E(Emat.data(),ng,ng); + + // construct A = (om^2 M - E), B = K + float freq = mesh.freq; + realw om = 2. * M_PI * freq; + realw omega2 = std::pow(om,2); + rmat2 A = rmat2(((realw)1. / K.array()).matrix().cast().asDiagonal()) * + (-E.cast() + rmat2(M.cast().asDiagonal() * omega2)); + rmat2 displ_all = A * 0.; + + // get eigen values/eigen vectors + Eigen::Array kr(ng),ki(ng); + LAPACKE_REAL(geev)( + LAPACK_COL_MAJOR,'N','V',ng,A.data(), + ng,kr.data(),ki.data(),nullptr, + ng,displ_all.data(),ng + ); + + // filter swd + Eigen::Array k = (kr + crealw{0,1.} * ki).sqrt(); + Eigen::Array c_all = (om / k).real(); + auto mask = ((c_all.real() >= mesh.PHASE_VELOC_MIN)&& + (c_all.real() <= mesh.PHASE_VELOC_MAX) && + k.real().abs() >= 10 *k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + for(int i = 0; i < c_all.size(); i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort to ascending order + int nc = idx0.size(); + std::vector idx(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c/displ + int size = displ_all.rows(); + c.resize(nc); egn.resize(nc * size); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + + // scale + float scale = displ_all(all,id).norm(); + for(int i = 0; i < size; i ++) { + egn[ic * size + i] = displ_all(i,id) / scale; + } + } + + // compute QZ if required + if(use_qz) { + // get hessenburg form by Schur decomposition + A = -E.cast() + rmat2(M.cast().asDiagonal()* omega2); + rmat2 B = rmat2(K.cast().asDiagonal()); + + schur_qz(ng,A,B,Qmat_,Zmat_,Smat_,Spmat_); + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, visco-elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param displ eigen functions(displ at y direction), shape(nc,nglob_el) + * @param use_qz if true, save QZ matrix + */ +void SolverLove:: +compute_egn_att(const Mesh &mesh, + std::vector &c, + std::vector &displ, + bool use_qz) +{ + typedef Eigen::MatrixX crmat2; + + // construct matrix + int ng = mesh.nglob_el; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map K(CKmat.data(),ng); + Eigen::Map> E(CEmat.data(),ng,ng); + + // construct A = K^{-1}(om^2 M - E) + float freq = mesh.freq; + float om = 2. * M_PI * freq; + realw omega2 = std::pow(om,2); + crmat2 A = (1. / K.array()).cast().matrix().asDiagonal() * + (-E + M.asDiagonal().toDenseMatrix() * omega2).cast(); + // crmat2 A = (crmat2((1. / K.array()).cast().matrix().asDiagonal()) * + // (-E.cast() + crmat2(M.cast().asDiagonal()) * omega2)); + + // solve it + crmat2 displ_all = A; + Eigen::ArrayX k(ng); + LAPACKE_CMPLX(geev)( + LAPACK_COL_MAJOR,'N','V',ng, + (LCREALW *)A.data(),ng,(LCREALW*)k.data(), + nullptr,ng,(LCREALW *)displ_all.data(),ng + ); + k = k.sqrt(); + + // filter SWD + using Eigen::indexing::all; + Eigen::ArrayX c_all = om / k; + auto mask = ((c_all.real() >= mesh.PHASE_VELOC_MIN)&& + (c_all.real() <= mesh.PHASE_VELOC_MAX) && + k.real().abs() >= k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + int nc = idx0.size(); + + // sort according to ascending order + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c/displ + c.resize(nc); displ.resize(nc * ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + + // scale factor + crealw scale = displ_all(all,id).norm(); + for(int i = 0; i < ng; i ++) { + displ[ic * ng + i] = displ_all(i,id) / scale; + } + } + + // save QZ matrix + if(use_qz) { + // get hessenburg form by Schur decomposition + //typedef lapack_complex_double ldcmplx; + A = -E.cast() + crmat2(M.cast().asDiagonal()) * omega2; + crmat2 B = K.cast().asDiagonal(); + + schur_qz(ng,A,B,cQmat_,cZmat_,cSmat_,cSpmat_); + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param ur/ul left/right eigenvectors, shape(nc,nglob_el*2+nglob_ac) + * @param use_qz if true, save QZ matrix + */ +void SolverRayl:: +compute_egn(const Mesh &mesh, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::MatrixX rmat2; + + // mapping M,K,E to matrix + int ng = mesh.nglob_ac + mesh.nglob_el * 2; + Eigen::Map M(Mmat.data(),ng); + Eigen::Map> K(Kmat.data(),ng,ng); + Eigen::Map> E(Emat.data(),ng,ng); + + // prepare matrix A = om^2 M -E + float freq = mesh.freq; + realw om = 2. * M_PI * freq; + realw omega2 = om * om; + + // solve this system + rmat2 A = omega2 * rmat2(M.cast().asDiagonal()) - E.cast(); + rmat2 B = K.cast(); + Eigen::ArrayX alphar(ng),alphai(ng),beta(ng); + rmat2 vsl(ng,ng),vsr(ng,ng); + + // generalized eigenvalue problem + // A x = k B x + LAPACKE_REAL(ggev)( + LAPACK_COL_MAJOR,'V','V',ng,A.data(),ng,B.data(),ng, + alphar.data(),alphai.data(),beta.data(),vsl.data(),ng, + vsr.data(),ng); + + //eigenvalue + const crealw imag_i = {0,1.}; + Eigen::ArrayX k = ((alphar + imag_i * alphai) / beta).sqrt(); + + // filter SWD + using Eigen::indexing::all; + Eigen::ArrayX c_all = (om / k).real(); + auto mask = ((c_all >= mesh.PHASE_VELOC_MIN)&& + (c_all <= mesh.PHASE_VELOC_MAX) && + k.real().abs() >= 10 *k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + + // sort according to ascending order + int nc = idx0.size(); + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]] < c_all[idx0[i2]];}); + + // copy to c/displ + c.resize(nc); ur.resize(nc * ng); ul.resize(nc*ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + + // normalize factor + float sr = vsr(all,id).norm(); + float sl = vsl(all,id).norm(); + + // copy to ur/ul + for(int i = 0; i < ng; i ++) { + ur[ic*ng+i] = vsr(i,id) / sr; + ul[ic*ng+i] = vsl(i,id) / sl; + } + } + + // save qz matrix + if(use_qz) { + schur_qz(ng,A,B,Qmat_,Zmat_,Smat_,Spmat_); + } +} + +/** + * @brief compute rayleigh wave dispersion and eigenfunctions, visco-elastic case + * @param mesh Mesh class + * @param c dispersion, shape(nc) c = c0(1 + iQL^{-1}) + * @param ur/ul left/right eigenvectors, shape(nc,nglob_el*2+nglob_ac) + * @param use_qz if true, save QZ matrix + */ +void SolverRayl:: +compute_egn_att(const Mesh &mesh, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz) +{ + typedef Eigen::MatrixX crmat2; + + // mapping M,K,E to matrix + int ng = mesh.nglob_ac + mesh.nglob_el * 2; + + Eigen::Map M(CMmat.data(),ng); + Eigen::Map> K(CKmat.data(),ng,ng); + Eigen::Map> E(CEmat.data(),ng,ng); + + // prepare matrix A = om^2 M -E + float freq = mesh.freq; + realw om = 2. * M_PI * freq; + realw omega2 = om * om; + + // solve this system + crmat2 A = crmat2(M.cast().asDiagonal()) * omega2 - E.cast(); + crmat2 B = K.cast(); + Eigen::ArrayX alpha(ng),beta(ng); + crmat2 vsl(ng,ng),vsr(ng,ng); + + // generalized eigenvalue problem + // A x = k B x + // eigenvalues + LAPACKE_CMPLX(ggev)( + LAPACK_COL_MAJOR,'V','V',ng,(LCREALW*)A.data(),ng,(LCREALW*)B.data(),ng, + (LCREALW*)alpha.data(),(LCREALW*)beta.data(),(LCREALW*)vsl.data(),ng, + (LCREALW*)vsr.data(),ng + ); + + Eigen::ArrayX k = (alpha / beta).sqrt(); + + // filter SWD + using Eigen::indexing::all; + Eigen::ArrayX c_all = om / k; + auto mask = ((c_all.real() >= mesh.PHASE_VELOC_MIN)&& + (c_all.real() <= mesh.PHASE_VELOC_MAX) && + k.real().abs() >= k.imag().abs()); + std::vector idx0; idx0.reserve(mask.cast().sum()); + int nc_all = c_all.size(); + for(int i = 0; i < nc_all; i ++) { + if(mask[i]) { + idx0.push_back(i); + } + } + int nc = idx0.size(); + + // sort according to ascending order + std::vector idx; + idx.resize(nc); + for(int i = 0; i < nc; i ++ ) idx[i] = i; + std::sort(idx.begin(), idx.end(), + [&c_all,&idx0](size_t i1, size_t i2) {return c_all[idx0[i1]].real() < c_all[idx0[i2]].real();}); + + // copy to c/displ + c.resize(nc); ur.resize(nc * ng); ul.resize(nc*ng); + for(int ic = 0; ic < nc; ic ++) { + int id = idx0[idx[ic]]; + c[ic] = c_all[id]; + + // normalize factor + realw sr = vsr(all,id).norm(); + realw sl = vsl(all,id).norm(); + + for(int i = 0; i < ng; i ++) { + ul[ic * ng + i] = vsl(i,id) / sl; + ur[ic * ng + i] = vsr(i,id) / sr; + } + } + + // save qz matrix + if(use_qz) { + schur_qz(ng,A,B,cQmat_,cZmat_,cSmat_,cSpmat_); + } +} + +} // end namespace specswd + +#endif \ No newline at end of file diff --git a/src/vti/frechet.cpp b/src/vti/frechet.cpp new file mode 100644 index 0000000..637b4f4 --- /dev/null +++ b/src/vti/frechet.cpp @@ -0,0 +1,201 @@ +#include "vti/vti.hpp" +#include "vti/frechet_op.hpp" + +#include +#include + +namespace specswd +{ + + +/** + * @brief compute love wave phase velocity kernels, elastic case + * @param M Mesh clas + * @param c current phase velocity + * @param egn eigen function, shape(nglob_el) + * @param frekl Frechet kernels (N/L/rho) for elastic parameters, shape(3,nspec*NGLL + NGRL) + */ +void SolverLove:: +compute_phase_kl(const Mesh &M, + float c,const float *egn, + std::vector &frekl) const +{ + int ng = M.nglob_el; + Eigen::Map x(egn,ng); + Eigen::Map K(Kmat.data(),ng); + + // get coefs + float freq = M.freq; + double om = 2 * M_PI * freq; + float coef = -0.5 * std::pow(c,3) / std::pow(om,2) / (x * K * x).sum(); + + // allocate phase velocity kernels + int size = M.ibool_el.size(); + frekl.resize(3*size); // N/L/rho + + // get M/K/E coefs + float c_M = (om * om) * coef; + float c_K = -std::pow(om / c,2) * coef; + float c_E = -coef; + + // compute kernels + love_op_matrix( + freq,c_M,c_K,c_E,egn,egn,M.nspec_el,M.nglob_el, + M.ibool_el.data(),M.jaco.data(), + nullptr,nullptr,nullptr,nullptr, + frekl.data(),nullptr + ); +} + +/** + * @brief compute love wave phase velocity kernels, visco-elastic case + * @param M mesh class + * @param c current complex phase velocity + * @param egn eigen function, shape(nglob_el) + * @param frekl_c dRe(c)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + * @param frekl_q d(qi)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + */ +void SolverLove:: +compute_phase_kl_att(const Mesh &M, + scmplx c, const scmplx *egn, + std::vector &frekl_c, + std::vector &frekl_q) const +{ + int ng = M.nglob_el; + Eigen::Map x(egn,ng); + Eigen::Map K(CKmat.data(),ng); + + // coefs for phase kernel + float freq = M.freq; + float om = 2 * M_PI * freq; + float om_sq = om * om; + scmplx c_sq = c * c; + scmplx coef = -0.5f / om_sq * c_sq * c / (x * K * x).sum(); + + // left eigen vector + Eigen::ArrayXcf y = x.conjugate(); + + // allocate phase velocity kernels + int size = M.ibool_el.size(); + frekl_c.resize(5*size); // dc_L/d(N/L/QN/QL/rho) + frekl_q.resize(5*size); // d(Qi_L)/d(N/L/QN/QL/rho) + + // get M/K/E coefs + scmplx c_M = (float)(om * om) * coef; + scmplx c_K = -om_sq / c_sq * coef; + scmplx c_E = -coef; + + // get kernels + love_op_matrix( + freq,c_M,c_K,c_E,y.data(),x.data(),M.nspec_el,M.nglob_el, + M.ibool_el.data(),M.jaco.data(),M.xN.data(), + M.xL.data(), M.xQN.data(),M.xQL.data(), + frekl_c.data(),frekl_q.data() + ); + + // convert to c/QL kernel + get_fQ_kl(5*size,c,frekl_c.data(),frekl_q.data()); +} + +/** + * @brief compute Rayleigh wave phase kernels, elastic case + * @param M mesh class + * @param c current phase velocity + * @param ur/ul right/left eigen function, shape(nglob_el*2+nglob_ac) + * @param frekl Frechet kernels A/C/L/eta/kappa/rho_kl kernels for elastic parameters, shape(6,nspec*NGLL + NGRL) + */ +void SolverRayl:: +compute_phase_kl(const Mesh &M, + float c,const float *ur, + const float *ul, + std::vector &frekl) const +{ + int ng = M.nglob_el*2 + M.nglob_ac; + typedef Eigen::Matrix fmat2; + Eigen::Map x(ur,ng),y(ul,ng); + Eigen::Map K(Kmat.data(),ng,ng); + + // coefs for phase kernel + float freq = M.freq; + double om = 2 * M_PI * freq; + double coef = - 0.5 * std::pow(c,3) / std::pow(om,2) / (y.transpose() * K * x).sum(); + + // allocate kernels + int size = M.ibool.size(); + frekl.resize(6*size,0); // A/C/L/eta/kappa_ac/rho_kl + std::fill(frekl.begin(),frekl.end(),0.); + + // compute phase kernels + float c_M = (float)(om * om) * coef; + float c_E = -coef; + float c_K = -std::pow((float)om / c,2) * coef; + + rayl_op_matrix( + freq,c_M,c_K,c_E,ul,ur,M.nspec_el,M.nspec_ac, + M.nspec_el_grl,M.nspec_ac_grl,M.nglob_el,M.nglob_ac, + M.el_elmnts.data(),M.ac_elmnts.data(), + M.ibool_el.data(),M.ibool_ac.data(), + M.jaco.data(),M.xrho_el.data(),M.xrho_ac.data(), + M.xA.data(),M.xC.data(),M.xL.data(), + M.xeta.data(),nullptr,nullptr, + nullptr,M.xkappa_ac.data(),nullptr, + frekl.data(),nullptr + ); +} + +/** + * @brief compute Rayleigh wave phase kernels, visco-elastic case + * @param M mesh class + * @param c current phase velocity + * @param ur/ul right/left eigen function, shape(nglob_el*2+nglob_ac) + * @param frekl_c dRe(c)/d(A/C/L/eta/Qa/Qc/Ql/kappa/Qk/rho) kernels for elastic parameters, shape(10,nspec*NGLL + NGRL) + * @param frekl_q dRe(Q_R)/d(A/C/L/eta/Qa/Qc/Ql/kappa/Qk/rho) kernels for elastic parameters, shape(10,nspec*NGLL + NGRL) + */ +void SolverRayl:: +compute_phase_kl_att(const Mesh &M, + scmplx c,const scmplx *ur, + const scmplx *ul, + std::vector &frekl_c, + std::vector &frekl_q) const +{ + int ng = M.nglob_el*2 + M.nglob_ac; + typedef Eigen::Matrix cmat2; + Eigen::Map x(ur,ng),y(ul,ng); + Eigen::Map K(CKmat.data(),ng,ng); + + // get coefs + float freq = M.freq; + float om = 2 * M_PI * freq; + float om_sq = om * om; + scmplx c_sq = c * c; + scmplx coef = -0.5f / om_sq * c_sq * c / (y.adjoint() * K * x).sum(); + + // allocate phase velocity kernels + int size = M.ibool.size(); + frekl_c.resize(10*size,0); // A/C/L/eta/kappa_ac/rho_kl + frekl_q.resize(10*size,0); // A/C/L/eta/kappa_ac/rho_kl + std::fill(frekl_c.begin(),frekl_c.end(),0.); + std::fill(frekl_q.begin(),frekl_q.end(),0.); + + scmplx c_M = (float)(om * om) * coef; + scmplx c_E = -coef; + scmplx c_K = -om_sq / c_sq * coef; + + rayl_op_matrix( + freq,c_M,c_K,c_E,ul,ur,M.nspec_el,M.nspec_ac, + M.nspec_el_grl,M.nspec_ac_grl,M.nglob_el,M.nglob_ac, + M.el_elmnts.data(),M.ac_elmnts.data(), + M.ibool_el.data(),M.ibool_ac.data(), + M.jaco.data(),M.xrho_el.data(),M.xrho_ac.data(), + M.xA.data(),M.xC.data(),M.xL.data(), + M.xeta.data(),M.xQA.data(),M.xQC.data(), + M.xQL.data(),M.xkappa_ac.data(),M.xQk_ac.data(), + frekl_c.data(),frekl_q.data() + ); + + // convert to c/QR kernel + get_fQ_kl(10*size,c,frekl_c.data(),frekl_q.data()); +} + +} // namespace specswd + diff --git a/src/vti/frechet_group.cpp b/src/vti/frechet_group.cpp new file mode 100644 index 0000000..a7e44c3 --- /dev/null +++ b/src/vti/frechet_group.cpp @@ -0,0 +1,466 @@ +#include "vti/vti.hpp" +#include "vti/frechet_op.hpp" +#include "shared/iofunc.hpp" + +#include +#include + +namespace specswd +{ + +/** + * @brief compute group velocity and kernels for love wave group velocity, elastic case + * @param mesh Mesh class + * @param c current phase velocity + * @param egn eigen function, shape(nglob_el) + * @param frekl Frechet kernels (N/L/rho) for elastic parameters, shape(3,nspec*NGLL + NGRL) + */ +void SolverLove:: +compute_group_kl(const Mesh &mesh, + float c,const float *egn, + std::vector &frekl) const +{ + int ng = mesh.nglob_el; + Eigen::Map x(egn,ng); + Eigen::Map K(Kmat.data(),ng); + Eigen::Map M(Mmat.data(),ng); + + // mapping frekl + int size = mesh.ibool_el.size(); + frekl.resize(3*size); // N/L/rho + Eigen::Map f(frekl.data(),frekl.size()); + Eigen::ArrayXf f_temp(frekl.size()); + + // group velocity + // du / alpha = du/dc * dc/dalpha + float freq = mesh.freq; + double om = 2 * M_PI * freq; + float k2 = std::pow(om/c,2); + float xTKx = (x * K * x).sum(), xTMx = (x * M * x).sum(); + + // du_dx + Eigen::VectorXf du_dx = 2. * K * x / (c * xTMx) - + 2. * xTKx/c * M * x / std::pow(xTMx,2); + + // mapping Q,Z,S,Sp + Eigen::Map Q(Qmat_.data(),ng,ng); + Eigen::Map Z(Zmat_.data(),ng,ng); + Eigen::Map S(Smat_.data(),ng,ng); + Eigen::Map Sp(Spmat_.data(),ng,ng); + + // solve (A.H - conj(k)^2 B.H) lambda = conj(du_dx) + du_dx = Z.transpose() * du_dx.conjugate(); + Eigen::MatrixXf St = (S.transpose() - k2 * Sp.transpose()); + Eigen::VectorXf lamb = du_dx * 0.0f; + using Eigen::seq; + for(int i = 0; i < ng; i ++) { // forward substitution + float s = (St(i,seq(0,i-1)) * lamb(seq(0,i-1))).sum(); + bool SMALL_DIAG = std::abs(St(i,i)) < 1.0e-12; + lamb[i] = SMALL_DIAG ? 0. : (du_dx[i] - s) / St(i,i); + } + lamb = Q * lamb; + + // make lambda orthogonal to left eigenvector + lamb = lamb.array() - (x.array() * lamb.array()).sum() * x; + + // constant c + float du_dalpha = -xTKx / (c*c * xTMx); + du_dalpha *= -0.5f * std::pow(c,3) / (om * om); + float c12 = - (du_dalpha + (lamb.array() * K * x).sum()) / xTKx; + + // - (lambda + c y) ^H (dA / dm_i - k^2 dB / dm) x + lamb = lamb.array() + c12 * x; + float c_M = -om * om; + float c_K = k2; + float c_E = 1.; + love_op_matrix( + freq,c_M,c_K,c_E,lamb.data(),x.data(),mesh.nspec_el, + mesh.nglob_el,mesh.ibool_el.data(), + mesh.jaco.data(),mesh.xN.data(),mesh.xL.data(), + nullptr,nullptr,frekl.data(), + nullptr + ); + + // C_M and C_K + c_M = - xTKx / (c * xTMx * xTMx); + c_K = 1.0f/(c * xTMx); + c_E = 0.; + love_op_matrix( + freq,c_M,c_K,c_E,x.data(),x.data(),mesh.nspec_el, + mesh.nglob_el,mesh.ibool_el.data(), + mesh.jaco.data(),mesh.xN.data(),mesh.xL.data(), + nullptr,nullptr,f_temp.data(), + nullptr + ); + f += f_temp; +} + +/** + * @brief compute group velocity and kernels for rayleigh wave group velocity, elastic case + * @param mesh Mesh class + * @param c current phase velocity + * @param ur/ul right/left eigen function, shape(nglob_el*2+nglob_ac) + * @param frekl Frechet kernels (A/C/L/kappa/rho) for elastic parameters, shape(5,nspec*NGLL + NGRL) + */ +void SolverRayl:: +compute_group_kl(const Mesh &mesh, + float c,const float *ur, + const float *ul, + std::vector &frekl) const +{ + int ng = mesh.nglob_el * 2 + mesh.nglob_ac; + typedef Eigen::Matrix fmat2; + Eigen::Map x(ur,ng); + Eigen::Map y(ul,ng); + Eigen::Map K(Kmat.data(),ng,ng); + Eigen::Map M(Mmat.data(),ng); + + // resize kernels + int size = mesh.ibool.size(); + frekl.resize(6*size); // du_L/d(A/C/L/kappa/rho) + Eigen::Map f(frekl.data(),frekl.size()); + Eigen::ArrayXf f1(frekl.size()); + + // compute some coefs + // du / alpha = du/dc * dc/dalpha + float freq = mesh.freq; + double om = 2 * M_PI * freq; + float k2 = std::pow(om/c,2); + float yTKx = (y.transpose().matrix() * K * x.matrix()).sum(), + yTMx = (y * M * x).sum(); + float du_dalpha = -yTKx / (c*c * yTMx); + du_dalpha *= -0.5f * std::pow(c,3) / (om * om); + + // du_dx and du_dy + Eigen::VectorXf du_dx = K.transpose().matrix() * y.matrix() / (c * yTMx) - + yTKx * (M * y).matrix() / (c * yTMx * yTMx); + Eigen::VectorXf du_dy = K.matrix() * x.matrix() / (c * yTMx) - + yTKx * (M * x).matrix() / (c * yTMx * yTMx); + + // mapping Q,Z,S,Sp + Eigen::Map Q(Qmat_.data(),ng,ng); + Eigen::Map Z(Zmat_.data(),ng,ng); + Eigen::Map S(Smat_.data(),ng,ng); + Eigen::Map Sp(Spmat_.data(),ng,ng); + + // solve (A- k^2 B).T lam = du_dx + using Eigen::seq; + du_dx = Z.transpose() * du_dx.matrix(); + Eigen::MatrixXf P = S.transpose() - k2 * Sp.transpose(); + Eigen::VectorXf lamb = du_dx * 0.0f; + for(int i = 0; i < ng; i ++) { + // forward substitution + float s = (P(i,seq(0,i-1)) * lamb(seq(0,i-1))).sum(); + bool SMALL_DIAG = std::abs(P(i,i)) < 1.0e-12; + lamb[i] = SMALL_DIAG ? 0 : (du_dx[i] - s) / P(i,i); + } + lamb = Q * lamb; + // make lambda orthogonal to left eigenvector + lamb = lamb.array() - (y * lamb.array()).sum() * y; + + // solve (A-k^2 B) xi = du_dy + P = S - k2 * Sp; + du_dy = Q.transpose() * du_dy.matrix(); + Eigen::VectorXf xi = du_dy * 0.0f; + for(int i = ng-1; i >=0; i --) { + float s = (P(i,seq(i+1,ng-1)) * xi(seq(i+1,ng-1))).sum(); + bool SMALL_DIAG = std::abs(P(i,i)) < 1.0e-12; + xi[i] = SMALL_DIAG ? 0 : (du_dy[i] - s) / P(i,i); + } + xi = Z * xi; + // make xi orthogonal to right eigenvector + xi = xi.array() - (x * xi.array()).sum() * x; + + // c12 + float c12 = du_dalpha + (lamb.transpose().matrix() * K * x.matrix()).sum() + + (y.transpose().matrix() * K * xi.matrix()).sum(); + c12 = -c12 / yTKx; + + // -((lamb + c12 y).T (dA /d_m - k^2 dB / dm) x) + lamb = lamb.array() + c12 * y; + float c_M = -om * om; + float c_E = 1., c_K = k2; + rayl_op_matrix( + freq,c_M,c_K,c_E,lamb.data(),x.data(),mesh.nspec_el,mesh.nspec_ac, + mesh.nspec_el_grl,mesh.nspec_ac_grl,mesh.nglob_el,mesh.nglob_ac, + mesh.el_elmnts.data(),mesh.ac_elmnts.data(), + mesh.ibool_el.data(),mesh.ibool_ac.data(), + mesh.jaco.data(),mesh.xrho_el.data(),mesh.xrho_ac.data(), + mesh.xA.data(),mesh.xC.data(),mesh.xL.data(), + mesh.xeta.data(),mesh.xQA.data(),mesh.xQC.data(), + mesh.xQL.data(),mesh.xkappa_ac.data(),mesh.xQk_ac.data(), + f.data(),nullptr + ); + + // -(y.T (dA /d_m - k^2 dB / dm) xi) + rayl_op_matrix( + freq,c_M,c_K,c_E,y.data(),xi.data(),mesh.nspec_el,mesh.nspec_ac, + mesh.nspec_el_grl,mesh.nspec_ac_grl,mesh.nglob_el,mesh.nglob_ac, + mesh.el_elmnts.data(),mesh.ac_elmnts.data(), + mesh.ibool_el.data(),mesh.ibool_ac.data(), + mesh.jaco.data(),mesh.xrho_el.data(),mesh.xrho_ac.data(), + mesh.xA.data(),mesh.xC.data(),mesh.xL.data(), + mesh.xeta.data(),mesh.xQA.data(),mesh.xQC.data(), + mesh.xQL.data(),mesh.xkappa_ac.data(),mesh.xQk_ac.data(), + f1.data(),nullptr + ); + f += f1; + + // df/dM and df/dC + c_M = -yTKx / (c * yTMx * yTMx); + c_E = 0.; + c_K = 1.0f / (c * yTMx); + rayl_op_matrix( + freq,c_M,c_K,c_E,y.data(),x.data(),mesh.nspec_el,mesh.nspec_ac, + mesh.nspec_el_grl,mesh.nspec_ac_grl,mesh.nglob_el,mesh.nglob_ac, + mesh.el_elmnts.data(),mesh.ac_elmnts.data(), + mesh.ibool_el.data(),mesh.ibool_ac.data(), + mesh.jaco.data(),mesh.xrho_el.data(),mesh.xrho_ac.data(), + mesh.xA.data(),mesh.xC.data(),mesh.xL.data(), + mesh.xeta.data(),mesh.xQA.data(),mesh.xQC.data(), + mesh.xQL.data(),mesh.xkappa_ac.data(),mesh.xQk_ac.data(), + f1.data(),nullptr + ); + f += f1; +} + + +/** + * @brief compute love wave group velocity kernels, visco-elastic case + * @param mesh Mesh class + * @param c current complex phase velocity + * @param u current complex group velocity + * @param egn eigen function, shape(nglob_el) + * @param frekl_u dRe(u)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + * @param frekl_q d(qi)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + */ +void SolverLove:: +compute_group_kl_att(const Mesh &mesh, + scmplx c, scmplx u,const scmplx *egn, + std::vector &frekl_u, + std::vector &frekl_q) const +{ + int ng = mesh.nglob_el; + Eigen::Map x(egn,ng); + Eigen::Map K(CKmat.data(),ng); + Eigen::Map M(Mmat.data(),ng); + + // resize kernels + int size = mesh.ibool_el.size(); + frekl_u.resize(5*size); // du_L/d(N/L/QN/QL/rho) + frekl_q.resize(5*size); // d(Qi_L)/d(N/L/QN/QL/rho) + + // allocate temp frekl + Eigen::Map f_u(frekl_u.data(),5*size),f_q(frekl_q.data(),5*size); + Eigen::ArrayXf ftemp_r(5*size),ftemp_i(5*size); + + // group velocity + // du / alpha = du/dc * dc/dalpha + float freq = mesh.freq; + float om = 2 * M_PI * freq; + scmplx k2 = om * om / (c * c); + scmplx xTKx = (x * K * x).sum(), xTMx = (x * M * x).sum(); + + // du_dx + Eigen::VectorXcf du_dx = 2.0f * K * x / (c * xTMx) - + 2.0f * xTKx/c * M * x / (xTMx * xTMx); + + // mapping Q,Z,S,Sp + Eigen::Map Q(cQmat_.data(),ng,ng); + Eigen::Map Z(cZmat_.data(),ng,ng); + Eigen::Map S(cSmat_.data(),ng,ng); + Eigen::Map Sp(cSpmat_.data(),ng,ng); + + // solve (A.H - conj(k)^2 B.H) lambda = conj(du_dx) + du_dx = Z.adjoint() * du_dx.conjugate(); + Eigen::MatrixXcf St = (S.adjoint() - std::conj(k2) * Sp.adjoint()); + Eigen::VectorXcf lamb = du_dx * 0.0f; + using Eigen::seq; + for(int i = 0; i < ng; i ++) { // forward substitution + scmplx s = (St(i,seq(0,i-1)) * lamb(seq(0,i-1))).sum(); + bool SMALL_DIAG = std::abs(St(i,i)) < 1.0e-12; + lamb[i] = SMALL_DIAG ? 0. : (du_dx[i] - s) / St(i,i); + } + lamb = Q * lamb; + + // make lambda orthogonal to left eigenvector + lamb = lamb.array() - (x.array() * lamb.array()).sum() * x.conjugate().eval(); + + // constant c12 + scmplx du_dalpha = -xTKx / (c*c * xTMx); + du_dalpha *= -0.5f * (c * c * c) / (om * om); + scmplx c12_conj = - (du_dalpha + (lamb.conjugate().array() * K * x).sum()) / xTKx; + + // M/K/E coefs + scmplx c_E = 1.; + scmplx c_M = -om * om; + scmplx c_K = k2; + + // - (lambda + c y) ^H (dA / dm_i - k^2 dB / dm) x + lamb = lamb.array() + std::conj(c12_conj) * x.conjugate(); + love_op_matrix( + freq,c_M,c_K,c_E,lamb.data(),x.data(),mesh.nspec_el, + mesh.nglob_el,mesh.ibool_el.data(), + mesh.jaco.data(),mesh.xN.data(),mesh.xL.data(), + mesh.xQN.data(),mesh.xQL.data(),frekl_u.data(), + frekl_q.data() + ); + + // (y) ^H (c_M dM / dm_i + c_K dK / dm) x + c_M = - xTKx / (c * xTMx * xTMx); + c_K = 1.0f/(c * xTMx); + c_E = 0.; + lamb = x.conjugate(); + love_op_matrix( + freq,c_M,c_K,c_E,lamb.data(),x.data(),mesh.nspec_el, + mesh.nglob_el,mesh.ibool_el.data(), + mesh.jaco.data(),mesh.xN.data(),mesh.xL.data(), + mesh.xQN.data(),mesh.xQL.data(),ftemp_r.data(), + ftemp_i.data() + ); + f_u += ftemp_r; f_q += ftemp_i; + + + // convert to u/Q kernels + get_fQ_kl(5*size,u,frekl_u.data(),frekl_q.data()); +} + +/** + * @brief compute love wave group velocity kernels, visco-elastic case + * @param mesh Mesh class + * @param c current complex phase velocity + * @param u current complex group velocity + * @param ur/ul right/left eigen function, shape(nglob_el*2+nglob_ac) + * @param frekl_u dRe(u)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + * @param frekl_q d(qi)/d(N/L/QN/QL/rho) shape(5,nspec*NGLL + NGRL) + */ +void SolverRayl:: +compute_group_kl_att(const Mesh &mesh, + scmplx c, scmplx u, + const scmplx *ur,const scmplx *ul, + std::vector &frekl_u, + std::vector &frekl_q) const +{ + int ng = mesh.nglob_el * 2 + mesh.nglob_ac; + typedef Eigen::Matrix cfmat2; + Eigen::Map x(ur,ng); + Eigen::Map y(ul,ng); + Eigen::Map K(CKmat.data(),ng,ng); + Eigen::Map M(CMmat.data(),ng); + + // resize kernels + int size = mesh.ibool.size(); + frekl_u.resize(10*size); // du_L/d(A/C/L/eta/Qa/Qc/QL/kappa/xQk/rho) + Eigen::Map f_u(frekl_u.data(),10*size), f_q(frekl_q.data(),10*size); + Eigen::ArrayXf f1_r(frekl_u.size()),f1_i(frekl_u.size()); + + // compute some coefs + // du / alpha = du/dc * dc/dalpha + float freq = mesh.freq; + float om = 2 * M_PI * freq; + float om_sq = om * om; + scmplx c_sq = c * c; + scmplx k2 = om_sq / c_sq; + scmplx yHKx = (y.matrix().adjoint() * K * x.matrix()).sum(); // y.H @ K @ x + scmplx yHMx = (y.conjugate() * M * x).sum(); // y.H @ M @ x + scmplx du_dalpha = -yHKx / (c*c * yHMx); + du_dalpha *= -0.5f * c / k2; + + // du_dx and du_dy* + Eigen::VectorXcf du_dx = K.transpose().matrix() * y.conjugate().matrix() / (c * yHMx) - + yHKx * (M * y.conjugate()).matrix() / (c * yHMx * yHMx); + Eigen::VectorXcf du_dys = K.matrix() * x.matrix() / (c * yHMx) - + yHKx * (M * x).matrix() / (c * yHMx * yHMx); + + // mapping Q,Z,S,Sp + Eigen::Map Q(cQmat_.data(),ng,ng); + Eigen::Map Z(cZmat_.data(),ng,ng); + Eigen::Map S(cSmat_.data(),ng,ng); + Eigen::Map Sp(cSpmat_.data(),ng,ng); + + // solve (A- k^2 B).T lam = du_dx + using Eigen::seq; + du_dx = Z.adjoint() * du_dx.matrix(); + Eigen::MatrixXcf P = (S - k2 * Sp).adjoint(); + Eigen::VectorXcf lamb = du_dx * 0.0f; + for(int i = 0; i < ng; i ++) { + // forward substitution + scmplx s = (P(i,seq(0,i-1)) * lamb(seq(0,i-1))).sum(); + bool SMALL_DIAG = std::abs(P(i,i)) < 1.0e-12; + lamb[i] = SMALL_DIAG ? 0 : (du_dx[i] - s) / P(i,i); + } + lamb = Q * lamb; + // make lambda orthogonal to left eigenvector + lamb = lamb.array() - (y.conjugate() * lamb.array()).sum() * y; + + // solve (A-k^2 B) xi = du_dy + P = S - k2 * Sp; + du_dys = Q.adjoint() * du_dys.matrix(); + Eigen::VectorXcf xi = du_dys * 0.0f; + for(int i = ng-1; i >=0; i --) { + scmplx s = (P(i,seq(i+1,ng-1)) * xi(seq(i+1,ng-1))).sum(); + bool SMALL_DIAG = std::abs(P(i,i)) < 1.0e-12; + xi[i] = SMALL_DIAG ? 0 : (du_dys[i] - s) / P(i,i); + } + xi = Z * xi; + // make xi orthogonal to right eigenvector + xi = xi.array() - (x.conjugate() * xi.array()).sum() * x; + + // c12 + scmplx c12 = du_dalpha + (lamb.matrix().adjoint() * K * x.matrix()).sum() + + (y.matrix().adjoint() * K * xi.matrix()).sum(); + c12 = -c12 / yHKx; + + // -((lamb + c12 y).T (dA /d_m - k^2 dB / dm) x) + lamb = lamb.array() + c12 * y; + scmplx c_M = -om * om; + scmplx c_E = 1., c_K = k2; + rayl_op_matrix( + freq,c_M,c_K,c_E,lamb.data(),x.data(),mesh.nspec_el,mesh.nspec_ac, + mesh.nspec_el_grl,mesh.nspec_ac_grl,mesh.nglob_el,mesh.nglob_ac, + mesh.el_elmnts.data(),mesh.ac_elmnts.data(), + mesh.ibool_el.data(),mesh.ibool_ac.data(), + mesh.jaco.data(),mesh.xrho_el.data(),mesh.xrho_ac.data(), + mesh.xA.data(),mesh.xC.data(),mesh.xL.data(), + mesh.xeta.data(),mesh.xQA.data(),mesh.xQC.data(), + mesh.xQL.data(),mesh.xkappa_ac.data(),mesh.xQk_ac.data(), + f_u.data(),f_q.data() + ); + + // -(y.T (dA /d_m - k^2 dB / dm) xi) + rayl_op_matrix( + freq,c_M,c_K,c_E,y.data(),xi.data(),mesh.nspec_el,mesh.nspec_ac, + mesh.nspec_el_grl,mesh.nspec_ac_grl,mesh.nglob_el,mesh.nglob_ac, + mesh.el_elmnts.data(),mesh.ac_elmnts.data(), + mesh.ibool_el.data(),mesh.ibool_ac.data(), + mesh.jaco.data(),mesh.xrho_el.data(),mesh.xrho_ac.data(), + mesh.xA.data(),mesh.xC.data(),mesh.xL.data(), + mesh.xeta.data(),mesh.xQA.data(),mesh.xQC.data(), + mesh.xQL.data(),mesh.xkappa_ac.data(),mesh.xQk_ac.data(), + f1_r.data(),f1_i.data() + ); + f_u += f1_r; f_q += f1_i; + + // df/dM and df/dC + c_M = -yHKx / (c * yHMx * yHMx); + c_E = 0.; + c_K = 1.0f / (c * yHMx); + rayl_op_matrix( + freq,c_M,c_K,c_E,y.data(),x.data(),mesh.nspec_el,mesh.nspec_ac, + mesh.nspec_el_grl,mesh.nspec_ac_grl,mesh.nglob_el,mesh.nglob_ac, + mesh.el_elmnts.data(),mesh.ac_elmnts.data(), + mesh.ibool_el.data(),mesh.ibool_ac.data(), + mesh.jaco.data(),mesh.xrho_el.data(),mesh.xrho_ac.data(), + mesh.xA.data(),mesh.xC.data(),mesh.xL.data(), + mesh.xeta.data(),mesh.xQA.data(),mesh.xQC.data(), + mesh.xQL.data(),mesh.xkappa_ac.data(),mesh.xQk_ac.data(), + f1_r.data(),f1_i.data() + ); + f_u += f1_r; f_q += f1_i; + + // get U/Q kernels + get_fQ_kl(10*size,u,frekl_u.data(),frekl_q.data()); +} + + +} // namespace specswd diff --git a/src/vti/frechet_op.hpp b/src/vti/frechet_op.hpp new file mode 100644 index 0000000..a898ac5 --- /dev/null +++ b/src/vti/frechet_op.hpp @@ -0,0 +1,606 @@ +#ifndef SPECSWD_FRECHET_OP_H_ +#define SPECSWD_FRECHET_OP_H_ + +/** + * @brief derivative operators: + * @note y.H @ (dA / dm - alpha dB / dm) @ x + */ + +#include "shared/attenuation.hpp" +#include "shared/GQTable.hpp" + +#define GET_REAL(dc_dm,loc) frekl_r[loc*size+id1] = dc_dm.real(); \ + frekl_i[loc*size+id1] = dc_dm.imag(); + +namespace specswd +{ + +/** + * @brief convert df_complx/dm to df_real/dm and dfQi_dm, where f_complx = f_real (1 + 0.5 i * fQi) = f_real + i f_imag + * @param npts size of frekl_r + * @param f_cmplx user defiend quantity + * @param frekl_r,frekl_i real/imag parts of derivatives + */ +void inline +get_fQ_kl(int npts,std::complex f_cmplx, + const float *frekl_r, + float *__restrict frekl_i) +{ + float f_real = f_cmplx.real(); + float f_imag = f_cmplx.imag(); + float fQi = 2. * f_imag / f_real; + + for(int ipt = 0; ipt < npts; ipt ++) { + float dQidm = (frekl_i[ipt] * 2. - fQi * frekl_r[ipt]) / f_real; + frekl_i[ipt] = dQidm; + } +} + +/** + * @brief compute y^H @ d(c_M * M + c_K * K + c_E * E )/dm_i @ x dm_i where + * @param c_M,c_K,c_E coefs for each matrix + * @param y,x vectors, shape_like(eigenvector) + * @param freq input data type, float or complex + * @param nspec_el no. of elastic GLL elements + * @param nglob_el unique points in elastic domain + * @param ibool_el connectivity matrix,in el shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param jaco jacobians, shape(nspec_ac+nspec_el+1) + * @param xN VTI N parameter, in el + * @param xL VTI L parameter, in el + * @param xQN VTI Qn parameter, in el + * @param xQL VTI Ql parameter, in el + * @param frekl_r,frekl_i real/imaginary parts of derivatives + */ +template void +love_op_matrix(float freq,T c_M, T c_K,T c_E, const T *y,const T *x, + int nspec_el,int nglob_el, const int *ibool_el, + const float *jaco, const float *xN, + const float *xL,const float *xQN, + const float *xQL,float * __restrict frekl_r, + float * __restrict frekl_i) +{ + // check template type + static_assert(std::is_same_v || std::is_same_v,T>); + + using namespace GQTable; + std::array rW,lW; + size_t size = nspec_el*NGLL + NGRL; + for(int ispec = 0; ispec < nspec_el + 1; ispec ++) { + int id = ispec * NGLL; + float J = jaco[ispec]; // jacobians in this layers + + const bool is_gll = (ispec != nspec_el); + const float *w = is_gll? wgll.data(): wgrl.data(); + const float *hp = is_gll? hprime.data(): hprime_grl.data(); + const int NGL = is_gll? NGLL : NGRL;; + + // cache displ in a element + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id+i]; + rW[i] = x[iglob]; + lW[i] = y[iglob]; + if constexpr (std::is_same_v>) { + lW[i] = std::conj(lW[i]); + } + } + + // compute kernels + T dc_drho{}, dc_dN{}, dc_dL{}; + T dc_dqni{}, dc_dqli{}; + T sn = 1., sl = 1.; + T dsdqni{}, dsdqli{}; + for(int m = 0; m < NGL; m ++) { + dc_drho = w[m] * J * rW[m] * lW[m] * c_M; + + // get sls derivative if required + if constexpr (std::is_same_v>) { + get_sls_Q_derivative(freq,xQN[id+m],sn,dsdqni); + get_sls_Q_derivative(freq,xQL[id+m],sl,dsdqli); + dsdqni *= xN[id+m]; + dsdqli *= xL[id+m]; + } + + // N kernel + T temp = rW[m] * lW[m] * J * w[m] * c_K; + dc_dN = temp * sn; + dc_dqni = temp * dsdqni; + + // L kernel + T sx{},sy{}; + for(int i = 0; i < NGL; i ++) { + sx += hp[m*NGL+i] * rW[i]; + sy += hp[m*NGL+i] * lW[i]; + } + temp = sx * sy * w[m] / J * c_E; + dc_dL = temp * sl; + dc_dqli = temp * dsdqli; + + // copy to frekl + int id1 = id + m; + if constexpr (std::is_same_v>) { + GET_REAL(dc_dN,0); GET_REAL(dc_dL,1); + GET_REAL(dc_dqni,2); GET_REAL(dc_dqli,3); + GET_REAL(dc_drho,4); + } + else { + frekl_r[0*size+id1] = dc_dN; + frekl_r[1*size+id1] = dc_dL; + frekl_r[2*size+id1] = dc_drho; + } + } + } +} + +/** + * @brief compute y^H @ d(c_M * M + c_K * K + c_E * E )/dm_i @ x dm_i where + * + * @tparam T data type, float or complex + * @param c_M,c_K,c_E coefs for each matrix + * @param y,x vectors, shape_like(eigenvector) + * @param freq input data type, float or complex + * @param nspec_el no. of elastic GLL elements + * @param nspec_ac no. of acoustic GLL elements + * @param nspec_el_grl no. of elastic GRL elements + * @param nspec_ac_grl no. of acoustic GRL elements + * @param nglob_el unique points in elastic domain + * @param nglob_ac unique points in acoustic domain + * @param el_elmnts mapping from el elements to global index + * @param ac_elmnts mapping from ac elements to global index + * @param xrho_el density in elastic domain + * @param xrho_ac density in acoustic domain + * @param ibool_el connectivity matrix,in el shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param ibool_ac connectivity matrix,in ac shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param jaco jacobians, shape(nspec_ac+nspec_el+1) + * @param xA VTI A parameter, in el + * @param xC VTI C parameter, in el + * @param xL VTI L parameter, in el + * @param xeta VTI eta parameter, in el + * @param xQA VTI Qa parameter, in el + * @param xQC VTI Qc parameter, in el + * @param xQL VTI Ql parameter, in el + * @param xkappa_ac kappa in ac domain + * @param xQk_ac Qkappa, in ac domain + * @param frekl_r,frekl_i real/imaginary parts of derivatives + */ +template +void +rayl_op_matrix(float freq,T c_M,T c_K, T c_E,const T *y, const T *x, + int nspec_el,int nspec_ac,int nspec_el_grl,int nspec_ac_grl,int nglob_el, + int nglob_ac, const int *el_elmnts,const int *ac_elmnts, + const int* ibool_el, const int* ibool_ac, + const float *jaco,const float *xrho_el,const float *xrho_ac, + const float *xA, const float *xC,const float *xL,const float *xeta, + const float *xQA, const float *xQC,const float *xQL, + const float *xkappa_ac, const float *xQk_ac, + float *__restrict frekl_r, + float *__restrict frekl_i) +{ + // check template type + static_assert(std::is_same_v || std::is_same_v,T>); + + // constants + using namespace GQTable; + size_t size = nspec_el * NGLL + nspec_el_grl * NGRL + + nspec_ac * NGLL + nspec_ac_grl * NGRL; + + // loop elastic elements + std::array U,V,lU,lV; //left/right eigenvectors in on element + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id = ispec * NGLL; + + // jacobian + float J = jaco[iel]; + + // get const arrays + const bool is_gll = (ispec != nspec_el); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hp = is_gll? hprime.data(): hprime_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // cache U,V and lU,lV + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id + i]; + U[i] = x[iglob]; + V[i] = x[iglob + nglob_el]; + lU[i] = y[iglob]; + lV[i] = y[iglob + nglob_el]; + if constexpr (std::is_same_v>) { + lU[i] = std::conj(lU[i]); + lV[i] = std::conj(lV[i]); + } + } + + // compute kernel + T dc_drho{}, dc_dA{}, dc_dC{}, dc_dL{}; + T dc_deta{}, dc_dQci{},dc_dQai{},dc_dQli{}; + const T two = 2.; + for(int m = 0; m < NGL; m ++) { + T temp = weight[m] * J * c_M; + dc_drho = temp * (U[m] * lU[m] + V[m] * lV[m]); + + // get sls factor if required + T sa = 1.,sl = 1.,sc = 1.; + T dsdqai{},dsdqci{},dsdqli{}; + T C = xC[id+m], A = xA[id+m], L = xL[id+m], eta = xeta[m]; + if constexpr (std::is_same_v>) { + get_sls_Q_derivative(freq,xQA[id+m],sa,dsdqai); + get_sls_Q_derivative(freq,xQC[id+m],sc,dsdqci); + get_sls_Q_derivative(freq,xQL[id+m],sl,dsdqli); + dsdqai *= A; + dsdqci *= C; + dsdqli *= L; + } + + // K matrix + // dc_dA + temp = weight[m] * J * U[m] * lU[m] * c_K; + dc_dA = temp * sa; dc_dQai = temp * dsdqai; + + // dc_dL + temp = weight[m] * J * V[m] * lV[m] * c_K; + dc_dL = temp * sl; dc_dQli = temp * dsdqli; + + // Ematrix + T sx{},sy{},lsx{},lsy{}; + for(int i = 0; i < NGL; i ++) { + sx += hp[m*NGL+i] * U[i]; + sy += hp[m*NGL+i] * V[i]; + lsx += hp[m*NGL+i] * lU[i]; + lsy += hp[m*NGL+i] * lV[i]; + } + + // E1 + temp = weight[m] / J * sx * lsx * c_E; + dc_dL += temp * sl; dc_dQli += temp * dsdqli; + + // E3 + temp = weight[m] / J * sy * lsy * c_E; + dc_dC = temp * sc; dc_dQci = temp * dsdqci; + + // K2, d / dm_k sum_{ij} w_j F_j hpT(i,j) U_j lV_i + // = \sum_{i} w_k dF/dm_k hpT(i,k) U_k lV_i = lsy * w_k * U_k * dF/dm_k + temp = weight[m] * U[m] * lsy * c_K; + dc_deta = temp * (A*sa - two*L*sl); + temp *= eta; + dc_dA += temp * sa; dc_dQai += temp * dsdqai; + dc_dL += - temp * two * sl; dc_dQli += -temp * two * dsdqli; + + // K2, -d / dm_k sum_{ij} w_i L_i hp(i,j) U_j lV_i + // = - \sum_{j} w_k dL/dm_k hp(j,k) U_j lV_k = -sx * w_k * lV_k dL/dm_k + temp = -weight[m] * lV[m] * sx * c_K; + dc_dL += - temp * two * sl; dc_dQli += -temp * two * dsdqli; + + //E2 \sum_{j} w_k dF/dm_k hp(j,k) V_j lU_k = -sx * w_k * lV_k dF/dm_k + temp = weight[m] * lU[m] * sy * c_E; + dc_deta = temp * (A*sa - two*L*sl); + temp *= eta; + dc_dA += temp * sa; dc_dQai += temp * dsdqai; + dc_dL += - temp * two * sl; dc_dQli += -temp * two * dsdqli; + + // E2 -lsx * w_k * V_k * dL/dm_k + temp = -weight[m] * V[m] * lsx * c_E; + dc_dL += - temp * two * sl; dc_dQli += -temp * two * dsdqli; + + // copy them to frekl + int id1 = iel * NGLL + m; + if constexpr (std::is_same_v) { + frekl_r[0*size+id1] = dc_dA; + frekl_r[1*size+id1] = dc_dC; + frekl_r[2*size+id1] = dc_dL; + frekl_r[3*size+id1] = dc_deta; + frekl_r[5*size+id1] = dc_drho; + } + else { + GET_REAL(dc_dA,0); + GET_REAL(dc_dC,1); + GET_REAL(dc_dL,2); + GET_REAL(dc_deta,3); + GET_REAL(dc_dQai,4); + GET_REAL(dc_dQci,5); + GET_REAL(dc_dQli,6); + GET_REAL(dc_drho,9); + } + } + } + + // acoustic eleemnts + std::array chi,lchi; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { + int iel = ac_elmnts[ispec]; + int id = ispec * NGLL; + + // const arrays + const bool is_gll = (ispec != nspec_ac); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hp = is_gll? hprime.data(): hprime_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // jacobians + float J = jaco[iel]; + + // cache chi and lchi in one element + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_ac[id + i]; + chi[i] = (iglob == -1) ? 0: x[iglob+nglob_el*2]; + lchi[i] = (iglob == -1) ? 0.: y[iglob+nglob_el*2]; + if constexpr (std::is_same_v>) { + lchi[i] = std::conj(lchi[i]); + } + } + + // derivatives + T dc_dkappa{},dc_drho{}, dc_dqki{}; + T sk = 1., dskdqi = 0.; + for(int m = 0; m < NGL; m ++ ){ + // copy material + float rho = xrho_ac[id+m]; + float kappa = xkappa_ac[id+m]; + if constexpr (std::is_same_v>) { + get_sls_Q_derivative(freq,xQk_ac[id+m],sk,dskdqi); + dskdqi *= kappa; + } + + // kappa kernel + T temp = -c_M * weight[m]* J*chi[m] * lchi[m] / (sk * kappa) / (sk * kappa); + dc_dkappa = temp * sk; + dc_dqki = temp * dskdqi; + + dc_drho = - c_K * weight[m]* J * chi[m] * lchi[m] / rho / rho; + + T sx{},sy{}; + for(int i = 0; i < NGL; i ++) { + sx += hp[m*NGL+i] * chi[i]; + sy += hp[m*NGL+i] * lchi[i]; + } + dc_drho += -c_E * weight[m] / J / (rho*rho) * sx * sy; + + // copy to frekl + int id1 = iel * NGLL + m; + if constexpr (std::is_same_v) { + frekl_r[4*size+id1] = dc_dkappa; + frekl_r[5*size+id1] = dc_drho; + } + else { + GET_REAL(dc_dkappa,7); + GET_REAL(dc_dqki,8); + GET_REAL(dc_drho,9); + } + } + } +} + +// /** +// * @brief compute coef * y^dag @ d( (w^2 M -E) - k^2 K)/dm_i @ x dm_i +// * @param freq current frequency +// * @param c current phase velocity +// * @param coef derivative scaling coefs +// * @param y/x dot vector,shape(nglob_el*2+nglob_ac) +// * @param nspec_el/nglob_el mesh nelemnts/unique points for elastic +// * @param nspec_ac/nglob_ac mesh nelemnts/unique points for acoustic +// * @param nspec_el/ac_grl no. of GRL elements +// * @param ibool_el elastic connectivity matrix, shape(nspec_el*NGLL+nspec_el_grl*NGRL) +// * @param ibool_ac elastic connectivity matrix, shape(nspec_ac*NGLL+nspec_ac_grl*NGRL) +// * @param jaco jacobian matrix, shape (nspec_el + 1) +// * @param xA/xC/xL/xeta/xQA/xQC/xQL/xrho elastic model parameters,ibool_el.shape +// * @param xkappa_ac/xQk_ac/xrho_ac acoustic model parameters, ibool_ac.shape +// * @param frekl_r dc/d(A/C/L/kappa/rho) (elastic) or dc/d(A/C/L/QA/QC/QL/kappa/Qk/rho) (anelstic) +// * @param frekl_i nullptr or dqc/d(A/C/L/QA/QC/QL/kappa/Qk/rho) (anelstic) +// * @note frekl_r and frekl_i should be set to 0 before calling this routine +// */ +// template +// void +// rayl_deriv_op(float freq,T c,T coef,const T *y, const T *x, +// int nspec_el,int nspec_ac,int nspec_el_grl,int nspec_ac_grl,int nglob_el, +// int nglob_ac, const int *el_elmnts,const int *ac_elmnts, +// const int* ibool_el, const int* ibool_ac, +// const float *jaco,const float *xrho_el,const float *xrho_ac, +// const float *xA, const float *xC,const float *xL,const float *xeta, +// const float *xQA, const float *xQC,const float *xQL, +// const float *xkappa_ac, const float *xQk_ac, +// float *__restrict frekl_r, +// float *__restrict frekl_i) +// { +// // check template type +// static_assert(std::is_same_v || std::is_same_v,T>); + +// // constants +// using namespace GQTable; +// size_t size = nspec_el * NGLL + nspec_el_grl * NGRL + +// nspec_ac * NGLL + nspec_ac_grl * NGRL; +// T om = 2 * M_PI * freq; +// T k2 = std::pow(om / c,2); + +// // loop elastic elements +// std::array U,V,lU,lV; +// for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { +// int iel = el_elmnts[ispec]; +// int id = ispec * NGLL; + +// const float *weight = wgll.data(); +// const float *hp = hprime.data(); +// int NGL = NGLL; + +// // jacobian +// float J = jaco[iel]; + +// // grl case +// if(ispec == nspec_el) { +// weight = wgrl.data(); +// hp = hprime_grl.data(); +// NGL = NGRL; +// } + +// // cache U,V and lU,lV +// for(int i = 0; i < NGL; i ++) { +// int iglob = ibool_el[id + i]; +// U[i] = x[iglob] * coef; +// V[i] = x[iglob + nglob_el] * coef; +// lU[i] = y[iglob]; +// lV[i] = y[iglob + nglob_el]; +// if constexpr (std::is_same_v>) { +// lU[i] = std::conj(lU[i]); +// lV[i] = std::conj(lV[i]); +// } +// } + +// // compute kernel +// T dc_drho{}, dc_dA{}, dc_dC{}, dc_dL{}; +// T dc_deta{}, dc_dQci{},dc_dQai{},dc_dQli{}; +// const T two = 2.; +// for(int m = 0; m < NGL; m ++) { +// T temp = weight[m] * J; +// dc_drho = temp * om * om * +// (U[m] * lU[m] + V[m] * lV[m]); + +// // get sls factor if required +// T sa = 1.,sl = 1.,sc = 1.; +// T dsdqai{},dsdqci{},dsdqli{}; +// float C = xC[id+m], A = xA[id+m], +// L = xL[id+m], eta = xeta[m]; +// if constexpr (std::is_same_v>) { +// get_sls_Q_derivative(freq,xQA[id+m],sa,dsdqai); +// get_sls_Q_derivative(freq,xQC[id+m],sc,dsdqai); +// get_sls_Q_derivative(freq,xQL[id+m],sl,dsdqai); +// dsdqai *= A; +// dsdqci *= C; +// dsdqli *= L; +// } + +// // K matrix +// // dc_dA +// temp = -weight[m] * J * k2 * U[m] * lU[m]; +// dc_dA = temp * sa; dc_dQai = temp * dsdqai; + +// // dc_dL +// temp = -weight[m] * J * k2 * V[m] * lV[m]; +// dc_dL = temp * sl; dc_dQli = temp * dsdqli; + +// // Ematrix +// T sx{},sy{},lsx{},lsy{}; +// for(int i = 0; i < NGL; i ++) { +// sx += hp[m*NGL+i] * U[i]; +// sy += hp[m*NGL+i] * V[i]; +// lsx += hp[m*NGL+i] * lU[i]; +// lsy += hp[m*NGL+i] * lV[i]; +// } +// temp = -weight[m] / J * sx * lsx; +// dc_dL += temp * sl; dc_dQli += temp * dsdqli; + +// temp = - weight[m] / J * sy * lsy; +// dc_dC = temp * sc; dc_dQci = temp * dsdqci; + +// // eta +// temp = - (k2 * weight[m] * U[m] * lsy + +// weight[m] * lU[m] * sy); +// dc_deta = temp * (A*sa - two*L*sl); + +// temp *= eta; +// dc_dA += temp * sa; dc_dQai += temp * dsdqai; +// dc_dL += - temp * two * sl; dc_dQli += -temp * two * dsdqli; + +// temp = k2 * weight[m] * lV[m] * sx + weight[m] * V[m] * lsx; +// temp *= coef; +// dc_dL += temp * sl; +// dc_dQli += temp * dsdqli; + +// // copy them to frekl +// int id1 = iel * NGLL + m; +// if constexpr (std::is_same_v) { +// frekl_r[0*size+id1] = dc_dA; +// frekl_r[1*size+id1] = dc_dC; +// frekl_r[2*size+id1] = dc_dL; +// frekl_r[3*size+id1] = dc_deta; +// frekl_r[5*size+id1] = dc_drho; +// } +// else { +// GET_REAL(dc_dA,0); +// GET_REAL(dc_dC,1); +// GET_REAL(dc_dL,2); +// GET_REAL(dc_deta,3); +// GET_REAL(dc_dQai,4); +// GET_REAL(dc_dQci,5); +// GET_REAL(dc_dQli,6); +// GET_REAL(dc_drho,9); +// } +// } +// } + +// // acoustic eleemnts +// std::array chi,lchi; +// for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { +// int iel = ac_elmnts[ispec]; +// int id = ispec * NGLL; +// const float *weight = wgll.data(); +// const float *hp = hprime.data(); +// int NGL = NGLL; + +// // jacobians +// float J = jaco[iel]; + +// // grl case +// if(ispec == nspec_ac) { +// weight = wgrl.data(); +// hp = hprime_grl.data(); +// NGL = NGRL; +// } + +// // cache chi and lchi in one element +// for(int i = 0; i < NGL; i ++) { +// int iglob = ibool_ac[id + i]; +// chi[i] = (iglob == -1) ? 0: x[iglob+nglob_el*2] * coef; +// lchi[i] = (iglob == -1) ? 0.: y[iglob+nglob_el*2]; +// if constexpr (std::is_same_v>) { +// lchi[i] = std::conj(lchi[i]); +// } +// } + +// // derivatives +// T dc_dkappa{},dc_drho{}, dc_dqki{}; +// T sk = 1., dskdqi = 0.; +// for(int m = 0; m < NGL; m ++ ){ +// // copy material +// float rho = xrho_ac[id+m]; +// float kappa = xkappa_ac[id+m]; +// if constexpr (std::is_same_v>) { +// get_sls_Q_derivative(freq,xQk_ac[id+m],sk,dskdqi); +// dskdqi *= kappa; +// } + +// // kappa kernel +// T temp = std::pow(om/(sk * kappa),2) *weight[m]* J* +// chi[m] * lchi[m]; +// dc_dkappa = temp * sk; +// dc_dqki = temp * dskdqi; + +// dc_drho = -k2 * std::pow(om/rho,2) *weight[m]* J* +// chi[m] * lchi[m]; + +// T sx{},sy{}; +// for(int i = 0; i < NGL; i ++) { +// sx += hp[m*NGL+i] * chi[i]; +// sy += hp[m*NGL+i] * lchi[i]; +// } +// dc_drho += weight[m] / J / (rho*rho) * sx * sy; + +// // copy to frekl +// int id1 = iel * NGLL + m; +// if constexpr (std::is_same_v) { +// frekl_r[4*size+id1] = dc_dkappa; +// frekl_r[5*size+id1] = dc_drho; +// } +// else { +// GET_REAL(dc_dkappa,7); +// GET_REAL(dc_dqki,8); +// GET_REAL(dc_drho,9); +// } +// } +// } +// } + + +} // namespace specswd + +#undef GET_REAL + +#endif \ No newline at end of file diff --git a/src/vti/group_velocity.cpp b/src/vti/group_velocity.cpp new file mode 100644 index 0000000..a20d2bd --- /dev/null +++ b/src/vti/group_velocity.cpp @@ -0,0 +1,86 @@ +#include "vti/vti.hpp" + +#include + +namespace specswd +{ + +template T +get_love_group_vel(int ng,float freq, + T c, const T *egn, + const float *Mmat, + const T *Kmat) +{ + Eigen::Map> x(egn,ng); + Eigen::Map> K(Kmat,ng); + Eigen::Map> M(Mmat,ng); + + T u = (x * K * x).sum() / (c * (x * M * x).sum()); + + return u; +} + +/** + * @brief compute velocity of love wave, elastic case + */ +float SolverLove:: +group_vel(const Mesh &M, + float c,const float *egn) const +{ + return get_love_group_vel(M.nglob_el,M.freq,c,egn,Mmat.data(),Kmat.data()); +} + +/** + * @brief compute velocity of love wave, anelastic case + */ +scmplx SolverLove:: +group_vel_att(const Mesh &M, + scmplx c,const scmplx *egn) const +{ + return get_love_group_vel(M.nglob_el,M.freq,c,egn,Mmat.data(),CKmat.data()); +} + + +template T +get_rayl_group_vel(int ng,float freq, + T c, const T *ur,const T *ul, + const T *Mmat, + const T *Kmat) +{ + typedef Eigen::Matrix mat2; + Eigen::Map> x(ur,ng),y(ul,ng); + Eigen::Map K(Kmat,ng,ng); + Eigen::Map> M(Mmat,ng); + + T u_nume = (y.adjoint() * K * x); + T u_deno = c* y.adjoint() * M.asDiagonal() * x; + T u = u_nume / u_deno; + + return u; +} + +/** + * @brief compute velocity of love wave, elastic case + */ +float SolverRayl:: +group_vel(const Mesh &M, + float c,const float *ur, + const float *ul) const +{ + int ng = M.nglob_el*2 + M.nglob_ac; + return get_rayl_group_vel(ng,M.freq,c,ur,ul,Mmat.data(),Kmat.data()); +} + +/** + * @brief compute velocity of love wave, visco-elastic case + */ +scmplx SolverRayl:: +group_vel_att(const Mesh &M, + scmplx c,const scmplx *ur, + const scmplx *ul) const +{ + int ng = M.nglob_el*2 + M.nglob_ac; + return get_rayl_group_vel(ng,M.freq,c,ur,ul,CMmat.data(),CKmat.data()); +} + +} // namespace specswd diff --git a/src/vti/main_love.cpp b/src/vti/main_love.cpp new file mode 100644 index 0000000..0c03ff9 --- /dev/null +++ b/src/vti/main_love.cpp @@ -0,0 +1,219 @@ +#include "vti/vti.hpp" +#include "shared/iofunc.hpp" +#include "shared/GQTable.hpp" + +#include +#include +#include + + +int main (int argc, char **argv){ + // read model name + if(argc != 5 && argc != 6) { + printf("Usage: ./surflove modelfile f1 f2 nt [KERNEL_TYPE = 0]\n"); + printf("freqs = logspace(log10(f1),log10(f2),nt)\n"); + exit(1); + } + + // initialize GLL + GQTable:: initialize(); + + // read mesh + const char *filename = argv[1]; + specswd::Mesh mesh; + mesh.read_model(filename); + mesh.create_model_attributes(); + int nz = mesh.nz_tomo; + + // check if it's love wave + if(mesh.SWD_TYPE != 0) { + printf("THis module can only handle love wave!\n"); + exit(1); + } + + // print info to debug + mesh.print_model(); + + // Period + int nt; + float f1,f2; + sscanf(argv[2],"%g",&f1); sscanf(argv[3],"%g",&f2); + sscanf(argv[4],"%d",&nt); + f1 = std::log10(f1); f2 = std::log10(f2); + if(f1 > f2) std::swap(f1,f2); + std::vector freq(nt); + for(int it = 0; it < nt; it ++) { + double coef = (nt - 1); + if(coef == 0.) coef = 1.; + coef = 1. / coef; + double f = f1 + (f2 - f1) * coef * it; + freq[it] = std::pow(10,f); + } + + int KERNEL_TYPE = 1; + if(argc == 6) { + sscanf(argv[5],"%d",&KERNEL_TYPE); + } + + // create output dir + if(!std::filesystem::exists("out/")) + std::filesystem::create_directory("out/"); + + // open file to write out meta data + FILE *fp = fopen("out/swd.txt","w"); + FILE *fio = fopen("out/database.bin","wb"); + for(int it = 0; it < nt; it ++) { + fprintf(fp,"%g ",1. / freq[it]); + } + fprintf(fp,"\n"); + + // write meta data int database + using specswd::write_binary_f; + int nkers = 3,ncomp = 1; + write_binary_f(fio,&mesh.SWD_TYPE,1); + write_binary_f(fio,&mesh.HAS_ATT,1); + if(mesh.HAS_ATT) { + nkers = 5; + } + write_binary_f(fio,&nz,1); + write_binary_f(fio,&nkers,1); + write_binary_f(fio,&ncomp,1); + + // initialize solver + std::unique_ptr sol(new specswd::SolverLove); + + // compute phase velocity for each frequency + for(int it = 0; it < nt; it ++) { + // create database + mesh.create_database(freq[it],0.); + + // write coordinates + write_binary_f(fio,mesh.znodes.data(),mesh.znodes.size()); + + // get database dimension + int ng = mesh.nglob_el; + + // prepare all matrices + sol -> prepare_matrices(mesh); + + if(!mesh.HAS_ATT) { + std::vector c,egn,u,frekl; + std::vector frekl_tomo; + std::vector displ; + + // compute eigenvalue + sol -> compute_egn(mesh,c,egn,true); + + // allocate group velocity + int nc = c.size(); + u.resize(nc); + + for(int ic = 0; ic < nc; ic ++) { + u[ic] = sol -> group_vel(mesh,c[ic],&egn[ic*ng]); + switch (KERNEL_TYPE) { + case 0: + sol -> compute_phase_kl( + mesh,c[ic], + &egn[ic*ng],frekl + ); + break; + case 1: + sol -> compute_group_kl( + mesh,c[ic], + &egn[ic*ng],frekl + ); + break; + default: { + printf("KERNEL_TYPE = %d is not implemented!\n",KERNEL_TYPE); + exit(1); + break; + } + } + + // write T,c,u,mode + fprintf(fp,"%d %g %g %d\n",it,c[ic],u[ic],ic); + + // write displ + displ.resize(mesh.ibool_el.size()); + sol->egn2displ(mesh,c[ic],&egn[ic*ng],displ.data()); + write_binary_f(fio,displ.data(),displ.size()); + + // transform kernels + sol -> transform_kernels(mesh,frekl); + frekl_tomo.resize(nkers*nz); + int npts = mesh.ibool_el.size(); + for(int iker = 0; iker < nkers; iker ++) { + mesh.project_kl(&frekl[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + } + } + else { + using specswd::scmplx; + std::vector c,egn,legn,u; + std::vector frekl_c,frekl_q; + std::vector frekl_tomo; + std::vector displ; + + // compute eigenvalues + sol -> compute_egn_att(mesh,c,egn,true); + + // allocate group velocity + int nc = c.size(); + u.resize(nc); + + for(int ic = 0; ic < nc; ic ++) { + u[ic] = sol -> group_vel_att(mesh,c[ic],&egn[ic*ng]); + switch (KERNEL_TYPE) { + case 0: + sol -> compute_phase_kl_att ( + mesh,c[ic], + &egn[ic*ng],frekl_c,frekl_q + ); + break; + case 1: + sol -> compute_group_kl_att( + mesh,c[ic],u[ic], + &egn[ic*ng],frekl_c,frekl_q + ); + break; + default: { + printf("KERNEL_TYPE = %d is not implemented!\n",KERNEL_TYPE); + exit(1); + break; + } + } + + // write T,c,u,mode + fprintf(fp,"%d %g %g %g %g %d\n",it,c[ic].real(),u[ic].real(), + c[ic].imag(),u[ic].imag(),ic); + + // write displ + displ.resize(mesh.ibool_el.size()); + sol -> egn2displ_att(mesh,c[ic],&egn[ic*ng],displ.data()); + write_binary_f(fio,displ.data(),displ.size()); + + // write kernels + sol->transform_kernels(mesh,frekl_c); + sol->transform_kernels(mesh,frekl_q); + frekl_tomo.resize(nkers*nz); + int npts = mesh.ibool_el.size(); + for(int iker = 0; iker < nkers; iker ++) { + mesh.project_kl(&frekl_c[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + + for(int iker = 0; iker < nkers; iker ++) { + mesh.project_kl(&frekl_q[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + } + } + } + + // close file + fclose(fio); + fclose(fp); + + return 0; +} \ No newline at end of file diff --git a/src/vti/main_rayl.cpp b/src/vti/main_rayl.cpp new file mode 100644 index 0000000..111c4f9 --- /dev/null +++ b/src/vti/main_rayl.cpp @@ -0,0 +1,222 @@ +#include "vti/vti.hpp" +#include "shared/iofunc.hpp" +#include "shared/GQTable.hpp" + +#include +#include +#include + + +int main (int argc, char **argv){ + // read model name + if(argc != 5 && argc != 6) { + printf("Usage: ./surfrayl modelfile f1 f2 nt [KERNEL_TYPE = 0]\n"); + printf("freqs = logspace(log10(f1),log10(f2),nt)\n"); + exit(1); + } + + // initialize GLL + GQTable:: initialize(); + + // read mesh + const char *filename = argv[1]; + specswd::Mesh mesh; + mesh.read_model(filename); + mesh.create_model_attributes(); + int nz = mesh.nz_tomo; + + // check if it's Rayleigh wave + if(mesh.SWD_TYPE != 1) { + printf("THis module can only handle Rayleigh wave!\n"); + exit(1); + } + + // print info to debug + mesh.print_model(); + + // Period + int nt; + float f1,f2; + sscanf(argv[2],"%g",&f1); sscanf(argv[3],"%g",&f2); + sscanf(argv[4],"%d",&nt); + f1 = std::log10(f1); f2 = std::log10(f2); + if(f1 > f2) std::swap(f1,f2); + std::vector freq(nt); + for(int it = 0; it < nt; it ++) { + double coef = (nt - 1); + coef = coef == 0 ? 1: coef; + coef = 1. / coef; + double f = f1 + (f2 - f1) * coef * it; + freq[it] = std::pow(10,f); + } + + int KERNEL_TYPE = 0; + if(argc == 6) { + sscanf(argv[5],"%d",&KERNEL_TYPE); + } + + // create output dir + if(!std::filesystem::exists("out/")) + std::filesystem::create_directory("out/"); + + // open file to write out meta data + FILE *fp = fopen("out/swd.txt","w"); + FILE *fio = fopen("out/database.bin","wb"); + for(int it = 0; it < nt; it ++) { + fprintf(fp,"%g ",1. / freq[it]); + } + fprintf(fp,"\n"); + + // write meta data int database + using specswd::write_binary_f; + int nkers = 5,ncomp = 2; + write_binary_f(fio,&mesh.SWD_TYPE,1); + write_binary_f(fio,&mesh.HAS_ATT,1); + if(mesh.HAS_ATT) { + nkers = 10; + } + write_binary_f(fio,&nz,1); + write_binary_f(fio,&nkers,1); + write_binary_f(fio,&ncomp,1); + + // initialize solver + std::unique_ptr sol(new specswd::SolverRayl); + + // compute phase velocity for each frequency + for(int it = 0; it < nt; it ++) { + // create database + mesh.create_database(freq[it],0.); + + // write coordinates + write_binary_f(fio,mesh.znodes.data(),mesh.znodes.size()); + + // get database dimension + int ng = mesh.nglob_el * 2 + mesh.nglob_ac; + + // prepare all matrices + sol -> prepare_matrices(mesh); + + if(!mesh.HAS_ATT) { + std::vector c,ur,ul,u,frekl; + std::vector frekl_tomo; + std::vector displ; + + // compute eigenvalue + sol -> compute_egn(mesh,c,ur,ul,true); + + // allocate group velocity + int nc = c.size(); + u.resize(nc); + + for(int ic = 0; ic < nc; ic ++) { + u[ic] = sol -> group_vel(mesh,c[ic],&ur[ic*ng],&ul[ic*ng]); + switch (KERNEL_TYPE) { + case 0: + sol -> compute_phase_kl( + mesh,c[ic],&ur[ic*ng], + &ul[ic*ng],frekl + ); + break; + case 1: + sol -> compute_group_kl( + mesh,c[ic],&ur[ic*ng], + &ul[ic*ng],frekl + ); + break; + default: { + printf("KERNEL_TYPE = %d is not implemented!\n",KERNEL_TYPE); + exit(1); + break; + } + } + + // write T,c,u,mode + fprintf(fp,"%d %g %g %d\n",it,c[ic],u[ic],ic); + + // write displ + int npts = mesh.ibool.size(); + displ.resize(npts*ncomp); + sol->egn2displ(mesh,c[ic],&ur[ic*ng],displ.data()); + write_binary_f(fio,displ.data(),displ.size()); + + // transform kernels + sol -> transform_kernels(mesh,frekl); + frekl_tomo.resize(nkers*nz); + + for(int iker = 0; iker < nkers; iker ++) { + mesh.project_kl(&frekl[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + } + } + else { + using specswd::scmplx; + std::vector c,ur,ul,u; + std::vector frekl_c,frekl_q; + std::vector frekl_tomo; + std::vector displ; + + // compute eigenvalues + sol -> compute_egn_att(mesh,c,ur,ul,true); + + // allocate group velocity + int nc = c.size(); + u.resize(nc); + + for(int ic = 0; ic < nc; ic ++) { + u[ic] = sol -> group_vel_att(mesh,c[ic],&ur[ic*ng],&ul[ic*ng]); + switch (KERNEL_TYPE) { + case 0: + sol -> compute_phase_kl_att ( + mesh,c[ic],&ur[ic*ng], + &ul[ic*ng], + frekl_c,frekl_q + ); + break; + case 1: + sol -> compute_group_kl_att( + mesh,c[ic],u[ic], + &ur[ic*ng],&ul[ic*ng], + frekl_c,frekl_q + ); + break; + default: { + printf("KERNEL_TYPE = %d is not implemented!\n",KERNEL_TYPE); + exit(1); + break; + } + } + + // write T,c,u,mode + fprintf(fp,"%d %g %g %g %g %d\n",it,c[ic].real(),u[ic].real(), + c[ic].imag(),u[ic].imag(),ic); + + // write displ + int npts = mesh.ibool.size(); + displ.resize(npts * 2); + sol -> egn2displ_att(mesh,c[ic],&ur[ic*ng],displ.data()); + write_binary_f(fio,displ.data(),displ.size()); + + // write kernels + sol -> transform_kernels(mesh,frekl_c); + sol -> transform_kernels(mesh,frekl_q); + frekl_tomo.resize(nkers*nz); + for(int iker = 0; iker < nkers; iker ++) { + mesh.project_kl(&frekl_c[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + + for(int iker = 0; iker < nkers; iker ++) { + mesh.project_kl(&frekl_q[iker*npts],&frekl_tomo[iker*nz]); + } + write_binary_f(fio,frekl_tomo.data(),frekl_tomo.size()); + } + } + } + + // close file + fclose(fio); + fclose(fp); + + return 0; +} \ No newline at end of file diff --git a/src/vti/sem.cpp b/src/vti/sem.cpp new file mode 100644 index 0000000..7368be7 --- /dev/null +++ b/src/vti/sem.cpp @@ -0,0 +1,337 @@ +#include "vti/vti.hpp" +#include "shared/GQTable.hpp" +#include "shared/attenuation.hpp" + +using std::vector; + +namespace specswd +{ + +/** + * @brief prepare M/K/E matrices for Love wave + * @tparam T input data type, float or complex + * @param freq current frequency + * @param nspec # of elastic GLL elements + * @param nglob_el unique points in elastic domain + * @param ibool_el connectivity matrix, shape(nspec*NGLL+NGRL) + * @param jaco jacobians, shape(nspec+1) + * @param xL/xN/xQL/xQN/xrho L/N/QL/QN/rho shape(nspec*NGLL+NGRL) + * @param Mmat/Kmat/Emat M/K/E matrices + */ +template +static void +prepare_love_(float freq,int nspec,int nglob_el,const float *xrho, + const int* ibool_el,const float *jaco,const float *xL, + const float *xN,const float *xQL,const float *xQN, + vector &Mmat,vector &Kmat,vector &Emat) +{ + using namespace GQTable; + std::array sum_terms; + + // allocate space and set zero + int nglob = nglob_el; + Mmat.resize(nglob); Kmat.resize(nglob); + Emat.resize(nglob*nglob); + std::fill(Mmat.begin(),Mmat.end(),0.); + std::fill(Kmat.begin(),Kmat.end(),(T)0); + std::fill(Emat.begin(),Emat.end(),(T)0); + + for(int ispec = 0; ispec < nspec + 1; ispec ++) { + int id = ispec * NGLL; + const bool is_gll = (ispec != nspec); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hpT = is_gll? hprimeT.data(): hprimeT_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + T sl = 1.; + if constexpr (std::is_same_v) { + sl = get_sls_modulus_factor(freq,xQL[id+i]); + } + sum_terms[i] = xL[id + i] * sl * weight[i] / jaco[ispec]; + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id + i]; + + float temp = weight[i] * jaco[ispec]; + T sn = 1.; + if constexpr(std::is_same_v) { + sn = get_sls_modulus_factor(freq,xQN[id+i]); + } + Mmat[iglob] += temp * xrho[id + i]; + Kmat[iglob] += temp * xN[id + i] * sn; + + for(int j = 0; j < NGL; j ++) { + int iglob1 = ibool_el[id + j]; + T s{}; + for(int m = 0; m < NGL; m ++) { + s += sum_terms[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * nglob + iglob1] += s; + } + } + } +} + +/** + * @brief prepare M/K/E matrices for Love wave, an/elastic case + * + */ +void SolverLove::prepare_matrices(const Mesh &M) +{ + if(!M.HAS_ATT) { + prepare_love_(M.freq,M.nspec_el,M.nglob_el,M.xrho_el.data(), + M.ibool_el.data(),M.jaco.data(),M.xL.data(), + M.xN.data(),nullptr,nullptr,Mmat,Kmat,Emat); + } + else { + prepare_love_(M.freq,M.nspec_el,M.nglob_el,M.xrho_el.data(), + M.ibool_el.data(),M.jaco.data(),M.xL.data(), + M.xN.data(),M.xQL.data(),M.xQN.data(), + Mmat,CKmat,CEmat); + } +} + +/** + * @brief prepare M/K/E matrices for Love wave + * + * @tparam T + * @param freq input data type, float or complex + * @param nspec_el no. of elastic GLL elements + * @param nspec_ac no. of acoustic GLL elements + * @param nspec_el_grl no. of elastic GRL elements + * @param nspec_ac_grl no. of acoustic GRL elements + * @param nglob_el unique points in elastic domain + * @param nglob_ac unique points in acoustic domain + * @param el_elmnts mapping from el elements to global index + * @param ac_elmnts mapping from ac elements to global index + * @param xrho_el density in elastic domain + * @param xrho_ac density in acoustic domain + * @param ibool_el connectivity matrix,in el shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param ibool_ac connectivity matrix,in ac shape(nspec_?*NGLL+nspec_?_grl*NGRL) + * @param jaco jacobians, shape(nspec_ac+nspec_el+1) + * @param xA VTI A parameter, in el + * @param xC VTI C parameter, in el + * @param xL VTI L parameter, in el + * @param xeta VTI eta parameter, in el + * @param xQA VTI Qa parameter, in el + * @param xQC VTI Qc parameter, in el + * @param xQL VTI Ql parameter, in el + * @param xkappa_ac kappa in ac domain + * @param xQk_ac Qkappa, in ac domain + * @param nfaces_bdry no. of el-ac interfaces + * @param ispec_bdry element index on each side, (ispec_ac,ispec_el) = ispec_bdry[i,:], shape(nfaces_bdry,2) + * @param bdry_norm_direc if the ac-> el normal vector is downward + * @param Mmat,Kmat,Emat M/K/E matrices + */ +template +void +prepare_rayl_(float freq,int nspec_el,int nspec_ac, + int nspec_el_grl,int nspec_ac_grl,int nglob_el,int nglob_ac, + const int *el_elmnts,const int *ac_elmnts, + const float *xrho_el,const float *xrho_ac, + const int* ibool_el, const int* ibool_ac,const float *jaco, + const float *xA,const float *xC,const float *xL,const float *xeta, + const float *xQA, const float *xQC, const float *xQL, + const float *xkappa_ac, const float *xQk_ac,int nfaces_bdry, + const int* ispec_bdry,const char *bdry_norm_direc,vector &Mmat, + vector &Kmat,vector &Emat) +{ + // allocate space and set zero + int ng = nglob_ac + nglob_el * 2; + Mmat.resize(ng); + Emat.resize(ng * ng); + Kmat.resize(ng * ng); + std::fill(Mmat.begin(),Mmat.end(),(T)0.); + std::fill(Emat.begin(),Emat.end(),(T)0.); + std::fill(Kmat.begin(),Kmat.end(),(T)0.); + + // compute M/K/E for gll/grl layer, elastic + using namespace GQTable; + std::array A,L,C,F; + for(int ispec = 0; ispec < nspec_el + nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id = ispec * NGLL; + + // get const arrays + const bool is_gll = (ispec != nspec_el); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hpT = is_gll? hprimeT.data(): hprimeT_grl.data(); + const float *hp = is_gll? hprime.data(): hprime_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // jacobian + float J = jaco[iel]; + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + T sl = 1.,sa = 1.,sc = 1.; + if constexpr (std::is_same_v) { + sl = get_sls_modulus_factor(freq,xQL[id+i]); + sa = get_sls_modulus_factor(freq,xQA[id+i]); + sc = get_sls_modulus_factor(freq,xQC[id+i]); + } + C[i] = xC[id+i] * sc; + L[i] = xL[id+i] * sl; + A[i] = xA[id+i] * sa; + F[i] = xeta[id+i] * (A[i] - (T)2. * L[i]); + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id + i]; + T temp = weight[i] * J; + + // element wise M/K1/K3 + T M0 = temp * xrho_el[id + i]; + T K1 = temp * A[i]; + T K3 = temp * L[i]; + + // assemble + Mmat[iglob] += M0; + Mmat[iglob + nglob_el] += M0; + Kmat[iglob * ng + iglob] += K1; + Kmat[(nglob_el + iglob) * ng + (nglob_el + iglob)] += K3; + + // other matrices + for(int j = 0; j < NGL; j ++) { + int iglob1 = ibool_el[id + j]; + T E1{},E3{}; + for(int m = 0; m < NGL; m ++) { + E1 += L[m] * weight[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + E3 += C[m] * weight[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * ng + iglob1] += E1 / J; + Emat[(iglob + nglob_el) * ng + (iglob1 + nglob_el)] += E3 / J; + + // K2/E2 + T K2 = weight[j] * F[j] * hpT[i * NGL + j] - + weight[i] * L[i] * hp[i * NGL + j]; + T E2 = weight[i] * F[i] * hp[i * NGL + j] - + weight[j] * L[j] * hpT[i * NGL + j]; + Kmat[(nglob_el + iglob) * ng + iglob1] += K2; + Emat[iglob * ng + nglob_el + iglob1] += E2; + } + } + } + + // acoustic elements + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec ++) { + int iel = ac_elmnts[ispec]; + int id = ispec * NGLL; + + const bool is_gll = (ispec != nspec_ac); + const float *weight = is_gll? wgll.data(): wgrl.data(); + const float *hpT = is_gll? hprimeT.data(): hprimeT_grl.data(); + const int NGL = is_gll? NGLL : NGRL; + + // jacobian + float J = jaco[iel]; + + // cache temporary arrays + for(int i = 0; i < NGL; i ++) { + L[i] = weight[i] / (J * xrho_ac[id+i]); + } + + // compute M/K/E + for(int i = 0; i < NGL; i ++) { + int ig0 = ibool_ac[id + i]; + if(ig0 == -1) continue; + int iglob = ig0 + nglob_el * 2; + T temp = weight[i] * J; + + // assemble M and K + T sk = 1.; + if constexpr (std::is_same_v) { + sk = get_sls_modulus_factor(freq,xQk_ac[id+i]); + } + Mmat[iglob] += temp / (sk * xkappa_ac[id + i]); + Kmat[iglob * ng + iglob] += temp / xrho_ac[id + i]; + + // assemble E + for(int j = 0; j < NGL; j ++) { + int ig1 = ibool_ac[id + j]; + if(ig1 == -1) continue; + int iglob1 = ig1 + nglob_el * 2; + T s{}; + for(int m = 0; m < NGL; m ++) { + s += L[m] * hpT[i * NGL + m] * hpT[j * NGL + m]; + } + Emat[iglob * ng + iglob1] += s; + } + } + } + + // acoustic-elastic boundary + float om = M_PI * 2 * freq; + for(int iface = 0; iface < nfaces_bdry; iface ++) { + int ispec_ac = ispec_bdry[iface * 2 + 0]; + int ispec_el = ispec_bdry[iface * 2 + 1]; + T norm = -1.; + int igll_el = 0; + int igll_ac = NGLL - 1; + if(!bdry_norm_direc[iface]) { + norm = 1.; + igll_ac = 0; + igll_el = NGLL - 1; + } + + // get ac/el global loc + int iglob_el = ibool_el[ispec_el * NGLL + igll_el]; + int iglob_ac = ibool_ac[ispec_ac * NGLL + igll_ac]; + + // add contribution to E mat, elastic case + // E(nglob_el + iglob_el, nglob_el*2 + iglob_ac) += + int id = (nglob_el + iglob_el) * ng + (nglob_el * 2 + iglob_ac); + Emat[id] += (T)(om * om * norm); + + // acoustic case + // E(nglob_el*2 + iglob_ac, nglob_el + iglob_el) += norm + id = (nglob_el*2 + iglob_ac) * ng + (nglob_el + iglob_el); + Emat[id] += (T)norm; + } +} + +/** + * @brief preparing M/K/E matrices for Rayleigh wave + * @param M Mesh class + */ +void SolverRayl::prepare_matrices(const Mesh &M) +{ + if(!M.HAS_ATT) { + prepare_rayl_( + M.freq,M.nspec_el,M.nspec_ac, + M.nspec_el_grl,M.nspec_ac_grl,M.nglob_el, + M.nglob_ac,M.el_elmnts.data(),M.ac_elmnts.data(), + M.xrho_el.data(),M.xrho_ac.data(),M.ibool_el.data(), + M.ibool_ac.data(),M.jaco.data(),M.xA.data(), + M.xC.data(),M.xL.data(),M.xeta.data(), + nullptr,nullptr,nullptr,M.xkappa_ac.data(), + nullptr,M.nfaces_bdry,M.ispec_bdry.data(), + M.bdry_norm_direc.data(), + Mmat,Kmat,Emat + ); + } + else { + prepare_rayl_( + M.freq,M.nspec_el,M.nspec_ac, + M.nspec_el_grl,M.nspec_ac_grl,M.nglob_el, + M.nglob_ac,M.el_elmnts.data(),M.ac_elmnts.data(), + M.xrho_el.data(),M.xrho_ac.data(),M.ibool_el.data(), + M.ibool_ac.data(),M.jaco.data(),M.xA.data(), + M.xC.data(),M.xL.data(),M.xeta.data(), + M.xQA.data(),M.xQC.data(),M.xQL.data(), + M.xkappa_ac.data(),M.xQk_ac.data(), + M.nfaces_bdry,M.ispec_bdry.data(), + M.bdry_norm_direc.data(), + CMmat,CKmat,CEmat + ); + } + +} + + +} // namespace specswd diff --git a/src/vti/transform.cpp b/src/vti/transform.cpp new file mode 100644 index 0000000..cf455b0 --- /dev/null +++ b/src/vti/transform.cpp @@ -0,0 +1,319 @@ +#include "vti/vti.hpp" +#include "shared/GQTable.hpp" + +namespace specswd { + +template +void egn2displ_love_(int nspec,const int *ibool_el,const T *egn, + T * __restrict displ) +{ + using namespace GQTable; + for(int ispec = 0; ispec < nspec + 1; ispec ++) { + int NGL = NGLL; + if(ispec == nspec) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[ispec*NGLL+i]; + displ[ispec*NGLL+i] = (iglob!=-1) ?egn[iglob] : 0; + } + } +} + +/** + * @brief convert eigenvector to displacement,elastic case + * + * @param M mesh class + * @param c current phase velocity + * @param egn eigenvector + * @param displ output displacement, shape(nspec*NGLL+NGRL) + */ +void SolverLove:: +egn2displ(const Mesh &M,float c, const float *egn,float * __restrict displ ) const +{ + egn2displ_love_(M.nspec,M.ibool_el.data(),egn,displ); +} + +/** + * @brief convert eigenvector to displacement, visco-elastic case + * + * @param M mesh class + * @param c current phase velocity + * @param egn eigenvector + * @param displ output displacement, shape(nspec*NGLL+NGRL) + */ +void SolverLove:: +egn2displ_att(const Mesh &M,scmplx c, const scmplx *egn,scmplx * __restrict displ ) const +{ + egn2displ_love_(M.nspec,M.ibool_el.data(),egn,displ); +} + + +template +void egn2displ_rayl_(int nspec_el,int nspec_ac,int nspec_el_grl,int nspec_ac_grl, + int nglob_el,int nglob_ac,const float* jaco,const int *ibool_el, + const int *ibool_ac, const int *el_elmnts, + const int *ac_elmnts,const float *xrho_ac, + const T *egn, float freq,T c, T * __restrict displ) +{ + + // get wave number + T k = (T)(M_PI * 2.) * freq / c; + + // size + using namespace GQTable; + int npts = (nspec_el + nspec_ac) * NGLL + (nspec_ac_grl + nspec_el_grl) * NGRL; + + // loop elastic elements + for(int ispec = 0; ispec < nspec_el+nspec_el_grl; ispec ++) { + int iel = el_elmnts[ispec]; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + int NGL = NGLL; + + // grl case + if(ispec == nspec_el) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int iglob = ibool_el[id0+i]; + displ[0*npts + id1+i] = egn[iglob]; + displ[1*npts + id1+i] = egn[iglob + nglob_el] / k; // this is V\bar = kV + } + } + + // loop each acoustic element + std::array chi; + for(int ispec = 0; ispec < nspec_ac + nspec_ac_grl; ispec += 1) { + int iel = ac_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + int id1 = iel * NGLL; + const float *hp = &hprime[0]; + const float J = jaco[iel]; + + // GRL layer + if(ispec == nspec_ac) { + NGL = NGRL; + hp = &hprime_grl[0]; + } + + // cache chi in an element + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int iglob = ibool_ac[id]; + chi[i] = (iglob == -1) ? (T)0.: egn[nglob_el * 2 + iglob] / k; + } + + + // compute derivative dchi / dz + for(int i = 0; i < NGL; i ++) { + T dchi{}; + for(int j = 0; j < NGL; j ++) { + dchi += chi[j] * hp[i * NGL + j]; + } + dchi /= J; + + // set value to displ + displ[0*npts + id1+i] = k / xrho_ac[id0 + i] * chi[i]; + displ[1*npts + id1+i] = dchi / xrho_ac[id0 + i]; + } + } + +} + +/** + * @brief convert right eigenfunction to displacement, elastic case + * + * @param M Mesh class + * @param c current phase velocity + * @param egn eigenfunction,shape(nglob_el*2+nglob_ac) + * @param displ displacement, shape(2,npts) + */ +void SolverRayl:: +egn2displ(const Mesh &M,float c, const float *egn,float * __restrict displ ) const +{ + egn2displ_rayl_( + M.nspec_el,M.nspec_ac,M.nspec_el_grl,M.nspec_ac_grl, + M.nglob_el,M.nglob_ac,M.jaco.data(),M.ibool_el.data(), + M.ibool_ac.data(),M.el_elmnts.data(),M.ac_elmnts.data(), + M.xrho_ac.data(),egn,M.freq,c,displ + ); +} + +/** + * @brief convert right eigenfunction to displacement, visco-elastic case + * + * @param M Mesh class + * @param c current phase velocity + * @param egn eigenfunction,shape(nglob_el*2+nglob_ac) + * @param displ displacement, shape(2,npts) + */ +void SolverRayl:: +egn2displ_att(const Mesh &M,scmplx c, const scmplx *egn,scmplx * __restrict displ ) const +{ + egn2displ_rayl_( + M.nspec_el,M.nspec_ac,M.nspec_el_grl,M.nspec_ac_grl, + M.nglob_el,M.nglob_ac,M.jaco.data(),M.ibool_el.data(), + M.ibool_ac.data(),M.el_elmnts.data(),M.ac_elmnts.data(), + M.xrho_ac.data(),egn,M.freq,c,displ + ); +} + +/** + * @brief transform modulus kernel to velocity kernel, Love wave case + * @param M mesh class + * @param frekl frechet kernels, the shape depends on: + * - `1`: elastic love wave: N/L/rho -> vsh/vsv/rho + * - `2`: anelastic love wave: N/L/QNi/QLi/rho -> vsh/vsv/QNi/QLi/rho + */ +void SolverLove:: +transform_kernels(const Mesh &M,std::vector &frekl) const +{ + // check no. of kernels + using namespace GQTable; + int npts = M.nspec * NGLL + NGRL; + int nker = frekl.size() / npts; + int nker0 = 3; + if(M.HAS_ATT) nker0 = 5; + if(nker0 != nker) { + printf("target/current number of kernels = %d %d\n",nker0,nker); + printf("please check the size of frekl!\n"); + exit(1); + } + + for(int ipt = 0; ipt < npts; ipt ++) { + double N_kl,L_kl,rho_kl; + N_kl = frekl[0 * npts + ipt]; + L_kl = frekl[1 * npts + ipt]; + + int i = 2; + if(M.HAS_ATT) i =4; + rho_kl = frekl[i * npts + ipt]; + + // get variables + double L = M.xL[ipt], N = M.xN[ipt], rho = M.xrho_el[ipt]; + double vsh = std::sqrt(N / rho), vsv = std::sqrt(L / rho); + + // transform kernels + double vsh_kl = 2. * rho * vsh * N_kl, vsv_kl = 2. * rho * vsv * L_kl; + double r_kl = vsh * vsh * N_kl + + vsv * vsv * L_kl + rho_kl; + + // copy back to frekl array + frekl[0 * npts + ipt] = vsh_kl; + frekl[1 * npts + ipt] = vsv_kl; + frekl[i * npts + ipt] = r_kl; + } +} + +/** + * @brief transform modulus kernel to velocity kernel, Rayleigh wave case + * @param M mesh class + * @param frekl frechet kernels, the shape depends on: + * - `1`: elastic rayleigh wave: A/C/L/eta/kappa/rho -> vph/vpv/vsv/eta/vp/rho + * - `2` anelastic rayleigh wave: A/C/L/eta/QAi/QCi/QLi/kappa/Qki/rho -> vph/vpv/vsv/eta/QAi/QCi/QLi/vp/Qki/rho + */ +void SolverRayl:: +transform_kernels(const Mesh &M,std::vector &frekl) const +{ + // check no. of kernels + using namespace GQTable; + int npts = M.nspec * NGLL + NGRL; + int nker = frekl.size() / npts; + int nker0 = 6; + if(M.HAS_ATT) nker0 = 10; + if(nker0 != nker) { + printf("target/current number of kernels = %d %d\n",nker0,nker); + printf("please check the size of frekl!\n"); + exit(1); + } + + for(int ispec = 0; ispec < M.nspec_el + M.nspec_el_grl; ispec += 1) { + int iel = M.el_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + + // GRL layer + if(ispec == M.nspec_el) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int ipt = iel * NGLL + i; + double A_kl{},C_kl{}, L_kl{}, rho_kl{}; + + // loc of rho + int loc = 5; + if(M.HAS_ATT) loc = 9; + + // kernels + A_kl = frekl[0 * npts + ipt]; + C_kl = frekl[1 * npts + ipt]; + L_kl = frekl[2 * npts + ipt]; + rho_kl = frekl[loc * npts + ipt]; + + // compute vph/vpv/vsh/vsv/ + double rho = M.xrho_el[ipt]; + double vph = std::sqrt(M.xA[id] / rho); + double vpv = std::sqrt(M.xC[id] / rho); + double vsv = std::sqrt(M.xL[id] / rho); + + double vph_kl = 2. * rho * vph * A_kl; + double vpv_kl = 2. * rho * vpv * C_kl; + double vsv_kl = 2. * rho * vsv * L_kl; + double r_kl = vph * vph * A_kl + vpv * vpv * C_kl + + + vsv * vsv * L_kl + rho_kl; + frekl[0 * npts + ipt] = vph_kl; + frekl[1 * npts + ipt] = vpv_kl; + frekl[2 * npts + ipt] = vsv_kl; + frekl[loc * npts + ipt] = r_kl; + } + } + + // acoustic domain + for(int ispec = 0; ispec < M.nspec_ac + M.nspec_ac_grl; ispec += 1) { + int iel = M.ac_elmnts[ispec]; + int NGL = NGLL; + int id0 = ispec * NGLL; + + // GRL layer + if(ispec == M.nspec_ac) { + NGL = NGRL; + } + + for(int i = 0; i < NGL; i ++) { + int id = id0 + i; + int ipt = iel * NGLL + i; + + // kernels + double kappa_kl{}, rho_kl{}; + + // loc + int loc_k = 4, loc_r = 5; + if(M.HAS_ATT) { + loc_k = 7; + loc_r = 9; + } + + // modulus kernels + kappa_kl = frekl[loc_k * npts + ipt]; + rho_kl = frekl[loc_r * npts + ipt]; + + // velocity + double rho = M.xrho_ac[id]; + double vp = std::sqrt(M.xkappa_ac[id] / rho); + + //velocity kernels + double vp_kl = 2. * rho* vp * kappa_kl; + double r_kl = vp * vp * kappa_kl + rho_kl; + frekl[loc_k * npts + ipt] = vp_kl; + frekl[loc_r * npts + ipt] = r_kl; + } + } +} + +} \ No newline at end of file diff --git a/src/vti/vti.hpp b/src/vti/vti.hpp new file mode 100644 index 0000000..b55e15e --- /dev/null +++ b/src/vti/vti.hpp @@ -0,0 +1,137 @@ +#ifndef SPECSWD_SOLVER_H_ +#define SPECSWD_SOLVER_H_ + +#include "mesh/mesh.hpp" + +#include +#include + + +namespace specswd +{ + +typedef std::complex scmplx; + +class SolverLove { + +private: + // solver matrices + std::vector Mmat,Emat,Kmat; + std::vector CMmat,CEmat,CKmat; + + // QZ matrix all are column major + std::vector Qmat_,Zmat_,Smat_,Spmat_; // column major! + std::vector cQmat_,cZmat_,cSmat_,cSpmat_; + +public: + + // eigenfunctions/values + void prepare_matrices(const Mesh &M); + void compute_egn(const Mesh &M, + std::vector &c, + std::vector &egn, + bool use_qz=false); + void compute_egn_att(const Mesh &M, + std::vector &c, + std::vector &egn, + bool use_qz=false); + + // group velocity + float group_vel(const Mesh &M,float c,const float *egn) const; + scmplx group_vel_att(const Mesh &M,scmplx c, const scmplx *egn) const ; + + // phase velocity kernels + void compute_phase_kl(const Mesh &M, + float c,const float *egn, + std::vector &frekl) const; + void compute_phase_kl_att(const Mesh &M, + scmplx c, const scmplx *egn, + std::vector &frekl_c, + std::vector &frekl_q) const; + // group kernel + void compute_group_kl(const Mesh &M, + float c,const float *egn, + std::vector &frekl) const; + + void compute_group_kl_att(const Mesh &M, + scmplx c, scmplx u, const scmplx *egn, + std::vector &frekl_u, + std::vector &frekl_q) const; + // tranforms + void egn2displ(const Mesh &M,float c, + const float *egn, float * __restrict displ) const; + void egn2displ_att(const Mesh &M,scmplx c,const scmplx *egn, + scmplx * __restrict displ) const; + void transform_kernels(const Mesh &M,std::vector &frekl) const; +}; + +class SolverRayl { + +private: + // solver matrices + std::vector Mmat,Emat,Kmat; + std::vector CMmat,CEmat,CKmat; + + // QZ matrix all are column major + std::vector Qmat_,Zmat_,Smat_,Spmat_; // column major! + std::vector cQmat_,cZmat_,cSmat_,cSpmat_; + +public: + void prepare_matrices(const Mesh &M); + void compute_egn(const Mesh &M, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz=false); + void compute_egn_att(const Mesh &M, + std::vector &c, + std::vector &ur, + std::vector &ul, + bool use_qz=false); + + // group velocity + float group_vel(const Mesh &M, + float c,const float *ur, + const float *ul) const; + scmplx group_vel_att(const Mesh &M, + scmplx c, const scmplx *ur, + const scmplx *ul) const; + + // phase velocity kernels + void compute_phase_kl(const Mesh &M, + float c,const float *ur, + const float *ul, + std::vector &frekl) const; + void compute_phase_kl_att(const Mesh &M, + scmplx c, const scmplx *ur, + const scmplx *ul, + std::vector &frekl_c, + std::vector &frekl_q) const; + + // group velocity kernels + void compute_group_kl(const Mesh &M, + float c,const float *ur, + const float *ul, + std::vector &frekl) const; + void compute_group_kl_att(const Mesh &M, + scmplx c, scmplx u, + const scmplx *ur,const scmplx *ul, + std::vector &frekl_u, + std::vector &frekl_q) const; + + + // transforms + void egn2displ(const Mesh &M,float c, + const float*egn, float * __restrict displ) const; + void egn2displ_att(const Mesh &M,scmplx c,const scmplx *egn, + scmplx * __restrict displ) const; + void transform_kernels(const Mesh &M,std::vector &frekl) const; +}; + + +} // namespace specswd + + + + +#endif \ No newline at end of file