@@ -118,6 +118,49 @@ set_coord_points(struct frag *frag, const double *coord)
118118 return EFP_RESULT_SUCCESS ;
119119}
120120
121+ static enum efp_result
122+ set_coord_atoms (struct frag * frag , const double * coord )
123+ {
124+ /* allow fragments with less than 3 atoms by using multipole points of
125+ * ghost atoms; multipole points have the same coordinates as atoms */
126+ if (frag -> n_multipole_pts < 3 ) {
127+ efp_log ("fragment must contain at least three atoms" );
128+ return EFP_RESULT_FATAL ;
129+ }
130+
131+ int natoms = frag -> lib -> n_atoms ;
132+
133+ double ref [9 ] = {
134+ frag -> lib -> multipole_pts [0 ].x ,
135+ frag -> lib -> multipole_pts [0 ].y ,
136+ frag -> lib -> multipole_pts [0 ].z ,
137+ frag -> lib -> multipole_pts [1 ].x ,
138+ frag -> lib -> multipole_pts [1 ].y ,
139+ frag -> lib -> multipole_pts [1 ].z ,
140+ frag -> lib -> multipole_pts [2 ].x ,
141+ frag -> lib -> multipole_pts [2 ].y ,
142+ frag -> lib -> multipole_pts [2 ].z
143+ };
144+
145+ vec_t p1 ;
146+ mat_t rot1 , rot2 ;
147+
148+ efp_points_to_matrix (coord , & rot1 );
149+ efp_points_to_matrix (ref , & rot2 );
150+ rot2 = mat_transpose (& rot2 );
151+ frag -> rotmat = mat_mat (& rot1 , & rot2 );
152+ p1 = mat_vec (& frag -> rotmat , VEC (frag -> lib -> multipole_pts [0 ].x ));
153+
154+ /* center of mass */
155+ frag -> x = coord [0 ] - p1 .x ;
156+ frag -> y = coord [1 ] - p1 .y ;
157+ frag -> z = coord [2 ] - p1 .z ;
158+
159+ update_fragment (frag );
160+
161+ return EFP_RESULT_SUCCESS ;
162+ }
163+
121164static enum efp_result
122165set_coord_rotmat (struct frag * frag , const double * coord )
123166{
@@ -290,6 +333,28 @@ copy_frag(struct frag *dest, const struct frag *src)
290333 return EFP_RESULT_SUCCESS ;
291334}
292335
336+ // updates (shifts) parameters of fragment based on coordinates of fragment atoms
337+ static enum efp_result
338+ update_params (struct efp_atom * atoms , const struct frag * lib_orig , const struct frag * lib_current ) {
339+ return EFP_RESULT_SUCCESS ;
340+ }
341+
342+ // checks whether atoms in fragment "frag" match those in fragment "lib"
343+ static enum efp_result
344+ check_frag_atoms (struct frag * frag , const struct frag * lib ) {
345+ return EFP_RESULT_SUCCESS ;
346+ }
347+
348+ static enum efp_result
349+ clean_frag_atoms (struct frag * frag )
350+ {
351+ if (frag -> atoms ) {
352+ free (frag -> atoms );
353+ frag -> n_atoms = 0 ;
354+ }
355+ return EFP_RESULT_SUCCESS ;
356+ }
357+
293358static enum efp_result
294359check_opts (const struct efp_opts * opts )
295360{
@@ -885,13 +950,17 @@ efp_set_coordinates(struct efp *efp, enum efp_coord_type coord_type,
885950 case EFP_COORD_TYPE_ROTMAT :
886951 stride = 12 ;
887952 break ;
953+ case EFP_COORD_TYPE_ATOMS :
954+ stride = 9 ;
955+ break ;
888956 }
889957
890- for (size_t i = 0 ; i < efp -> n_frag ; i ++ , coord += stride )
891- if ((res = efp_set_frag_coordinates (efp , i , coord_type , coord ))) {
958+ for (size_t i = 0 ; i < efp -> n_frag ; i ++ , coord += stride ) {
959+ if ((res = efp_set_frag_coordinates (efp , i , coord_type , coord ))) {
892960 efp_log ("efp_set_coordinates() failure" );
893961 return res ;
894- }
962+ }
963+ }
895964
896965 return EFP_RESULT_SUCCESS ;
897966}
@@ -915,6 +984,8 @@ efp_set_frag_coordinates(struct efp *efp, size_t frag_idx,
915984 return set_coord_points (frag , coord );
916985 case EFP_COORD_TYPE_ROTMAT :
917986 return set_coord_rotmat (frag , coord );
987+ case EFP_COORD_TYPE_ATOMS :
988+ return set_coord_atoms (frag , coord );
918989 }
919990 efp_log ("efp_set_frag_coordinates() failure" );
920991 assert (0 );
@@ -1517,8 +1588,14 @@ efp_shutdown(struct efp *efp)
15171588 free_frag (efp -> lib [i ]);
15181589 free (efp -> lib [i ]);
15191590 }
1591+ // for the case of updated/shifted fragment parameters
1592+ for (size_t i = 0 ; i < efp -> n_lib_current ; i ++ ) {
1593+ free_frag (efp -> lib_current [i ]);
1594+ free (efp -> lib_current [i ]);
1595+ }
15201596 free (efp -> frags );
15211597 free (efp -> lib );
1598+ free (efp -> lib_current );
15221599 free (efp -> grad );
15231600 free (efp -> ptc );
15241601 free (efp -> ptc_xyz );
@@ -1605,6 +1682,19 @@ efp_add_fragment(struct efp *efp, const char *name)
16051682 enum efp_result res ;
16061683 struct frag * frag = efp -> frags + efp -> n_frag - 1 ;
16071684
1685+ // if update/rotate parameters
1686+ if (efp -> opts .update_params == 1 ) {
1687+ // first, sanity check: do fragment atoms match those in the library fragment?
1688+ if (res = check_frag_atoms (frag , lib )) {
1689+ efp_log ("check_frag_atoms() failure" );
1690+ return res ;
1691+ }
1692+ frag -> rmsd = calc_rmsd (frag ,lib );
1693+ if (frag -> rmsd < efp -> opts .update_params_cutoff ) {
1694+ update_params (frag -> atoms ,lib , frag -> lib_current );
1695+ }
1696+ }
1697+
16081698 if ((res = copy_frag (frag , lib ))) {
16091699 efp_log ("copy_frag() failure" );
16101700 return res ;
@@ -1766,6 +1856,23 @@ efp_get_frag_atoms(struct efp *efp, size_t frag_idx, size_t size,
17661856 return EFP_RESULT_SUCCESS ;
17671857}
17681858
1859+ EFP_EXPORT enum efp_result
1860+ efp_set_frag_atoms (struct efp * efp , size_t frag_idx , size_t n_atoms ,
1861+ struct efp_atom * atoms )
1862+ {
1863+ struct frag * frag ;
1864+
1865+ assert (efp );
1866+ assert (atoms );
1867+ assert (frag_idx < efp -> n_frag );
1868+
1869+ frag = efp -> frags + frag_idx ;
1870+ frag -> n_atoms = n_atoms ;
1871+ memcpy (frag -> atoms , atoms , n_atoms * sizeof (struct efp_atom ));
1872+
1873+ return EFP_RESULT_SUCCESS ;
1874+ }
1875+
17691876EFP_EXPORT void
17701877efp_torque_to_derivative (const double * euler , const double * torque ,
17711878 double * deriv )
@@ -1983,3 +2090,4 @@ n_symm_frag(struct efp *efp, size_t *symm_frag) {
19832090 }
19842091}
19852092
2093+
0 commit comments