From ef40d30d7e5d5d2b96d3c2cf6374558af5addfd9 Mon Sep 17 00:00:00 2001 From: Sejoslaw Date: Sat, 20 Jun 2020 10:00:42 +0200 Subject: [PATCH] Added basic support for Molecules; --- Chemistry.NET.Tests/ChemicalStackTests.cs | 48 +++++++++++++ Chemistry.NET.Tests/MoleculeTests.cs | 30 ++++++++ Chemistry.NET/Chemistry.NET.csproj | 2 +- .../Compounds/Collections/CompoundStack.cs | 71 +++++++++++++++++++ .../Compounds/Collections/ElementStack.cs | 21 ++++++ .../Compounds/Collections/IChemicalStack.cs | 22 ++++++ .../ModelsLogics/ChemicalCompound.cs | 33 +++------ Chemistry.NET/Molecules/IMolecule.cs | 31 ++++++++ .../ModelsLogics/ChemicalCompound.cs | 26 +++++++ README.md | 2 +- 10 files changed, 260 insertions(+), 26 deletions(-) create mode 100644 Chemistry.NET.Tests/ChemicalStackTests.cs create mode 100644 Chemistry.NET.Tests/MoleculeTests.cs create mode 100644 Chemistry.NET/Molecules/IMolecule.cs create mode 100644 Chemistry.NET/Molecules/ModelsLogics/ChemicalCompound.cs diff --git a/Chemistry.NET.Tests/ChemicalStackTests.cs b/Chemistry.NET.Tests/ChemicalStackTests.cs new file mode 100644 index 0000000..cb204b7 --- /dev/null +++ b/Chemistry.NET.Tests/ChemicalStackTests.cs @@ -0,0 +1,48 @@ +/// +/// Author: Krzysztof Dobrzyński +/// Project: Chemistry.NET +/// Source: https://github.com/Sejoslaw/Chemistry.NET +/// + +using System; +using System.Collections.Generic; +using System.Linq; +using Chemistry.NET.Common; +using Chemistry.NET.Compounds.Collections; +using Chemistry.NET.Compounds.Models; +using Xunit; + +namespace Chemistry.NET.Tests +{ + public class ChemicalStackTests + { + [Fact] + public void Should_calculate_electrons_neutrons_protons_for_ElementStack() + { + foreach (var element in Container.Elements) + { + var randomElementNumberOnStack = new Random().Next(); + var stack = new ElementStack(element, randomElementNumberOnStack); + + Assert.Equal(stack.GetTotalElectronsCount(), element.Structure.ElectronsCount * randomElementNumberOnStack); + Assert.Equal(stack.GetTotalNeutronsCount(), element.Structure.NeutronsCount * randomElementNumberOnStack); + Assert.Equal(stack.GetTotalProtonsCount(), element.Structure.ProtonsCount * randomElementNumberOnStack); + Assert.Equal(stack.GetAtoms().Count(), 1); + } + } + + [Theory] + [InlineData("H2O", 10, 8, 10, 2)] + [InlineData("H2O2", 18, 16, 18, 2)] + [InlineData("H(CH2)4", 33, 24, 33, 2)] + public void Should_calculate_electrons_neutrons_protons_for_CompoundStack(string compoundSymbol, int electrons, int neutrons, int protons, int atoms) + { + var compound = ChemicalCompound.New(compoundSymbol, ""); + + Assert.Equal(compound.GetTotalElectronsCount(), electrons); + Assert.Equal(compound.GetTotalNeutronsCount(), neutrons); + Assert.Equal(compound.GetTotalProtonsCount(), protons); + Assert.Equal(compound.GetAtoms().Count(), atoms); + } + } +} \ No newline at end of file diff --git a/Chemistry.NET.Tests/MoleculeTests.cs b/Chemistry.NET.Tests/MoleculeTests.cs new file mode 100644 index 0000000..e2c4e96 --- /dev/null +++ b/Chemistry.NET.Tests/MoleculeTests.cs @@ -0,0 +1,30 @@ +/// +/// Author: Krzysztof Dobrzyński +/// Project: Chemistry.NET +/// Source: https://github.com/Sejoslaw/Chemistry.NET +/// + +using Chemistry.NET.Compounds.Models; +using Xunit; + +namespace Chemistry.NET.Tests +{ + public class MoleculeTests + { + [Theory] + [InlineData("H2", true, false, true)] + [InlineData("H2O", false, true, false)] + [InlineData("CHO", false, true, false)] + [InlineData("CH(CH2)4", false, true, false)] + [InlineData("CH", false, true, true)] + [InlineData("CH(CH2Li3)4", false, true, false)] + public void Check_molecule_properties(string compoundSymbol, bool isHomonuclear, bool isHeteronuclear, bool isDiatomic) + { + var compound = ChemicalCompound.New(compoundSymbol, ""); + + Assert.Equal(compound.IsHomonuclear, isHomonuclear); + Assert.Equal(compound.IsHeteronuclear, isHeteronuclear); + Assert.Equal(compound.IsDiatomic, isDiatomic); + } + } +} \ No newline at end of file diff --git a/Chemistry.NET/Chemistry.NET.csproj b/Chemistry.NET/Chemistry.NET.csproj index 2409a03..54550cd 100644 --- a/Chemistry.NET/Chemistry.NET.csproj +++ b/Chemistry.NET/Chemistry.NET.csproj @@ -3,7 +3,7 @@ netstandard2.1 Chemistry.NET - 1.8.1 + 1.9.0 https://github.com/Sejoslaw/Chemistry.NET https://github.com/Sejoslaw/Chemistry.NET https://github.com/Sejoslaw/Chemistry.NET diff --git a/Chemistry.NET/Compounds/Collections/CompoundStack.cs b/Chemistry.NET/Compounds/Collections/CompoundStack.cs index 7b941ea..402bb4e 100644 --- a/Chemistry.NET/Compounds/Collections/CompoundStack.cs +++ b/Chemistry.NET/Compounds/Collections/CompoundStack.cs @@ -4,8 +4,11 @@ /// Source: https://github.com/Sejoslaw/Chemistry.NET /// +using System; using System.Collections; using System.Collections.Generic; +using System.Linq; +using Chemistry.NET.Elements.Models; namespace Chemistry.NET.Compounds.Collections { @@ -31,5 +34,73 @@ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + + public IEnumerable GetAtoms() + { + var stacks = new List(); + + foreach (var node in Nodes) + { + if (node is ElementStack elementStack) + { + AppendToAppropriateStack(stacks, elementStack); + } + else if (node is CompoundStack compoundStack) + { + var innerStacks = compoundStack.GetAtoms(); + innerStacks.ToList().ForEach(innerStack => AppendToAppropriateStack(stacks, innerStack)); + } + } + + return stacks; + } + + public int GetTotalElectronsCount() + { + return GetTotalCount(e => e.Structure.ElectronsCount); + } + + public int GetTotalProtonsCount() + { + return GetTotalCount(e => e.Structure.ProtonsCount); + } + + public int GetTotalNeutronsCount() + { + return GetTotalCount(e => e.Structure.NeutronsCount); + } + + protected int GetTotalCount(Func func) + { + var total = 0; + + foreach (var node in Nodes) + { + if (node is ElementStack elementStack) + { + total += func(elementStack.Element) * elementStack.Count; + } + else if (node is CompoundStack compoundStack) + { + total += compoundStack.GetTotalCount(func); + } + } + + return total * Count; + } + + private void AppendToAppropriateStack(List stacks, ElementStack elementStack) + { + foreach (var stack in stacks) + { + if (stack.Element == elementStack.Element) + { + stack.IncreaseStackSize(elementStack.Count); + return; + } + } + + stacks.Add(elementStack); + } } } diff --git a/Chemistry.NET/Compounds/Collections/ElementStack.cs b/Chemistry.NET/Compounds/Collections/ElementStack.cs index 8e3a8bb..9726aa8 100644 --- a/Chemistry.NET/Compounds/Collections/ElementStack.cs +++ b/Chemistry.NET/Compounds/Collections/ElementStack.cs @@ -4,6 +4,7 @@ /// Source: https://github.com/Sejoslaw/Chemistry.NET /// +using System.Collections.Generic; using Chemistry.NET.Elements.Models; namespace Chemistry.NET.Compounds.Collections @@ -33,5 +34,25 @@ public virtual void IncreaseStackSize(int count = 1) { Count += count; } + + public int GetTotalElectronsCount() + { + return Element.Structure.ElectronsCount * Count; + } + + public int GetTotalProtonsCount() + { + return Element.Structure.ProtonsCount * Count; + } + + public int GetTotalNeutronsCount() + { + return Element.Structure.NeutronsCount * Count; + } + + public IEnumerable GetAtoms() + { + yield return this; + } } } diff --git a/Chemistry.NET/Compounds/Collections/IChemicalStack.cs b/Chemistry.NET/Compounds/Collections/IChemicalStack.cs index 96b8a1e..a977cd3 100644 --- a/Chemistry.NET/Compounds/Collections/IChemicalStack.cs +++ b/Chemistry.NET/Compounds/Collections/IChemicalStack.cs @@ -4,6 +4,8 @@ /// Source: https://github.com/Sejoslaw/Chemistry.NET /// +using System.Collections.Generic; + namespace Chemistry.NET.Compounds.Collections { /// @@ -21,5 +23,25 @@ public interface IChemicalStack /// /// void IncreaseStackSize(int count = 1); + /// + /// Returns the number of electrons in the stack. + /// + /// + int GetTotalElectronsCount(); + /// + /// Returns the number of protons in the stack. + /// + /// + int GetTotalProtonsCount(); + /// + /// Returns the number of neutrons in the stack. + /// + /// + int GetTotalNeutronsCount(); + /// + /// Returns the total amount of stacks on the current stack. + /// + /// + IEnumerable GetAtoms(); } } diff --git a/Chemistry.NET/Compounds/ModelsLogics/ChemicalCompound.cs b/Chemistry.NET/Compounds/ModelsLogics/ChemicalCompound.cs index 4ecb9d7..30a7923 100644 --- a/Chemistry.NET/Compounds/ModelsLogics/ChemicalCompound.cs +++ b/Chemistry.NET/Compounds/ModelsLogics/ChemicalCompound.cs @@ -4,10 +4,9 @@ /// Source: https://github.com/Sejoslaw/Chemistry.NET /// -using System; +using System.Collections.Generic; using Chemistry.NET.Compounds.Collections; using Chemistry.NET.Compounds.Parsers.ChemicalCompounds; -using Chemistry.NET.Elements.Models; namespace Chemistry.NET.Compounds.Models { @@ -16,38 +15,24 @@ namespace Chemistry.NET.Compounds.Models /// public partial class ChemicalCompound { - public int GetTotalElectronsCount() + public IEnumerable GetAtoms() { - return GetTotalCount(e => e.Structure.ElectronsCount); + return StructureTree.GetAtoms(); } - public int GetTotalProtonsCount() + public int GetTotalElectronsCount() { - return GetTotalCount(e => e.Structure.ProtonsCount); + return StructureTree.GetTotalElectronsCount(); } - public int GetTotalNeutronsCount() + public int GetTotalProtonsCount() { - return GetTotalCount(e => e.Structure.NeutronsCount); + return StructureTree.GetTotalProtonsCount(); } - private int GetTotalCount(Func func) + public int GetTotalNeutronsCount() { - var total = 0; - - foreach (var node in StructureTree) - { - if (node is ElementStack elementStack) - { - total += func(elementStack.Element) * elementStack.Count; - } - else if (node is CompoundStack compoundStack) - { - total += GetTotalCount(func) * compoundStack.Count; - } - } - - return total; + return StructureTree.GetTotalNeutronsCount(); } /// diff --git a/Chemistry.NET/Molecules/IMolecule.cs b/Chemistry.NET/Molecules/IMolecule.cs new file mode 100644 index 0000000..a3c8fa4 --- /dev/null +++ b/Chemistry.NET/Molecules/IMolecule.cs @@ -0,0 +1,31 @@ +/// +/// Author: Krzysztof Dobrzyński +/// Project: Chemistry.NET +/// Source: https://github.com/Sejoslaw/Chemistry.NET +/// + +namespace Chemistry.NET.Molecules +{ + /// + /// Describes an object to be a Molecule. + /// + public interface IMolecule + { + /// + /// Homonuclear molecules are molecules composed of only one type of element. + /// Homonuclear molecules may consist of various numbers of atoms, depending on the element's properties. + /// + /// + bool IsHomonuclear { get; } + /// + /// A heteronuclear molecule is a molecule composed of atoms of more than one chemical element. + /// + /// + bool IsHeteronuclear { get; } + /// + /// Diatomic molecules are molecules composed of only two atoms, of the same or different chemical elements. + /// + /// + bool IsDiatomic { get; } + } +} diff --git a/Chemistry.NET/Molecules/ModelsLogics/ChemicalCompound.cs b/Chemistry.NET/Molecules/ModelsLogics/ChemicalCompound.cs new file mode 100644 index 0000000..55c9a80 --- /dev/null +++ b/Chemistry.NET/Molecules/ModelsLogics/ChemicalCompound.cs @@ -0,0 +1,26 @@ +/// +/// Author: Krzysztof Dobrzyński +/// Project: Chemistry.NET +/// Source: https://github.com/Sejoslaw/Chemistry.NET +/// + +using System.Linq; +using Chemistry.NET.Molecules; + +namespace Chemistry.NET.Compounds.Models +{ + public partial class ChemicalCompound : IMolecule + { + public bool IsHomonuclear => this.GetAtoms().Count() == 1; + public bool IsHeteronuclear => this.GetAtoms().Count() > 1; + public bool IsDiatomic + { + get + { + var atoms = this.GetAtoms(); + return (atoms.Count() == 1 && atoms.ElementAt(0).Count == 2) || + (atoms.Count() == 2 && atoms.ElementAt(0).Count == 1 && atoms.ElementAt(1).Count == 1); + } + } + } +} diff --git a/README.md b/README.md index 8ffd5cd..18084d6 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Layer | Name | Description 2 | Isotopes | Contains information about known isotopes and their properties. (6500+ isotopes preconfigured) 3 | Compounds | This is a higher-level layer which let's user build advanced compounds from known elements and isotopes. (2400+ compounds preconfigured) 3 | Ions | Describes ionization functionality for each of the elements. (540+ ions preconfigured) -X | Molecules | TBA +4 | Molecules | Contains information which can be used to indicate Molecule-related properties for a Chemical Compound. X | Lipids | TBA X | Steroids | TBA X | Polymers | TBA