/* FILE: fftwdemag.h            -*-Mode: c++-*-
 *
 * Average H demag field across rectangular cells.
 * This implementation uses the 3rd party FFTW library to
 * perform the forward/inverse FFT's.
 *
 */

#ifndef _FFTW_DEMAG
#define _FFTW_DEMAG

#include <fftw3.h>

#include "oc.h"
#include "director.h"
#include "energy.h"
#include "simstate.h"
#include "mesh.h"

/* End includes */

class FFTW_Demag:public Oxs_Energy {
private:
  // Dimensional variables:
  //  xdim,  ydim,  zdim : Mesh (problem) dimensions.
  // lxdim, lydim, lzdim : Logical dimensions for FFT.
  // vxdim, vydim, vzdim : Physical dimensions for V1/2/3 arrays,
  //                       with complex-type elements.
  // rvxdim, rvydim, rvzdim : Physical dimensions for rV1/2/3,
  //                       with double-type elements.
  // axdim, aydim, azdim : Physical dimensions for A?? arrays.
  mutable OC_INDEX xdim;   mutable OC_INDEX ydim;   mutable OC_INDEX zdim;
  mutable OC_INDEX lxdim;  mutable OC_INDEX lydim;  mutable OC_INDEX lzdim;
  mutable OC_INDEX vxdim;  mutable OC_INDEX vydim;  mutable OC_INDEX vzdim;
  mutable OC_INDEX rvxdim; mutable OC_INDEX rvydim; mutable OC_INDEX rvzdim;
  mutable OC_INDEX axdim;  mutable OC_INDEX aydim;  mutable OC_INDEX azdim;
  mutable OC_INDEX vystride;  mutable OC_INDEX vzstride;
  mutable OC_INDEX vtotalsize;
  mutable OC_INDEX rvystride; mutable OC_INDEX rvzstride;
  mutable OC_INDEX rvtotalsize;
  mutable OC_INDEX aystride;  mutable OC_INDEX azstride;
  mutable OC_INDEX atotalsize;
  mutable OC_UINT4m mesh_id;

  // The A## arrays hold demag coefficients, transformed into
  // frequency domain.  These are held long term.  Vx, Vy, Vz
  // is temporary space to convert M into H.
  mutable double *A00; mutable double *A01; mutable double *A02;
  mutable double *A11; mutable double *A12; mutable double *A22;
  mutable fftw_complex *V1;
  mutable fftw_complex *V2;
  mutable fftw_complex *V3;
  mutable double *rV1; mutable double *rV2; mutable double *rV3;
  /// rV? are aliases to V?.

  mutable fftw_plan forward_plan;
  mutable fftw_plan backward_plan;

  void (FFTW_Demag::*initmem)(const Oxs_Mesh*) const;
  void StandardInitializeMemory(const Oxs_Mesh* mesh) const;
  void FastInitializeMemory(const Oxs_Mesh* mesh) const;
  /// Allocates and fills coefficient arrays and plans.
  /// Conceptually const.

  void ReleaseMemory() const; // Conceptually 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.
  FFTW_Demag(const char* name,     // Child instance id
	     Oxs_Director* newdtr, // App director
	     const char* argstr);  // MIF input block parameters
  virtual ~FFTW_Demag() { ReleaseMemory(); }
  virtual OC_BOOL Init();
};


#endif // _FFTW_DEMAG
