##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018-2020, by the
# software owners: The Regents of the University of California, through
# Lawrence Berkeley National Laboratory,  National Technology & Engineering
# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia
# University Research Corporation, et al. All rights reserved.
#
# Please see the files COPYRIGHT.txt and LICENSE.txt for full copyright and
# license information, respectively. Both files are also available online
# at the URL "https://github.com/IDAES/idaes-pse".
##############################################################################
"""
Example of defining a reaction package for the follwoing reaction system:

R1)  A + B --> 2C  Power law rate reaction
R2)  B + C <-> D  Power law equilibrium reaction

Author: Andrew Lee
"""
from pyomo.environ import units as pyunits

from idaes.core import LiquidPhase, Component

from idaes.generic_models.properties.core.state_definitions import FcTP
from idaes.generic_models.properties.core.eos.ideal import Ideal

from idaes.generic_models.properties.core.generic.generic_reaction import (
        ConcentrationForm)
from idaes.generic_models.properties.core.reactions.dh_rxn import \
    constant_dh_rxn
from idaes.generic_models.properties.core.reactions.rate_constant import \
    arrhenius
from idaes.generic_models.properties.core.reactions.rate_forms import \
    power_law_rate
from idaes.generic_models.properties.core.reactions.equilibrium_constant import \
    van_t_hoff
from idaes.generic_models.properties.core.reactions.equilibrium_forms import \
    power_law_equil


# First, create a thermophsyical property definition that will be used
# with the reactions
import idaes.generic_models.properties.core.pure.Perrys as Perrys

# For this example, the thermophsycial properties will only define components
# and phases, but in practice users would also need to define some properties
thermo_configuration = {
    "components": {
        'A': {"type": Component,
              "enth_mol_liq_comp": Perrys,
              "parameter_data": {
                  "cp_mol_liq_comp_coeff": {
                      '1': (1E2, pyunits.J/pyunits.kmol/pyunits.K),
                      '2': (-2E-1, pyunits.J/pyunits.kmol/pyunits.K**2),
                      '3': (6.5E-4, pyunits.J/pyunits.kmol/pyunits.K**3),
                      '4': (0, pyunits.J/pyunits.kmol/pyunits.K**4),
                      '5': (0, pyunits.J/pyunits.kmol/pyunits.K**5)},
                  "enth_mol_form_liq_comp_ref": (
                      5e4, pyunits.J/pyunits.mol)}},
        'B': {"type": Component,
              "enth_mol_liq_comp": Perrys,
              "parameter_data": {
                  "cp_mol_liq_comp_coeff": {
                      '1': (1E2, pyunits.J/pyunits.kmol/pyunits.K),
                      '2': (-2E-1, pyunits.J/pyunits.kmol/pyunits.K**2),
                      '3': (6.5E-4, pyunits.J/pyunits.kmol/pyunits.K**3),
                      '4': (0, pyunits.J/pyunits.kmol/pyunits.K**4),
                      '5': (0, pyunits.J/pyunits.kmol/pyunits.K**5)},
                  "enth_mol_form_liq_comp_ref": (
                      5e4, pyunits.J/pyunits.mol)}},
        'C': {"type": Component,
              "enth_mol_liq_comp": Perrys,
              "parameter_data": {
                  "cp_mol_liq_comp_coeff": {
                      '1': (1E2, pyunits.J/pyunits.kmol/pyunits.K),
                      '2': (-2E-1, pyunits.J/pyunits.kmol/pyunits.K**2),
                      '3': (6.5E-4, pyunits.J/pyunits.kmol/pyunits.K**3),
                      '4': (0, pyunits.J/pyunits.kmol/pyunits.K**4),
                      '5': (0, pyunits.J/pyunits.kmol/pyunits.K**5)},
                  "enth_mol_form_liq_comp_ref": (
                      5e4, pyunits.J/pyunits.mol)}},
        'D': {"type": Component,
              "enth_mol_liq_comp": Perrys,
              "parameter_data": {
                  "cp_mol_liq_comp_coeff": {
                      '1': (1E2, pyunits.J/pyunits.kmol/pyunits.K),
                      '2': (-2E-1, pyunits.J/pyunits.kmol/pyunits.K**2),
                      '3': (6.5E-4, pyunits.J/pyunits.kmol/pyunits.K**3),
                      '4': (0, pyunits.J/pyunits.kmol/pyunits.K**4),
                      '5': (0, pyunits.J/pyunits.kmol/pyunits.K**5)},
                  "enth_mol_form_liq_comp_ref": (
                      5e4, pyunits.J/pyunits.mol)}}},
    "phases":  {'Liq': {"type": LiquidPhase,
                        "equation_of_state": Ideal}},
    "state_definition": FcTP,
    "state_bounds": {"flow_mol_comp": (0, 500, 1000),
                     "temperature": (273.15, 300, 450),
                     "pressure": (5e4, 1e5, 1e6)},
    "pressure_ref": 1e5,
    "temperature_ref": 300,
    "base_units": {"time": pyunits.s,
                   "length": pyunits.m,
                   "mass": pyunits.kg,
                   "amount": pyunits.mol,
                   "temperature": pyunits.K}}


# Next, create the reaction property definition which describes the system on
# reactions to be modeled.
rxn_configuration = {
    "base_units": {"time": pyunits.s,
                   "length": pyunits.m,
                   "mass": pyunits.kg,
                   "amount": pyunits.mol,
                   "temperature": pyunits.K},
    "rate_reactions": {
        "R1": {"stoichiometry": {("Liq", "A"): -1,
                                 ("Liq", "B"): -1,
                                 ("Liq", "C"): 2},
               "heat_of_reaction": constant_dh_rxn,
               "rate_constant": arrhenius,
               "rate_form": power_law_rate,
               "concentration_form": ConcentrationForm.moleFraction,
               "parameter_data": {
                   "dh_rxn_ref": (-10000, pyunits.J/pyunits.mol),
                   "arrhenius_const": (1, pyunits.mol/pyunits.m**3/pyunits.s),
                   "energy_activation": (1000, pyunits.J/pyunits.mol)}}},
    "equilibrium_reactions": {
        "R2": {"stoichiometry": {("Liq", "B"): -1,
                                 ("Liq", "C"): -1,
                                 ("Liq", "D"): 1},
               "heat_of_reaction": constant_dh_rxn,
               "equilibrium_constant": van_t_hoff,
               "equilibrium_form": power_law_equil,
               "concentration_form": ConcentrationForm.moleFraction,
               "parameter_data": {
                   "dh_rxn_ref": (-20000, pyunits.J/pyunits.mol),
                   "k_eq_ref": (100, None),
                   "T_eq_ref": (350, pyunits.K)}}}}
