From d4189efaa9ec1f12aca39a8bf713266fbc3aad9b Mon Sep 17 00:00:00 2001 From: "Kurt A. O'Hearn" <ohearnku@msu.edu> Date: Wed, 3 Mar 2021 17:07:25 -0500 Subject: [PATCH] sPuReMD: rework QMMM interface to use string representations of atom element types. --- sPuReMD/src/spuremd.c | 79 +++++++++++-------- sPuReMD/src/spuremd.h | 8 +- .../qmmm_amber/fortran_stub/driver.F03 | 41 ++-------- .../qm2_extern_reaxff_puremd_module.F03 | 32 ++++---- 4 files changed, 72 insertions(+), 88 deletions(-) diff --git a/sPuReMD/src/spuremd.c b/sPuReMD/src/spuremd.c index a39aa774..f4ab6109 100644 --- a/sPuReMD/src/spuremd.c +++ b/sPuReMD/src/spuremd.c @@ -37,6 +37,8 @@ #include "tool_box.h" #include "vector.h" +#include <ctype.h> + /* Handles additional entire geometry calculations after * perturbing atom positions during a simulation step @@ -954,10 +956,10 @@ int set_control_parameter( const void * const handle, const char * const keyword * for the first simulation * * qm_num_atoms: num. atoms in the QM region - * qm_types: element types for QM atoms + * qm_symbols: element types for QM atoms * qm_pos: coordinates of QM atom positions (consecutively arranged), in Angstroms * mm_num_atoms: num. atoms in the MM region - * mm_types: element types for MM atoms + * mm_symbols: element types for MM atoms * mm_pos_q: coordinates and charges of MM atom positions (consecutively arranged), in Angstroms / Coulombs * sim_box_info: simulation box information, where the entries are * - box length per dimension (3 entries) @@ -965,13 +967,13 @@ int set_control_parameter( const void * const handle, const char * const keyword * ffield_file: file containing force field parameters * control_file: file containing simulation parameters */ -void * setup_qmmm( int qm_num_atoms, const int * const qm_types, - const double * const qm_pos, int mm_num_atoms, const int * const mm_types, +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, const char * const ffield_file, const char * const control_file ) { int i; -// char atom_name[9]; + char element[3]; rvec x; spuremd_handle *spmd_handle; @@ -1000,6 +1002,8 @@ void * setup_qmmm( int qm_num_atoms, const int * const qm_types, sim_box_info[3], sim_box_info[4], sim_box_info[5], &spmd_handle->system->box ); + element[2] = '\0'; + for ( i = 0; i < spmd_handle->system->N_qm; ++i ) { x[0] = qm_pos[3 * i]; @@ -1009,12 +1013,14 @@ void * setup_qmmm( int qm_num_atoms, const int * const qm_types, Fit_to_Periodic_Box( &spmd_handle->system->box, x ); spmd_handle->workspace->orig_id[i] = i + 1; -// spmd_handle->system->atoms[i].type = Get_Atom_Type( &system->reax_param, -// element, sizeof(element) ); - spmd_handle->system->atoms[i].type = qm_types[i]; -// strncpy( spmd_handle->system->atoms[i].name, atom_name, -// sizeof(spmd_handle->system->atoms[i].name) - 1 ); -// spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; + element[0] = toupper( qm_symbols[2 * i] ); + element[1] = toupper( qm_symbols[2 * i + 1] ); + Trim_Spaces( element, sizeof(element) ); + spmd_handle->system->atoms[i].type = Get_Atom_Type( &spmd_handle->system->reax_param, + element, sizeof(element) ); + strncpy( spmd_handle->system->atoms[i].name, element, + sizeof(spmd_handle->system->atoms[i].name) - 1 ); + spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; rvec_Copy( spmd_handle->system->atoms[i].x, x ); rvec_MakeZero( spmd_handle->system->atoms[i].v ); rvec_MakeZero( spmd_handle->system->atoms[i].f ); @@ -1033,12 +1039,14 @@ void * setup_qmmm( int qm_num_atoms, const int * const qm_types, Fit_to_Periodic_Box( &spmd_handle->system->box, x ); spmd_handle->workspace->orig_id[i] = i + 1; -// spmd_handle->system->atoms[i].type = Get_Atom_Type( &system->reax_param, -// element, sizeof(element) ); - spmd_handle->system->atoms[i].type = mm_types[i - spmd_handle->system->N_qm]; -// strncpy( spmd_handle->system->atoms[i].name, atom_name, -// sizeof(spmd_handle->system->atoms[i].name) - 1 ); -// spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; + element[0] = toupper( mm_symbols[2 * (i - spmd_handle->system->N_qm)] ); + element[1] = toupper( mm_symbols[2 * (i - spmd_handle->system->N_qm) + 1] ); + Trim_Spaces( element, sizeof(element) ); + spmd_handle->system->atoms[i].type = Get_Atom_Type( &spmd_handle->system->reax_param, + element, sizeof(element) ); + strncpy( spmd_handle->system->atoms[i].name, element, + sizeof(spmd_handle->system->atoms[i].name) - 1 ); + spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; rvec_Copy( spmd_handle->system->atoms[i].x, x ); rvec_MakeZero( spmd_handle->system->atoms[i].v ); rvec_MakeZero( spmd_handle->system->atoms[i].f ); @@ -1059,10 +1067,10 @@ void * setup_qmmm( int qm_num_atoms, const int * const qm_types, * * handle: pointer to wrapper struct with top-level data structures * qm_num_atoms: num. atoms in the QM region - * qm_types: element types for QM atoms + * qm_symbols: element types for QM atoms * qm_pos: coordinates of QM atom positions (consecutively arranged), in Angstroms * mm_num_atoms: num. atoms in the MM region - * mm_types: element types for MM atoms + * mm_symbols: element types for MM atoms * mm_pos_q: coordinates and charges of MM atom positions (consecutively arranged), in Angstroms / Coulombs * sim_box_info: simulation box information, where the entries are * - box length per dimension (3 entries) @@ -1073,12 +1081,13 @@ void * setup_qmmm( int qm_num_atoms, const int * const qm_types, * returns: SPUREMD_SUCCESS upon success, SPUREMD_FAILURE otherwise */ int reset_qmmm( const void * const handle, int qm_num_atoms, - const int * const qm_types, const double * const qm_pos, - int mm_num_atoms, const int * const mm_types, + 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, const char * const ffield_file, const char * const control_file ) { int i, ret; + char element[3]; rvec x; spuremd_handle *spmd_handle; @@ -1127,12 +1136,14 @@ int reset_qmmm( const void * const handle, int qm_num_atoms, Fit_to_Periodic_Box( &spmd_handle->system->box, x ); spmd_handle->workspace->orig_id[i] = i + 1; -// spmd_handle->system->atoms[i].type = Get_Atom_Type( &system->reax_param, -// element, sizeof(element) ); - spmd_handle->system->atoms[i].type = qm_types[i]; -// strncpy( spmd_handle->system->atoms[i].name, atom_name, -// sizeof(spmd_handle->system->atoms[i].name) - 1 ); -// spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; + element[0] = toupper( qm_symbols[2 * i] ); + element[1] = toupper( qm_symbols[2 * i + 1] ); + Trim_Spaces( element, sizeof(element) ); + spmd_handle->system->atoms[i].type = Get_Atom_Type( &spmd_handle->system->reax_param, + element, sizeof(element) ); + strncpy( spmd_handle->system->atoms[i].name, element, + sizeof(spmd_handle->system->atoms[i].name) - 1 ); + spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; rvec_Copy( spmd_handle->system->atoms[i].x, x ); rvec_MakeZero( spmd_handle->system->atoms[i].v ); rvec_MakeZero( spmd_handle->system->atoms[i].f ); @@ -1150,12 +1161,14 @@ int reset_qmmm( const void * const handle, int qm_num_atoms, Fit_to_Periodic_Box( &spmd_handle->system->box, x ); spmd_handle->workspace->orig_id[i] = i + 1; -// spmd_handle->system->atoms[i].type = Get_Atom_Type( &system->reax_param, -// element, sizeof(element) ); - spmd_handle->system->atoms[i].type = mm_types[i - spmd_handle->system->N_qm]; -// strncpy( spmd_handle->system->atoms[i].name, atom_name, -// sizeof(spmd_handle->system->atoms[i].name) - 1 ); -// spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; + element[0] = toupper( mm_symbols[2 * (i - spmd_handle->system->N_qm)] ); + element[1] = toupper( mm_symbols[2 * (i - spmd_handle->system->N_qm) + 1] ); + Trim_Spaces( element, sizeof(element) ); + spmd_handle->system->atoms[i].type = Get_Atom_Type( &spmd_handle->system->reax_param, + element, sizeof(element) ); + strncpy( spmd_handle->system->atoms[i].name, element, + sizeof(spmd_handle->system->atoms[i].name) - 1 ); + spmd_handle->system->atoms[i].name[sizeof(spmd_handle->system->atoms[i].name) - 1] = '\0'; rvec_Copy( spmd_handle->system->atoms[i].x, x ); rvec_MakeZero( spmd_handle->system->atoms[i].v ); rvec_MakeZero( spmd_handle->system->atoms[i].f ); diff --git a/sPuReMD/src/spuremd.h b/sPuReMD/src/spuremd.h index cae887f4..22f534e5 100644 --- a/sPuReMD/src/spuremd.h +++ b/sPuReMD/src/spuremd.h @@ -73,13 +73,13 @@ int set_control_parameter( const void * const, const char * const, const char ** const ); #if defined(QMMM) -void * setup_qmmm( int, const int * const, - const double * const, int, const int * const, +void * setup_qmmm( int, const char * const, + const double * const, int, const char * const, const double * const, const double * const, const char * const, const char * const ); -int reset_qmmm( const void * const, int, const int * const, - const double * const, int, const int * const, +int reset_qmmm( const void * const, int, const char * const, + const double * const, int, const char * const, const double * const, const double * const, const char * const, const char * const ); diff --git a/test/library/qmmm_amber/fortran_stub/driver.F03 b/test/library/qmmm_amber/fortran_stub/driver.F03 index 7532f50e..68a287cf 100644 --- a/test/library/qmmm_amber/fortran_stub/driver.F03 +++ b/test/library/qmmm_amber/fortran_stub/driver.F03 @@ -14,7 +14,7 @@ contains integer (c_int), intent(in) :: num_qm_atoms, num_mm_atoms real (c_double), intent(out) :: sim_box_info(6) real (c_double), intent(out) :: qm_pos(3*num_qm_atoms), qm_q(num_qm_atoms), mm_pos_q(4*num_mm_atoms) - character(len=5), intent(out) :: qm_types(num_qm_atoms), mm_types(num_mm_atoms) + character(len=2), intent(out) :: qm_types(num_qm_atoms), mm_types(num_mm_atoms) character(len=200) :: line integer :: bgf_version, num_descrp, num_remark, num_format, line_num @@ -59,7 +59,7 @@ contains if (line(1:6) == 'HETATM') then if (bgf_version < 400) then if (nqm < num_qm_atoms) then - read (line, '(30x,3f10.5,1x,a5,6x,f10.5)', end=40, err=40) & + read (line, '(30x,3f10.5,4x,a2,6x,f10.5)', end=40, err=40) & qm_pos(3*nqm+1), qm_pos(3*nqm+2), qm_pos(3*nqm+3), & qm_types(nqm+1), qm_q(nqm+1) @@ -67,7 +67,7 @@ contains else ! take the MM charges from BGF file; ! Amber would set instead in real QM/MM simulation - read (line, '(30x,3f10.5,1x,a5,6x,f10.5)', end=40, err=40) & + read (line, '(30x,3f10.5,4x,a2,6x,f10.5)', end=40, err=40) & mm_pos_q(4*nmm+1), mm_pos_q(4*nmm+2), mm_pos_q(4*nmm+3), & mm_types(nmm+1), mm_pos_q(4*nmm+4) @@ -117,8 +117,7 @@ program driver integer (c_int) :: num_qm_atoms, num_mm_atoms real (c_double) :: sim_box_info(6), e_total real (c_double), dimension(:), allocatable :: qm_pos, qm_q, qm_f, mm_pos_q, mm_f - character(len=5), dimension(:), allocatable :: qm_types, mm_types - integer (c_int), dimension(:), allocatable :: qm_types_map, mm_types_map + character(len=2), dimension(:), allocatable :: qm_types, mm_types num_args = command_argument_count( ) if (num_args /= 3) then @@ -138,12 +137,10 @@ program driver read (args(3), *) num_mm_atoms allocate( qm_types(num_qm_atoms) ) - allocate( qm_types_map(num_qm_atoms) ) allocate( qm_pos(3*num_qm_atoms) ) allocate( qm_q(num_qm_atoms) ) allocate( qm_f(3*num_qm_atoms) ) allocate( mm_types(num_mm_atoms) ) - allocate( mm_types_map(num_mm_atoms) ) allocate( mm_pos_q(4*num_mm_atoms) ) allocate( mm_f(3*num_mm_atoms) ) @@ -158,32 +155,8 @@ program driver stop endif - do ix = 1, num_qm_atoms - if (trim(adjustl(qm_types(ix))) == 'C') then - qm_types_map(ix) = 0 - else if (trim(adjustl(qm_types(ix))) == 'H') then - qm_types_map(ix) = 1 - else if (trim(adjustl(qm_types(ix))) == 'O') then - qm_types_map(ix) = 2 - else - stop 'ERROR: unrecogized QM atom type' - endif - end do - - do ix = 1, num_mm_atoms - if (trim(adjustl(mm_types(ix))) == 'C') then - mm_types_map(ix) = 0 - else if (trim(adjustl(mm_types(ix))) == 'H') then - mm_types_map(ix) = 1 - else if (trim(adjustl(mm_types(ix))) == 'O') then - mm_types_map(ix) = 2 - else - stop 'ERROR: unrecogized MM atom type' - endif - end do - - call get_reaxff_puremd_forces( num_qm_atoms, qm_pos, qm_types_map, & - qm_q, num_mm_atoms, mm_pos_q, mm_types_map, e_total, qm_f, & + call get_reaxff_puremd_forces( num_qm_atoms, qm_pos, qm_types, & + qm_q, num_mm_atoms, mm_pos_q, mm_types, e_total, qm_f, & mm_f, qmcharge ) write (stdout, fmt=75) 'Total energy:', e_total @@ -202,12 +175,10 @@ program driver deallocate(args) deallocate(qm_types) - deallocate(qm_types_map) deallocate(qm_pos) deallocate(qm_q) deallocate(qm_f) deallocate(mm_types) - deallocate(mm_types_map) deallocate(mm_pos_q) deallocate(mm_f) diff --git a/test/library/qmmm_amber/fortran_stub/qm2_extern_reaxff_puremd_module.F03 b/test/library/qmmm_amber/fortran_stub/qm2_extern_reaxff_puremd_module.F03 index 772c5354..8f7469e2 100644 --- a/test/library/qmmm_amber/fortran_stub/qm2_extern_reaxff_puremd_module.F03 +++ b/test/library/qmmm_amber/fortran_stub/qm2_extern_reaxff_puremd_module.F03 @@ -5,17 +5,17 @@ module qm2_extern_reaxff_puremd_module interface type(c_ptr) function setup_qmmm & - (num_qm_atoms, qm_types, qm_pos, & - num_mm_atoms, mm_types, mm_pos_q, sim_box_info, & + (num_qm_atoms, qm_symbols, qm_pos, & + num_mm_atoms, mm_symbols, mm_pos_q, sim_box_info, & ffield_filename, control_filename) & bind(C, name='setup_qmmm') use, intrinsic :: iso_c_binding implicit none integer (c_int), value :: num_qm_atoms - type(c_ptr), value :: qm_types + type(c_ptr), value :: qm_symbols type(c_ptr), value :: qm_pos integer (c_int), value :: num_mm_atoms - type(c_ptr), value :: mm_types + type(c_ptr), value :: mm_symbols type(c_ptr), value :: mm_pos_q type(c_ptr), value :: sim_box_info type(c_ptr), value :: ffield_filename @@ -23,18 +23,18 @@ module qm2_extern_reaxff_puremd_module end function setup_qmmm integer (c_int) function reset_qmmm & - (handle, num_qm_atoms, qm_types, qm_pos, & - num_mm_atoms, mm_types, mm_pos_q, sim_box_info, & + (handle, num_qm_atoms, qm_symbols, qm_pos, & + num_mm_atoms, mm_symbols, mm_pos_q, sim_box_info, & ffield_filename, control_filename) & bind(C, name='reset_qmmm') use, intrinsic :: iso_c_binding implicit none type(c_ptr), value :: handle integer (c_int), value :: num_qm_atoms - type(c_ptr), value :: qm_types + type(c_ptr), value :: qm_symbols type(c_ptr), value :: qm_pos integer (c_int), value :: num_mm_atoms - type(c_ptr), value :: mm_types + type(c_ptr), value :: mm_symbols type(c_ptr), value :: mm_pos_q type(c_ptr), value :: sim_box_info type(c_ptr), value :: ffield_filename @@ -119,19 +119,19 @@ module qm2_extern_reaxff_puremd_module type(c_ptr), save, private :: handle = c_null_ptr contains - subroutine get_reaxff_puremd_forces( num_qm_atoms, qm_pos, qm_types, & - qm_q, num_mm_atoms, mm_pos_q, mm_types, e_total, & + subroutine get_reaxff_puremd_forces( num_qm_atoms, qm_pos, qm_symbols, & + qm_q, num_mm_atoms, mm_pos_q, mm_symbols, e_total, & qm_f, mm_f, qmcharge ) use, intrinsic :: iso_c_binding implicit none integer (c_int), intent(in) :: num_qm_atoms ! number of QM atoms real (c_double), target, intent(in) :: qm_pos(3,num_qm_atoms) ! QM atom coordinates - integer (c_int), target, intent(in) :: qm_types(num_qm_atoms) ! QM atom types + character(len=2), dimension(num_qm_atoms), target, intent(in) :: qm_symbols ! QM atom types real (c_double), target, intent(inout) :: qm_q(num_qm_atoms) ! QM atom charges (nuclear charge in au) integer (c_int), intent(in) :: num_mm_atoms ! number of MM atoms real (c_double), target, intent(in) :: mm_pos_q(4,num_mm_atoms) ! MM atom coordinates and charges (nuclear charge in au) - integer (c_int), target, intent(in) :: mm_types(num_mm_atoms) ! MM atom types + character(len=2), dimension(num_qm_atoms), target, intent(in) :: mm_symbols ! MM atom types real (c_double), target, intent(out) :: e_total ! SCF energy (kcal/mol) real (c_double), target, intent(out) :: qm_f(3,num_qm_atoms) ! SCF QM force (AMU * Angstroms / ps^2) real (c_double), target, intent(out) :: mm_f(3,num_mm_atoms) ! SCF MM force (AMU * Angstroms / ps^2) @@ -159,8 +159,8 @@ contains if ( first_call ) then first_call = .false. - handle = setup_qmmm( num_qm_atoms, c_loc(qm_types), & - c_loc(qm_pos), num_mm_atoms, c_loc(mm_types), & + handle = setup_qmmm( num_qm_atoms, c_loc(qm_symbols), & + c_loc(qm_pos), num_mm_atoms, c_loc(mm_symbols), & c_loc(mm_pos_q), c_loc(sim_box_info), c_loc(ffield_filename), c_null_ptr ) ! NVE ensemble @@ -297,8 +297,8 @@ contains c_loc(e_total), c_null_ptr, c_null_ptr, c_null_ptr ) if ( ret /= 0_c_int ) stop "ERROR: get_reaxff_puremd_forces::get_system_info" else - ret = reset_qmmm( handle, num_qm_atoms, c_loc(qm_types), & - c_loc(qm_pos), num_mm_atoms, c_loc(mm_types), & + ret = reset_qmmm( handle, num_qm_atoms, c_loc(qm_symbols), & + c_loc(qm_pos), num_mm_atoms, c_loc(mm_symbols), & c_loc(mm_pos_q), c_loc(sim_box_info), c_null_ptr, c_null_ptr ) if ( ret /= 0_c_int ) stop "ERROR: get_reaxff_puremd_forces::reset_qmmm" -- GitLab