void Reset_Pressures( simulation_data *data ) { data->flex_bar.P_scalar = 0; rtensor_MakeZero( data->flex_bar.P ); data->iso_bar.P = 0; rvec_MakeZero( data->int_press ); rvec_MakeZero( data->my_ext_press ); rvec_MakeZero( data->ext_press ); }
void Generate_Initial_Velocities( reax_system *system, real T ) { int i; real m, scale, norm; if( T <= 0.1 ) { for( i = 0; i < system->n; i++ ) rvec_MakeZero( system->my_atoms[i].v ); } else { Randomize(); for( i = 0; i < system->n; i++ ) { rvec_Random( system->my_atoms[i].v ); norm = rvec_Norm_Sqr( system->my_atoms[i].v ); m = system->reax_param.sbp[ system->my_atoms[i].type ].mass; scale = sqrt( m * norm / (3.0 * K_B * T) ); rvec_Scale( system->my_atoms[i].v, 1./scale, system->my_atoms[i].v ); // fprintf( stderr, "v = %f %f %f\n", // system->my_atoms[i].v[0], // system->my_atoms[i].v[1], // system->my_atoms[i].v[2] ); // fprintf( stderr, "scale = %f\n", scale ); // fprintf( stderr, "v = %f %f %f\n", // system->my_atoms[i].v[0], // system->my_atoms[i].v[1], // system->my_atoms[i].v[2] ); } } }
/************************ initialize system ************************/ int Reposition_Atoms( reax_system *system, control_params *control, simulation_data *data, mpi_datatypes *mpi_data, char *msg ) { int i; rvec dx; /* reposition atoms */ if( control->reposition_atoms == 0 ) { //fit atoms to periodic box rvec_MakeZero( dx ); } else if( control->reposition_atoms == 1 ) { //put center of mass to center rvec_Scale( dx, 0.5, system->big_box.box_norms ); rvec_ScaledAdd( dx, -1., data->xcm ); } else if( control->reposition_atoms == 2 ) { //put center of mass to origin rvec_Scale( dx, -1., data->xcm ); } else { strcpy( msg, "reposition_atoms: invalid option" ); return FAILURE; } for( i = 0; i < system->n; ++i ) // Inc_on_T3_Gen( system->my_atoms[i].x, dx, &(system->big_box) ); rvec_Add( system->my_atoms[i].x, dx ); return SUCCESS; }
void Compute_Pressure(reax_system* system, control_params *control, simulation_data* data, mpi_datatypes *mpi_data) { int i; reax_atom *p_atom; rvec tmp, tx, int_press; simulation_box *big_box = &(system->big_box); /* Calculate internal pressure */ rvec_MakeZero( int_press ); // 0: both int and ext, 1: ext only, 2: int only if( control->press_mode == 0 || control->press_mode == 2 ) { for( i = 0; i < system->n; ++i ) { p_atom = &( system->my_atoms[i] ); /* transform x into unitbox coordinates */ Transform_to_UnitBox( p_atom->x, big_box, 1, tx ); /* this atom's contribution to internal pressure */ rvec_Multiply( tmp, p_atom->f, tx ); rvec_Add( int_press, tmp ); } } /* sum up internal and external pressure */ MPI_Allreduce( int_press, data->int_press, 3, MPI_DOUBLE, MPI_SUM, mpi_data->comm_mesh3D ); MPI_Allreduce( data->my_ext_press, data->ext_press, 3, MPI_DOUBLE, MPI_SUM, mpi_data->comm_mesh3D ); /* kinetic contribution */ data->kin_press = 2.*(E_CONV*data->sys_en.e_kin) / (3.*big_box->V*P_CONV); /* Calculate total pressure in each direction */ data->tot_press[0] = data->kin_press - (( data->int_press[0] + data->ext_press[0] ) / ( big_box->box_norms[1] * big_box->box_norms[2] * P_CONV )); data->tot_press[1] = data->kin_press - (( data->int_press[1] + data->ext_press[1] ) / ( big_box->box_norms[0] * big_box->box_norms[2] * P_CONV )); data->tot_press[2] = data->kin_press - (( data->int_press[2] + data->ext_press[2] ) / ( big_box->box_norms[0] * big_box->box_norms[1] * P_CONV )); data->iso_bar.P = ( data->tot_press[0] + data->tot_press[1] + data->tot_press[2] ) / 3.; }
void Calculate_Dipole_Moment( reax_system *system, control_params *control, simulation_data *data, static_storage *workspace, list *bonds, FILE *fout ) { int i, atom, count; molecule m; real mu_sum; rvec tmpvec, mu; int *mark = workspace->mark; //fprintf( fout, "starting dipole moment calculations...\n" ); mu_sum = 0; count = 0; for( atom = 0; atom < system->N; ++atom ) /* start discovering water molecules from the central O atom */ if( !mark[atom] && system->atoms[atom].type == 2 ) { rvec_MakeZero( mu ); memset( &m, 0, sizeof(molecule) ); Get_Molecule( atom, &m, mark, system, control, bonds, 0, fout ); if( Get_Type_of_Molecule( &m ) == WATER ) { ++count; for( i = 1; i < 2; ++i ) { Distance_on_T3_Gen( system->atoms[ m.atom_list[0] ].x, system->atoms[ m.atom_list[i] ].x, &(system->box), tmpvec ); rvec_ScaledAdd( mu, -system->atoms[m.atom_list[0]].q / 2.0, tmpvec ); } mu_sum += rvec_Norm( mu ); } } fprintf( fout, "%7d %10d %10.5f\n", data->step, count, mu_sum / count * ECxA_to_DEBYE ); fflush( fout ); }
void Compute_Center_of_Mass( reax_system *system, simulation_data *data, mpi_datatypes *mpi_data, MPI_Comm comm ) { int i; double m, det; //xx, xy, xz, yy, yz, zz; double tmp_mat[6], tot_mat[6]; rvec my_xcm, my_vcm, my_amcm, my_avcm; rvec tvec, diff; rtensor mat, inv; rvec_MakeZero( my_xcm ); // position of CoM rvec_MakeZero( my_vcm ); // velocity of CoM rvec_MakeZero( my_amcm ); // angular momentum of CoM rvec_MakeZero( my_avcm ); // angular velocity of CoM /* Compute the position, vel. and ang. momentum about the centre of mass */ for( i = 0; i < system->n; ++i ) { m = system->reax_param.sbp[ system->my_atoms[i].type ].mass; rvec_ScaledAdd( my_xcm, m, system->my_atoms[i].x ); rvec_ScaledAdd( my_vcm, m, system->my_atoms[i].v ); rvec_Cross( tvec, system->my_atoms[i].x, system->my_atoms[i].v ); rvec_ScaledAdd( my_amcm, m, tvec ); } MPI_Allreduce( my_xcm, data->xcm, 3, MPI_DOUBLE, MPI_SUM, comm ); MPI_Allreduce( my_vcm, data->vcm, 3, MPI_DOUBLE, MPI_SUM, comm ); MPI_Allreduce( my_amcm, data->amcm, 3, MPI_DOUBLE, MPI_SUM, comm ); rvec_Scale( data->xcm, data->inv_M, data->xcm ); rvec_Scale( data->vcm, data->inv_M, data->vcm ); rvec_Cross( tvec, data->xcm, data->vcm ); rvec_ScaledAdd( data->amcm, -data->M, tvec ); data->etran_cm = 0.5 * data->M * rvec_Norm_Sqr( data->vcm ); /* Calculate and then invert the inertial tensor */ for( i = 0; i < 6; ++i ) tmp_mat[i] = 0; //my_xx = my_xy = my_xz = my_yy = my_yz = my_zz = 0; for( i = 0; i < system->n; ++i ){ m = system->reax_param.sbp[ system->my_atoms[i].type ].mass; rvec_ScaledSum( diff, 1., system->my_atoms[i].x, -1., data->xcm ); tmp_mat[0]/*my_xx*/ += diff[0] * diff[0] * m; tmp_mat[1]/*my_xy*/ += diff[0] * diff[1] * m; tmp_mat[2]/*my_xz*/ += diff[0] * diff[2] * m; tmp_mat[3]/*my_yy*/ += diff[1] * diff[1] * m; tmp_mat[4]/*my_yz*/ += diff[1] * diff[2] * m; tmp_mat[5]/*my_zz*/ += diff[2] * diff[2] * m; } MPI_Reduce( tmp_mat, tot_mat, 6, MPI_DOUBLE, MPI_SUM, MASTER_NODE, comm ); if( system->my_rank == MASTER_NODE ) { mat[0][0] = tot_mat[3] + tot_mat[5]; // yy + zz; mat[0][1] = mat[1][0] = -tot_mat[1]; // -xy; mat[0][2] = mat[2][0] = -tot_mat[2]; // -xz; mat[1][1] = tot_mat[0] + tot_mat[5]; // xx + zz; mat[2][1] = mat[1][2] = -tot_mat[4]; // -yz; mat[2][2] = tot_mat[0] + tot_mat[3]; // xx + yy; /* invert the inertial tensor */ det = ( mat[0][0] * mat[1][1] * mat[2][2] + mat[0][1] * mat[1][2] * mat[2][0] + mat[0][2] * mat[1][0] * mat[2][1] ) - ( mat[0][0] * mat[1][2] * mat[2][1] + mat[0][1] * mat[1][0] * mat[2][2] + mat[0][2] * mat[1][1] * mat[2][0] ); inv[0][0] = mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]; inv[0][1] = mat[0][2] * mat[2][1] - mat[0][1] * mat[2][2]; inv[0][2] = mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1]; inv[1][0] = mat[1][2] * mat[2][0] - mat[1][0] * mat[2][2]; inv[1][1] = mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0]; inv[1][2] = mat[0][2] * mat[1][0] - mat[0][0] * mat[1][2]; inv[2][0] = mat[1][0] * mat[2][1] - mat[2][0] * mat[1][1]; inv[2][1] = mat[2][0] * mat[0][1] - mat[0][0] * mat[2][1]; inv[2][2] = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1]; if( det > ALMOST_ZERO ) rtensor_Scale( inv, 1./det, inv ); else rtensor_MakeZero( inv ); /* Compute the angular velocity about the centre of mass */ rtensor_MatVec( data->avcm, inv, data->amcm ); } MPI_Bcast( data->avcm, 3, MPI_DOUBLE, MASTER_NODE, comm ); /* Compute the rotational energy */ data->erot_cm = 0.5 * E_CONV * rvec_Dot( data->avcm, data->amcm ); }
/* IMPORTANT: This function assumes that current kinetic energy * the system is already computed * * IMPORTANT: In Klein's paper, it is stated that a dU/dV term needs * to be added when there are long-range interactions or long-range * corrections to short-range interactions present. * We may want to add that for more accuracy. */ void Compute_Pressure(reax_system* system, control_params *control, simulation_data* data, mpi_datatypes *mpi_data) { int i; reax_atom *p_atom; rvec tmp, tx, int_press; simulation_box *big_box = &(system->big_box); /* Calculate internal pressure */ rvec_MakeZero( int_press ); // 0: both int and ext, 1: ext only, 2: int only if( control->press_mode == 0 || control->press_mode == 2 ) { for( i = 0; i < system->n; ++i ) { p_atom = &( system->my_atoms[i] ); /* transform x into unitbox coordinates */ Transform_to_UnitBox( p_atom->x, big_box, 1, tx ); /* this atom's contribution to internal pressure */ rvec_Multiply( tmp, p_atom->f, tx ); rvec_Add( int_press, tmp ); #if defined(DEBUG) fprintf( stderr, "%8d%8.2f%8.2f%8.2f", i+1, p_atom->x[0], p_atom->x[1], p_atom->x[2] ); fprintf( stderr, "%8.2f%8.2f%8.2f", p_atom->f[0], p_atom->f[1], p_atom->f[2] ); fprintf( stderr, "%8.2f%8.2f%8.2f\n", int_press[0], int_press[1], int_press[2] ); #endif } } /* sum up internal and external pressure */ #if defined(DEBUG) fprintf(stderr,"p%d:p_int(%10.5f %10.5f %10.5f)p_ext(%10.5f %10.5f %10.5f)\n", system->my_rank, int_press[0], int_press[1], int_press[2], data->my_ext_press[0], data->my_ext_press[1], data->my_ext_press[2] ); #endif MPI_Allreduce( int_press, data->int_press, 3, MPI_DOUBLE, MPI_SUM, mpi_data->comm_mesh3D ); MPI_Allreduce( data->my_ext_press, data->ext_press, 3, MPI_DOUBLE, MPI_SUM, mpi_data->comm_mesh3D ); #if defined(DEBUG) fprintf( stderr, "p%d: %10.5f %10.5f %10.5f\n", system->my_rank, data->int_press[0], data->int_press[1], data->int_press[2] ); fprintf( stderr, "p%d: %10.5f %10.5f %10.5f\n", system->my_rank, data->ext_press[0], data->ext_press[1], data->ext_press[2] ); #endif /* kinetic contribution */ data->kin_press = 2.*(E_CONV*data->sys_en.e_kin) / (3.*big_box->V*P_CONV); /* Calculate total pressure in each direction */ data->tot_press[0] = data->kin_press - (( data->int_press[0] + data->ext_press[0] ) / ( big_box->box_norms[1] * big_box->box_norms[2] * P_CONV )); data->tot_press[1] = data->kin_press - (( data->int_press[1] + data->ext_press[1] ) / ( big_box->box_norms[0] * big_box->box_norms[2] * P_CONV )); data->tot_press[2] = data->kin_press - (( data->int_press[2] + data->ext_press[2] ) / ( big_box->box_norms[0] * big_box->box_norms[1] * P_CONV )); /* Average pressure for the whole box */ data->iso_bar.P = ( data->tot_press[0] + data->tot_press[1] + data->tot_press[2] ) / 3.; }