Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LayeredDihedral and LayeredImproper support #569

Open
wants to merge 41 commits into
base: old_main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
6add25d
WIP- Add LayeredDihedral and LayeredImproper classes
umesh-timalsina Jul 13, 2021
57debcb
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Jul 13, 2021
e563d41
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Jul 16, 2021
461a509
WIP- Make existing API work after layered classes addition
umesh-timalsina Jul 16, 2021
8257f2f
Merge remote-tracking branch 'origin/561-layered-dihedrals' into 561-…
umesh-timalsina Jul 16, 2021
2cff78a
WIP- Add layered dihedral and layered improper attributes
umesh-timalsina Jul 16, 2021
6e9ad3c
WIP- fix negation in typed check predicates
umesh-timalsina Jul 16, 2021
2693f89
Add simple unit test for layered dihedrals
rsdefever Jul 16, 2021
60ec0d8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 16, 2021
cfd9125
WIP- add is_layered check while updating
umesh-timalsina Jul 16, 2021
caff017
Merge remote-tracking branch 'origin/561-layered-dihedrals' into 561-…
umesh-timalsina Jul 16, 2021
39dacc3
WIP- Use indexedset for layered dihedral/improper potentials
umesh-timalsina Jul 20, 2021
baec981
WIP- Add test for layered impropers
umesh-timalsina Jul 20, 2021
5ed6b2b
Merge remote-tracking branch 'upstream/master' into 561-layered-dihed…
umesh-timalsina Jul 20, 2021
fa9eb17
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Jul 27, 2021
76fa76b
WIP- Add _get_types function in topology.py for dihedral/impropers
umesh-timalsina Jul 27, 2021
da62893
WIP- use _get_types function in is_fully_typed
umesh-timalsina Jul 27, 2021
fa751fa
WIP- Remove layered_dihedral property
umesh-timalsina Jul 27, 2021
8e987e6
WIP- Remove unused import
umesh-timalsina Jul 27, 2021
569e769
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Jul 27, 2021
5c117c1
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Jul 30, 2021
e28ba6e
WIP- fix issues with object construction; add tests
umesh-timalsina Aug 2, 2021
c5ead83
Merge remote-tracking branch 'origin/561-layered-dihedrals' into 561-…
umesh-timalsina Aug 2, 2021
9e2f7dc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 2, 2021
6cb0289
WIP- Add documentation, fix object creation errors
umesh-timalsina Aug 2, 2021
8f7106a
Merge branch 'master' into 561-layered-dihedrals
daico007 Aug 26, 2021
2dd6fee
WIP- Address PR review comments
umesh-timalsina Aug 31, 2021
2a76937
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Aug 31, 2021
21c6c73
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Sep 21, 2021
24d86c4
Merge branch 'master' into 561-layered-dihedrals
daico007 Sep 21, 2021
fc02615
WIP- Merge branch master
umesh-timalsina Sep 23, 2021
21970ac
Merge branch 'master' into 561-layered-dihedrals
daico007 Sep 27, 2021
c6c3242
Merge branch 'master' into 561-layered-dihedrals
daico007 Oct 5, 2021
802185d
Merge branch 'master' into 561-layered-dihedrals
justinGilmer Oct 8, 2021
a1338dd
Merge branch 'master' into 561-layered-dihedrals
daico007 Nov 24, 2021
99ebe68
Merge branch 'master' into 561-layered-dihedrals
umesh-timalsina Dec 10, 2021
afbd33a
Merge branch 'master' into 561-layered-dihedrals
daico007 Jan 4, 2022
580b7df
Update gmso/core/dihedral.py
umesh-timalsina Feb 24, 2022
8534186
Merge branch 'main' into 561-layered-dihedrals
daico007 May 9, 2022
6140f01
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 9, 2022
ca1afa1
Merge branch 'main' into 561-layered-dihedrals
daico007 May 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gmso/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from .core.bond import Bond
from .core.bond_type import BondType
from .core.box import Box
from .core.dihedral import Dihedral
from .core.dihedral import Dihedral, LayeredDihedral
from .core.dihedral_type import DihedralType
from .core.element import Element
from .core.forcefield import ForceField
from .core.improper import Improper
from .core.improper import Improper, LayeredImproper
from .core.improper_type import ImproperType
from .core.pairpotential_type import PairPotentialType
from .core.subtopology import SubTopology
Expand Down
2 changes: 1 addition & 1 deletion gmso/abc/abstract_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def name(self):

