/***************************************************************************
**
**  This file is part of gpsh.
**
**  gpsh is free software: you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation, either version 3 of the License, or
**  (at your option) any later version.
**
**  gpsh is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2019-03-23
**  Copyright: 2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef KENNETTSH_H
#define KENNETTSH_H

#include <QGpCoreWave.h>

class KennettSH
{
public:
  KennettSH(Seismic1DModel * model);
  ~KennettSH();

  double sh(double frequency, double receiverDepth);
private:
  void setFrequency(Complex ckx, Complex comega, Complex * calpha, Complex * cbeta);

  void reflect1(int jcas);
  void reflect2();
  void reflect4(int jcas);

  inline Complex& rd(int i, int j, int k) const;
  inline Complex& ru(int i, int j, int k) const;
  inline Complex& td(int i, int j, int k) const;
  inline Complex& tu(int i, int j, int k) const;
  inline Complex& nt(int i, int j, int k) const;
  inline Complex& mt(int i, int j, int k) const;
  inline Complex& fdo(int i, int j, int k) const;
  inline Complex& fup(int i, int j, int k) const;

  inline Complex& ftdo(int i, int j, int k) const;
  inline Complex& ftup(int i, int j, int k) const;
  inline Complex& cfwave(int i, int j) const;

  Seismic1DModel * _model;

  // dim1a
  Complex ai;
  double pi, pi2;
  Complex omega, omega2, cwx, cwx2;

  // dim1e
  Complex * cvp;
  Complex * cvs;
  int _layerCount;

  // dim1a
  Complex * cka;
  Complex * ckb;
  Complex * cka2;
  Complex * ckb2;
  Complex * cnu;
  Complex * cgam;

  // dim2c
  Complex * _rd;	  // was [300][2][2]
  Complex * _ru;	  // was [300][2][2]
  Complex * _td;	  // was [300][2][2]
  Complex * _tu;    // was [300][2][2]
  Complex * rdsh;
  Complex * rush;
  Complex * tdsh;
  Complex * tush;
  Complex * me1;
  Complex * me2;

  // dim2d
  Complex * _nt; // was [300][2][2]
  Complex * _mt; // was [300][2][2]
  Complex * ntsh;
  Complex * mtsh;

  // dim2e
  Complex * _fdo; // was [300][2][2]
  Complex * _fup; // was [300][2][2]
  Complex * fupsh;
  Complex * fdosh;

  // reflect4 locals
  Complex * _ftup;
  Complex * _ftdo;
  Complex * _cfwave;
};

inline Complex& KennettSH::rd(int i, int j, int k) const
{
  return _rd[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::ru(int i, int j, int k) const
{
  return _ru[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::td(int i, int j, int k) const
{
  return _td[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::tu(int i, int j, int k) const
{
  return _tu[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::nt(int i, int j, int k) const
{
  return _nt[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::mt(int i, int j, int k) const
{
  return _mt[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::fdo(int i, int j, int k) const
{
  return _fdo[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::fup(int i, int j, int k) const
{
  return _fup[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::ftup(int i, int j, int k) const
{
  return _ftup[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::ftdo(int i, int j, int k) const
{
  return _ftdo[i+_layerCount*(j+2*k-3)];
}

inline Complex& KennettSH::cfwave(int i, int j) const
{
  return _cfwave[i+4*_layerCount*(j-1)];
}

#endif // KENNETTSH_H

