Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
178 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
from datetime import datetime | ||
from typing import Dict, List | ||
|
||
from monty.json import MontyDecoder | ||
from pydantic import BaseModel, Field, validator | ||
from pymatgen import Structure | ||
from pymatgen.apps.battery.battery_abc import AbstractElectrode | ||
from pymatgen.apps.battery.insertion_battery import InsertionElectrode | ||
from pymatgen.core.periodic_table import ElementBase | ||
from pymatgen.entries.computed_entries import ComputedEntry | ||
|
||
|
||
class WorkingIon(ElementBase): | ||
Li = "Li" | ||
Ca = "Ca" | ||
Mg = "Mg" | ||
|
||
|
||
class VoltagePairDoc(BaseModel): | ||
""" | ||
Data for individual voltage steps. | ||
Note: Each voltage step is represented as a sub_electrode (ConversionElectrode/InsertionElectrode) | ||
object to gain access to some basic statistics about the voltage step | ||
""" | ||
|
||
max_delta_volume: str = Field( | ||
None, | ||
description="Volume changes in % for a particular voltage step using: " | ||
"max(charge, discharge) / min(charge, discharge) - 1", | ||
) | ||
|
||
average_voltage: float = Field( | ||
None, description="The average voltage in V for a particular voltage step.", | ||
) | ||
|
||
capacity_grav: float = Field(None, description="Gravimetric capacity in mAh/g.") | ||
|
||
capacity_vol: float = Field(None, description="Volumetric capacity in mAh/cc.") | ||
|
||
energy_grav: float = Field( | ||
None, description="Gravimetric energy (Specific energy) in Wh/kg." | ||
) | ||
|
||
energy_vol: float = Field( | ||
None, description="Volumetric energy (Energy Density) in Wh/l." | ||
) | ||
|
||
fracA_charge: float = Field( | ||
None, description="Atomic fraction of the working ion in the charged state." | ||
) | ||
fracA_discharge: float = Field( | ||
None, description="Atomic fraction of the working ion in the discharged state." | ||
) | ||
|
||
@classmethod | ||
def from_voltage_pair_from_sub_electrode( | ||
cls, sub_electrode: AbstractElectrode, **kwargs | ||
): | ||
""" | ||
Convert A pymatgen electrode object to a document | ||
""" | ||
return cls(**sub_electrode.get_summary_dict(), **kwargs) | ||
|
||
|
||
class InsertionVoltagePairDoc(VoltagePairDoc): | ||
""" | ||
Features specific to insertion electrode | ||
""" | ||
|
||
stability_charge: float = Field( | ||
None, description="The energy above hull of the charged material." | ||
) | ||
|
||
stability_discharge: float = Field( | ||
None, description="The energy above hull of the discharged material." | ||
) | ||
|
||
|
||
class InsertionElectrodeDoc(InsertionVoltagePairDoc): | ||
""" | ||
Insertion electrode | ||
""" | ||
|
||
task_id: str = Field(None, description="The id for this battery document.") | ||
|
||
framework_formula: str = Field( | ||
None, description="The id for this battery document." | ||
) | ||
|
||
host_structure: Structure = Field( | ||
None, description="Host structure (structure without the working ion)", | ||
) | ||
|
||
adj_pairs: List[InsertionVoltagePairDoc] = Field( | ||
None, description="Returns all the Voltage Steps", | ||
) | ||
|
||
working_ion: WorkingIon = Field( | ||
None, description="The working ion as an Element object", | ||
) | ||
|
||
num_steps: float = Field( | ||
None, | ||
description="The number of distinct voltage steps in from fully charge to " | ||
"discharge based on the stable intermediate states", | ||
) | ||
|
||
max_voltage_step: float = Field( | ||
None, description="Maximum absolute difference in adjacent voltage steps" | ||
) | ||
|
||
last_updated: datetime = Field( | ||
None, | ||
description="Timestamp for the most recent calculation for this Material document", | ||
) | ||
|
||
# Make sure that the datetime field is properly formatted | ||
@validator("last_updated", pre=True) | ||
def last_updated_dict_ok(cls, v): | ||
return MontyDecoder().process_decoded(v) | ||
|
||
@classmethod | ||
def from_entries( | ||
cls, | ||
grouped_entries: List[ComputedEntry], | ||
working_ion_entry: ComputedEntry, | ||
task_id: str, | ||
host_structure: Structure, | ||
): | ||
ie = InsertionElectrode.from_entries( | ||
entries=grouped_entries, working_ion_entry=working_ion_entry | ||
) | ||
ie.get_summary_dict() | ||
d = ie.get_summary_dict() | ||
d["num_steps"] = d.pop("nsteps", None) | ||
return cls(task_id=task_id, host_structure=host_structure, **d) | ||
|
||
|
||
# class ConversionVoltagePairDoc(VoltagePairDoc): | ||
# """ | ||
# Features specific to conversion electrode | ||
# """ | ||
# | ||
# reactions: Dict = Field( | ||
# None, description="The reaction the characterizes that particular voltage step." | ||
# ) | ||
# | ||
# | ||
# class ConversionElectrode(ConversionVoltagePairDoc): | ||
# task_id: str = Field(None, description="The id for this battery document.") | ||
# | ||
# adj_pairs: List[ConversionVoltagePairDoc] = Field( | ||
# None, description="Returns all the adjacent Voltage Steps", | ||
# ) | ||
# | ||
# working_ion: WorkingIon = Field( | ||
# None, description="The working ion as an Element object", | ||
# ) | ||
# | ||
# num_steps: float = Field( | ||
# None, | ||
# description="The number of distinct voltage steps in from fully charge to " | ||
# "discharge based on the stable intermediate states", | ||
# ) | ||
# | ||
# max_voltage_step: float = Field( | ||
# None, description="Maximum absolute difference in adjacent voltage steps" | ||
# ) | ||
# | ||
# last_updated: datetime = Field( | ||
# None, | ||
# description="Timestamp for the most recent calculation for this Material document", | ||
# ) | ||
# | ||
# # Make sure that the datetime field is properly formatted | ||
# @validator("last_updated", pre=True) | ||
# def last_updated_dict_ok(cls, v): | ||
# return MontyDecoder().process_decoded(v) |