/* FILE: randomsiteexchange.h            -*-Mode: c++-*-
 *
 * 6 neighbor exchange energy on random links on rectangular mesh,
 * with random A.
 *
 */

#ifndef _OXS_RANDOMSITEEXCHANGE
#define _OXS_RANDOMSITEEXCHANGE

#include <vector>

#include "oc.h"
#include "director.h"
#include "energy.h"
#include "meshvalue.h"
#include "simstate.h"
#include "threevector.h"

OC_USE_STD_NAMESPACE;

/* End includes */

// MSC++ 5.0 doesn't like embedded classes used for
// vector template types.  So, we just define this
// outside, with a really long name. <g>
struct Oxs_RandomSiteExchangeLinkParams {
  OC_INDEX index1,index2;  // Offsets into mesh to cells in pair
  OC_REAL8m Acoef;          // A * (directional cellsize)^-2
};

// The next 3 operators are defined so MSVC++ 5.0 will accept
// vector<Oxs_RandomSiteExchangeLinkParams>, but are left undefined
// because there is no meaningful way to define them.
OC_BOOL operator<(const Oxs_RandomSiteExchangeLinkParams&,
               const Oxs_RandomSiteExchangeLinkParams&);
OC_BOOL operator>(const Oxs_RandomSiteExchangeLinkParams&,
               const Oxs_RandomSiteExchangeLinkParams&);
OC_BOOL operator==(const Oxs_RandomSiteExchangeLinkParams&,
                const Oxs_RandomSiteExchangeLinkParams&);

class Oxs_RandomSiteExchange:public Oxs_Energy {
private:
  OC_REAL8m linkprob;  // Probability that one link from any given
  /// cell has non-zero A.
  OC_REAL8m Amin,Amax; // Uniform range of values for links with
  /// non-zero A.

  mutable vector<Oxs_RandomSiteExchangeLinkParams> links;
  void FillLinkList(const Oxs_Mesh* mesh) const;

  mutable OC_UINT4m mesh_id;

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

  // Supplied outputs, in addition to those provided by Oxs_Energy.
  Oxs_ScalarOutput<Oxs_RandomSiteExchange> maxspinangle_output;
  Oxs_ScalarOutput<Oxs_RandomSiteExchange> stage_maxspinangle_output;
  Oxs_ScalarOutput<Oxs_RandomSiteExchange> run_maxspinangle_output;
  void UpdateDerivedOutputs(const Oxs_SimState& state);
  String MaxSpinAngleStateName() const {
    String dummy_name = InstanceName();
    dummy_name += ":Max Spin Angle";
    return dummy_name;
  }
  String StageMaxSpinAngleStateName() const {
    String dummy_name = InstanceName();
    dummy_name += ":Stage Max Spin Angle";
    return dummy_name;
  }
  String RunMaxSpinAngleStateName() const {
    String dummy_name = InstanceName();
    dummy_name += ":Run Max Spin Angle";
    return dummy_name;
  }

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


#endif // _OXS_RANDOMSITEEXCHANGE
