## Cheetah template for skeletal writer in C
## See the Cheetah documentation for proper syntax

//
// Automatically generated by skel. Modify at your own risk.

\#include "adios.h"
\#include "mpi.h"
\#include "skel/skel_xml_output.h"
\#include <stdlib.h>
\#include <stdio.h>

int main (int argc, char ** argv)
{

MPI_Init (&argc, &argv);

double skel_init_timer = 0;
double skel_open_timer = 0;
double skel_access_timer = 0;
double skel_close_timer = 0;
double skel_total_timer = 0;

// Time the init
MPI_Barrier (MPI_COMM_WORLD);
skel_init_timer -= MPI_Wtime();

#if $noxml
adios_init_noxml (MPI_COMM_WORLD);
#else
adios_init ("${project}_skel.xml", MPI_COMM_WORLD);
#end if

skel_init_timer += MPI_Wtime();

int skel_mpi_size, skel_mpi_rank, skel_i;
uint64_t adios_groupsize;
MPI_Comm_rank (MPI_COMM_WORLD, &skel_mpi_rank);
MPI_Comm_size (MPI_COMM_WORLD, &skel_mpi_size);

int64_t adios_handle;
uint64_t skel_total_size;

// Scalar declarations
#for v in filter (lambda x: x.get_dims() is None, $bpy.get_vars() ):
$v.get_c_type() $v.get_safe_name();
#end for

// Skel variables for global array management
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
    #for sv in $v.get_offset_vars()
int $sv [$bpy.get_num_procs()] = {$v.get_offset_values_str($sv)};
    #end for
#end for


// Array declarations
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
$v.get_c_type() * $v.get_safe_name();
#end for

#if $noxml
int64_t skel_adios_group;

int color = skel_mpi_rank / 2;

adios_allocate_buffer (ADIOS_BUFFER_ALLOC_NOW, $bpy.get_buf_size_mb());
adios_declare_group (&skel_adios_group, "${bpy.get_group_name()}", "", adios_stat_no);

char paramstring[<%= len(self.bpy.get_parameters()) + 64 %>];
//sprintf (paramstring, "color:%i;%s", color, "$bpy.get_parameters()");
sprintf (paramstring, "%s", "$bpy.get_parameters()");
adios_select_method (skel_adios_group, "$bpy.get_method()", paramstring, "");

## This loop generates any needed skel auxiliary variables
#for v in $bpy.get_vars():
    #if $v.has_global_bounds():
        #for sv in $v.get_offset_vars()
adios_define_var (skel_adios_group, "$sv", "", adios_integer, "", "", "");
        #end for
    #end if
#end for

## This loop handles the user defined variables
    #for v in $bpy.get_vars():
adios_define_var (skel_adios_group, "$v.get_name()", "", $v.get_adios_type(), "$v.get_dims_str()", "$v.get_global_dims_str()", "$v.get_offset_vars_str()");
    #end for


#end if

int skel_steps = ${bpy.get_steps()};
int step;
for (step = 0; step < skel_steps; step++)
{

  // Scalar Initializations
#for v in filter (lambda x: x.get_dims() is None, $bpy.get_vars() ):
    #if not v.get_value(): 
    $v.get_safe_name = 16; <% sys.stderr.write ('No value found for variable "%s", using default value.\n' % v.get_name()) %>
    #else:
    $v.get_safe_name = $v.get_value();
    #end if
#end for
 
 

  // Array Allocation & Initializations
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
    $v.get_safe_name() = ($v.get_c_type()*) malloc (#echo '*'.join (str(x) for x in $v.get_dims() )#*sizeof ($v.get_c_type()));
    for (skel_i = 0; skel_i < #echo '*'.join (str(x) for x in $v.get_dims() )#; skel_i++)
        $v.get_safe_name()[skel_i] = ($v.get_c_type()) skel_mpi_rank;
#end for

##fields_FieldE_x = (float*) malloc (size_x*size_y*size_z * sizeof (float) );
##for (skel_i = 0; skel_i < size_x*size_y*size_z; skel_i++) 
##    fields_FieldE_x[skel_i] = (float) skel_mpi_rank;


// Time the opens
MPI_Barrier (MPI_COMM_WORLD);
skel_open_timer -= MPI_Wtime();
skel_total_timer -= MPI_Wtime();
MPI_Comm comm = MPI_COMM_WORLD;
adios_open(&adios_handle, "${bpy.get_group_name()}", "out_${bpy.get_group_name()}_write.bp", "w", comm);
skel_open_timer += MPI_Wtime();

// Time the writes
skel_access_timer -= MPI_Wtime();

// Set the adios group size
adios_groupsize =
#for v in $bpy.get_vars():
                     $v.get_size() +
#end for
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
    #for sv in $v.get_offset_vars()
                     4 + 
    #end for
#end for
                     0;

adios_group_size (adios_handle, adios_groupsize, &skel_total_size);


// Write each variable
// First the scalars
#for v in filter (lambda x: x.get_dims() is None, $bpy.get_vars() ):
    adios_write (adios_handle, "$v.get_name", &$v.get_safe_name());
#end for

// Next Skel variables
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
    #for sv in $v.get_offset_vars()
    adios_write (adios_handle, "$sv", &($sv [skel_mpi_rank] ) );
    #end for
#end for

// Now the arrays
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
    adios_write (adios_handle, "$v.get_name", $v.get_safe_name());
#end for


// Stop timing the writes
skel_access_timer += MPI_Wtime();

// Time the closes
skel_close_timer -= MPI_Wtime();
adios_close (adios_handle);
skel_close_timer += MPI_Wtime();
skel_total_timer += MPI_Wtime();

// Output results

 skel_write_coarse_xml_data (skel_open_timer, skel_access_timer, skel_close_timer, skel_total_timer);
double skel_total_init, skel_total_open, skel_total_access, skel_total_close, skel_total_total;
MPI_Reduce (&skel_init_timer, &skel_total_init, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce (&skel_open_timer, &skel_total_open, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce (&skel_access_timer, &skel_total_access, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce (&skel_close_timer, &skel_total_close, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce (&skel_total_timer, &skel_total_total, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
if (skel_mpi_rank == 0) {
    fprintf (stdout, "\n");
    fprintf (stdout, "\n*************************");
    fprintf (stdout, "\n   Groupsize: %lli", adios_groupsize);
    fprintf (stdout, "\n  Open Time: %f", skel_total_open);
    fprintf (stdout, "\nAccess Time: %f", skel_total_access);
    fprintf (stdout, "\n Close Time: %f", skel_total_close);
    fprintf (stdout, "\n Total Time: %f", skel_total_total);
    fprintf (stdout, "\n*************************");
    fprintf (stdout, "\n");
}

// Free the arrays
#for v in filter (lambda x: x.get_dims() is not None, $bpy.get_vars() ):
    free ($v.get_safe_name);
#end for

} // End for step = 0 to skel_steps - 1



// Clean up
adios_finalize(0);
MPI_Finalize();
}
