// SPINFLIP.C
// Functions concerned with spin flips
// © 2021 Peter J. Meyer
#include "iss.h"
// Returns true if spin to be flipped, false otherwise.
// Ising: s is 2 * spin * spin_sum
// Potts: s is the sum of the kronecker deltas for the initial spin value
// minus the sum for the new spin value.
// This function is called only with the Metropolis or the Glauber algorithm.
/*----------------*/
int flip_spin(int s)
{
return ( dynamics_is_metropolis && s <= 0 ? true : PRNG1() < w[s+2*coord_num] );
}
/*------------------------------------------------------*/
void do_ising_spin_flip(int spin_value, int i, int j, ...)
{
int k, l;
num_spins_flipped_this_sweep++;
abs_magnetization -= 2*spin_value;
switch ( dimensionality )
{
case 2:
if ( internal_energy_measured )
abs_internal_energy += 2*spin_value*nn_spin_sum(i,j);
// Actually abs_internal_energy += 2*J*spin_value*nn_spin_sum(i,j);
// but J factored in in norm_internal_energy() in MEAS.C.
switch ( spin_value )
{
case UP_SPIN: // Bit 0 of sites2[i][j] is 0.
sites2[i][j] |= BIT1_0;
break;
case DOWN_SPIN: // Bit 0 of sites2[i][j] is 1.
sites2[i][j] &= BIT0_0;
break;
}
break;
case 3:
k = *(((int *)(&j))+1);
if ( internal_energy_measured )
abs_internal_energy += 2*spin_value*nn_spin_sum(i,j,k);
switch ( spin_value )
{
case UP_SPIN:
sites3[i][j][k] |= BIT1_0;
break;
case DOWN_SPIN:
sites3[i][j][k] &= BIT0_0;
break;
}
break;
case 4:
k = *(((int *)(&j))+1);
l = *(((int *)(&j))+2);
if ( internal_energy_measured )
abs_internal_energy += 2*spin_value*nn_spin_sum(i,j,k,l);
switch ( spin_value )
{
case UP_SPIN:
sites4[i][j][k][l] |= BIT1_0;
break;
case DOWN_SPIN:
sites4[i][j][k][l] &= BIT0_0;
break;
}
break;
}
}
/*-------------------------------------------*/
void do_q_state_potts_spin_flip(int spin_value,
int new_spin_value,
int i, int j, ...)
{
int k, l;
num_spins_flipped_this_sweep++;
if ( spin_value == UP_SPIN )
abs_magnetization -= 2;
// Because spin changes from an up-spin to a non-up-spin.
else if ( new_spin_value == UP_SPIN )
abs_magnetization += 2;
// Because spin changes from a non-up-spin to an up-spin.
// If neither the spin value nor the new spin value are up-spins
// then the absolute magnetization does not change.
switch ( dimensionality )
{
case 2:
// TENTATIVE !!
// Need to check calculation of internal energy and specific heat with Potts model.
if ( internal_energy_measured )
abs_internal_energy += 2*spin_value*sum_kronecker_deltas(spin_value,i,j);
sites2[i][j] &= ~spin_value_mask;
sites2[i][j] |= --new_spin_value;
break;
case 3:
k = *(((int *)(&j))+1);
if ( internal_energy_measured )
abs_internal_energy += 2*spin_value*sum_kronecker_deltas(spin_value,i,j,k);
sites3[i][j][k] &= ~spin_value_mask;
sites3[i][j][k] |= --new_spin_value;
break;
case 4:
k = *(((int *)(&j))+1);
l = *(((int *)(&j))+2);
if ( internal_energy_measured )
abs_internal_energy += 2*spin_value*sum_kronecker_deltas(spin_value,i,j,k,l);
sites4[i][j][k][l] &= ~spin_value_mask;
sites4[i][j][k][l] |= --new_spin_value;
break;
}
}
// The following function is called from assign_initial_spins()
// when an assignment of initial spins results in zero magnetization
// and the user has specified adjust_zero_initial_magnetization.
// This function calls functions above which change the value of abs_magnetization.
// This is of no import since the return value of assign_initial_spins()
// is assigned to abs_magnetization.
/*------------------------------*/
void flip_initial_spin_to_up(void)
{
int i, j, k, l, spin, site_occupied;
// Locate a non-UP-spin and flip it to UP.
switch ( dimensionality )
{
case 2:
for ( i=0; i<size; i++ )
{
for ( j=0; j<size; j++ )
{
spin = site_occupied = spin_at_site(i,j);
if ( site_occupied )
{
if ( spin != UP_SPIN )
{
if ( model_is_ising )
do_ising_spin_flip(spin,i,j);
else // model is q-state Potts
do_q_state_potts_spin_flip(spin,UP_SPIN,i,j);
return;
}
}
}
}
break;
case 3:
for ( i=0; i<size; i++ )
{
for ( j=0; j<size; j++ )
{
for ( k=0; k<size; k++ )
{
spin = site_occupied = spin_at_site(i,j,k);
if ( site_occupied )
{
if ( spin != UP_SPIN )
{
if ( model_is_ising )
do_ising_spin_flip(spin,i,j,k);
else // model is q-state Potts
do_q_state_potts_spin_flip(spin,UP_SPIN,i,j,k);
return;
}
}
}
}
}
break;
case 4:
for ( i=0; i<size; i++ )
{
for ( j=0; j<size; j++ )
{
for ( k=0; k<size; k++ )
{
for ( l=0; l<size; l++ )
{
spin = site_occupied = spin_at_site(i,j,k,l);
if ( site_occupied )
{
if ( spin != UP_SPIN )
{
if ( model_is_ising )
do_ising_spin_flip(spin,i,j,k,l);
else // model is q-state Potts
do_q_state_potts_spin_flip(spin,UP_SPIN,i,j,k,l);
return;
}
}
}
}
}
}
break;
}
}