/**
 * arrays_write.c
 *
 * ADIOS is freely available under the terms of the BSD license described
 * in the COPYING file in the top level directory of this source distribution.
 *
 * Copyright (c) 2008 - 2009.  UT-BATTELLE, LLC. All rights reserved.
 *
 *  Created on: Jul 1, 2013
 *  Author: Magda Slawinska aka Magic Magg magg dot gatech at gmail.com
 *
 * This is an example of writing a 1D array of doubles. Each process
 * writes the NX sized array of doubles.
 */

#include "mpi.h"
#include "adios.h"
#include "adios_read.h"  // for adios_errno

#include "misc.h"
#include "utils.h"
#include "cfg.h"
#include "test_common.h"

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>

static struct adios_tsprt_opts adios_opts;
static int  rank=0, size=0;

static int
create_and_write_stream(char *filename, MPI_Comm  comm)
{
    int64_t	adios_grp;
    int64_t 	adios_handle;   // the ADIOS file handle
    int  NX = NX_DIM;             // size of 1D array we will write
    double t[NX_DIM];             // this will contain the variables to be tranpsorted
    int err_count = 0;
    int retval;


    // now declare a group
    adios_declare_group(&adios_grp, "temperature", "iter", adios_stat_default);

    SET_ERROR_IF_NOT_ZERO(adios_select_method(adios_grp, adios_opts.transport, "", ""), err_count);
    RET_IF_ERROR(err_count, rank);

    int global_bounds= NX * size;
    int		offsets= NX * rank;

    adios_define_var (adios_grp, "NX", "", adios_integer, 0, 0, 0);
    adios_define_var (adios_grp, "size", "", adios_integer, 0, 0, 0);
    adios_define_var (adios_grp, "rank", "", adios_integer, 0, 0, 0);
    adios_define_var (adios_grp, "global_bounds", "", adios_integer, 0, 0, 0);
    adios_define_var (adios_grp, "offsets", "", adios_integer, 0, 0, 0);
    // NX - local var dimensions, global_bounds - global dimension, offsets - variable local offsets
    adios_define_var (adios_grp, "var_1d_array", "", adios_double, "10", "global_bounds", "offsets");
    
    // open our group and transport method associated with it
    adios_open (&adios_handle, "temperature", filename, "w", comm);
    // NX, size, rank, global_bounds, offsets,var_1d_array
    uint64_t adios_groupsize = 4 + 4 + 4 + 4 + 4 + NX * 8;
    uint64_t adios_totalsize = 0;
    
    retval=adios_group_size (adios_handle, adios_groupsize, &adios_totalsize);
    if (test_verbose) {
	fprintf(stderr, "Rank=%d adios_group_size(): adios_groupsize=%" PRIu64 ", adios_totalsize=%" PRIu64 ", retval=%d\n",
		rank, adios_groupsize, adios_totalsize, retval);
    }
    
    // init the array that I will transport over the sea
    gen_1D_array(t, NX, rank);
    
    // write; don't check errors for simplicity reasons
    adios_write(adios_handle, "NX", &NX);
    adios_write(adios_handle, "size", &size);
    adios_write(adios_handle, "rank", &rank);
    adios_write(adios_handle, "global_bounds", &global_bounds);
    adios_write(adios_handle, "offsets", &offsets);
    adios_write(adios_handle, "var_1d_array", t);
    
    if (test_verbose) {
	fprintf(stderr, "Rank=%d committed write\n", rank);
    }
    
    adios_close(adios_handle);
    
}    

int main(int argc, char ** argv)
{
    char filename[256];    // stream 1
    char filename2[256];    // stream 2
    MPI_Comm  comm = MPI_COMM_WORLD; // required for ADIOS
	
    int64_t 	adios_handle2;   // the ADIOS file handle

    GET_ENTRY_OPTIONS(adios_opts, "Runs writers.");


    // where I will write the data
    strcpy(filename, FILE_NAME);
    strcpy(filename2, "test2.bp");

    // MPI initialization
    MPI_Init(&argc, &argv);
    MPI_Comm_rank (comm, &rank);
    MPI_Comm_size (comm, &size);

    if (adios_init_noxml(comm)) printf("ADIOS INIT FAILED\n");

    // returns 0 (buffer allocated) or 1 (seems everything fine)
    // I guess size of the buffer in MB
    adios_set_max_buffer_size (20);
    
    create_and_write_stream(filename, comm);

    create_and_write_stream(filename2, comm);

    // clean and finalize the system
    adios_finalize(rank);

    MPI_Finalize();

    return 0;
}

