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

RMG-Electrochem #2316

Open
wants to merge 110 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
18d15d7
Add reaction library to test example for liquidSurfaceReactor
mjohnson541 Sep 4, 2021
fed4eed
added Faraday's Constant `F`
davidfarinajr May 12, 2021
07d5dcc
added Potential as `V` quantity
davidfarinajr May 12, 2021
69cd7a9
added `H+` and `e` atomtypes, increment/decrement charge attributes
davidfarinajr May 12, 2021
7a838a9
added atomtype unit tests
davidfarinajr May 12, 2021
fad4adf
added `gain_charge` and `lose_charge` actions
davidfarinajr May 12, 2021
5c943b7
added `is_proton` and `is_electron` group methods
davidfarinajr May 12, 2021
3f03438
added group unit tests
davidfarinajr May 12, 2021
d64a296
added `is_electron` and `is_proton` methods to Atom and Mol
davidfarinajr May 12, 2021
5286352
added GAIN and LOSE CHARGE actions to Atoms
davidfarinajr May 12, 2021
9f2de34
added updated charge method and revised `update` Molecule method
davidfarinajr May 12, 2021
5eae0c3
do not raise charge exception by default when creating molecule from …
davidfarinajr May 12, 2021
b4212fa
H -> H0 in find_h_bonds Molecule method
davidfarinajr May 12, 2021
0289b79
try to generate_resonance_structures, and return a deep copy of the m…
davidfarinajr May 12, 2021
edd0129
added molecule.pxd declarations
davidfarinajr May 12, 2021
378b598
added Species `is_electron` and `is_proton` methods
davidfarinajr May 12, 2021
9d5e587
do not raise charge exception by default when creating species from a…
davidfarinajr May 12, 2021
8b8adff
added `get_net_charge` method for Species
davidfarinajr May 12, 2021
6b31a06
do not forbid ions
davidfarinajr May 12, 2021
8eb389a
added `SurfaceChargeTransfer` and `SurfaceChargeTransferBEP` kinetic …
davidfarinajr May 12, 2021
9ee890a
added unit tests for SurfaceChargeTranser kinetic model
davidfarinajr May 12, 2021
eb2095b
added Molecule unit tests
davidfarinajr May 12, 2021
069444a
added `electrons` reaction attr and reaction methods for charge trans…
davidfarinajr May 12, 2021
811bcbc
added reaction tests for charge transfer reactions
davidfarinajr May 12, 2021
c094955
adding charged species and electrons to family.py
davidfarinajr May 12, 2021
edfb710
added family test for `Surface_Proton_Electron_Reduction_Alpha` family
davidfarinajr May 12, 2021
78e7f76
added support for loading `SurfaceChargeTransfer` kinetics from the d…
davidfarinajr May 12, 2021
9114451
update charge before updating lone pairs for solvation `transform_lon…
davidfarinajr May 12, 2021
456ed8e
making rules for SurfaceChargeTransfer training reactions
davidfarinajr May 12, 2021
a2201ab
added SurfaceChargeTransfer kinetics import
davidfarinajr May 12, 2021
536eb36
added H+ and e to translator
davidfarinajr May 12, 2021
96f89e3
update_atomtypes -> update in translator.py
davidfarinajr May 12, 2021
5a832c5
added `SurfaceChargeTransfer` to yml
davidfarinajr May 12, 2021
6e48b43
added `adsorption_groups` attr to thermoDB
davidfarinajr Sep 2, 2021
597bb66
added fluorine to thermo `correct_binding_energy` method
davidfarinajr Sep 2, 2021
33a06b9
add LiH and LiF to atom energy corrections fitting species list
mjohnson541 Oct 4, 2021
27f2e72
add Li atom spin
mjohnson541 Oct 4, 2021
58da613
don't check Li partial charges in adjlists
mjohnson541 Oct 4, 2021
7a57e75
add Li atomtype
mjohnson541 Oct 4, 2021
3ffbfb7
add atom information for Li
mjohnson541 Oct 4, 2021
30b9e4d
handle Lithium electron calculations
mjohnson541 Oct 4, 2021
80b5d98
handle SurfaceChargeTransfer in to_rms
mjohnson541 Oct 8, 2021
6147486
add Li to R and R!H lists
mjohnson541 Dec 7, 2021
5f413af
filter out resonance structures that try to put - charges on Li
mjohnson541 Dec 7, 2021
4ad20ae
add Li McGowan volume
mjohnson541 Dec 9, 2021
ffd7e22
add is_lithium for GroupAtom
mjohnson541 Dec 9, 2021
58e5061
add additional Li BDEs
mjohnson541 Dec 9, 2021
17a3c63
add Li to bond dictionaries in thermo
mjohnson541 Jan 11, 2022
2c4fbde
ensure atomtypes get updated on loading in thermo entries
mjohnson541 Jan 11, 2022
638b864
add solute data to KineticsModel and Arrhenius
mjohnson541 Jan 11, 2022
998ffb1
add ArrheniusChargeTransfer kinetics type
mjohnson541 Jan 11, 2022
a6013c5
create ArrheniusChargeTransferBM type
mjohnson541 Jan 11, 2022
4410294
add ChargeTransfer types to kinetics/__init__.py
mjohnson541 Jan 11, 2022
4f06814
avoid issue with auto decay reactions
mjohnson541 Jan 11, 2022
53f214c
handle ChargeTransfer kinetics with in reaction.py
mjohnson541 Jan 11, 2022
9cbf444
add handling ArrheniusChargeTransfer and fix handling SurfaceChargeTr…
mjohnson541 Jan 11, 2022
732f057
Revert "Remove charge transfer types from average_kinetics (to be rev…
rwest Jul 17, 2023
8ec47b8
enable access to SoluteData object in kinetics database
mjohnson541 Jan 11, 2022
ba2d9f9
update rule fitting
mjohnson541 Jan 11, 2022
9697e62
enable use of non-surface charge transfer families
mjohnson541 Jan 11, 2022
3fa4dc1
add charge transfer types to database context
mjohnson541 Jan 11, 2022
b06e552
add Li0 and Li+ atomtypes
mjohnson541 Jan 11, 2022
1d0d4dd
enable surface and bulk potentials to be specified separately
mjohnson541 Jan 11, 2022
7f5d8ec
Allow approximating a solvent not in the database with another solvent
mjohnson541 Feb 28, 2022
4e99274
standardize ascend option in cross validate
mjohnson541 Jan 11, 2022
5f582ea
Average kinetics when n=1 or E0<0
mjohnson541 Feb 28, 2022
62fcb55
add comment to averaged kinetics
mjohnson541 Feb 28, 2022
b550f2a
fix BM fitting
mjohnson541 Feb 28, 2022
c6536ce
add functions for solvent correcting kinetics
mjohnson541 Jun 18, 2022
dd505f6
add functionality for site specific solvent corrections
mjohnson541 Jun 18, 2022
5d9a9ac
apply_solvent_correction in fix_barrier_height
mjohnson541 Jun 18, 2022
1884255
enable solvent parameters to be directly specified in input file
mjohnson541 Jun 18, 2022
125c9d8
adapt fix_barrier_height calls
mjohnson541 Jun 18, 2022
1aaedc8
handle ArrheniusChargeTransfer => Arrheniusq
mjohnson541 Jun 18, 2022
ceaa28e
add index of refraction to SolventData objects
mjohnson541 Sep 9, 2022
7a95fa2
fix KineticsModel outputs
mjohnson541 Jan 9, 2023
814fbf7
add SoluteTSData object
mjohnson541 Jan 9, 2023
4bc483b
add SoluteTSDIffData object
mjohnson541 Jan 9, 2023
c76e327
add function to convert SoluteData and SoluteTSDiffData to SoluteTSData
mjohnson541 Jan 9, 2023
425bdf7
Enable database to understand new objects
mjohnson541 Jan 9, 2023
370a966
Enable LibraryReaction to handle SoluteTSData
mjohnson541 Jan 9, 2023
b949bec
Enable TemplateReaction to handle new TS solvent corrections
mjohnson541 Jan 9, 2023
f899089
only use kinetics that have arrhenius forms for tree generation
mjohnson541 Jan 9, 2023
1bc3a7a
enable solute data to be pulled from further up the tree as necessary
mjohnson541 Jan 9, 2023
120e506
enable fitting of TS solute rules
mjohnson541 Jan 9, 2023
28473b1
allow training reaction notebook to handle reactions without gas phas…
mjohnson541 Jan 9, 2023
0dba75b
fix arrhenius test
mjohnson541 May 7, 2023
837f0f1
fix atomtype test
mjohnson541 May 7, 2023
cc3c443
add is_lithium to fragment
mjohnson541 May 7, 2023
5634365
handle charge properly in fragment smiles hack
mjohnson541 May 7, 2023
a861172
skip nodes that are empty when pulling solute data
mjohnson541 May 7, 2023
64bb21a
remove test that solvent is in initial species
mjohnson541 May 7, 2023
335228a
adapt corrTest
mjohnson541 May 9, 2023
c7c4643
update product template after generation
mjohnson541 May 9, 2023
572bd82
add Li adsorption to test data
mjohnson541 May 9, 2023
1df7896
add adsorptionLi.py to testing database
mjohnson541 May 10, 2023
76aef1a
don't check collision limit for reactions without kinetics
mjohnson541 Jun 3, 2023
05e12ce
skip coverage dependence checks for electrochem families
mjohnson541 Jun 3, 2023
a716e57
add additional special groups to skip sample molecule generation
mjohnson541 Jun 3, 2023
ab3678b
fix charge handling in make sample molecule
mjohnson541 Jun 10, 2023
87d5d4d
Refactor some rate fitting in rule generation.
rwest Jul 17, 2023
7823ad8
Minor refactor.
rwest Jul 18, 2023
d70da49
Fix ArrheniusBM.get_activation_energy unit test.
rwest Jul 18, 2023
824cbb0
Consistently use T=298. K for fitting and evaluating Blowers-Masel ra…
rwest Jul 18, 2023
e479209
Fixes and tweaks to Blowers Masel classes' fit_to_reactions methods.
rwest Jul 18, 2023
6c352db
modifed arrbm `fit_to_data` unit test
davidfarinajr Jan 18, 2022
f805d04
TEMPORARY: set database branch to lithium
mjohnson541 Jan 10, 2023
752d413
fix atomtype charge checking
mjohnson541 Jul 27, 2023
fd4457c
fix typo in database test
mjohnson541 Jul 27, 2023
5df983b
allow `cat` of regression diff to fail, print a warning instead
JacksonBurns Jul 28, 2023
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
8 changes: 4 additions & 4 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ jobs:
env:
# if running on RMG-Py but requiring changes on an un-merged branch of RMG-database, replace
# main with the name of the branch
RMG_DATABASE_BRANCH: main
RMG_DATABASE_BRANCH: lithium

# This is true only if this is a reference case for the regression testing:
REFERENCE_JOB: ${{ github.ref == 'refs/heads/main' && github.repository == 'ReactionMechanismGenerator/RMG-Py' }}
Expand Down Expand Up @@ -302,7 +302,7 @@ jobs:
export FAILED=Yes
fi
echo "" # blank line so next block is interpreted as markdown
cat "$regr_test-core.log"
cat "$regr_test-core.log" || (echo "Dumping the whole log failed, please download it from GitHub actions. Here are the first 100 lines:" && head -n100 "$regr_test-core.log")
echo "</details>"
echo "<details>"
if python-jl scripts/checkModels.py \
Expand All @@ -319,7 +319,7 @@ jobs:
export FAILED=Yes
fi
echo "" # blank line so next block is interpreted as markdown
cat "$regr_test-edge.log"
cat "$regr_test-edge.log" || (echo "Dumping the whole log failed, please download it from GitHub actions. Here are the first 100 lines:" && head -n100 "$regr_test-core.log")
echo "</details>"

# Check for Regression between Reference and Dynamic (skip superminimal)
Expand Down Expand Up @@ -410,4 +410,4 @@ jobs:
uses: docker/build-push-action@v4
with:
push: true
tags: reactionmechanismgenerator/rmg:latest
tags: reactionmechanismgenerator/rmg:latest
4 changes: 3 additions & 1 deletion arkane/encorr/ae.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@
'Methane',
'Methyl',
'Ammonia',
'Chloromethane'
'Chloromethane',
'Lithium Hydride',
'Lithium Fluoride'
]


Expand Down
2 changes: 1 addition & 1 deletion arkane/encorr/bac.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class BAC:
ref_databases = {}
atom_spins = {
'H': 0.5, 'C': 1.0, 'N': 1.5, 'O': 1.0, 'F': 0.5,
'Si': 1.0, 'P': 1.5, 'S': 1.0, 'Cl': 0.5, 'Br': 0.5, 'I': 0.5
'Si': 1.0, 'P': 1.5, 'S': 1.0, 'Cl': 0.5, 'Br': 0.5, 'I': 0.5, 'Li': 0.5,
}
exp_coeff = 3.0 # Melius-type parameter (Angstrom^-1)

Expand Down
4 changes: 2 additions & 2 deletions arkane/encorr/corrTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def test_get_bac(self):
bac_type=bac_type,
)
# test value is obtained by BAC(self.freq_lot, bac_type=bac_type).get_correction(bonds=bonds, coords=CCCBDB_coords, nums=nums).value_si
test_value = 700
test_value = -466
self.assertAlmostEqual(bac, test_value, places=None, delta=100)

# test Melius BACs
Expand All @@ -100,7 +100,7 @@ def test_get_bac(self):
bac_type=bac_type,
)
# test value is obtained by BAC(self.freq_lot, bac_type=bac_type).get_correction(bonds=bonds, coords=CCCBDB_coords, nums=nums).value_si
test_value = 949
test_value = -234
self.assertAlmostEqual(bac, test_value, places=None, delta=100)

def test_assign_frequency_scale_factor(self):
Expand Down
2 changes: 1 addition & 1 deletion examples/rmg/liquid_cat/input.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Data sources
database(
thermoLibraries=['surfaceThermoPt111', 'primaryThermoLibrary', 'thermo_DFT_CCSDTF12_BAC','DFT_QCI_thermo'], # 'surfaceThermoPt' is the default. Thermo data is derived using bindingEnergies for other metals
reactionLibraries = [],
reactionLibraries = [('Surface/CPOX_Pt/Deutschmann2006_adjusted', False)], # when Ni is used change the library to Surface/Deutschmann_Ni
seedMechanisms = [],
kineticsDepositories = ['training'],
kineticsFamilies = ['surface','default'],
Expand Down
6 changes: 3 additions & 3 deletions ipython/kinetics_library_to_training_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,9 @@ def process_reactions(database, libraries, families, compare_kinetics=True, show
units = 'cm^3/(mol*s)'
elif len(lib_rxn.reactants) == 3:
units = 'cm^6/(mol^2*s)'
A = lib_rxn.kinetics.A
lib_rxn.kinetics.A = ScalarQuantity(value=A.value_si*A.get_conversion_factor_from_si_to_cm_mol_s(),units=units,uncertainty_type=A.uncertainty_type,uncertainty=A.uncertainty_si*A.get_conversion_factor_from_si_to_cm_mol_s())
if hasattr(lib_rxn.kinetics,'A'):
A = lib_rxn.kinetics.A
lib_rxn.kinetics.A = ScalarQuantity(value=A.value_si*A.get_conversion_factor_from_si_to_cm_mol_s(),units=units,uncertainty_type=A.uncertainty_type,uncertainty=A.uncertainty_si*A.get_conversion_factor_from_si_to_cm_mol_s())

if fam_rxn.family in reaction_dict:
reaction_dict[fam_rxn.family].append(lib_rxn)
Expand Down Expand Up @@ -436,4 +437,3 @@ def manual_selection(master_dict, multiple_dict, database):
print('================================================================================')
print('Manual selection of reactions completed.')
print('================================================================================')

2 changes: 1 addition & 1 deletion rmgpy/chemkin.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ def read_reaction_comments(reaction, comments, read=True):
raise ChemkinError('Unexpected species identifier {0} encountered in flux pairs '
'for reaction {1}.'.format(prod_str, reaction))
reaction.pairs.append((reactant, product))
assert len(reaction.pairs) == max(len(reaction.reactants), len(reaction.products))
#assert len(reaction.pairs) == max(len(reaction.reactants), len(reaction.products))

elif isinstance(reaction, TemplateReaction) and 'rate rule ' in line:
bracketed_rule = tokens[-1]
Expand Down
2 changes: 1 addition & 1 deletion rmgpy/constants.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@
# #
###############################################################################

cdef double pi, Na, kB, R, h, hbar, c, e, m_e, m_p, m_n, amu, a0, E_h
cdef double pi, Na, kB, R, h, hbar, c, e, m_e, m_p, m_n, amu, a0, E_h, F
4 changes: 4 additions & 0 deletions rmgpy/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
#: :math:`\pi = 3.14159 \ldots`
pi = float(math.pi)

#: Faradays Constant F in C/mol
F = 96485.3321233100184

################################################################################

# Cython does not automatically place module-level variables into the module
Expand All @@ -130,4 +133,5 @@
'm_n': m_n,
'm_p': m_p,
'pi': pi,
'F': F
})
7 changes: 5 additions & 2 deletions rmgpy/data/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from rmgpy.data.reference import Reference, Article, Book, Thesis
from rmgpy.exceptions import DatabaseError, InvalidAdjacencyListError
from rmgpy.kinetics.uncertainties import RateUncertainty
from rmgpy.kinetics.arrhenius import ArrheniusChargeTransfer, ArrheniusChargeTransferBM
from rmgpy.molecule import Molecule, Group


Expand Down Expand Up @@ -228,6 +229,8 @@ def load(self, path, local_context=None, global_context=None):
local_context['shortDesc'] = self.short_desc
local_context['longDesc'] = self.long_desc
local_context['RateUncertainty'] = RateUncertainty
local_context['ArrheniusChargeTransfer'] = ArrheniusChargeTransfer
local_context['ArrheniusChargeTransferBM'] = ArrheniusChargeTransferBM
local_context['metal'] = self.metal
local_context['site'] = self.site
local_context['facet'] = self.facet
Expand Down Expand Up @@ -1350,8 +1353,8 @@ def is_molecule_forbidden(self, molecule):
raise NotImplementedError('Checking is only implemented for forbidden Groups, Molecule, and Species.')

# Until we have more thermodynamic data of molecular ions we will forbid them
if molecule.get_net_charge() != 0:
return True
# if molecule.get_net_charge() != 0:
# return True

return False

Expand Down
12 changes: 9 additions & 3 deletions rmgpy/data/kinetics/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@
from rmgpy.kinetics import Arrhenius, ArrheniusEP, ThirdBody, Lindemann, Troe, \
PDepArrhenius, MultiArrhenius, MultiPDepArrhenius, \
Chebyshev, KineticsData, StickingCoefficient, \
StickingCoefficientBEP, SurfaceArrhenius, SurfaceArrheniusBEP, ArrheniusBM
StickingCoefficientBEP, SurfaceArrhenius, SurfaceArrheniusBEP, \
ArrheniusBM, SurfaceChargeTransfer, KineticsModel
from rmgpy.molecule import Molecule, Group
from rmgpy.reaction import Reaction, same_species_lists
from rmgpy.species import Species

from rmgpy.data.solvation import SoluteData, SoluteTSData, SoluteTSDiffData

################################################################################

Expand Down Expand Up @@ -78,8 +79,13 @@ def __init__(self):
'StickingCoefficientBEP': StickingCoefficientBEP,
'SurfaceArrhenius': SurfaceArrhenius,
'SurfaceArrheniusBEP': SurfaceArrheniusBEP,
'SurfaceChargeTransfer': SurfaceChargeTransfer,
'R': constants.R,
'ArrheniusBM': ArrheniusBM
'ArrheniusBM': ArrheniusBM,
'SoluteData': SoluteData,
'SoluteTSData': SoluteTSData,
'SoluteTSDiffData': SoluteTSDiffData,
'KineticsModel': KineticsModel,
}
self.global_context = {}

Expand Down
34 changes: 31 additions & 3 deletions rmgpy/data/kinetics/depository.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

from rmgpy.data.base import Database, Entry, DatabaseError
from rmgpy.data.kinetics.common import save_entry
from rmgpy.kinetics import SurfaceChargeTransfer, SurfaceArrheniusBEP
from rmgpy.reaction import Reaction


Expand All @@ -60,7 +61,8 @@
pairs=None,
depository=None,
family=None,
entry=None
entry=None,
electrons=None,
):
Reaction.__init__(self,
index=index,
Expand All @@ -72,7 +74,8 @@
transition_state=transition_state,
duplicate=duplicate,
degeneracy=degeneracy,
pairs=pairs
pairs=pairs,
electrons=electrons,
)
self.depository = depository
self.family = family
Expand Down Expand Up @@ -104,12 +107,34 @@
"""
return self.depository.label

def apply_solvent_correction(self, solvent):
"""
apply kinetic solvent correction
"""
from rmgpy.data.rmg import get_db
solvation_database = get_db('solvation')
solvent_data = solvation_database.get_solvent_data(solvent)
solute_data = self.kinetics.solute
correction = solvation_database.get_solvation_correction(solute_data, solvent_data)
dHR = 0.0
dSR = 0.0

Check warning on line 120 in rmgpy/data/kinetics/depository.py

View check run for this annotation

Codecov / codecov/patch

rmgpy/data/kinetics/depository.py#L114-L120

Added lines #L114 - L120 were not covered by tests
for spc in self.reactants:
spc_solute_data = solvation_database.get_solute_data(spc)
spc_correction = solvation_database.get_solvation_correction(spc_solute_data, solvent_data)
dHR += spc_correction.enthalpy
dSR += spc_correction.entropy

Check warning on line 125 in rmgpy/data/kinetics/depository.py

View check run for this annotation

Codecov / codecov/patch

rmgpy/data/kinetics/depository.py#L122-L125

Added lines #L122 - L125 were not covered by tests

dH = correction.enthalpy-dHR
dA = np.exp((correction.entropy-dSR)/constants.R)
self.kinetics.Ea.value_si += dH
self.kinetics.A.value_si *= dA
self.kinetics.comment += "\nsolvation correction raised barrier by {0} kcal/mol and prefactor by factor of {1}".format(dH/4184.0,dA)

Check warning on line 131 in rmgpy/data/kinetics/depository.py

View check run for this annotation

Codecov / codecov/patch

rmgpy/data/kinetics/depository.py#L127-L131

Added lines #L127 - L131 were not covered by tests

################################################################################

class KineticsDepository(Database):
"""
A class for working with an RMG kinetics depository. Each depository
A class for working with an RMG kinetics depository. Each depository
corresponds to a reaction family (a :class:`KineticsFamily` object). Each
entry in a kinetics depository involves a reaction defined either by a
real reactant and product species (as in a kinetics library).
Expand Down Expand Up @@ -187,6 +212,9 @@
''.format(product, self.label))
# Same comment about molecule vs species objects as above.
rxn.products.append(species_dict[product])

if isinstance(entry.data, (SurfaceChargeTransfer, SurfaceArrheniusBEP)):
rxn.electrons = entry.data.electrons.value

if not rxn.is_balanced():
raise DatabaseError('Reaction {0} in kinetics depository {1} was not balanced! Please reformulate.'
Expand Down
Loading
Loading