// oth.h
#ifndef _OTH_H_
#define _OTH_H_

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#include <limits.h>
#include <assert.h>

#ifdef _OPENMP
#include <omp.h>
#endif

#define PROGRAM "OpenTHFD"
#define VERSION_MAJOR (4)
#define VERSION_MINOR (0)
#define VERSION_BUILD (3)

#ifdef MAIN
#define EXTERN
#else
#define EXTERN extern
#endif

#define FN_log      "oth.log"
#define FN_out      "oth.out"
#define FN_geom3d_0 "geom3d.htm"
#define FN_ev2d_0   "ev2d.htm"
#define FN_ev3d_0   "ev3d.htm"
#define FN_geom3d_1 "geom.ev3"
#define FN_ev2d_1   "ev.ev2"
#define FN_ev3d_1   "ev.ev3"
#define FN_far0d    "far0d.log"
#define FN_far1d    "far1d.log"
#define FN_far2d    "far2d.log"
#define FN_near1d   "near1d.log"
#define FN_near2d   "near2d.log"

#define PI       (4.0*atan(1.0))
#define C        (2.99792458e8)
#define MU0      (4*PI*1e-7)
#define EPS0     (1/(C*C*MU0))
#define ETA0     (C*MU0)
#define EPS      (1e-6)
#define EPS2     (EPS*EPS)
#define DTOR     (PI/180)
#define PEC      (1)
#define MUR      (1)
#define PML      (2)
#define LOAD_R   (3)
#define LOAD_C   (4)
#define LOAD_L   (5)
#define NNZ      (13)

#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#endif
#define MINMAX(x,y,z) (MAX((x), MIN((y), (z))))

#define NEX(i,j,k) (NEXI*(i)+NEXJ*(j)+NEXK*(k)+NEX0)
#define NEY(i,j,k) (NEYI*(i)+NEYJ*(j)+NEYK*(k)+NEY0)
#define NEZ(i,j,k) (NEZI*(i)+NEZJ*(j)+NEZK*(k)+NEZ0)

#define NHX(i,j,k) (NHXI*(i)+NHXJ*(j)+NHXK*(k)+NHX0)
#define NHY(i,j,k) (NHYI*(i)+NHYJ*(j)+NHYK*(k)+NHY0)
#define NHZ(i,j,k) (NHZI*(i)+NHZJ*(j)+NHZK*(k)+NHZ0)

#define MEX(i,j,k) mE[NEX(i,j,k)]
#define MEY(i,j,k) mE[NEY(i,j,k)]
#define MEZ(i,j,k) mE[NEZ(i,j,k)]

#define MHX(i,j,k) mH[NHX(i,j,k)]
#define MHY(i,j,k) mH[NHY(i,j,k)]
#define MHZ(i,j,k) mH[NHZ(i,j,k)]

