/* FILE: demagold.h            -*-Mode: c++-*-
 *
 * Average H demag field across rectangular cells.  This is a modified
 * version of the simpledemag class, which uses symmetries in the
 * interaction coefficients to reduce memory usage.
 *
 * This code in this file uses the older scalar FFT code.  For general
 * use, the use of this code has been replaced by the newer Oxs_Demag
 * which uses the faster Oxs_FFT3v (ThreeVector) FFT code.
 *
 */

#ifndef _OXS_DEMAGOLD
#define _OXS_DEMAGOLD

#include "energy.h"
#include "fft.h"
#include "key.h"
#include "mesh.h"
#include "meshvalue.h"
#include "simstate.h"
#include "threevector.h"
#include "rectangularmesh.h"

/* End includes */

class Oxs_DemagOld:public Oxs_Energy {
private:
#if REPORT_TIME
  mutable Nb_StopWatch ffttime;
  mutable Nb_StopWatch convtime;
  mutable Nb_StopWatch dottime;
#endif // REPORT_TIME

  mutable OC_INDEX rdimx; // Natural size of real data
  mutable OC_INDEX rdimy; // Digital Mars compiler wants these as separate
  mutable OC_INDEX rdimz; //    statements, because of "mutable" keyword.
  mutable OC_INDEX cdimx; // Full size of complex data
  mutable OC_INDEX cdimy;
  mutable OC_INDEX cdimz;
  // 2*cdimx>=rdimx, cdimy>=rdimy, cdimz>=rdimz
  // cdim[xyz] should be powers of 2.
  mutable OC_INDEX cstridey; // Strides across complex data
  mutable OC_INDEX cstridez;
  // cstridey>=cdimx, cstridez>=cdimy*cstridey
  // The stride sizes for the real arrays are just double the
  // complex strides, except cstride1 and rstride1 are assumed
  // to be 1.  Total matrix size is effectively cdimz*cstridez
  // Oxs_Complex elements, or twice that many "double" elements.

  mutable OC_UINT4m mesh_id;

  // The A## arrays hold demag coefficients, transformed into
  // frequency domain.  These are held long term.  xcomp,
  // ycomp, and zcomp are used as temporary space, first to hold
  // the transforms of Mx, My, and Mz, then to store Hx, Hy, and
  // Hz.
  mutable OC_INDEX adimx;
  mutable OC_INDEX adimy;
  mutable OC_INDEX adimz;
  mutable OC_INDEX astridey;
  mutable OC_INDEX astridez;
  mutable OXS_COMPLEX_REAL_TYPE *A00;
  mutable OXS_COMPLEX_REAL_TYPE *A01;
  mutable OXS_COMPLEX_REAL_TYPE *A02;
  mutable OXS_COMPLEX_REAL_TYPE *A11;
  mutable OXS_COMPLEX_REAL_TYPE *A12;
  mutable OXS_COMPLEX_REAL_TYPE *A22;
  mutable Oxs_Complex *xcomp;
  mutable Oxs_Complex *ycomp;
  mutable Oxs_Complex *zcomp;
  mutable Oxs_FFT3D fft; // All transforms are same size, so we need
  /// only one Oxs_FFT3D object.

  void (Oxs_DemagOld::*fillcoefs)(const Oxs_Mesh*) const;
  void FillCoefficientArraysFast(const Oxs_Mesh* mesh) const;
  void FillCoefficientArraysStandard(const Oxs_Mesh* mesh) const;
  /// The "standard" variant is simpler but slower, and is retained
  /// mainly for testing and development purposes.

  OC_INDEX NextPowerOfTwo(OC_INDEX n) const;  // Helper function
  void ReleaseMemory() const;

protected:
  virtual void GetEnergy(const Oxs_SimState& state,
			 Oxs_EnergyData& oed) const;

public:
  virtual const char* ClassName() const; // ClassName() is
  /// automatically generated by the OXS_EXT_REGISTER macro.
  Oxs_DemagOld(const char* name,     // Child instance id
	       Oxs_Director* newdtr, // App director
	       const char* argstr);  // MIF input block parameters
  virtual ~Oxs_DemagOld();
  virtual OC_BOOL Init();
};


#endif // _OXS_DEMAGOLD
