/* FILE: transformzeeman.h         -*-Mode: c++-*-
 *
 * Zeeman (applied field) energy, derived from Oxs_Energy class,
 * specified from a Tcl proc.  This is a generalization of the
 * Oxs_ScriptUZeeman and Oxs_FixedZeeman classes.
 *
 */

#ifndef _OXS_TRANSFORMZEEMAN
#define _OXS_TRANSFORMZEEMAN

#include <vector>

#include "nb.h"

#include "director.h"
#include "energy.h"
#include "chunkenergy.h"
#include "simstate.h"
#include "threevector.h"
#include "util.h"
#include "vectorfield.h"

OC_USE_STD_NAMESPACE;

/* End includes */

class Oxs_TransformZeeman:public Oxs_ChunkEnergy {
private:
  vector<Nb_TclCommandLineOption> command_options;
  Nb_TclCommand cmd;

  OC_REAL8m hmult;
  OC_UINT4m number_of_stages;

  void GetAppliedField
  (const Oxs_SimState& state,
   ThreeVector& row1, ThreeVector& row2, ThreeVector& row3,
   ThreeVector& drow1, ThreeVector& drow2, ThreeVector& drow3) const;

  enum TransformType { identity, diagonal, symmetric, general };
  TransformType transform_type;

  mutable OC_UINT4m mesh_id;
  Oxs_OwnedPointer<Oxs_VectorField> fixedfield_init;
  mutable Oxs_MeshValue<ThreeVector> fixedfield;
  /// fixedfield is a cached value filled by
  /// fixedfield_init when a change in mesh is
  /// detected.
  mutable OC_REAL8m max_fixedfield; // Cached value, maximum
  // magnitude across fixedfield.

  // Transform implementation; the D* entries are derivatives.
  mutable ThreeVector tfrm_row1,tfrm_row2,tfrm_row3;
  mutable ThreeVector Dtfrm_row1,Dtfrm_row2,Dtfrm_row3;

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 {
    ComputeEnergyAlt(state,oced);
  }

  virtual void ComputeEnergyChunkInitialize
  (const Oxs_SimState& state,
   Oxs_ComputeEnergyDataThreaded& ocedt,
   Oc_AlignedVector<Oxs_ComputeEnergyDataThreadedAux>& thread_ocedtaux,
   int number_of_threads) const;

  virtual void ComputeEnergyChunk(const Oxs_SimState& state,
                                  Oxs_ComputeEnergyDataThreaded& ocedt,
                                  Oxs_ComputeEnergyDataThreadedAux& ocedtaux,
                                  OC_INDEX node_start,OC_INDEX node_stop,
                                  int threadnumber) const;
public:
  virtual const char* ClassName() const; // ClassName() is
  /// automatically generated by the OXS_EXT_REGISTER macro.
  Oxs_TransformZeeman(const char* name,     // Child instance id
		      Oxs_Director* newdtr, // App director
		      const char* argstr);  // MIF input block parameters
  virtual ~Oxs_TransformZeeman();
  virtual OC_BOOL Init();
  virtual void StageRequestCount(unsigned int& min,
				 unsigned int& max) const;
};


#endif // _OXS_TRANSFORMZEEMAN
