@@ -268,7 +268,6 @@ def normalize(self, archive, logger) -> None:
268
268
)
269
269
270
270
if self .forces is not None and self .energies is None :
271
- print ('in gen energies' )
272
271
try :
273
272
# generated energies from forces numerically using spline
274
273
self .energies = self .compute_energies (
@@ -308,8 +307,38 @@ def normalize(self, archive, logger) -> None:
308
307
)
309
308
310
309
311
- class PolynomialPotential (Potential ):
310
+ class PolynomialForceConstant (ParameterEntry ):
311
+ """
312
+ Section defining a force constant for a potential of polynomial form.
312
313
"""
314
+
315
+ name = Quantity (
316
+ type = str ,
317
+ shape = [],
318
+ description = """
319
+ Name of the force constant.
320
+ """ ,
321
+ )
322
+
323
+ exponent = Quantity (
324
+ type = np .int32 ,
325
+ shape = [],
326
+ description = """
327
+ Exponent for this term in the polynomial.
328
+ """ ,
329
+ )
330
+
331
+ value = Quantity (
332
+ type = np .float64 ,
333
+ shape = [],
334
+ description = """
335
+ Value of the force constant.
336
+ """ ,
337
+ )
338
+
339
+
340
+ class PolynomialPotential (Potential ):
341
+ r"""
313
342
Abstract class for potentials with polynomial form:
314
343
$V(x) = [\left k_1 (x - x_0) + k_2 (x - x_0)^2 + x_3 (x - x_0)^3 + \dots + C$,
315
344
where $\{x_1, x_2, x_3 \dots}$ are the `force_constants` for each term in the polynomial
@@ -318,7 +347,7 @@ class PolynomialPotential(Potential):
318
347
"""
319
348
320
349
force_constants = SubSection (
321
- sub_section = ParameterEntry .m_def ,
350
+ sub_section = PolynomialForceConstant .m_def ,
322
351
repeats = True ,
323
352
description = """
324
353
List of force constants value and corresponding unit for polynomial potentials.
@@ -329,13 +358,17 @@ def normalize(self, archive, logger) -> None:
329
358
super ().normalize (archive , logger )
330
359
331
360
self .name = 'PolynomialPotential'
361
+ if not self .functional_form :
362
+ self .functional_form = 'polynomial'
363
+ elif self .functional_form != 'polynomial' :
364
+ logger .warning ('Incorrect functional form set for PolynomialPotential.' )
332
365
333
366
334
367
class BondPotential (Potential ):
335
368
"""
336
369
Section containing information about bond potentials.
337
370
338
- Suggested types are: harmonic, cubic, Morse, fene, tabulated
371
+ Suggested types are: harmonic, cubic, polynomial, Morse, fene, tabulated
339
372
"""
340
373
341
374
equilibrium_value = Quantity (
@@ -419,47 +452,19 @@ def normalize(self, archive, logger) -> None:
419
452
logger .warning ('Incorrect functional form set for CubicBond.' )
420
453
421
454
422
- # TODO Add Fourth Power potential from gromacs, might want to make it a more general quartic polynomial, even though it's not as general
423
- # class QuarticBond(BondPotential):
424
- # r"""
425
- # Section containing information about a Cubic bond potential:
426
- # $V(r) = \frac{1}{2} k_r (r - r_0)^2 + \frac{1}{3} k_c (r - r_0)^3 + C$,
427
- # where $k_r$ is the (harmonic) `force_constant`, $k_c$ is the `force_constant_cubic`,
428
- # and $r_0$ is the `equilibrium_value` of $r$.
429
- # C is an arbitrary constant (not stored).
430
- # """
431
-
432
- # force_constant_cubic = Quantity(
433
- # type=np.float64,
434
- # shape=[],
435
- # unit='J / m**3',
436
- # description="""
437
- # Specifies the cubic force constant of the bond potential.
438
- # """,
439
- # )
440
-
441
- # def normalize(self, archive, logger) -> None:
442
- # super().normalize(archive, logger)
443
-
444
- # self.name = 'CubicBond'
445
- # if not self.functional_form:
446
- # self.functional_form = 'cubic'
447
- # elif self.functional_form != 'cubic':
448
- # logger.warning('Incorrect functional form set for CubicBond.')
449
-
450
-
451
455
class PolynomialBond (PolynomialPotential , BondPotential ):
452
456
"""
453
457
Section containing information about a polynomial bond potential:
454
458
"""
455
459
456
460
def __init__ (self ):
461
+ super ().__init__ ()
457
462
docstring = PolynomialPotential .__doc__
458
463
pattern = r'\$V\(x\)(.*?)(\(not stored\)\.)'
459
464
match = re .search (pattern , docstring , re .DOTALL )
460
465
extracted_text = '<functional form missing>'
461
466
if match :
462
- extracted_text = match .group (1 ).strip ()
467
+ extracted_text = match .group (). strip () # .group( 1).strip()
463
468
self .__doc__ = rf"""{ self .__doc__ } { extracted_text } .
464
469
Here the dependent variable of the potential, $x$, corresponds to the bond distance."""
465
470
@@ -572,7 +577,7 @@ class AnglePotential(Potential):
572
577
"""
573
578
Section containing information about angle potentials.
574
579
575
- Suggested types are: harmonic, cosine, fourier_series, urey_bradley, tabulated
580
+ Suggested types are: harmonic, cosine, restricted_cosinse, fourier_series, urey_bradley, polynomial , tabulated
576
581
"""
577
582
578
583
equilibrium_value = Quantity (
@@ -745,12 +750,13 @@ class PolynomialAngle(PolynomialPotential, AnglePotential):
745
750
"""
746
751
747
752
def __init__ (self ):
753
+ super ().__init__ ()
748
754
docstring = PolynomialPotential .__doc__
749
755
pattern = r'\$V\(x\)(.*?)(\(not stored\)\.)'
750
756
match = re .search (pattern , docstring , re .DOTALL )
751
757
extracted_text = '<functional form missing>'
752
758
if match :
753
- extracted_text = match .group (1 ).strip ()
759
+ extracted_text = match .group (). strip () # .group( 1).strip()
754
760
self .__doc__ = rf"""{ self .__doc__ } { extracted_text } .
755
761
Here the dependent variable of the potential, $x$, corresponds to the angle between three particles."""
756
762
@@ -790,6 +796,81 @@ def normalize(self, archive, logger) -> None:
790
796
self .name = 'TabulatedAngle'
791
797
792
798
799
+ class DihedralPotential (Potential ):
800
+ """
801
+ Section containing information about dihedral potentials.
802
+
803
+ Suggested types are: fourier_series, tabulated
804
+
805
+ # ? Something about angle convention?
806
+ """
807
+
808
+ equilibrium_value = Quantity (
809
+ type = np .float64 ,
810
+ unit = 'degree' ,
811
+ shape = [],
812
+ description = """
813
+ Specifies the equilibrium dihedral angle.
814
+ """ ,
815
+ )
816
+
817
+ force_constant = Quantity (
818
+ type = np .float64 ,
819
+ shape = [],
820
+ unit = 'J / degree**2' ,
821
+ description = """
822
+ Specifies the force constant of the dihedral angle potential.
823
+ """ ,
824
+ )
825
+
826
+ def normalize (self , archive , logger ) -> None :
827
+ super ().normalize (archive , logger )
828
+
829
+ self .name = 'DihedralPotential'
830
+ if not self .type :
831
+ self .type = 'dihedral'
832
+ elif self .type != 'dihedral' :
833
+ logger .warning ('Incorrect type set for DihedralPotential.' )
834
+
835
+ if self .n_particles :
836
+ if self .n_particles != 4 :
837
+ logger .warning (
838
+ 'Incorrect number of particles set for DihedralPotential.'
839
+ )
840
+ else :
841
+ self .n_particles = 4
842
+
843
+
844
+ class TabulatedDihedral (DihedralPotential , TabulatedPotential ):
845
+ """
846
+ Section containing information about a tabulated bond potential. The value of the potential and/or force
847
+ is stored for a set of corresponding bin distances.
848
+ """
849
+
850
+ bins = Quantity (
851
+ type = np .float64 ,
852
+ unit = 'degree' ,
853
+ shape = [],
854
+ description = """
855
+ List of bin dihedral angles.
856
+ """ ,
857
+ )
858
+
859
+ forces = Quantity (
860
+ type = np .float64 ,
861
+ unit = 'J/degree' ,
862
+ shape = [],
863
+ description = """
864
+ List of force values associated with each bin.
865
+ """ ,
866
+ )
867
+
868
+ def normalize (self , archive , logger ) -> None :
869
+ super ().normalize (archive , logger )
870
+
871
+ self .name = 'TabulatedDihedral'
872
+
873
+
793
874
class ForceField (ModelMethod ):
794
875
"""
795
876
Section containing the parameters of a (classical, particle-based) force field model.
0 commit comments