예제 #1
0
파일: result.c 프로젝트: juapebe/HPC
void write_hyperprior(DATA *data, SUMMARY *summary) {
  FILE *fp1 = fopen("hist_alpha_prey", "w");
  FILE *fp2 = fopen("hist_alpha_IP", "w");
  FILE *fp3 = fopen("hist_mu", "w");
  FILE *fp4 = fopen("hist_eta", "w");
  FILE *fp5 = fopen("hist_eta0", "w");

  write_histogram(fp1, &(summary->hist_alpha_prey));
  write_histogram(fp2, &(summary->hist_alpha_IP));
  write_histogram(fp3, &(summary->hist_mu));
  write_histogram2(fp4, &(summary->hist_eta));
  write_histogram2(fp5, &(summary->hist_eta0));

  fclose(fp1);
  fclose(fp2);
  fclose(fp3);
  fclose(fp4);
  fclose(fp5);
}  
예제 #2
0
int start_node(  struct ChannelsConfigInterface *chan_if, int nodeid ){
    BigArrayPtr sorted_array = NULL;
    const size_t data_size = sizeof(BigArrayItem)*ARRAY_ITEMS_COUNT;

    /*If can use bitonic sort*/
    if ( test_sse41_CPU() ){
        WRITE_LOG(LOG_ERR, "allocate bitonic sort memories\n");
        /*we needed an extra buf to use with bitonic sort*/
        BigArrayPtr extra_buf = NULL;

        /*allocated memory should be aligned*/
        extra_buf = aligned_malloc(data_size, SSE2_ALIGNMENT);
        if ( !extra_buf ) {
            WRITE_LOG(LOG_ERR, "Can't allocate memories\n");
            abort();
        }
        sorted_array = aligned_malloc(data_size, SSE2_ALIGNMENT);
        if (!sorted_array) {
            WRITE_LOG(LOG_ERR, "Can't allocate memories\n");
            abort();
        }
        /*Read source data from STDIN*/
        struct UserChannel *channel = chan_if->Channel(chan_if, EInputOutputNode, 1, EChannelModeRead );
        const ssize_t readed = read( channel->fd, (void*)sorted_array, data_size);
        WRITE_FMT_LOG(LOG_ERR, "readed input file, expected size=%d, read size=%d\n", data_size, readed);
        assert(readed == data_size );
        WRITE_LOG(LOG_DETAILED_UI, "Start bitonic sorting\n");
        bitonic_sort_chunked((float*)sorted_array, ARRAY_ITEMS_COUNT, (float*)extra_buf, DEFAULT_CHUNK_SIZE);
        WRITE_LOG(LOG_DETAILED_UI, "Bitonic sorting complete\n");
        aligned_free(extra_buf);
    }
    /*If can't use bitonic  - then use c qsort*/
    else{
        WRITE_LOG(LOG_ERR, "qsort will used\n");
        BigArrayPtr unsorted_array = NULL;
        unsorted_array = malloc( data_size );
        if ( !unsorted_array ) {
            WRITE_LOG(LOG_ERR, "Can't allocate memories\n");
            abort();
        }
        if ( unsorted_array ){
            /*Read source data from STDIN*/
            const ssize_t readed = read( STDIN, (void*)unsorted_array, data_size);
            WRITE_FMT_LOG(LOG_ERR, "readed input file, expected size=%d, read size=%d\n", data_size, readed);
            assert(readed == data_size );
        }
        WRITE_LOG(LOG_DETAILED_UI, "Start qsort sorting\n");
        sorted_array = alloc_copy_array( unsorted_array, ARRAY_ITEMS_COUNT );
        qsort( sorted_array, ARRAY_ITEMS_COUNT, sizeof(BigArrayItem), quicksort_BigArrayItem_comparator );
        free(unsorted_array);
    }

    struct UserChannel *channel = chan_if->Channel( chan_if, EManagerNode, 1, EChannelModeWrite );
    assert(channel);
#if LOG_LEVEL == LOG_DEBUG
    channel->DebugPrint(channel, stderr);
#endif
    /*send crc of sorted array to the manager node*/
    uint32_t crc = array_crc( sorted_array, ARRAY_ITEMS_COUNT );
    WRITE_FMT_LOG(LOG_DEBUG, "write crc=%u into fd=%d", crc, channel->fd);
    write_crc( channel->fd, crc );
    /*send of crc complete*/

    /*prepare histogram data, with step defined by BASE_HISTOGRAM_STEP*/
    int histogram_len = 0;
    HistogramArrayPtr histogram_array = alloc_histogram_array_get_len(
            sorted_array, 0, ARRAY_ITEMS_COUNT, BASE_HISTOGRAM_STEP, &histogram_len );

    WRITE_LOG(LOG_DEBUG, "histogram prepared, sending...");

    struct Histogram single_histogram;
    single_histogram.src_nodeid = nodeid;
    single_histogram.array_len = histogram_len;
    single_histogram.array = histogram_array;

    /*send histogram to manager*/
    channel = chan_if->Channel(chan_if, EManagerNode, 1, EChannelModeWrite);
    assert(channel);
    write_histogram( channel->fd, &single_histogram );

    struct UserChannel *chanw = chan_if->Channel(chan_if, EManagerNode, 1, EChannelModeWrite);
    channel = chan_if->Channel(chan_if, EManagerNode, 1, EChannelModeRead);
    assert(channel);
    assert(chanw);
    /*read request for detailed histogram and send it to manager*/
    read_requests_write_detailed_histograms( channel->fd, chanw->fd, nodeid, sorted_array, ARRAY_ITEMS_COUNT );
    WRITE_LOG(LOG_UI, "\n!!!!!!!Histograms Sending complete!!!!!!.\n");

    /* source nodes count not available because not has channels intended to communicate with source nodes
     * therefore will use dest nodes count because it's equal to source nodes count */
    int *dst_nodes_list = NULL;
    int dst_nodes_count = chan_if->GetNodesListByType(chan_if, EDestinationNode, &dst_nodes_list );

    int src_nodes_count = dst_nodes_count;
    WRITE_FMT_LOG( LOG_DEBUG, "src_nodes_count=%d\n", src_nodes_count );

    /*read range request (data start, end, dest node id) from manager node*/
    struct request_data_t req_data_array[src_nodes_count];
    init_request_data_array( req_data_array, src_nodes_count);
    channel = chan_if->Channel( chan_if, EManagerNode, 1, EChannelModeRead );
    assert(channel);
    read_range_request( channel->fd, req_data_array );

    WRITE_FMT_LOG( LOG_UI, "qsort array len=%d\n", src_nodes_count);
    /*sort request data by dest node id to be deterministic*/
    qsort( req_data_array, src_nodes_count, sizeof(struct request_data_t), quicksort_reqdata_by_destnodeid_comparator );
    WRITE_LOG( LOG_UI, "qsort OK" );

    /*send array data to the destination nodes, bounds for pieces of data was
     * received previously with range request */
    for ( int i=0; i < src_nodes_count; i++ ){
        int dst_nodeid = req_data_array[i].dst_nodeid;
        channel = chan_if->Channel( chan_if, EDestinationNode, dst_nodeid, EChannelModeWrite );
        int dst_write_fd = channel->fd;
        WRITE_FMT_LOG(LOG_DEBUG, "write_sorted_ranges write fd=%d", dst_write_fd );
        WRITE_FMT_LOG(LOG_DEBUG, "req_data_array[i].dst_nodeid=%d", req_data_array[i].dst_nodeid );
        write_sorted_ranges( dst_write_fd, &req_data_array[i], sorted_array );
    }
    WRITE_LOG(LOG_UI, "Sending Ranges Complete-OK");

    if ( test_sse41_CPU() )
        aligned_free(sorted_array);
    else
        free(sorted_array);
    return 0;
}
예제 #3
0
파일: mc.c 프로젝트: mpmccode/mpmc
/* implements the Markov chain */
int mc(system_t *system) {
    int j, msgsize;
    double initial_energy, final_energy, current_energy;
    double rot_partfunc;
    observables_t *observables_mpi;
    avg_nodestats_t *avg_nodestats_mpi;
    sorbateInfo_t *sinfo_mpi = 0;
    double *temperature_mpi = 0;
    char *snd_strct = 0, *rcv_strct = 0;
    system->count_autorejects = 0;  // initialize counter for skipped close (unphysical) contacts
                                    // char linebuf[MAXLINE];  (unused variable)
#ifdef MPI
    MPI_Datatype msgtype;
#endif /* MPI */

    /* allocate the statistics structures */
    observables_mpi = calloc(1, sizeof(observables_t));
    memnullcheck(observables_mpi, sizeof(observables_t), __LINE__ - 1, __FILE__);
    avg_nodestats_mpi = calloc(1, sizeof(avg_nodestats_t));
    memnullcheck(avg_nodestats_mpi, sizeof(avg_nodestats_t), __LINE__ - 1, __FILE__);
    // if multiple-sorbates, allocate sorb statistics struct
    if (system->sorbateCount > 1) {
        sinfo_mpi = calloc(system->sorbateCount, sizeof(sorbateInfo_t));
        memnullcheck(sinfo_mpi, sizeof(sorbateInfo_t), __LINE__ - 1, __FILE__);
        system->sorbateGlobal = calloc(system->sorbateCount, sizeof(sorbateAverages_t));
        memnullcheck(system->sorbateGlobal, sizeof(sorbateAverages_t), __LINE__ - 1, __FILE__);
    }

    // compute message size
    msgsize = sizeof(observables_t) + sizeof(avg_nodestats_t);
    if (system->calc_hist) msgsize += system->n_histogram_bins * sizeof(int);
    if (system->sorbateCount > 1) msgsize += system->sorbateCount * sizeof(sorbateInfo_t);

#ifdef MPI
    MPI_Type_contiguous(msgsize, MPI_BYTE, &msgtype);
    MPI_Type_commit(&msgtype);
#endif /* MPI */

    /* allocate MPI structures */
    snd_strct = calloc(msgsize, 1);
    memnullcheck(snd_strct, sizeof(msgsize), __LINE__ - 1, __FILE__);
    if (!rank) {
        rcv_strct = calloc(size, msgsize);
        memnullcheck(rcv_strct, size * sizeof(msgsize), __LINE__ - 1, __FILE__);
        temperature_mpi = calloc(size, sizeof(double));  //temperature list for parallel tempering
        memnullcheck(temperature_mpi, size * sizeof(double), __LINE__ - 1, __FILE__);
    }

    /* update the grid for the first time */
    if (system->cavity_bias) cavity_update_grid(system);

    /* set volume observable */
    system->observables->volume = system->pbc->volume;

    /* get the initial energy of the system */
    initial_energy = energy(system);

#ifdef QM_ROTATION
    /* solve for the rotational energy levels */
    if (system->quantum_rotation) quantum_system_rotational_energies(system);
#endif /* QM_ROTATION */

    /* be a bit forgiving of the initial state */
    if (!isfinite(initial_energy))
        initial_energy = system->observables->energy = MAXVALUE;

    /* if root, open necessary output files */
    if (!rank)
        if (open_files(system) < 0) {
            error(
                "MC: could not open files\n");
            return (-1);
        }

    // write initial observables to stdout and logs
    if (!rank) {
        calc_system_mass(system);
        // average in the initial values once  (we don't want to double-count the initial state when using MPI)
        update_root_averages(system, system->observables, system->avg_observables);
        // average in the initial sorbate values
        if (system->sorbateCount > 1) {
            update_sorbate_info(system);                             //local update
            update_root_sorb_averages(system, system->sorbateInfo);  //global update
        }
        // write initial observables exactly once
        if (system->file_pointers.fp_energy)
            write_observables(system->file_pointers.fp_energy, system, system->observables, system->temperature);
        if (system->file_pointers.fp_energy_csv)
            write_observables_csv(system->file_pointers.fp_energy_csv, system, system->observables, system->temperature);
        output(
            "MC: initial values:\n");
        write_averages(system);
    }

    /* save the initial state */
    checkpoint(system);

    /* main MC loop */
    for (system->step = 1; system->step <= system->numsteps; (system->step)++) {
        /* restore the last accepted energy */
        initial_energy = system->observables->energy;

        /* perturb the system */
        make_move(system);

        /* calculate the energy change */
        final_energy = energy(system);

#ifdef QM_ROTATION
        /* solve for the rotational energy levels */
        if (system->quantum_rotation && (system->checkpoint->movetype == MOVETYPE_SPINFLIP))
            quantum_system_rotational_energies(system);
#endif /* QM_ROTATION */
        if (system->checkpoint->movetype != MOVETYPE_REMOVE)
            rot_partfunc = system->checkpoint->molecule_altered->rot_partfunc;
        else
            rot_partfunc = system->checkpoint->molecule_backup->rot_partfunc;

        /* treat a bad contact as a reject */
    if (!isfinite(final_energy)){
            system->observables->energy = MAXVALUE;
            system->nodestats->boltzmann_factor = 0;
        } else
            boltzmann_factor(system, initial_energy, final_energy, rot_partfunc);

        /* Metropolis function */
        if ((get_rand(system) < system->nodestats->boltzmann_factor) && (system->iter_success == 0)) {
            /////////// ACCEPT

            current_energy = final_energy;

            /* checkpoint */
            checkpoint(system);
            register_accept(system);

            /* SA */
            if (system->simulated_annealing) {
                if (system->simulated_annealing_linear == 1) {
                    system->temperature = system->temperature + (system->simulated_annealing_target - system->temperature) / (system->numsteps - system->step);
                    if (system->numsteps - system->step == 0)
                        system->temperature = system->simulated_annealing_target;
                } else
                    system->temperature = system->simulated_annealing_target + (system->temperature - system->simulated_annealing_target) * system->simulated_annealing_schedule;
            }

        } else {
            /////////////// REJECT

            current_energy = initial_energy;  //used in parallel tempering

            //reset the polar iterative failure flag
            system->iter_success = 0;

            /* restore from last checkpoint */
            restore(system);
            register_reject(system);

        }  // END REJECT

        // perform parallel_tempering
        if ((system->parallel_tempering) && (system->step % system->ptemp_freq == 0))
            temper_system(system, current_energy);

        /* track the acceptance_rate */
        track_ar(system->nodestats);

        /* each node calculates its stats */
        update_nodestats(system->nodestats, system->avg_nodestats);

        /* do this every correlation time, and at the very end */
        if (!(system->step % system->corrtime) || (system->step == system->numsteps)) {
            /* copy observables and avgs to the mpi send buffer */
            /* histogram array is at the end of the message */
            if (system->calc_hist) {
                zero_grid(system->grids->histogram->grid, system);
                population_histogram(system);
            }

            // update frozen and total system mass
            calc_system_mass(system);

            // update sorbate info on each node
            if (system->sorbateCount > 1)
                update_sorbate_info(system);

/*write trajectory files for each node -> one at a time to avoid disk congestion*/
#ifdef MPI
            for (j = 0; j < size; j++) {
                MPI_Barrier(MPI_COMM_WORLD);
                if (j == rank) write_states(system);
            }
#else
            write_states(system);
#endif

            /*restart files for each node -> one at a time to avoid disk congestion*/
            if (write_molecules_wrapper(system, system->pqr_restart) < 0) {
                error(
                    "MC: could not write restart state to disk\n");
                return (-1);
            }

/*dipole/field data for each node -> one at a time to avoid disk congestion*/
#ifdef MPI
            if (system->polarization) {
                for (j = 0; j < size; j++) {
                    MPI_Barrier(MPI_COMM_WORLD);
                    if (j == rank) {
                        write_dipole(system);
                        write_field(system);
                    }
                }
            }
#else
            if (system->polarization) {
                write_dipole(system);
                write_field(system);
            }
#endif

            /* zero the send buffer */
            memset(snd_strct, 0, msgsize);
            memcpy(snd_strct, system->observables, sizeof(observables_t));
            memcpy(snd_strct + sizeof(observables_t), system->avg_nodestats, sizeof(avg_nodestats_t));
            if (system->calc_hist)
                mpi_copy_histogram_to_sendbuffer(snd_strct + sizeof(observables_t) + sizeof(avg_nodestats_t),
                                                 system->grids->histogram->grid, system);
            if (system->sorbateCount > 1)
                memcpy(snd_strct + sizeof(observables_t) + sizeof(avg_nodestats_t) + (system->calc_hist) * system->n_histogram_bins * sizeof(int),  //compensate for the size of hist data, if neccessary
                       system->sorbateInfo,
                       system->sorbateCount * sizeof(sorbateInfo_t));

            if (!rank) memset(rcv_strct, 0, size * msgsize);

#ifdef MPI
            MPI_Gather(snd_strct, 1, msgtype, rcv_strct, 1, msgtype, 0, MPI_COMM_WORLD);
            MPI_Gather(&(system->temperature), 1, MPI_DOUBLE, temperature_mpi, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
//need to gather shit for sorbate stats also
#else
            memcpy(rcv_strct, snd_strct, msgsize);
            temperature_mpi[0] = system->temperature;
#endif /* MPI */
            /* head node collects all observables and averages */
            if (!rank) {
                /* clear avg_nodestats to avoid double-counting */
                clear_avg_nodestats(system);
                //loop for each core -> shift data into variable_mpi, then average into avg_observables
                for (j = 0; j < size; j++) {
                    /* copy from the mpi buffer */
                    memcpy(observables_mpi, rcv_strct + j * msgsize, sizeof(observables_t));
                    memcpy(avg_nodestats_mpi, rcv_strct + j * msgsize + sizeof(observables_t), sizeof(avg_nodestats_t));
                    if (system->calc_hist)
                        mpi_copy_rcv_histogram_to_data(rcv_strct + j * msgsize + sizeof(observables_t) + sizeof(avg_nodestats_t), system->grids->histogram->grid, system);
                    if (system->sorbateCount > 1)
                        memcpy(sinfo_mpi,
                               rcv_strct + j * msgsize + sizeof(observables_t) + sizeof(avg_nodestats_t) + (system->calc_hist) * system->n_histogram_bins * sizeof(int),  //compensate for the size of hist data, if neccessary
                               system->sorbateCount * sizeof(sorbateInfo_t));

                    /* write observables */
                    if (system->file_pointers.fp_energy)
                        write_observables(system->file_pointers.fp_energy, system, observables_mpi, temperature_mpi[j]);
                    if (system->file_pointers.fp_energy_csv)
                        write_observables_csv(system->file_pointers.fp_energy_csv, system, observables_mpi, temperature_mpi[j]);
                    if (system->file_pointers.fp_xyz) {
                        write_molecules_xyz(system, system->file_pointers.fp_xyz);  //L
                    }
                    /* collect the averages */
                    /* if parallel tempering, we will collect obserables from the coldest bath. this can't be done for
					 * nodestats though, since nodestats are averaged over each corrtime, rather than based on a single 
					 * taken at the corrtime */
                    update_root_nodestats(system, avg_nodestats_mpi, system->avg_observables);
                    if (!system->parallel_tempering) {
                        update_root_averages(system, observables_mpi, system->avg_observables);
                        if (system->calc_hist) update_root_histogram(system);
                        if (system->sorbateCount > 1) update_root_sorb_averages(system, sinfo_mpi);
                    } else if (system->ptemp->index[j] == 0) {
                        update_root_averages(system, observables_mpi, system->avg_observables);
                        if (system->calc_hist) update_root_histogram(system);
                        if (system->sorbateCount > 1) update_root_sorb_averages(system, sinfo_mpi);
                    }
                }

                /* write the averages to stdout */
                if (system->file_pointers.fp_histogram)
                    write_histogram(system->file_pointers.fp_histogram, system->grids->avg_histogram->grid, system);

                if (write_performance(system->step, system) < 0) {
                    error(
                        "MC: could not write performance data to stdout\n");
                    return (-1);
                }
                if (write_averages(system) < 0) {
                    error(
                        "MC: could not write statistics to stdout\n");
                    return (-1);
                }

            } /* !rank */
        }     /* corrtime */
    }         /* main loop */

    /* write output, close any open files */
    free(snd_strct);

    // restart files for each node
    if (write_molecules_wrapper(system, system->pqr_output) < 0) {
        error(
            "MC: could not write final state to disk\n");
        return (-1);
    }

    if (!rank) {
        close_files(system);
        free(rcv_strct);
        free(temperature_mpi);
    }

    if (system->sorbateCount > 1) {
        free(system->sorbateGlobal);
        free(sinfo_mpi);
    }

    free(observables_mpi);
    free(avg_nodestats_mpi);

    printf(
        "MC: Total auto-rejected moves: %i\n", system->count_autorejects);

    return (0);
}
예제 #4
0
void FrameRender()
{
   // Store start time for parse.
   START_TIME

   Current_Token_Count = 0;
   tparse_frame = tphoton_frame = trender_frame = 0.0;

   // Parse the scene file.
   Send_Progress("Parsing", PROGRESS_PARSING);

   opts.Do_Stats = false;

   // Set up noise-tables
   Initialize_Noise();

   // Set up function VM
   POVFPU_Init();

   // Init module specific stuff.
   Initialize_Mesh_Code();

   Parse();

   opts.Do_Stats = true;

   if (opts.Radiosity_Enabled)
      Experimental_Flag |= EF_RADIOS;

   if (Experimental_Flag)
   {
      char str[512] = "" ;

      if (Experimental_Flag & EF_SPLINE)
        strcat (str, str [0] ? ", spline" : "spline") ;
      if (Experimental_Flag & EF_RADIOS)
        strcat (str, str [0] ? ", radiosity" : "radiosity") ;
      if (Experimental_Flag & EF_SLOPEM)
        strcat (str, str [0] ? ", slope pattern" : "slope pattern") ;
      if (Experimental_Flag & EF_ISOFN) 
        strcat (str, str [0] ? ", function '.hf'" : "function '.hf'") ;
      if (Experimental_Flag & EF_TIFF) 
        strcat (str, str [0] ? ", TIFF image support" : "TIFF image support") ;

      Warning(0, "This rendering uses the following experimental feature(s): %s.\n"
                 "The design and implementation of these features is likely to change in future versions\n"
                 "of POV-Ray. Full backward compatibility with the current implementation is NOT guaranteed.",
                 str);
   }

   Experimental_Flag = 0;

   // Switch off standard anti-aliasing.

   if((Frame.Camera->Aperture != 0.0) && (Frame.Camera->Blur_Samples > 0))
   {
      opts.Options &= ~ANTIALIAS;

      Warning(0, "Focal blur is used. Standard antialiasing is switched off.");
   }

   // Create the bounding box hierarchy.

   Stage = STAGE_SLAB_BUILDING;

   if(opts.Use_Slabs)
      Send_Progress("Creating bounding slabs", PROGRESS_CREATING_BOUNDING_SLABS);

   // Init module specific stuff.
   Initialize_Atmosphere_Code();
   Initialize_BBox_Code();
   Initialize_Lighting_Code();
   Initialize_VLBuffer_Code();
   Initialize_Radiosity_Code();

   // Always call this to print number of objects.
   Build_Bounding_Slabs(&Root_Object);

   // Create the vista buffer.
   Build_Vista_Buffer();

   // Create the light buffers.
   Build_Light_Buffers();

   // Save variable values.
   variable_store(STORE);

   // Get the parsing time.
   STOP_TIME
   tparse = TIME_ELAPSED
   Send_ProgressUpdate(PROGRESS_PARSING, 0);

   // Output parsing statistics.
   Send_ParseStatistics();

   if (photonOptions.photonsEnabled)
   {
     /* Store start time for photons. */
     START_TIME

     /* now backwards-trace the scene and build the photon maps */
     InitBacktraceEverything();
     BuildPhotonMaps();

     /* Get the photon-shooting time. */
     STOP_TIME
     tphoton = TIME_ELAPSED

     /* Get total parsing time. */
     tphoton_total += tphoton;
     tphoton_frame = tphoton;
     tphoton = 0;
   }

   /* Store start time for the rest of parsing. */
   START_TIME
   Stage = STAGE_INIT;

   // Open output file and if we are continuing an interrupted trace,
   // read in the previous file settings and any data there.  This has to
   // be done before any image-size related allocations, since the settings
   // in a resumed file take precedence over that specified by the user. [AED]
   open_output_file();

   // Start the display.
   if(opts.Options & DISPLAY)
   {
      Send_Progress("Displaying", PROGRESS_DISPLAYING);

      Display_Started = POV_DISPLAY_INIT(opts.Preview_RefCon, Frame.Screen_Width, Frame.Screen_Height);

      // Display vista tree.
      Draw_Vista_Buffer();
   }
   else
   {
      Display_Started = false;
   }

   // Get things ready for ray tracing (misc init, mem alloc)
   Initialize_Renderer();

   // This had to be taken out of open_output_file() because we don't have
   // the final image size until the output file has been opened, so we can't
   // initialize the display until we know this, which in turn means we can't
   // read the rendered part before the display is initialized. [AED]
   if((opts.Options & DISKWRITE) && (opts.Options & CONTINUE_TRACE))
   {
      Read_Rendered_Part(Actual_Output_Name);

      if (opts.Last_Line > Frame.Screen_Height)
         opts.Last_Line = Frame.Screen_Height;

      if (opts.Last_Column > Frame.Screen_Width)
         opts.Last_Column = Frame.Screen_Width;
   }

   // Get the rest of the parsing time.
   STOP_TIME
   tparse += TIME_ELAPSED

   // Store start time for trace.
   START_TIME

   // Get total parsing time.
   tparse_total += tparse;
   tparse_frame = tparse;
   tparse = 0;

   // Start tracing.
   Stage = STAGE_RENDERING;

   POV_PRE_RENDER

   Send_Progress("Rendering", PROGRESS_RENDERING);

   // Macro for setting up any special FP options
   CONFIG_MATH

   // Ok, go for it - trace the picture.

   // If radiosity preview has been done, we are continuing a trace, so it
   // is important NOT to do the preview, even if the user requests it, as it
   // will cause discontinuities in radiosity shading by (probably) calculating
   // a few more radiosity values.

   // Note that radiosity REQUIRES a mosaic preview prior to main scan
   if ( opts.Radiosity_Enabled && !opts.Radiosity_Preview_Done)
      Start_Tracing_Radiosity_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);

   else if((opts.Options & PREVIEW) && (opts.Options & DISPLAY))
      Start_Tracing_Mosaic_Preview(opts.PreviewGridSize_Start, opts.PreviewGridSize_End);

   switch(opts.Tracing_Method)
   {
      case 2:
         Start_Adaptive_Tracing();
         break;
      case 1:
      default:
         Start_Non_Adaptive_Tracing();
   }

   // Record time so well spent before file close so it can be in comments
   STOP_TIME
   trender = TIME_ELAPSED

   // shutdown (freeing memory) does not get included in the time!

   // Get total render time.
   trender_total += trender;
   trender_frame = trender;
   trender = 0;

   // Close out our file
   if(Output_File != NULL)
   {
      delete Output_File;
      Output_File = NULL;
   }

   // For all those who never rtfm [trf]
   if((Highest_Trace_Level >= Max_Trace_Level) && (Had_Max_Trace_Level == false))
      PossibleError("Maximum trace level reached! If your scene contains black spots\nread more about the max_trace_level setting in the documentation!");

   Stage = STAGE_SHUTDOWN;

   POV_PRE_SHUTDOWN

   // DESTROY lots of stuff
   /* NK phmap */
   FreeBacktraceEverything();
   Deinitialize_Atmosphere_Code();
   Deinitialize_BBox_Code();
   Deinitialize_Lighting_Code();
   Deinitialize_Mesh_Code();
   Deinitialize_VLBuffer_Code();
   Deinitialize_Radiosity_Code();
   Destroy_Light_Buffers();
   Destroy_Vista_Buffer();
   Destroy_Bounding_Slabs();
   Destroy_Frame();
   Terminate_Renderer();
   FreeFontInfo();
   Free_Iteration_Stack();
   Free_Noise_Tables();

   POVFPU_Terminate();

   POV_POST_SHUTDOWN

   if((opts.Options & DISPLAY) && Display_Started)
   {
      POV_DISPLAY_FINISHED(opts.Preview_RefCon);

      POV_DISPLAY_CLOSE(opts.Preview_RefCon);

      Display_Started = false;
   }

   if(opts.histogram_on)
      write_histogram(opts.Histogram_File_Name);

   Send_Progress("Done Tracing", PROGRESS_DONE_TRACING);

   // Print stats ...
   Send_RenderStatistics();

   if(opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME)
   {
      // Add them up
      sum_statistics(totalstats, stats);

      // ... and then clear them for the next frame
      init_statistics(stats);
   }

   // Restore variable values.
   variable_store(RESTORE);
}
int main(int argc, char *argv[]){
	struct file_records_t file_records;
	int sourcefd = -1;
	if ( argc > 2 ){
		char logname[50];
		sprintf(logname, "%s%s%s.log", CLIENT_LOG, SOURCE, argv[2]);
		OPEN_LOG(logname, SOURCE, atoi(argv[2]));
		file_records.vfs_path = argv[1];
		int err = get_all_files_from_dbtable(DB_PATH, SOURCE, &file_records);
		WRITE_FMT_LOG(LOG_ERR, "get_all_files_from_dbtable err=%d", err);
		if ( err != 0 ) return 1;
	}
	else{
		printf("usage: 1st arg: should be path to VFS folder, 2nd: unique node integer id\n");fflush(0);
		return 1;
	}

	int nodeid = atoi(argv[2]);

	BigArrayPtr unsorted_array = NULL;
	BigArrayPtr partially_sorted_array = NULL;
	/*get unsorted data*/
	char inputfile[100];
	memset(inputfile, '\0', 100);
	sprintf(inputfile, SOURCE_FILE_FMT, nodeid );
	sourcefd = open(inputfile, O_RDONLY);
	if ( sourcefd >= 0 ){
		const size_t data_size = sizeof(BigArrayItem)*ARRAY_ITEMS_COUNT;
		unsorted_array = malloc( data_size );
		if ( unsorted_array ){
			const ssize_t readed = read(sourcefd, unsorted_array, data_size);
			assert(readed == data_size );
		}
		close(sourcefd);
	}
	else{
		WRITE_FMT_LOG(LOG_ERR, "Can not open input file %s", inputfile);
		exit(0);
	}

	/*sort data locally*/
	partially_sorted_array = alloc_merge_sort( unsorted_array, ARRAY_ITEMS_COUNT );

	//if first part of sorting in single thread are completed
	if ( test_sort_result( unsorted_array, partially_sorted_array, ARRAY_ITEMS_COUNT ) ){
		if ( ARRAY_ITEMS_COUNT ){
			WRITE_FMT_LOG(LOG_UI, "Single process sorting complete min=%u, max=%u: TEST OK.\n",
					partially_sorted_array[0], partially_sorted_array[ARRAY_ITEMS_COUNT-1] );
		}

		/*send crc of sorted array to the manager node*/
		uint32_t crc = array_crc( partially_sorted_array, ARRAY_ITEMS_COUNT );
		WRITE_FMT_LOG(LOG_DEBUG, "crc=%u", crc);
		struct file_record_t* write_crc_r = match_file_record_by_fd( &file_records, SOURCE_FD_WRITE_CRC);
		WRITE_FMT_LOG(LOG_DEBUG, "SOURCE_FD_WRITE_CRC fd=%p", write_crc_r);
		assert(write_crc_r);
		write_crc( write_crc_r->fpath, crc );
		WRITE_LOG(LOG_DEBUG, "crc wrote");
		/*send of crc complete*/

		int histogram_len = 0;
		HistogramArrayPtr histogram_array = alloc_histogram_array_get_len(
				partially_sorted_array, 0, ARRAY_ITEMS_COUNT, 1000, &histogram_len );

		struct Histogram single_histogram;
		single_histogram.src_nodeid = nodeid;
		single_histogram.array_len = histogram_len;
		single_histogram.array = histogram_array;
		//send histogram to manager

		struct file_record_t* write_hist_r = match_file_record_by_fd( &file_records, SOURCE_FD_WRITE_HISTOGRAM);
		assert(write_hist_r);
		write_histogram( write_hist_r->fpath, &single_histogram );

		struct file_record_t* read_dhist_req_r = match_file_record_by_fd( &file_records, SOURCE_FD_READ_D_HISTOGRAM_REQ);
		struct file_record_t* write_dhist_req_r = match_file_record_by_fd( &file_records, SOURCE_FD_WRITE_D_HISTOGRAM_REQ);
		assert(read_dhist_req_r);
		assert(write_dhist_req_r);
		read_requests_write_detailed_histograms( read_dhist_req_r->fpath, write_dhist_req_r->fpath, nodeid,
			partially_sorted_array, ARRAY_ITEMS_COUNT );

		WRITE_LOG(LOG_DETAILED_UI, "\n!!!!!!!Histograms Sending complete!!!!!!.\n");

		struct request_data_t req_data_array[SRC_NODES_COUNT];
		init_request_data_array( req_data_array, SRC_NODES_COUNT);
		//////////////////////////////
		struct file_record_t* read_sequnce_req_r = match_file_record_by_fd( &file_records, SOURCE_FD_READ_SEQUENCES_REQ);
		assert(read_sequnce_req_r);
		read_range_request( read_sequnce_req_r->fpath, req_data_array );
		//////////////////////////////

		//////////////////////////////
		for ( int i=0; i < SRC_NODES_COUNT; i++ ){
			int dst_nodeid = req_data_array[i].dst_nodeid;
			int dst_write_fd = dst_nodeid - FIRST_DEST_NODEID + SOURCE_FD_WRITE_SORTED_RANGES_REQ;
			int dst_read_fd = dst_nodeid - FIRST_DEST_NODEID + SOURCE_FD_READ_SORTED_RANGES_REQ;
			WRITE_FMT_LOG(LOG_DEBUG, "write_sorted_ranges fdw=%d, fdr=%d", dst_write_fd, dst_read_fd );

			struct file_record_t* write_ranges_req_r = match_file_record_by_fd( &file_records, dst_write_fd);
			struct file_record_t* read_ranges_req_r = match_file_record_by_fd( &file_records, dst_read_fd);
			assert(write_ranges_req_r);
			assert(read_ranges_req_r);

			WRITE_FMT_LOG(LOG_DEBUG, "req_data_array[i].dst_nodeid=%d", req_data_array[i].dst_nodeid );
			write_sorted_ranges( write_ranges_req_r->fpath, read_ranges_req_r->fpath,
					&req_data_array[i], partially_sorted_array );
		}

		WRITE_FMT_LOG(LOG_DETAILED_UI, "[%d]Sending Ranges Complete-OK", nodeid);
		//////////////////////////////

		free(unsorted_array);
		free(partially_sorted_array);
	}
	else{
		WRITE_LOG(LOG_UI, "Single process sorting failed: TEST FAILED.\n");
		exit(0);
	}
}