This section provides an extended dissection of a simple Oxs_Energy child class. The computational details are kept as simple as possible, so the discussion can focus on the C++ class structural details. Although the calculation details will vary between energy terms, the class structure issues discussed here apply across the board to all energy terms.
The particular example presented here is for simulating uniaxial magneto-crystalline energy, with a single anisotropy constant, K1, and a single axis, axis, which are uniform across the sample. The class definition (.h) and code (.cc) are displayed in Fig. 4.2 and 4.3, respectively.
/* FILE: exampleanisotropy.h * * Example anisotropy class definition. * This class is derived from the Oxs_Energy class. * */ #ifndef _OXS_EXAMPLEANISOTROPY #define _OXS_EXAMPLEANISOTROPY #include "energy.h" #include "threevector.h" #include "meshvalue.h" /* End includes */ class Oxs_ExampleAnisotropy:public Oxs_Energy { private: double K1; // Primary anisotropy coeficient ThreeVector axis; // Anisotropy direction public: virtual const char* ClassName() const; // ClassName() is /// automatically generated by the OXS_EXT_REGISTER macro. virtual BOOL Init(); Oxs_ExampleAnisotropy(const char* name, // Child instance id Oxs_Director* newdtr, // App director Tcl_Interp* safe_interp, // Safe interpreter const char* argstr); // MIF input block parameters virtual ~Oxs_ExampleAnisotropy() {} virtual void GetEnergyAndField(const Oxs_SimState& state, Oxs_MeshValue<REAL8m>& energy, Oxs_MeshValue<ThreeVector>& field ) const; }; #endif // _OXS_EXAMPLEANISOTROPY
/* FILE: exampleanisotropy.cc -*-Mode: c++-*- * * Example anisotropy class implementation. * This class is derived from the Oxs_Energy class. * */ #include "exampleanisotropy.h" // Oxs_Ext registration support OXS_EXT_REGISTER(Oxs_ExampleAnisotropy); /* End includes */ #define MU0 12.56637061435917295385e-7 /* 4 PI 10^7 */ // Constructor Oxs_ExampleAnisotropy::Oxs_ExampleAnisotropy( const char* name, // Child instance id Oxs_Director* newdtr, // App director Tcl_Interp* safe_interp, // Safe interpreter const char* argstr) // MIF input block parameters : Oxs_Energy(name,newdtr,safe_interp,argstr) { // Process arguments K1=GetRealInitValue("K1"); axis=GetThreeVectorInitValue("axis"); VerifyAllInitArgsUsed(); } BOOL Oxs_ExampleAnisotropy::Init() { return 1; } void Oxs_ExampleAnisotropy::GetEnergyAndField (const Oxs_SimState& state, Oxs_MeshValue<REAL8m>& energy, Oxs_MeshValue<ThreeVector>& field ) const { const Oxs_MeshValue<REAL8m>& Ms_inverse = *(state.Ms_inverse); const Oxs_MeshValue<ThreeVector>& spin = state.spin; UINT4m size = state.mesh->Size(); for(UINT4m i=0;i<size;++i) { REAL8m field_mult = (2.0/MU0)*K1*Ms_inverse[i]; if(field_mult==0.0) { energy[i]=0.0; field[i].Set(0.,0.,0.); continue; } REAL8m dot = axis*spin[i]; field[i] = (field_mult*dot) * axis; if(K1>0) { energy[i] = -K1*(dot*dot-1.0); // Make easy axis zero energy } else { energy[i] = -K1*dot*dot; // Easy plane is zero energy } } }