//  TS_VALS.C
//  © 2021 Peter J. Meyer

#include "iss.h"

#include <process.h>

#define ALWAYS_WRITE_AUTOCORRELATION true

/*----------------------------------------*/
void write_timeslice_values(FILE *of, int w)
{
int i, write_normed_magnetization;
int write_autocorrelation=true, p=5;
double first_second_moment, magnetization_0;

magnetization_0 = fabs(magnetization[0][0]);
write_normed_magnetization = ( magnetization_0 > 0.001 && magnetization_0 < 1 );
//  If magnetization_0 < 0.001 then the normed magnetization values are too large.

//  Print first line of heading.

fprintf(of,"\n\n%*s%*s",w/2+1,"Time",w,"Mean");

if ( standard_deviation_measured )
    fprintf(of,"%*s",w,"Std.");

if ( write_normed_magnetization ) 
    fprintf(of,"%*s",w,"Normed");

if ( second_moment_measured )
    {
    fprintf(of,"%*s",w,"Second");
    fprintf(of,"%*s",w,"2ndmom");
    }

if ( autocorrelation_measured )
    {
    fprintf(of,"%*s",w,"Auto-");
    #if WR_ST_DEV_AUTOCORRELATON
    fprintf(of,"%*s",w,"Std.dev.");
    #endif
    }

if ( internal_energy_measured )
    {
    fprintf(of,"%*s",w,"Internal");
    fprintf(of,"%*s",w,"Std.dev.");
    fprintf(of,"%*s",w,"Specific");
    }

if ( binder_cumulant_measured )
    fprintf(of,"%*s",w,"Binder");

if ( log_values_requested )
    {
    fprintf(of,"%*s%*s",w,"lnMCS",w,"lnMean");

    if ( write_normed_magnetization )
        fprintf(of,"%*s",w,"lnNormed");

    #if WR_LOG_ST_DEV_MAGNETISM
    if ( standard_deviation_measured )
        fprintf(of,"%*s",w,"lnStd.");
    #endif

    if ( second_moment_measured )
        {
        fprintf(of,"%*s",w,"lnSecond");
        fprintf(of,"%*s",w,"ln2ndmom");
        }

    if ( autocorrelation_measured )
        fprintf(of,"%*s",w,"lnAuto-");

    if ( internal_energy_measured )
        {
        fprintf(of,"%*s",w,"ln Int.");
        //  Not printing log of std. dev. of internal energy.
        fprintf(of,"%*s",w,"ln Spec.");
        }
    }

//  Print second line of heading.

fprintf(of,"\n%*s%*s",w/2+1,"point",w,"magn'n");

if ( standard_deviation_measured )
    fprintf(of,"%*s",w,"dev'n");

if ( write_normed_magnetization )
    fprintf(of,"%*s",w,"magn'n");

if ( second_moment_measured )
    {
    fprintf(of,"%*s",w,"moment");
    fprintf(of,"%*s",w,"/first");
    }

if ( autocorrelation_measured )
    {
    fprintf(of,"%*s",w,"corr'n");
    #if WR_ST_DEV_AUTOCORRELATON
    fprintf(of,"%*s",w,"Autocor.");
    #endif
    }

if ( internal_energy_measured )
    {
    fprintf(of,"%*s",w,"energy");
    fprintf(of,"%*s",w,"int.en.");
    fprintf(of,"%*s",w,"heat");
    }

if ( binder_cumulant_measured )
    fprintf(of,"%*s",w,"cumulant");

if ( log_values_requested )
    {
    fprintf(of,"%*s%*s",w,"",w,"magn'n");

    if ( write_normed_magnetization )
        fprintf(of,"%*s",w,"magn'n");

    #if WR_LOG_ST_DEV_MAGNETISM
    if ( standard_deviation_measured )
        fprintf(of,"%*s",w,"dev'n");
    #endif

    if ( second_moment_measured )
        {
        fprintf(of,"%*s",w,"moment");
        fprintf(of,"%*s",w,"/first");
        }

    if ( autocorrelation_measured )
        fprintf(of,"%*s",w,"corr'n");

    if ( internal_energy_measured )
        {
        fprintf(of,"%*s",w,"energy");
        //  Not printing log of std. dev. of internal energy.
        fprintf(of,"%*s",w,"heat");
        }
    }

fprintf(of,"\n\n");

if ( second_moment_measured )
    {
    if ( ( first_second_moment = magnetization[1][2] ) == NON_EXISTENT )
        first_second_moment = 0;
    //  Why not first_second_moment = magnetization[*0*][2] ?
    //  Why norm the 2nd moment wrt value at 2nd timeslice not 1st?
    }

//  Now print the values.

for ( i=0; i<num_time_slices; i++ )
    {
    if ( magnetization[i][2] == NON_EXISTENT )
        break;

    //  Write MCS and magnetization.
    fprintf(of,"%*d%*.*f",
        w/2+1,i*step_length,w,p,magnetization[i][0]);

    //  Write standard deviation.
    if ( standard_deviation_measured )
        {
        if ( magnetization[i][1] != NON_EXISTENT )
            fprintf(of,"%*.*f",w,p,magnetization[i][1]);
        else
            fprintf(of,"%*s",w,"");
        }
    if ( write_normed_magnetization )
        fprintf(of,"%*.*f",w,p,magnetization[i][0]/magnetization_0);

    //  Write second moment.
    if ( second_moment_measured )
        {
        fprintf(of,"%*.*f",w,p,magnetization[i][2]);  
        if ( i )
            {      
            if ( first_second_moment )
                fprintf(of,"%*.*f",w,4,magnetization[i][2]/first_second_moment);
            else
                fprintf(of,"%*s",w,"");
            }
        else
            fprintf(of,"%*s",w,"");
        }

    //  Write autocorrelation and standard deviation of autocorrelation.
    if ( autocorrelation_measured )
        {
        if ( write_autocorrelation || ALWAYS_WRITE_AUTOCORRELATION )
            {
            fprintf(of,"%*.*f",w,p,autocorrelation[i][0]);
            #if WR_ST_DEV_AUTOCORRELATON
            if ( autocorrelation[i][1] != NON_EXISTENT )
                fprintf(of,"%*.*f",w,p,autocorrelation[i][1]);
            else
                fprintf(of,"%*s",w,"");
            #endif
            write_autocorrelation = ( autocorrelation[i][0] > 0 );
            }
        else
            {
            fprintf(of,"%*s",w,"");
            #if WR_ST_DEV_AUTOCORRELATON
            fprintf(of,"%*s",w,"");
            #endif
            }
        }

    if ( internal_energy_measured )
        {
        //  internal energy per spin
        fprintf(of,"%*.*f",w,p,internal_energy[i][0]);
        //  standard deviation of internal energy per spin
        if ( internal_energy[i][1] != NON_EXISTENT )
            fprintf(of,"%*.*f",w,p,internal_energy[i][1]);
        else
            fprintf(of,"%*s",w,"");
        //  specific heat per spin
        fprintf(of,"%*.*f",w,p,internal_energy[i][2]);
        #if false
        if ( internal_energy[i][2] != NON_EXISTENT )
            fprintf(of,"%*.*f",w,p,internal_energy[i][2]);
        else
            fprintf(of,"%*s",w,"");
        #endif
        }

    if ( binder_cumulant_measured )
        fprintf(of,"%*.*f",w,p,magnetization[i][3]);

    if ( log_values_requested )
        {
        //  Write log of MCS.
        if ( i > 0 )
            fprintf(of,"%*.*f",w,p,log(i*step_length));
        else
            fprintf(of,"%*s",w,"");

        //  Write log of magnetization.
        if ( magnetization[i][0] > 0 )
            fprintf(of,"%*.*f",w,p,log(magnetization[i][0]));
        else
            fprintf(of,"%*s",w,"");

        //  Write log of normed magnetization.
        if ( write_normed_magnetization )
            {
            if ( magnetization[i][0] > 0 )
                fprintf(of,"%*.*f",w,p,log(magnetization[i][0]/magnetization_0));
            else
                fprintf(of,"%*s",w,"");   
            }
 
        #if WR_LOG_ST_DEV_MAGNETISM
        //  Write log of standard deviation.
        if ( standard_deviation_measured )
            {
            if ( magnetization[i][1] > 0 )
                fprintf(of,"%*.*f",w,p,log(magnetization[i][1]));
            else
                fprintf(of,"%*s",w,"");
            }
        #endif

        //  Write log of second moment.
        if ( second_moment_measured )
            {
            if (  magnetization[i][2] > 0 ) 
                fprintf(of,"%*.*f",w,p,log(magnetization[i][2]));
            else
                fprintf(of,"%*s",w,"");
            if ( i )
                {
                if ( first_second_moment 
                    && magnetization[i][2]/first_second_moment > 0 )
                    fprintf(of,"%*.*f",w,p,
                        log(magnetization[i][2]/first_second_moment));
                else
                    fprintf(of,"%*s",w,"");
                }
            else
                fprintf(of,"%*s",w,"");
            }

        //  Write log of autocorrelation.
        if ( autocorrelation_measured )
            {
            if ( write_autocorrelation && autocorrelation[i][0] > 0 )
                fprintf(of,"%*.*f",w,p,log(autocorrelation[i][0]));         
            else
                fprintf(of,"%*s",w,"");
            }

        if ( internal_energy_measured )
            {
            //  log of internal energy
            if ( internal_energy[i][0] > 0 )
                fprintf(of,"%*.*f",w,p,log(internal_energy[i][0]));
            else
                fprintf(of,"%*s",w,"");
            //  log of specific heat
            if ( internal_energy[i][2] > 0 )
                fprintf(of,"%*.*f",w,p,log(internal_energy[i][2]));
            else
                fprintf(of,"%*s",w,"");
            }           
        }

    #if !COMPLETE_SAMPLE_ON_ESCAPE
    //  This is #defined in ISS_DEF.H
    if ( escape_key_termination )
        {
        if ( (unsigned long)(i*step_length) == step_length*(mcs_done/step_length) )
            fprintf(of,"    Escape");
            //  Show where data is discontinuous.
        }
    #endif

    fprintf(of,"\n");
    }
}