(chemistry)=

# Writing Formulas

`pyEQL` interprets the chemical formula of a substance to calculate its molecular
weight and formal charge. The formula is also used as a key to search the
[property database](database.md) for parameters (e.g. diffusion coefficient) that are
used in subsequent calculations.

## How to Enter Valid Chemical Formulas

Generally speaking, type the chemical formula of your solute the "normal" way
and `pyEQL` should be able to interpret it. Internally, `pyEQL` uses a utility function `pyEQL.utils.standardize_formula`
to process all formulas into a standard form. At present, this is done by passing the formula through the
[`pymatgen.core.ion.Ion`](https://pymatgen.org/pymatgen.core.html#pymatgen.core.ion.Ion) class. Anything that the `Ion`
class can understand will be processed into a valid formula by `pyEQL`.

Here are some examples:

| Substance       |             You enter             | `pyEQL` understands |
| :-------------- | :-------------------------------: | :-----------------: |
| Sodium Chloride |   "NaCl", "NaCl(aq)", or "ClNa"   |     "NaCl(aq)"      |
| Sodium Sulfate  |      "Na2(SO4)" or "Na2SO4"       |    "Na(SO4)(aq)"    |
| Sodium Ion      | "Na+", "Na+1", "Na1+", or "Na[+]" |      "Na[+1]"       |
| Magnesium Ion   |    "Mg+2", "Mg++", or "Mg[++]"    |      "Mg[+2]"       |
| Methanol        |          "CH3OH", "CH4O"          |     "CH3OH(aq)"     |
| Phosphate Ion   |         "PO4-3", "PO₄³⁻"          |      "PO4[-3]"      |

Specifically, `standardize_formula` uses `Ion.from_formula(<formula>).reduced_formla` (shown in the right hand column
of the table) to identify solutes. Notice that for charged species, the charges are always placed inside square brackets
(e.g., `Na[+1]`) and always include the charge number (even for monovalent ions). Uncharged species are always suffixed
by `(aq)` to disambiguate them from solids.

```{important}
**When writing multivalent ion formulas, it is strongly recommended that you put the charge number AFTER the + or -
sign** (e.g., type "Mg+2" NOT "Mg2+"). The latter formula is ambiguous - it could mean $Mg_2^+$ or $Mg^{+2}$ and it will be processed incorrectly into `Mg[+0.5]`

There is **one exception** to the rule above. If you really want to list the charge number
first , you can use unicode superscript characters (e.g., "Co²⁺"), and `pyEQL` will understand
these regardless of the order of the `+` and the `2`. So you can write "Co²⁺" and it will be
correctly standardized to `Co[+2]`
```

(manual-testing)=

## Manually testing a formula

If you want to make sure `pyEQL` is understanding your formula correctly, you can manually test it as follows:

```
>>> from pyEQL.utils import standardize_formula
>>> standardize_formula(<your_formula>)
...
```

## Formulas you will see when using `Solution`

When using the `Solution` class,

- When creating a `Solution`, you can enter chemical formulas in any format you prefer, as long as `standardize_formula` can understand it (see [manual testing](#manually-testing-a-formula)).
- The keys (solute formulas) in `Solution.components` are standardized. So if you entered `Na+` for sodium ion, it will appear in `components` as `Na[+1]`.
- However, the `components` attribute is a special dictionary that automatically standardizes formulas when accessed. So, you can still enter the formula
  however you want. For example, the following all access or modify the same element in `components`:

  ```python
  >>> Solution.components.get('Na+')
  >>> Solution.components["Na+1"]
  >>> Solution.components.update("Na[+]": 2)
  >>> Solution.components["Na[+1]"]
  ```

- Arguments to `Solution.get_property` can be entered in any format you prefer. When `pyEQL` queries the database, it will automatically standardize the formula.
- Property data in the database is uniquely identified by the standardized ion formula (output of `Ion.from_formula(<formula>).reduced_formla`, e.g. "Na[+1]" for sodium ion).