#ifdef __cplusplus
extern "C" {
#endif

// struct

typedef struct {double r, i;} d_complex_t;
typedef struct {float  r, i;} f_complex_t;

typedef struct {
	int         type;                 // 1=number, 2=file, 3=R, 4=C, 5=L
	d_complex_t cepsr;                // epsilon_r
	d_complex_t cmur;                 // mu_r
	double      rcl, dsdl;            // R or C or L, dS / dl
	int         ntable;               // number of table
	double      **table;              // table
	char        dirload;
	double      posload[3];
} material_data_t;

typedef struct {
	int         type;                 // 1=number, 2=file, 3=R, 4=C, 5=L
	d_complex_t cepsr;                // epsilon_r
	d_complex_t cmur;                 // mu_r
	d_complex_t cnur;                 // 1 / mu_r
	d_complex_t cv;                   // c/v = sqrt(epsilon_r * mu_r)
} material_t;

typedef struct {
	int         m;                    // material id = 0,1,2,...
	int         shape;                // shape, 1:rectangle, 2:sphere, ...
	double      g[8];                 // geometry [m]
} geometry_t;

typedef struct {
	char        dir;                  // direction X/Y/Z
	int         i, j, k;              // index
	d_complex_t volt;                 // voltage
	double      z0;                   // feed line impedance
	double      dx, dy, dz;           // cell size
} feed_t;

typedef struct {
	int         pol;                  // 1=V, 2=H, 3=RHCP, 4=LHCP, 5=Elliptical
	double      theta;                // theta [deg]
	double      phi;                  // phi [deg]
	double      a, r;                 // Elliptical: angle [deg], axial ratio
	double      r1[3], t1[3], p1[3];  // unit vector
	int         isemi;
	double      psemi;
	int         msemi1, msemi2;
	int         ifull;
	int         mfull;
} planewave_t;

typedef struct {
	int         xpbc, ypbc, zpbc;     // PBC (0/1)
	d_complex_t fx, fy, fz;           // factors
} pbc_t;

typedef struct {
	int         maxiter;              // max iteration
	int         nout;                 // output interval
	double      converg;              // convergence
} solver_t;

typedef struct {
	char        dir;                  // direction : X/Y/Z
	int         i, j, k;              // position index
} point_t;                            // point

typedef struct {
	char        dir;                  // direction : X/Y/Z/V/H
	int         div;                  // division of angle 360 deg
	double      angle;                // V/H constant angle [deg]
} far1d_t;                            // far1d field

typedef struct {
	int         divtheta, divphi;     // division in theta and phi
} far2d_t;                            // far2d field

typedef struct {
	char        cmp[3];               // component : E/Ex/Ey/Ez/H/Hx/Hy/Hz
	char        dir;                  // direction : X/Y/Z
	double      pos1, pos2;           // position
	int         id1, id2;             // node index
} near1d_t;                           // near1d field

typedef struct {
	char        cmp[3];               // component : E/Ex/Ey/Ez/H/Hx/Hy/Hz
	char        dir;                  // direction : X/Y/Z
	double      pos0;                 // position
	int         id0;                  // node index
} near2d_t;                           // near2d field

typedef struct {
	int         db;                   // dB (0/1)
	int         user;                 // 0/1 : auto/user
	double      min, max;             // min, max
	int         div;                  // division
} scale_t;                            // scale

// variables

EXTERN char        Title[256];    // title

EXTERN int         NMaterial;     // number of materials
EXTERN material_t  *Material;     // material

EXTERN int         NGeometry;     // number of geometries
EXTERN geometry_t  *Geometry;     // geometry

EXTERN int         NFeed;         // numver of feed
EXTERN feed_t      *Feed;         // feed

EXTERN int         NPoint;        // number of points
EXTERN point_t     *Point;        // point

EXTERN int         IPlanewave;    // planewave (0/1)
EXTERN planewave_t Planewave;     // planewave

EXTERN int         NFrequency;    // number of frequencies
EXTERN double      *Frequency;    // frequency

// solver

EXTERN int         SCALING;       // scaling (0/1)
EXTERN int         MATRIX;        // matrix (0/1)
EXTERN solver_t    Solver;        // solver
EXTERN int         Iseed;         // seed of random number

EXTERN int         Nx, Ny, Nz;

EXTERN int64_t     NEXI, NEXJ, NEXK, NEX0;
EXTERN int64_t     NEYI, NEYJ, NEYK, NEY0;
EXTERN int64_t     NEZI, NEZJ, NEZK, NEZ0;

EXTERN int64_t     NHXI, NHXJ, NHXK, NHX0;
EXTERN int64_t     NHYI, NHYJ, NHYK, NHY0;
EXTERN int64_t     NHZI, NHZJ, NHZK, NHZ0;

EXTERN int64_t     NE, NH;

EXTERN int         i0Ex, i1Ex, j0Ex, j1Ex, k0Ex, k1Ex;
EXTERN int         i0Ey, i1Ey, j0Ey, j1Ey, k0Ey, k1Ey;
EXTERN int         i0Ez, i1Ez, j0Ez, j1Ez, k0Ez, k1Ez;

EXTERN int         i0Hx, i1Hx, j0Hx, j1Hx, k0Hx, k1Hx;
EXTERN int         i0Hy, i1Hy, j0Hy, j1Hy, k0Hy, k1Hy;
EXTERN int         i0Hz, i1Hz, j0Hz, j1Hz, k0Hz, k1Hz;

EXTERN double      *Xn, *Yn, *Zn;
EXTERN double      *Xc, *Yc, *Zc;
EXTERN double      *DXn, *DYn, *DZn;
EXTERN double      *DXc, *DYc, *DZc;
EXTERN double      *KRXn, *KRYn, *KRZn;
EXTERN double      *KRXc, *KRYc, *KRZc;
EXTERN double      *KDXn, *KDYn, *KDZn;
EXTERN double      *KDXc, *KDYc, *KDZc;
EXTERN double      *KRXp, *KRYp, *KRZp;
EXTERN double      *KRXm, *KRYm, *KRZm;

EXTERN int         *mE, *mH;
EXTERN d_complex_t *Acg;
EXTERN d_complex_t *Ecg, *Bcg, *Rcg, *Pcg, *Qcg, *Tcg, *Ucg, *R0cg;
EXTERN f_complex_t ****Ex, ****Ey, ****Ez;

EXTERN int         Abc;                     // ABC : MUR or PML
EXTERN int         Lpml;                    // PML
EXTERN double      Mpml, R0pml;             // PML
EXTERN int         NFxpml, NFypml, NFzpml;  // PML
EXTERN double      *Fxpml, *Fypml, *Fzpml;  // PML
EXTERN pbc_t       Pbc;                     // PBC

EXTERN int         *NIter;                  // number of iterations
EXTERN double      **Residual;              // residual
EXTERN double      **Eaverage;              // E average

EXTERN int         NGline;                  // number of geometry lines
EXTERN double      (*Gline)[2][3];          // geometery lines
EXTERN int         *MGline;                 // material of geometry lines

EXTERN d_complex_t *Zin;                    // input impedance
EXTERN double      *Ref;                    // reflection
EXTERN d_complex_t *Spara;                  // S-parameter
EXTERN double      *PLoss;                  // power loss

EXTERN int         Plot3dGeom;              // plot geometery 3D

// post

EXTERN int         HTML;                    // 0:ev, 1:HTML

EXTERN int         MatchingLoss;            // include matching loss (0/1)

EXTERN int         Piter[2];                // iteration (0/1)

EXTERN int         IFreq[7];                // frequency char.s (0/1)
EXTERN scale_t     FreqScale[7];            // scale
EXTERN int         Freqdiv;                 // x-axis division

EXTERN int         IFar0d;                  // frequency char of far0d (0/1)
EXTERN double      Far0d[2];                // theta, phi [deg]
EXTERN scale_t     Far0dScale;              // scale

EXTERN int         NFar1d;                  // number of far1d
EXTERN far1d_t     *Far1d;                  // parameters
EXTERN int         Far1dStyle;              // style (0/1)
EXTERN int         Far1dComp[3];            // component (0/1)
EXTERN int         Far1dNorm;               // normalize (0/1)
EXTERN scale_t     Far1dScale;              // scale

EXTERN int         NFar2d;                  // number of far2d (0/1)
EXTERN far2d_t     Far2d;                   // parameters
EXTERN int         Far2dComp[7];            // component (0/1)
EXTERN scale_t     Far2dScale;              // scale
EXTERN double      Far2dObj;                // object

EXTERN int         NNear1d;                 // number of near1d
EXTERN near1d_t    *Near1d;                 // parameters
EXTERN scale_t     Near1dScale;             // scale
EXTERN int         Near1dExclude;           // exclude incidence (0/1)

EXTERN int         NNear2d;                 // number of near2d
EXTERN int         Near2dDim[2];            // 2d/3d (0/1)
EXTERN near2d_t    *Near2d;                 // parameters
EXTERN int         Near2dFrame;             // animation frames
EXTERN scale_t     Near2dScale;             // scale
EXTERN int         Near2dObj;               // object (0/1/2)
EXTERN int         Near2dContour;           // contour (0/1/2/3)
EXTERN int         Near2dExclude;           // exclude incidence (0/1)
EXTERN int         Near2dIzoom;             // zoom ? (0/1)
EXTERN double      Near2dHzoom[2];          // zoom (horizontal)
EXTERN double      Near2dVzoom[2];          // zoom (vertical)

EXTERN double      Width2d, Height2d;       // window size (2D)
EXTERN double      Fontsize2d;              // font size (2D)

#ifdef __cplusplus
}
#endif

#endif
