Skip to content

Commit

Permalink
[FIX] Correct melting and boiling points for Carbon allotropes (#214)
Browse files Browse the repository at this point in the history
* correct db values and update PhaseTransition model

* reduce number of rosw in test after removing diamond

* update docs

* add missing boiling point for red P

* update melting_point and boiling_point to return either float or None

* add tests for boiling and melting_points

* update type annotations

* simplify tests
  • Loading branch information
lmmentel authored Dec 28, 2024
1 parent edfce37 commit 3d4b1ca
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 43 deletions.
27 changes: 27 additions & 0 deletions alembic/versions/88ac4b3cbd41_phase_transisions_extra_columns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""phase transisions extra columns
Revision ID: 88ac4b3cbd41
Revises: edad0a76e11e
Create Date: 2024-12-22 15:42:17.215685
"""

# revision identifiers, used by Alembic.
revision = '88ac4b3cbd41'
down_revision = 'edad0a76e11e'
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa


def upgrade():
op.add_column("phasetransitions", sa.Column("is_sublimation_point", sa.Boolean))
op.add_column("phasetransitions", sa.Column("is_transition", sa.Boolean))


def downgrade():
with op.batch_alter_table("phasetransitions") as batch_op:
batch_op.drop_column("is_sublimation_point")
batch_op.drop_column("is_transition")
64 changes: 36 additions & 28 deletions docs/source/data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ The following data are currently available:
+-----------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+--------------+------------------------------------------------------+
| ``mass_number`` | Mass number of the most abundant isotope | | computed | |
+-----------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+--------------+------------------------------------------------------+
| ``melting_point`` | Melting point | K | stored | :cite:`haynes2016crc` |
| ``melting_point`` | Melting point at 101.325 kPa pressure | K | stored | :cite:`haynes2016crc` |
+-----------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+--------------+------------------------------------------------------+
| ``mendeleev_number`` | Mendeleev's number ([#f_mendeleev_number]_) | | stored | :cite:`Pettifor1984,Villars2004` |
+-----------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+--------------+------------------------------------------------------+
Expand Down Expand Up @@ -292,7 +292,7 @@ Class: :py:class:`Isotope <mendeleev.models.Isotope>`
Isotope Decay Modes
===================

Class: :py:class:`Isotope <mendeleev.models.IsotopeDecayMode>`
Class: :py:class:`IsotopeDecayMode <mendeleev.models.IsotopeDecayMode>`

+-----------------------------------+---------------------------------------------------------------------------------+------+--------------+--------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
Expand Down Expand Up @@ -372,7 +372,7 @@ for compatibility. The table below provides explanations of the symbols.
Atomic Scattering Factors
=========================

Class: :py:class:`Element <mendeleev.models.ScatteringFactor>`
Class: :py:class:`ScatteringFactor <mendeleev.models.ScatteringFactor>`

+-------------------+----------------------------------------------+------+--------------+-------------------------------------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
Expand All @@ -389,7 +389,7 @@ Class: :py:class:`Element <mendeleev.models.ScatteringFactor>`
Ionization Energies
===================

Class: :py:class:`Element <mendeleev.models.IonizationEnergy>`
Class: :py:class:`IonizationEnergy <mendeleev.models.IonizationEnergy>`

+---------------------------+-------------------------------------------------------------------------+------+--------------+---------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
Expand Down Expand Up @@ -424,7 +424,7 @@ Class: :py:class:`Element <mendeleev.models.IonizationEnergy>`
Ionic Radii
===========

Class: :py:class:`Element <mendeleev.models.IonicRadius>`
Class: :py:class:`IonicRadius <mendeleev.models.IonicRadius>`

+--------------------+-----------------------------------------+------+--------------+----------------------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
Expand Down Expand Up @@ -460,7 +460,7 @@ by adding 14 pm to the ``ionic_radius`` values according to :cite:`Shannon1976`.
Oxidation States
================

Class: :py:class:`Element <mendeleev.models.OxidationState>`
Class: :py:class:`OxidationState <mendeleev.models.OxidationState>`

+---------------------+--------------------------------------------------------------------------+------+--------------+---------------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
Expand All @@ -475,32 +475,36 @@ Class: :py:class:`Element <mendeleev.models.OxidationState>`
Phase Transitions
=================

Class: :py:class:`Element <mendeleev.models.PhaseTransition>`

+------------------------------+--------------------------------------+------+--------------+-----------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
+==============================+======================================+======+==============+=======================+
| ``allotrope`` | Allotrope name | | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``atomic_number`` | Atomic number | | stored | |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``boiling_point`` | Boiling point | K | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``critical_pressure`` | Critical pressure | MPa | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``critical_temperature`` | Critical temperature | K | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``melting_point`` | Melting point | K | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``triple_point_pressure`` | Pressure in kPa of the triple point | kPa | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
| ``triple_point_temperature`` | Temperature in K of the triple point | K | stored | :cite:`haynes2016crc` |
+------------------------------+--------------------------------------+------+--------------+-----------------------+
Class: :py:class:`PhaseTransition <mendeleev.models.PhaseTransition>`

+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
+==============================+==================================================================================================================================+======+==============+=======================+
| ``allotrope`` | Allotrope name | | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``atomic_number`` | Atomic number | | stored | |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``boiling_point`` | Boiling point | K | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``critical_pressure`` | Critical pressure | MPa | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``critical_temperature`` | Critical temperature | K | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``is_sublimation_point`` | Indicates that boiling_point marks a sublimation point, where the vapor pressure of the solid phase reaches 101.325 kPa | | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``is_transition`` | Indicates that melting_point marks the temperature of the transition to the crystalline form immediately below that entry | | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``melting_point`` | Melting point at 101.325 kPa pressure ([#f_melting_point]_) | K | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``triple_point_pressure`` | Pressure in kPa of the triple point | kPa | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+
| ``triple_point_temperature`` | Temperature in K of the triple point | K | stored | :cite:`haynes2016crc` |
+------------------------------+----------------------------------------------------------------------------------------------------------------------------------+------+--------------+-----------------------+

Screening Constants
===================

Class: :py:class:`Element <mendeleev.models.ScreeningConstant>`
Class: :py:class:`ScreeningConstant <mendeleev.models.ScreeningConstant>`

+-------------------+--------------------------------+------+--------------+-----------------------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
Expand Down Expand Up @@ -565,6 +569,10 @@ Class: :py:class:`Element <mendeleev.models.ScreeningConstant>`
- Tennessine
- Oganesson
.. [#f_melting_point] **melting_point**
Melting points for carbon from the original source are not included since they are not at standard pressure.
.. [#f_electron_affinity] **electron_affinity**
Electron affinities were taken from :cite:`haynes2014crc` for the elements for which the data was available. For He, Be, N, Ar and Xe affinities were taken from :cite:`Andersen2004` where they were specified for metastable ions and therefore the values are negative.
Expand Down
Binary file modified mendeleev/elements.db
Binary file not shown.
65 changes: 58 additions & 7 deletions mendeleev/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

"""Module defining the database models for elements and related properties."""

from __future__ import annotations
from typing import Any, Callable, Dict, List, Tuple, Union
from operator import attrgetter
import enum
import math
import urllib.parse
import warnings

import numpy as np
from sqlalchemy import Column, Boolean, Integer, String, Float, ForeignKey, Text, Enum
Expand Down Expand Up @@ -290,20 +292,50 @@ def inchi(self) -> str:
return f"InchI=1S/{self.symbol}"

@property
def boiling_point(self) -> Union[float, Dict[str, float]]:
"""Boiling point"""
def boiling_point(self) -> float | None:
"""Proxy for boiling point from the ``PhaseTransition`` object.
For elements with a single allotrope return the boiling point,
for elements with multiple allotropes where the boiling points
are equal return the boiling point, otherwise return None.
"""
if len(self.phase_transitions) == 1:
return self.phase_transitions[0].boiling_point
elif len(self.phase_transitions) == 2:
bps = [pt.boiling_point for pt in self.phase_transitions]
if math.isclose(*bps, rel_tol=1e-2):
return self.phase_transitions[0].boiling_point
else:
warnings.warn(
f"{self.symbol} has multiple allotropes, "
"check <{self.symbol}.phase_transitions> for details.",
UserWarning,
)
else:
return {pt.allotrope: pt.boiling_point for pt in self.phase_transitions}
return None

@property
def melting_point(self) -> Union[float, Dict[str, float]]:
"""Melting point"""
def melting_point(self) -> float | None:
"""Proxy for melting point from the ``PhaseTransition`` object.
For elements with a single allotrope return the melting point,
for elements with multiple allotropes where the melting points
are equal return the melting point, otherwise return None.
"""
if len(self.phase_transitions) == 1:
return self.phase_transitions[0].melting_point
elif len(self.phase_transitions) == 2:
mps = [pt.melting_point for pt in self.phase_transitions]
if math.isclose(*mps, rel_tol=1e-2):
return self.phase_transitions[0].melting_point
else:
warnings.warn(
f"{self.symbol} has multiple allotropes, "
"check <{self.symbol}.phase_transitions> for details.",
UserWarning,
)
else:
return {pt.allotrope: pt.melting_point for pt in self.phase_transitions}
return None

@property
def nist_webbook_url(self) -> str:
Expand Down Expand Up @@ -1241,9 +1273,28 @@ class PhaseTransition(Base):
triple_point_temperature = Column(Float)
triple_point_pressure = Column(Float)
allotrope = Column(String)
is_sublimation_point = Column(Boolean)
is_transition = Column(Boolean)

def __str__(self) -> str:
return f"{self.atomic_number} Tm={self.melting_point} Tb={self.boiling_point}"
return (
"PhaseTransition("
+ ", ".join(
[
f"atomic_number={self.atomic_number}",
f"allotrope={self.allotrope}",
f"melting_point={self.melting_point}",
f"boiling_point={self.boiling_point}",
f"triple_point_temperature={self.triple_point_temperature}",
f"triple_point_pressure={self.triple_point_pressure}",
f"critical_temperature={self.critical_temperature}",
f"critical_pressure={self.critical_pressure}",
f"is_sublimation_point={self.is_sublimation_point}",
f"is_transition={self.is_transition}",
]
)
+ ")"
)

def __repr__(self) -> str:
return str(self)
Expand Down
Loading

0 comments on commit 3d4b1ca

Please sign in to comment.