@root_validator(pre=True)
def validate_fields(cls, values):
connection_members = values.get("connection_members")
connection_members = values.get("connection_members", [])

if all(isinstance(member, dict) for member in connection_members):
connection_members = [
Expand Down
1 change: 1 addition & 0 deletions gmso/abc/gmso_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,4 @@ class Config:
extra = "forbid"
json_encoders = GMSOJSONHandler.json_encoders
allow_population_by_field_name = True
validate_assignment = True
121 changes: 98 additions & 23 deletions gmso/core/dihedral.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
from typing import Callable, ClassVar, Optional, Tuple
from typing import Callable, ClassVar, Iterable, Optional, Tuple

from pydantic import Field
from boltons.setutils import IndexedSet
from pydantic import Field, ValidationError, validator

from gmso.abc.abstract_connection import Connection
from gmso.core.atom import Atom
from gmso.core.dihedral_type import DihedralType
from gmso.utils.misc import validate_type


class Dihedral(Connection):
class BaseDihedral(Connection):
__base_doc__ = """A 4-partner connection between sites.

This is a subclass of the gmso.Connection superclass.
This class has strictly 4 members in its connection_members.
This is a subclass of the gmso.Connection superclass. This class
has strictly 4 members in its connection_members and used as
a base class to define many different forms of a Dihedral.

The connection_type in this class corresponds to gmso.DihedralType.
The connectivity of a dihedral is:
m1–m2–m3–m4
Expand All @@ -21,7 +25,7 @@ class Dihedral(Connection):
Notes
-----
Inherits some methods from Connection:
__eq__, __repr__, _validate methods
__eq__, _validate methods

Additional _validate methods are presented
"""
Expand All @@ -31,19 +35,6 @@ class Dihedral(Connection):
..., description="The 4 atoms involved in the dihedral."
)

dihedral_type_: Optional[DihedralType] = Field(
default=None, description="DihedralType of this dihedral."
)

@property
def dihedral_type(self):
return self.__dict__.get("dihedral_type_")

@property
def connection_type(self):
# ToDo: Deprecate this?
return self.__dict__.get("dihedral_type_")

def equivalent_members(self):
"""Get a set of the equivalent connection member tuples

Expand Down Expand Up @@ -96,18 +87,102 @@ def _equivalent_members_hash(self):
)
)

def is_layered(self):
return hasattr(self, "dihedral_types_")

def __repr__(self):
return (
f"<{self.__class__.__name__} {self.name},\n "
f"connection_members: {self.connection_members},\n "
f"potential: {str(self.dihedral_types if self.is_layered() else self.dihedral_type)},\n "
f"id: {id(self)}>"
)

class Config:
fields = {
"connection_members_": "connection_members",
}
alias_to_fields = {
"connection_members": "connection_members_",
}


class Dihedral(BaseDihedral):
__base_doc__ = """A 4-Partner connection between 2 sites with a single dihedral type association
umesh-timalsina marked this conversation as resolved.
Show resolved Hide resolved

Notes
-----
This class inherits from BaseDihedral.
"""
dihedral_type_: Optional[DihedralType] = Field(
default=None, description="DihedralType of this dihedral."
)

@property
def dihedral_type(self):
return self.__dict__.get("dihedral_type_")

@property
def connection_type(self):
# ToDo: Deprecate this?
return self.__dict__.get("dihedral_type_")

def __setattr__(self, key, value):
if key == "connection_type":
super(Dihedral, self).__setattr__("dihedral_type", value)
super().__setattr__("dihedral_type", value)
else:
super(Dihedral, self).__setattr__(key, value)
super().__setattr__(key, value)

class Config:
fields = {
"dihedral_type_": "dihedral_type",
"connection_members_": "connection_members",
}
alias_to_fields = {
"dihedral_type": "dihedral_type_",
"connection_members": "connection_members_",
}


class LayeredDihedral(BaseDihedral):
__base_doc__ = """A 4-Partner connection between 2 sites with a multiple dihedral type associations
umesh-timalsina marked this conversation as resolved.
Show resolved Hide resolved

