コード例 #1
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);
}
コード例 #2
0
ファイル: seqsa.c プロジェクト: BackupTheBerlios/yasa-svn
/*
 * Sequential version.
 */
int
seqsa_solver(char *stg_filename, char *ssf_filename)
{
    int malloced;
    int freed;

    int malloced_initial;
    int freed_initial;

    int malloced_select;
    int freed_select;

    struct stg *tg;
    struct ssf_status *status;
    struct ssf *schedule;

    double eps;
    unsigned seed;

    int i;
    double t0;
    double t;

    struct iss *alpha;  /* present solution */
    struct iss *beta;   /* neighbour solution of alpha */

    double cost_alpha;
    double cost_beta;

    double r;
    double bf;  /* Boltzmann Factor p(alpha -> beta) */


    printf("** Sequential Simulated Annealing Solver\n");

    /* Allocate data structures. */
    malloced = 0;
    freed = 0;
    tg = new_task_graph_from_file(stg_filename, &malloced);
    status = new_status(&malloced);
    strncpy(status->name, "YASA Sequential", 20);

    eps = 1e-3;
    seed = 0;
    t0 = 1000.0;

    alpha = NULL;
    beta = NULL;

    /* Solve. */
    srand(seed);
    print_task_graph(tg);

    malloced_initial = 0;
    freed_initial = 0;
    alpha = create_initial_solution(tg, &malloced_initial, &freed_initial);
    printf("malloced %d bytes for initial solution\n", malloced_initial);
    printf("freed %d bytes for initial solution\n", freed_initial);
    printf("difference: %d bytes\n", malloced_initial - freed_initial);

    cost_alpha = cost(tg, alpha);

    i = 0;
    t = t0;
    
    while (t > eps) {
        printf("i = %d, t = %f\n", i, t);

        malloced_select = 0;
        freed_select = 0;
        beta = select_neighbour(tg, alpha, &malloced_select, &freed_select);
        printf("malloced %d bytes for selection\n", malloced_select);
        printf("freed %d bytes for selection\n", freed_select);
        printf("difference: %d bytes\n", malloced_select - freed_select);
        cost_beta = cost(tg, beta);

        if (cost_beta <= cost_alpha) {
            /* TODO alpha := beta */
            cost_alpha = cost_beta;
        } else {
            r = get_random_r();  /* r from (0, 1) */
            bf = boltzmann_factor(t, cost_alpha, cost_beta);
            printf("r = %f, bf = %f\n", r, bf);
            if (r < bf) {
                /* TODO alpha := beta */
                cost_alpha = cost_beta;
            }
        }
        i++;
        t = new_temp(t, i);
    }
    printf("stopping at i = %d, t = %f.\n", i, t);

    /* alpha to schedule */
    //schedule = new_schedule(tg, alpha, &malloced);
    schedule = new_schedule(tg, &malloced);
    printf("malloced %d bytes\n", malloced);

    /* Display Results */
    print_schedule(schedule);
    write_schedule_to_file(ssf_filename, schedule, status);

    /* Free data structures. */
    free_schedule(schedule, &freed);
    // TODO free initial solution
    free_status(status, &freed);
    free_task_graph(tg, &freed);
    printf("freed %d bytes => ", freed);
    if (malloced == freed)
        printf("OK.\n");
    else {
        printf("Error: malloced != freed!\n");
        return (1);
    }

    return (0);
}