From 9ece9d499630385f360e5c4225b44eade51aaa44 Mon Sep 17 00:00:00 2001 From: "Kurt A. O'Hearn" <ohearnku@msu.edu> Date: Thu, 16 Dec 2021 15:24:54 -0500 Subject: [PATCH] sPuReMD: add support for custom charge constraints with EEM for QM/MM simulations. --- sPuReMD/src/forces.c | 51 ++++++++++- sPuReMD/src/init_md.c | 26 ++++-- sPuReMD/src/reax_types.h | 18 ++++ sPuReMD/src/spuremd.c | 181 ++++++++++++++++++++++++++++++++++----- sPuReMD/src/spuremd.h | 6 +- 5 files changed, 252 insertions(+), 30 deletions(-) diff --git a/sPuReMD/src/forces.c b/sPuReMD/src/forces.c index 7a1258a9..d8c5b6aa 100644 --- a/sPuReMD/src/forces.c +++ b/sPuReMD/src/forces.c @@ -361,7 +361,8 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst break; case EE_CM: - if ( system->num_molec_charge_constraints == 0 ) + if ( system->num_molec_charge_constraints == 0 + && system->num_custom_charge_constraints == 0 ) { H->start[system->N] = *Htop; H_sp->start[system->N] = *H_sp_top; @@ -439,6 +440,47 @@ static void Init_Charge_Matrix_Remaining_Entries( reax_system const * const syst } ++(*H_sp_top); } + + for ( i = system->num_molec_charge_constraints; + i < system->num_molec_charge_constraints + system->num_custom_charge_constraints; ++i ) + { + H->start[system->N + i] = *Htop; + H_sp->start[system->N + i] = *H_sp_top; + + for ( j = system->custom_charge_constraint_start[i - system->num_molec_charge_constraints]; + j <= system->custom_charge_constraint_start[i - system->num_molec_charge_constraints + 1]; ++j ) + { + /* custom charge constraint on atoms */ + if ( *Htop < H->m ) + { + H->j[*Htop] = system->custom_charge_constraint_atom_index[j] - 1; + H->val[*Htop] = system->custom_charge_constraint_coeff[j]; + } + ++(*Htop); + + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->custom_charge_constraint_atom_index[j] - 1; + H_sp->val[*H_sp_top] = system->custom_charge_constraint_coeff[j]; + } + ++(*H_sp_top); + } + + /* explicit zeros on diagonals */ + if ( *Htop < H->m ) + { + H->j[*Htop] = system->N + i; + H->val[*Htop] = 0.0; + } + ++(*Htop); + + if ( *H_sp_top < H_sp->m ) + { + H_sp->j[*H_sp_top] = system->N + i; + H_sp->val[*H_sp_top] = 0.0; + } + ++(*H_sp_top); + } } break; @@ -1367,7 +1409,8 @@ static void Estimate_Storages_CM( reax_system const * const system, break; case EE_CM: - if ( system->num_molec_charge_constraints == 0 ) + if ( system->num_molec_charge_constraints == 0 + && system->num_custom_charge_constraints == 0 ) { Htop += system->N_cm; } @@ -1378,6 +1421,10 @@ static void Estimate_Storages_CM( reax_system const * const system, Htop += system->molec_charge_constraint_ranges[2 * i + 1] - system->molec_charge_constraint_ranges[2 * i] + 1; } + for ( i = 0; i < system->num_custom_charge_constraints; ++i ) + { + Htop += system->custom_charge_constraint_count[i]; + } } break; diff --git a/sPuReMD/src/init_md.c b/sPuReMD/src/init_md.c index 8563ff82..29db6775 100644 --- a/sPuReMD/src/init_md.c +++ b/sPuReMD/src/init_md.c @@ -397,11 +397,13 @@ static void Init_Workspace( reax_system * const system, break; case EE_CM: system->N_cm = system->N - + (system->num_molec_charge_constraints == 0 ? 1 : system->num_molec_charge_constraints); + + (system->num_molec_charge_constraints == 0 ? 1 : system->num_molec_charge_constraints) + + (system->num_custom_charge_constraints == 0 ? 1 : system->num_custom_charge_constraints); if ( realloc == TRUE || system->N_cm > system->N_cm_max ) { system->N_cm_max = system->N_max - + (system->num_molec_charge_constraints == 0 ? 1 : system->num_molec_charge_constraints); + + (system->num_molec_charge_constraints == 0 ? 1 : system->num_molec_charge_constraints) + + (system->num_custom_charge_constraints == 0 ? 1 : system->num_custom_charge_constraints); } break; case ACKS2_CM: @@ -467,15 +469,27 @@ static void Init_Workspace( reax_system * const system, workspace->b_s[i] = -system->reax_param.sbp[ system->atoms[i].type ].chi; } - if ( system->num_molec_charge_constraints == 0 ) + if ( system->num_molec_charge_constraints == 0 + && system->num_custom_charge_constraints == 0 ) { workspace->b_s[system->N] = control->cm_q_net; } else { - for ( i = 0; i < system->num_molec_charge_constraints; ++i ) + if ( system->num_molec_charge_constraints > 0 ) { - workspace->b_s[system->N + i] = system->molec_charge_constraints[i]; + for ( i = 0; i < system->num_molec_charge_constraints; ++i ) + { + workspace->b_s[system->N + i] = system->molec_charge_constraints[i]; + } + } + if ( system->num_custom_charge_constraints > 0 ) + { + for ( i = 0; i < system->num_custom_charge_constraints; ++i ) + { + workspace->b_s[system->N + system->num_molec_charge_constraints + i] + = system->custom_charge_constraint_rhs[i]; + } } } break; @@ -1329,6 +1343,8 @@ static void Finalize_System( reax_system *system, control_params *control, system->max_num_molec_charge_constraints = 0; system->num_molec_charge_constraints = 0; + system->max_num_custom_charge_constraints = 0; + system->num_custom_charge_constraints = 0; reax = &system->reax_param; diff --git a/sPuReMD/src/reax_types.h b/sPuReMD/src/reax_types.h index 49975296..61da0a81 100644 --- a/sPuReMD/src/reax_types.h +++ b/sPuReMD/src/reax_types.h @@ -898,6 +898,24 @@ struct reax_system unsigned int num_molec_charge_constraints; /* max. num. of charge constraints on groups of atoms (i.e., molecules) */ unsigned int max_num_molec_charge_constraints; + /* num. of custom charge constraints */ + unsigned int num_custom_charge_constraints; + /* max. num. of custom charge constraints */ + unsigned int max_num_custom_charge_constraints; + /* num. of custom charge constraint entries (atom indices, coefficients) */ + unsigned int num_custom_charge_constraint_entries; + /* max. num. of custom charge constraint entries (atom indices, coefficients) */ + unsigned int max_num_custom_charge_constraint_entries; + /* entry counts for each custom charge constraint */ + int *custom_charge_constraint_count; + /* indices for custom charge constraint info (atom indices, coefficients) */ + int *custom_charge_constraint_start; + /* 1-based atom numbers used to identify entries for each custom charge constraint */ + int *custom_charge_constraint_atom_index; + /* coefficients of entries for each custom charge constraint */ + real *custom_charge_constraint_coeff; + /* right-hand side (RHS) constant values for each custom charge constraint */ + real *custom_charge_constraint_rhs; /* atomic interaction parameters */ reax_interaction reax_param; /* grid specifying domain (i.e., spatial) decompisition diff --git a/sPuReMD/src/spuremd.c b/sPuReMD/src/spuremd.c index 81feaa42..c778d81d 100644 --- a/sPuReMD/src/spuremd.c +++ b/sPuReMD/src/spuremd.c @@ -227,6 +227,9 @@ void * setup( const char * const geo_file, const char * const ffield_file, spmd_handle->system->N_max = 0; spmd_handle->system->max_num_molec_charge_constraints = 0; + spmd_handle->system->num_molec_charge_constraints = 0; + spmd_handle->system->max_num_custom_charge_constraints = 0; + spmd_handle->system->num_custom_charge_constraints = 0; Read_Input_Files( geo_file, ffield_file, control_file, spmd_handle->system, spmd_handle->control, @@ -1021,18 +1024,27 @@ int set_control_parameter( const void * const handle, const char * const keyword * sim_box_info: simulation box information, where the entries are * - box length per dimension (3 entries) * - angles per dimension (3 entries) - * num_charge_constraints: num. of charge constraints for charge model - * charge_constraint_start: starting atom num. (1-based) of atom group for a charge constraint - * charge_constraint_end: ending atom num. (1-based) of atom group for a charge constraint - * charge_constraint_value: charge constraint value for atom group + * num_charge_constraint_contig: num. of contiguous charge constraints for charge model + * charge_constraint_contig_start: starting atom num. (1-based) of atom group for a charge constraint + * charge_constraint_contig_end: ending atom num. (1-based) of atom group for a charge constraint + * charge_constraint_contig_value: charge constraint value for atom group + * num_charge_constraint_custom: num. of custom charge constraints for charge model + * charge_constraint_custom_count: counts for each custom charge constraint + * charge_constraint_custom_atom_index: atom indices (1-based) for custom charge constraints + * charge_constraint_custom_coeff: coefficients for custom charge constraints + * charge_constraint_custom_rhs: right-hand side (RHS) constants for custom charge constraints * ffield_file: file containing force field parameters * control_file: file containing simulation parameters */ void * setup_qmmm( int qm_num_atoms, const char * const qm_symbols, const double * const qm_pos, int mm_num_atoms, const char * const mm_symbols, const double * const mm_pos_q, const double * const sim_box_info, - int num_charge_constraints, const int * const charge_constraint_start, - const int * const charge_constraint_end, const double * const charge_constraint_value, + int num_charge_constraint_contig, const int * const charge_constraint_contig_start, + const int * const charge_constraint_contig_end, const double * const charge_constraint_contig_value, + int num_charge_constraint_custom, const int * const charge_constraint_custom_count, + const int * const charge_constraint_custom_atom_index, + const double * const charge_constraint_custom_coeff, + const double * const charge_constraint_custom_rhs, const char * const ffield_file, const char * const control_file ) { int i; @@ -1051,8 +1063,8 @@ void * setup_qmmm( int qm_num_atoms, const char * const qm_symbols, spmd_handle->data, spmd_handle->workspace, spmd_handle->out_control, FALSE ); - spmd_handle->system->max_num_molec_charge_constraints = num_charge_constraints; - spmd_handle->system->num_molec_charge_constraints = num_charge_constraints; + spmd_handle->system->max_num_molec_charge_constraints = num_charge_constraint_contig; + spmd_handle->system->num_molec_charge_constraints = num_charge_constraint_contig; if ( spmd_handle->system->num_molec_charge_constraints > 0 ) { @@ -1065,9 +1077,54 @@ void * setup_qmmm( int qm_num_atoms, const char * const qm_symbols, for ( i = 0; i < spmd_handle->system->num_molec_charge_constraints; ++i ) { - spmd_handle->system->molec_charge_constraint_ranges[2 * i] = charge_constraint_start[i]; - spmd_handle->system->molec_charge_constraint_ranges[2 * i + 1] = charge_constraint_end[i]; - spmd_handle->system->molec_charge_constraints[i] = charge_constraint_value[i]; + spmd_handle->system->molec_charge_constraint_ranges[2 * i] = charge_constraint_contig_start[i]; + spmd_handle->system->molec_charge_constraint_ranges[2 * i + 1] = charge_constraint_contig_end[i]; + spmd_handle->system->molec_charge_constraints[i] = charge_constraint_contig_value[i]; + } + } + + spmd_handle->system->max_num_custom_charge_constraints = num_charge_constraint_custom; + spmd_handle->system->num_custom_charge_constraints = num_charge_constraint_custom; + spmd_handle->system->num_custom_charge_constraint_entries = 0; + + if ( spmd_handle->system->num_custom_charge_constraints > 0 ) + { + spmd_handle->system->custom_charge_constraint_count = smalloc( + sizeof(int) * spmd_handle->system->num_custom_charge_constraints, + __FILE__, __LINE__ ); + spmd_handle->system->custom_charge_constraint_start = smalloc( + sizeof(int) * (spmd_handle->system->num_custom_charge_constraints + 1), + __FILE__, __LINE__ ); + spmd_handle->system->custom_charge_constraint_rhs = smalloc( + sizeof(real) * spmd_handle->system->num_custom_charge_constraints, + __FILE__, __LINE__ ); + + for ( i = 0; i < spmd_handle->system->num_custom_charge_constraints; ++i ) + { + spmd_handle->system->custom_charge_constraint_count[i] = charge_constraint_custom_count[i]; + spmd_handle->system->custom_charge_constraint_start[i] = (i == 0 ? 0 : + charge_constraint_custom_count[i - 1] + charge_constraint_custom_count[i - 1]); + spmd_handle->system->num_custom_charge_constraint_entries += charge_constraint_custom_count[i]; + spmd_handle->system->custom_charge_constraint_rhs[i] = charge_constraint_custom_rhs[i]; + } + } + + spmd_handle->system->max_num_custom_charge_constraint_entries + = spmd_handle->system->num_custom_charge_constraint_entries; + + if ( spmd_handle->system->num_custom_charge_constraint_entries > 0 ) + { + spmd_handle->system->custom_charge_constraint_atom_index = smalloc( + sizeof(int) * spmd_handle->system->num_custom_charge_constraint_entries, + __FILE__, __LINE__ ); + spmd_handle->system->custom_charge_constraint_coeff = smalloc( + sizeof(real) * spmd_handle->system->num_custom_charge_constraint_entries, + __FILE__, __LINE__ ); + + for ( i = 0; i < spmd_handle->system->num_custom_charge_constraint_entries; ++i ) + { + spmd_handle->system->custom_charge_constraint_atom_index[i] = charge_constraint_custom_atom_index[i]; + spmd_handle->system->custom_charge_constraint_coeff[i] = charge_constraint_custom_coeff[i]; } } @@ -1176,10 +1233,15 @@ void * setup_qmmm( int qm_num_atoms, const char * const qm_symbols, * sim_box_info: simulation box information, where the entries are * - box length per dimension (3 entries) * - angles per dimension (3 entries) - * num_charge_constraints: num. of charge constraints for charge model - * charge_constraint_start: starting atom num. (1-based) of atom group for a charge constraint - * charge_constraint_end: ending atom num. (1-based) of atom group for a charge constraint - * charge_constraint_value: charge constraint value for atom group + * num_charge_constraint_contig: num. of contiguous charge constraints for charge model + * charge_constraint_contig_start: starting atom num. (1-based) of atom group for a charge constraint + * charge_constraint_contig_end: ending atom num. (1-based) of atom group for a charge constraint + * charge_constraint_contig_value: charge constraint value for atom group + * num_charge_constraint_custom: num. of custom charge constraints for charge model + * charge_constraint_custom_count: counts for each custom charge constraint + * charge_constraint_custom_atom_index: atom indices (1-based) for custom charge constraints + * charge_constraint_custom_coeff: coefficients for custom charge constraints + * charge_constraint_custom_rhs: right-hand side (RHS) constants for custom charge constraints * ffield_file: file containing force field parameters * control_file: file containing simulation parameters * @@ -1189,8 +1251,12 @@ int reset_qmmm( const void * const handle, int qm_num_atoms, const char * const qm_symbols, const double * const qm_pos, int mm_num_atoms, const char * const mm_symbols, const double * const mm_pos_q, const double * const sim_box_info, - int num_charge_constraints, const int * const charge_constraint_start, - const int * const charge_constraint_end, const double * const charge_constraint_value, + int num_charge_constraint_contig, const int * const charge_constraint_contig_start, + const int * const charge_constraint_contig_end, const double * const charge_constraint_contig_value, + int num_charge_constraint_custom, const int * const charge_constraint_custom_count, + const int * const charge_constraint_custom_atom_index, + const double * const charge_constraint_custom_coeff, + const double * const charge_constraint_custom_rhs, const char * const ffield_file, const char * const control_file ) { int i, ret; @@ -1219,7 +1285,7 @@ int reset_qmmm( const void * const handle, int qm_num_atoms, spmd_handle->data, spmd_handle->workspace, spmd_handle->out_control, TRUE ); - spmd_handle->system->num_molec_charge_constraints = num_charge_constraints; + spmd_handle->system->num_molec_charge_constraints = num_charge_constraint_contig; if ( spmd_handle->system->num_molec_charge_constraints > spmd_handle->system->max_num_molec_charge_constraints ) @@ -1247,9 +1313,82 @@ int reset_qmmm( const void * const handle, int qm_num_atoms, { for ( i = 0; i < spmd_handle->system->num_molec_charge_constraints; ++i ) { - spmd_handle->system->molec_charge_constraint_ranges[2 * i] = charge_constraint_start[i]; - spmd_handle->system->molec_charge_constraint_ranges[2 * i + 1] = charge_constraint_end[i]; - spmd_handle->system->molec_charge_constraints[i] = charge_constraint_value[i]; + spmd_handle->system->molec_charge_constraint_ranges[2 * i] = charge_constraint_contig_start[i]; + spmd_handle->system->molec_charge_constraint_ranges[2 * i + 1] = charge_constraint_contig_end[i]; + spmd_handle->system->molec_charge_constraints[i] = charge_constraint_contig_value[i]; + } + } + + spmd_handle->system->num_custom_charge_constraints = num_charge_constraint_custom; + + if ( spmd_handle->system->num_custom_charge_constraints + > spmd_handle->system->max_num_custom_charge_constraints ) + { + if ( spmd_handle->system->max_num_custom_charge_constraints > 0 ) + { + sfree( spmd_handle->system->custom_charge_constraint_count, + __FILE__, __LINE__ ); + sfree( spmd_handle->system->custom_charge_constraint_start, + __FILE__, __LINE__ ); + sfree( spmd_handle->system->custom_charge_constraint_rhs, + __FILE__, __LINE__ ); + } + + spmd_handle->system->custom_charge_constraint_count = smalloc( + sizeof(int) * spmd_handle->system->num_custom_charge_constraints, + __FILE__, __LINE__ ); + spmd_handle->system->custom_charge_constraint_start = smalloc( + sizeof(int) * (spmd_handle->system->num_custom_charge_constraints + 1), + __FILE__, __LINE__ ); + spmd_handle->system->custom_charge_constraint_rhs = smalloc( + sizeof(real) * spmd_handle->system->num_custom_charge_constraints, + __FILE__, __LINE__ ); + + spmd_handle->system->max_num_custom_charge_constraints + = spmd_handle->system->num_custom_charge_constraints; + } + + spmd_handle->system->num_custom_charge_constraint_entries = 0; + if ( spmd_handle->system->num_custom_charge_constraints > 0 ) + { + for ( i = 0; i < spmd_handle->system->num_custom_charge_constraints; ++i ) + { + spmd_handle->system->custom_charge_constraint_count[i] = charge_constraint_custom_count[i]; + spmd_handle->system->custom_charge_constraint_start[i] = (i == 0 ? 0 : + charge_constraint_custom_count[i - 1] + charge_constraint_custom_count[i - 1]); + spmd_handle->system->num_custom_charge_constraint_entries += charge_constraint_custom_count[i]; + spmd_handle->system->custom_charge_constraint_rhs[i] = charge_constraint_custom_rhs[i]; + } + } + + if ( spmd_handle->system->num_custom_charge_constraint_entries + > spmd_handle->system->max_num_custom_charge_constraint_entries ) + { + if ( spmd_handle->system->max_num_custom_charge_constraint_entries > 0 ) + { + sfree( spmd_handle->system->custom_charge_constraint_atom_index, + __FILE__, __LINE__ ); + sfree( spmd_handle->system->custom_charge_constraint_coeff, + __FILE__, __LINE__ ); + } + + spmd_handle->system->custom_charge_constraint_atom_index = smalloc( + sizeof(int) * spmd_handle->system->num_custom_charge_constraint_entries, + __FILE__, __LINE__ ); + spmd_handle->system->custom_charge_constraint_coeff = smalloc( + sizeof(real) * spmd_handle->system->num_custom_charge_constraint_entries, + __FILE__, __LINE__ ); + + spmd_handle->system->max_num_custom_charge_constraint_entries + = spmd_handle->system->num_custom_charge_constraint_entries; + } + + if ( spmd_handle->system->num_custom_charge_constraint_entries > 0 ) + { + for ( i = 0; i < spmd_handle->system->num_custom_charge_constraint_entries; ++i ) + { + spmd_handle->system->custom_charge_constraint_atom_index[i] = charge_constraint_custom_atom_index[i]; + spmd_handle->system->custom_charge_constraint_coeff[i] = charge_constraint_custom_coeff[i]; } } diff --git a/sPuReMD/src/spuremd.h b/sPuReMD/src/spuremd.h index 5b4d44f0..a644bb21 100644 --- a/sPuReMD/src/spuremd.h +++ b/sPuReMD/src/spuremd.h @@ -77,13 +77,15 @@ void * setup_qmmm( int, const char * const, const double * const, int, const char * const, const double * const, const double * const, int, const int * const, const int * const, const double * const, - const char * const, const char * const ); + int, const int * const, const int * const, const double * const, + const double * const, const char * const, const char * const ); int reset_qmmm( const void * const, int, const char * const, const double * const, int, const char * const, const double * const, const double * const, int, const int * const, const int * const, const double * const, - const char * const, const char * const); + int, const int * const, const int * const, const double * const, + const double * const, const char * const, const char * const); int get_atom_positions_qmmm( const void * const, double * const, double * const ); -- GitLab