Notes
-----
This class inherits from BaseDihedral.
"""

dihedral_types_: Optional[IndexedSet] = Field(
default=None, description="DihedralTypes of this dihedral."
)

@property
def dihedral_types(self):
return self.__dict__.get("dihedral_types_")

@property
def connection_types(self):
# ToDo: Deprecate this?
return self.__dict__.get("dihedral_types_")

def __setattr__(self, key, value):
if key == "connection_types":
super().__setattr__("dihedral_types", value)
else:
super().__setattr__(key, value)

@validator("dihedral_types_", pre=True)
def validate_dihedral_types(cls, dihedral_types):
if not isinstance(dihedral_types, Iterable) or isinstance(
dihedral_types, str
):
raise ValidationError("DihedralTypes should be iterable", cls)

validate_type(dihedral_types, DihedralType)
return IndexedSet(dihedral_types)

class Config:
fields = {
"dihedral_types_": "dihedral_types",
}
alias_to_fields = {
"dihedral_types": "dihedral_types_",
}
93 changes: 71 additions & 22 deletions gmso/core/improper.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
"""Support for improper style connections (4-member connection)."""
from typing import Callable, ClassVar, Optional, Tuple
from typing import Callable, ClassVar, Iterable, Optional, Tuple

from pydantic import Field
from boltons.setutils import IndexedSet
from pydantic import Field, ValidationError, validator

from gmso.abc.abstract_connection import Connection
from gmso.core.atom import Atom
from gmso.core.improper_type import ImproperType
from gmso.utils.misc import validate_type


class Improper(Connection):
class BaseImproper(Connection):
__base_doc__ = """sA 4-partner connection between sites.
umesh-timalsina marked this conversation as resolved.
Show resolved Hide resolved

This is a subclass of the gmso.Connection superclass.
Expand Down Expand Up @@ -39,21 +41,6 @@ class Improper(Connection):
"then the three atoms connected to the central site.",
)

improper_type_: Optional[ImproperType] = Field(
default=None, description="ImproperType of this improper."
)

@property
def improper_type(self):
"""Return Potential object for this connection if it exists."""
return self.__dict__.get("improper_type_")

@property
def connection_type(self):
"""Return Potential object for this connection if it exists."""
# ToDo: Deprecate this?
return self.__dict__.get("improper_type_")

def equivalent_members(self):
"""Get a set of the equivalent connection member tuples.

Expand Down Expand Up @@ -106,21 +93,83 @@ def _equivalent_members_hash(self):
)
)

class Config:
"""Pydantic configuration to link fields to their public attribute."""

fields = {
"connection_members_": "connection_members",
}
alias_to_fields = {
"connection_members": "connection_members_",
}


class Improper(BaseImproper):
improper_type_: Optional[ImproperType] = Field(
default=None, description="ImproperType of this improper."
)

@property
def improper_type(self):
"""Return Potential object for this connection if it exists."""
return self.__dict__.get("improper_type_")

@property
def connection_type(self):
"""Return Potential object for this connection if it exists."""
# ToDo: Deprecate this?
return self.__dict__.get("improper_type_")

def __setattr__(self, key, value):
"""Set attribute override to support connection_type key."""
if key == "connection_type":
super(Improper, self).__setattr__("improper_type", value)
super().__setattr__("improper_type", value)
else:
super(Improper, self).__setattr__(key, value)
super().__setattr__(key, value)

class Config:
"""Pydantic configuration to link fields to their public attribute."""

fields = {
"improper_type_": "improper_type",
"connection_members_": "connection_members",
}
alias_to_fields = {
"improper_type": "improper_type_",
"connection_members": "connection_members_",
}


class LayeredImproper(BaseImproper):
improper_types_: Optional[IndexedSet] = Field(
default=None, description="ImproperTypes of this improper."
)

@property
def improper_types(self):
return self.__dict__.get("improper_types_")

@property
def connection_types(self):
# ToDo: Deprecate this?
return self.__dict__.get("improper_types_")

def __setattr__(self, key, value):
if key == "connection_types":
super().__setattr__("improper_types_", value)
else:
super().__setattr__(key, value)

@validator("improper_types_", pre=True, always=True)
def validate_dihedral_types(cls, improper_types):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def validate_dihedral_types(cls, improper_types):
def validate_improper_types(cls, improper_types):

if not isinstance(improper_types, Iterable):
raise ValidationError("ImproperTypes should be iterable", cls)

validate_type(improper_types, ImproperType)
return IndexedSet(improper_types)

class Config:
fields = {
"improper_types_": "improper_types",
}
alias_to_fields = {
"improper_types": "improper_types_",
}
Loading