/*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: . ----------------------------------------------------------------------*/ #include "pair_reaxc.h" #include "reaxc_traj.h" #include "reaxc_list.h" #include "reaxc_tool_box.h" #include "error.h" int Reallocate_Output_Buffer( LAMMPS_NS::Error *error_ptr, output_controls *out_control, int req_space ) { if (out_control->buffer_len > 0) free( out_control->buffer ); out_control->buffer_len = (int)(req_space*SAFE_ZONE); out_control->buffer = (char*) malloc(out_control->buffer_len*sizeof(char)); if (out_control->buffer == NULL) { char errmsg[256]; snprintf(errmsg, 256, "Insufficient memory for required buffer size %d", (int) (req_space*SAFE_ZONE)); error_ptr->one(FLERR,errmsg); } return SUCCESS; } void Write_Skip_Line( output_controls *out_control, mpi_datatypes * /*mpi_data*/, int my_rank, int skip, int num_section ) { if (my_rank == MASTER_NODE) fprintf( out_control->strj, INT2_LINE, "chars_to_skip_section:", skip, num_section ); } int Write_Header( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes * /*mpi_data*/ ) { int num_hdr_lines, my_hdr_lines, buffer_req; char ensembles[ens_N][25] = { "NVE", "NVT", "fully flexible NPT", "semi isotropic NPT", "isotropic NPT" }; char reposition[3][25] = { "fit to periodic box", "CoM to center of box", "CoM to origin" }; char t_regime[3][25] = { "T-coupling only", "step-wise", "constant slope" }; char traj_methods[TF_N][10] = { "custom", "xyz" }; char atom_formats[8][40] = { "none", "invalid", "invalid", "invalid", "xyz_q", "xyz_q_fxfyfz", "xyz_q_vxvyvz", "detailed_atom_info" }; char bond_formats[3][30] = { "none", "basic_bond_info", "detailed_bond_info" }; char angle_formats[2][30] = { "none", "basic_angle_info" }; /* set header lengths */ num_hdr_lines = NUM_HEADER_LINES; my_hdr_lines = num_hdr_lines * ( system->my_rank == MASTER_NODE ); buffer_req = my_hdr_lines * HEADER_LINE_LEN; if (buffer_req > out_control->buffer_len * DANGER_ZONE) Reallocate_Output_Buffer( control->error_ptr, out_control, buffer_req ); /* only the master node writes into trajectory header */ if (system->my_rank == MASTER_NODE) { /* clear the contents of line & buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; /* to skip the header */ sprintf( out_control->line, INT_LINE, "chars_to_skip_header:", (num_hdr_lines-1) * HEADER_LINE_LEN ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* general simulation info */ sprintf( out_control->line, STR_LINE, "simulation_name:", out_control->traj_title ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, BIGINT_LINE, "number_of_atoms:", system->bigN ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "ensemble_type:", ensembles[ control->ensemble ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "number_of_steps:", control->nsteps ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "timestep_length_(in_fs):", control->dt * 1000 ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* restart info */ sprintf( out_control->line, STR_LINE, "is_this_a_restart?:", (control->restart ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "write_restart_files?:", ((out_control->restart_freq > 0) ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "frequency_to_write_restarts:", out_control->restart_freq ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* preferences */ sprintf( out_control->line, STR_LINE, "tabulate_long_range_intrs?:", (control->tabulate ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "table_size:", control->tabulate ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "restrict_bonds?:", (control->restrict_bonds ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "bond_restriction_length:", control->restrict_bonds ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "reposition_atoms?:", reposition[control->reposition_atoms] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "remove_CoM_velocity?:", (control->ensemble==NVE) ? 0 : control->remove_CoM_vel); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* cut-off values */ sprintf( out_control->line, REAL_LINE, "bonded_intr_dist_cutoff:", control->bond_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "nonbonded_intr_dist_cutoff:", control->nonb_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "hbond_dist_cutoff:", control->hbond_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "reax_bond_threshold:", control->bo_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "physical_bond_threshold:", control->bg_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "valence_angle_threshold:", control->thb_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, SCI_LINE, "QEq_tolerance:", control->q_err ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* temperature controls */ sprintf( out_control->line, REAL_LINE, "initial_temperature:", control->T_init ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "target_temperature:", control->T_final ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "thermal_inertia:", control->Tau_T ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "temperature_regime:", t_regime[ control->T_mode ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "temperature_change_rate_(K/ps):", control->T_rate / control->T_freq ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* pressure controls */ sprintf( out_control->line, REAL3_LINE, "target_pressure_(GPa):", control->P[0], control->P[1], control->P[2] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL3_LINE, "virial_inertia:", control->Tau_P[0], control->Tau_P[1], control->Tau_P[2] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* trajectory */ sprintf( out_control->line, INT_LINE, "energy_dumping_freq:", out_control->energy_update_freq ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "trajectory_dumping_freq:", out_control->write_steps ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "compress_trajectory_output?:", (out_control->traj_compress ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "trajectory_format:", traj_methods[ out_control->traj_method ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "atom_info:", atom_formats[ out_control->atom_info ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "bond_info:", bond_formats[ out_control->bond_info ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "angle_info:", angle_formats[ out_control->angle_info ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* analysis */ //sprintf( out_control->line, STR_LINE, "molecular_analysis:", // (control->molec_anal ? "yes" : "no") ); //strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "molecular_analysis_frequency:", control->molecular_analysis ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); } /* dump out the buffer */ if (system->my_rank == MASTER_NODE) fprintf( out_control->strj, "%s", out_control->buffer ); return SUCCESS; } int Write_Init_Desc( reax_system *system, control_params * /*control*/, output_controls *out_control, mpi_datatypes *mpi_data ) { int i, me, np, cnt, buffer_len, buffer_req; reax_atom *p_atom; MPI_Status status; me = system->my_rank; np = system->wsize; /* skip info */ Write_Skip_Line( out_control, mpi_data, me, system->bigN * INIT_DESC_LEN, system->bigN ); if (out_control->traj_method == REG_TRAJ && me == MASTER_NODE) buffer_req = system->bigN * INIT_DESC_LEN + 1; else buffer_req = system->n * INIT_DESC_LEN + 1; if (buffer_req > out_control->buffer_len * DANGER_ZONE) Reallocate_Output_Buffer( system->error_ptr, out_control, buffer_req ); out_control->line[0] = 0; out_control->buffer[0] = 0; for( i = 0; i < system->n; ++i ) { p_atom = &( system->my_atoms[i] ); sprintf( out_control->line, INIT_DESC, p_atom->orig_id, p_atom->type, p_atom->name, system->reax_param.sbp[ p_atom->type ].mass ); strncpy( out_control->buffer + i*INIT_DESC_LEN, out_control->line, INIT_DESC_LEN+1 ); } if (me != MASTER_NODE) { MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np * INIT_DESCS + me, mpi_data->world ); } else { buffer_len = system->n * INIT_DESC_LEN; for( i = 0; i < np; ++i ) if (i != MASTER_NODE) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*INIT_DESCS+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Init_Traj( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data, char *msg ) { char fname[MAX_STR+8]; int atom_line_len[ NR_OPT_ATOM ] = { 0, 0, 0, 0, ATOM_BASIC_LEN, ATOM_wV_LEN, ATOM_wF_LEN, ATOM_FULL_LEN }; int bond_line_len[ NR_OPT_BOND ] = { 0, BOND_BASIC_LEN, BOND_FULL_LEN }; int angle_line_len[ NR_OPT_ANGLE ] = { 0, ANGLE_BASIC_LEN }; /* generate trajectory name */ sprintf( fname, "%s.trj", control->sim_name ); /* how should I write atoms? */ out_control->atom_line_len = atom_line_len[ out_control->atom_info ]; out_control->write_atoms = ( out_control->atom_line_len ? 1 : 0 ); /* bonds? */ out_control->bond_line_len = bond_line_len[ out_control->bond_info ]; out_control->write_bonds = ( out_control->bond_line_len ? 1 : 0 ); /* angles? */ out_control->angle_line_len = angle_line_len[ out_control->angle_info ]; out_control->write_angles = ( out_control->angle_line_len ? 1 : 0 ); /* allocate line & buffer space */ out_control->line = (char*) calloc( MAX_TRJ_LINE_LEN + 1, sizeof(char) ); out_control->buffer_len = 0; out_control->buffer = NULL; /* write trajectory header and atom info, if applicable */ if (out_control->traj_method == REG_TRAJ) { if (system->my_rank == MASTER_NODE) out_control->strj = fopen( fname, "w" ); } else { strcpy( msg, "init_traj: unknown trajectory option" ); return FAILURE; } Write_Header( system, control, out_control, mpi_data ); Write_Init_Desc( system, control, out_control, mpi_data ); return SUCCESS; } int Write_Frame_Header( reax_system *system, control_params *control, simulation_data *data, output_controls *out_control, mpi_datatypes * /*mpi_data*/ ) { int me, num_frm_hdr_lines, my_frm_hdr_lines, buffer_req; me = system->my_rank; /* frame header lengths */ num_frm_hdr_lines = 22; my_frm_hdr_lines = num_frm_hdr_lines * ( me == MASTER_NODE ); buffer_req = my_frm_hdr_lines * HEADER_LINE_LEN; if (buffer_req > out_control->buffer_len * DANGER_ZONE) Reallocate_Output_Buffer( control->error_ptr, out_control, buffer_req ); /* only the master node writes into trajectory header */ if (me == MASTER_NODE) { /* clear the contents of line & buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; /* skip info */ sprintf( out_control->line, INT_LINE, "chars_to_skip_frame_header:", (num_frm_hdr_lines - 1) * HEADER_LINE_LEN ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* step & time */ sprintf( out_control->line, INT_LINE, "step:", data->step ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "time_in_ps:", data->step * control->dt ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* box info */ sprintf( out_control->line, REAL_LINE, "volume:", system->big_box.V ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL3_LINE, "box_dimensions:", system->big_box.box_norms[0], system->big_box.box_norms[1], system->big_box.box_norms[2] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL3_LINE, "coordinate_angles:", 90.0, 90.0, 90.0 ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* system T and P */ sprintf( out_control->line, REAL_LINE, "temperature:", data->therm.T ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "pressure:", (control->ensemble==iNPT) ? data->iso_bar.P : data->flex_bar.P_scalar ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* energies */ sprintf( out_control->line, REAL_LINE, "total_energy:", data->sys_en.e_tot ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "total_kinetic:", data->sys_en.e_kin ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "total_potential:", data->sys_en.e_pot ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "bond_energy:", data->sys_en.e_bond ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "atom_energy:", data->sys_en.e_ov + data->sys_en.e_un ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "lone_pair_energy:", data->sys_en.e_lp ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "valence_angle_energy:", data->sys_en.e_ang + data->sys_en.e_pen ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "3-body_conjugation:", data->sys_en.e_coa ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "hydrogen_bond_energy:", data->sys_en.e_hb ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "torsion_angle_energy:", data->sys_en.e_tor ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "4-body_conjugation:", data->sys_en.e_con ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "vdWaals_energy:", data->sys_en.e_vdW ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "electrostatics_energy:", data->sys_en.e_ele ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "polarization_energy:", data->sys_en.e_pol ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); } /* dump out the buffer */ if (system->my_rank == MASTER_NODE) fprintf( out_control->strj, "%s", out_control->buffer ); return SUCCESS; } int Write_Atoms( reax_system *system, control_params * /*control*/, output_controls *out_control, mpi_datatypes *mpi_data ) { int i, me, np, line_len, buffer_len, buffer_req, cnt; MPI_Status status; reax_atom *p_atom; me = system->my_rank; np = system->wsize; line_len = out_control->atom_line_len; Write_Skip_Line( out_control, mpi_data, me, system->bigN*line_len, system->bigN ); if (out_control->traj_method == REG_TRAJ && me == MASTER_NODE) buffer_req = system->bigN * line_len + 1; else buffer_req = system->n * line_len + 1; if (buffer_req > out_control->buffer_len * DANGER_ZONE) Reallocate_Output_Buffer( system->error_ptr, out_control, buffer_req ); /* fill in buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; for( i = 0; i < system->n; ++i ) { p_atom = &( system->my_atoms[i] ); switch( out_control->atom_info ) { case OPT_ATOM_BASIC: sprintf( out_control->line, ATOM_BASIC, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->q ); break; case OPT_ATOM_wF: sprintf( out_control->line, ATOM_wF, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->f[0], p_atom->f[1], p_atom->f[2], p_atom->q ); break; case OPT_ATOM_wV: sprintf( out_control->line, ATOM_wV, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->v[0], p_atom->v[1], p_atom->v[2], p_atom->q ); break; case OPT_ATOM_FULL: sprintf( out_control->line, ATOM_FULL, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->v[0], p_atom->v[1], p_atom->v[2], p_atom->f[0], p_atom->f[1], p_atom->f[2], p_atom->q ); break; default: system->error_ptr->one(FLERR,"Write_traj_atoms: unknown atom trajectory format"); } strncpy( out_control->buffer + i*line_len, out_control->line, line_len+1 ); } if (me != MASTER_NODE) { MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np*ATOM_LINES+me, mpi_data->world ); } else { buffer_len = system->n * line_len; for( i = 0; i < np; ++i ) if (i != MASTER_NODE) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*ATOM_LINES+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Write_Bonds(reax_system *system, control_params *control, reax_list *bonds, output_controls *out_control, mpi_datatypes *mpi_data) { int i, j, pj, me, np; int my_bonds, num_bonds; int line_len, buffer_len, buffer_req, cnt; MPI_Status status; bond_data *bo_ij; me = system->my_rank; np = system->wsize; line_len = out_control->bond_line_len; /* count the number of bonds I will write */ my_bonds = 0; for( i=0; i < system->n; ++i ) for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { j = bonds->select.bond_list[pj].nbr; if( system->my_atoms[i].orig_id <= system->my_atoms[j].orig_id && bonds->select.bond_list[pj].bo_data.BO >= control->bg_cut ) ++my_bonds; } /* allreduce - total number of bonds */ MPI_Allreduce( &my_bonds, &num_bonds, 1, MPI_INT, MPI_SUM, mpi_data->world ); Write_Skip_Line( out_control, mpi_data, me, num_bonds*line_len, num_bonds ); if (out_control->traj_method == REG_TRAJ && me == MASTER_NODE) buffer_req = num_bonds * line_len + 1; else buffer_req = my_bonds * line_len + 1; if (buffer_req > out_control->buffer_len * DANGER_ZONE) Reallocate_Output_Buffer( system->error_ptr, out_control, buffer_req ); /* fill in the buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; my_bonds = 0; for( i=0; i < system->n; ++i ) { for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { bo_ij = &( bonds->select.bond_list[pj] ); j = bo_ij->nbr; if( system->my_atoms[i].orig_id <= system->my_atoms[j].orig_id && bo_ij->bo_data.BO >= control->bg_cut ) { switch( out_control->bond_info ) { case OPT_BOND_BASIC: sprintf( out_control->line, BOND_BASIC, system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, bo_ij->d, bo_ij->bo_data.BO ); break; case OPT_BOND_FULL: sprintf( out_control->line, BOND_FULL, system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, bo_ij->d, bo_ij->bo_data.BO, bo_ij->bo_data.BO_s, bo_ij->bo_data.BO_pi, bo_ij->bo_data.BO_pi2 ); break; default: system->error_ptr->one(FLERR, "Write_traj_bonds: FATAL! invalid bond_info option"); } strncpy( out_control->buffer + my_bonds*line_len, out_control->line, line_len+1 ); ++my_bonds; } } } if (me != MASTER_NODE) { MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np*BOND_LINES+me, mpi_data->world ); } else { buffer_len = my_bonds * line_len; for( i = 0; i < np; ++i ) if (i != MASTER_NODE) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*BOND_LINES+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Write_Angles( reax_system *system, control_params *control, reax_list *bonds, reax_list *thb_intrs, output_controls *out_control, mpi_datatypes *mpi_data ) { int i, j, k, pi, pk, me, np; int my_angles, num_angles; int line_len, buffer_len, buffer_req, cnt; bond_data *bo_ij, *bo_jk; three_body_interaction_data *angle_ijk; MPI_Status status; me = system->my_rank; np = system->wsize; line_len = out_control->angle_line_len; /* count the number of valence angles I will output */ my_angles = 0; for( j = 0; j < system->n; ++j ) for( pi = Start_Index(j, bonds); pi < End_Index(j, bonds); ++pi ) { bo_ij = &(bonds->select.bond_list[pi]); i = bo_ij->nbr; if (bo_ij->bo_data.BO >= control->bg_cut) // physical j&i bond for( pk = Start_Index( pi, thb_intrs ); pk < End_Index( pi, thb_intrs ); ++pk ) { angle_ijk = &(thb_intrs->select.three_body_list[pk]); k = angle_ijk->thb; bo_jk = &(bonds->select.bond_list[ angle_ijk->pthb ]); if( system->my_atoms[i].orig_id < system->my_atoms[k].orig_id && bo_jk->bo_data.BO >= control->bg_cut ) // physical j&k bond ++my_angles; } } /* total number of valences */ MPI_Allreduce(&my_angles, &num_angles, 1, MPI_INT, MPI_SUM, mpi_data->world); Write_Skip_Line( out_control, mpi_data, me, num_angles*line_len, num_angles ); if (out_control->traj_method == REG_TRAJ && me == MASTER_NODE) buffer_req = num_angles * line_len + 1; else buffer_req = my_angles * line_len + 1; if (buffer_req > out_control->buffer_len * DANGER_ZONE) Reallocate_Output_Buffer( system->error_ptr, out_control, buffer_req ); /* fill in the buffer */ my_angles = 0; out_control->line[0] = 0; out_control->buffer[0] = 0; for( j = 0; j < system->n; ++j ) for( pi = Start_Index(j, bonds); pi < End_Index(j, bonds); ++pi ) { bo_ij = &(bonds->select.bond_list[pi]); i = bo_ij->nbr; if (bo_ij->bo_data.BO >= control->bg_cut) // physical j&i bond for( pk = Start_Index( pi, thb_intrs ); pk < End_Index( pi, thb_intrs ); ++pk ) { angle_ijk = &(thb_intrs->select.three_body_list[pk]); k = angle_ijk->thb; bo_jk = &(bonds->select.bond_list[ angle_ijk->pthb ]); if( system->my_atoms[i].orig_id < system->my_atoms[k].orig_id && bo_jk->bo_data.BO >= control->bg_cut ) { // physical j&k bond sprintf( out_control->line, ANGLE_BASIC, system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, system->my_atoms[k].orig_id, RAD2DEG( angle_ijk->theta ) ); strncpy( out_control->buffer + my_angles*line_len, out_control->line, line_len+1 ); ++my_angles; } } } if (me != MASTER_NODE) { MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np*ANGLE_LINES+me, mpi_data->world ); } else { buffer_len = my_angles * line_len; for( i = 0; i < np; ++i ) if (i != MASTER_NODE) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*ANGLE_LINES+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Append_Frame( reax_system *system, control_params *control, simulation_data *data, reax_list **lists, output_controls *out_control, mpi_datatypes *mpi_data ) { Write_Frame_Header( system, control, data, out_control, mpi_data ); if (out_control->write_atoms) Write_Atoms( system, control, out_control, mpi_data ); if (out_control->write_bonds) Write_Bonds( system, control, (*lists + BONDS), out_control, mpi_data ); if (out_control->write_angles) Write_Angles( system, control, (*lists + BONDS), (*lists + THREE_BODIES), out_control, mpi_data ); return SUCCESS; } int End_Traj( int my_rank, output_controls *out_control ) { if (my_rank == MASTER_NODE) fclose( out_control->strj ); free( out_control->buffer ); free( out_control->line ); return SUCCESS; }