/* FILE: simpledemag.h            -*-Mode: c++-*-
 *
 * Average H demag field across rectangular cells.  Simple
 * implementation that does not take advantage of any memory
 * saving or calculation speed improvements possible using
 * symmetries in interaction tensor or realness of data in
 * spatial domain.
 *
 */

#ifndef _OXS_SIMPLEDEMAG
#define _OXS_SIMPLEDEMAG

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

/* End includes */

class Oxs_SimpleDemag:public Oxs_Energy {
private:
  mutable OC_INDEX xdim;  // Natural size
  mutable OC_INDEX ydim;
  mutable OC_INDEX zdim;
  mutable OC_INDEX totalsize;
  mutable OC_INDEX pxdim;  // Padded size
  mutable OC_INDEX pydim;
  mutable OC_INDEX pzdim;
  mutable OC_INDEX ptotalsize;

  mutable OC_UINT4m mesh_id;
  mutable OC_REAL8m energy_density_error_estimate; // Cached value,
  /// initialized when mesh changes.

  // The A## arrays hold demag coefficients, transformed into
  // frequency domain.  These are held long term.  Mx, My, Mz
  // and Hcomp are used as temporary space to convert M into
  // H.
  mutable Oxs_Complex *A00;
  mutable Oxs_Complex *A01;
  mutable Oxs_Complex *A02;
  mutable Oxs_Complex *A11;
  mutable Oxs_Complex *A12;
  mutable Oxs_Complex *A22;
  mutable Oxs_Complex *Mx;
  mutable Oxs_Complex *My;
  mutable Oxs_Complex *Mz;
  mutable Oxs_Complex *Hcomp;
  mutable Oxs_FFT3D fft; // All transforms are same size, so we need
  /// only one Oxs_FFT3D object.

  void FillCoefficientArrays(const Oxs_Mesh* mesh) const;
  /// Conceptually const.

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

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

  virtual void ComputeEnergy(const Oxs_SimState& state,
                             Oxs_ComputeEnergyData& oced) const;

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


#endif // _OXS_SIMPLEDEMAG
