Skip to content

Conversation

@SuixiongTay
Copy link
Collaborator

@SuixiongTay SuixiongTay commented Nov 6, 2025

Summary

  • Implemented the Solution.to_phreeqc() method to the Solution() class.

Todos:

  • Converts pyEQL formula Solution() schema to PHREEQC SOLUTION keyword
  • Handle polyatomic ions (ex. S(6) to describe SO4[2-])
  • Handle gases defined from atmosphere
  • Remove the charge (chg) from formula (k = el + chg) and refactor test_to_phreeqc()
  • Test Solution() kwarg

PHREEQC input:

Format output should match the PHREEQC example below:

SOLUTION 0
 temp 25.00
 pH 7.00
 pe 8.50
 units mol/L
 Na 1.000445e-03
 Cl 6.318224e-04
END

Addressing PR #287

@codecov
Copy link

codecov bot commented Nov 6, 2025

Codecov Report

❌ Patch coverage is 4.54545% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.71%. Comparing base (dad14f6) to head (b4362ba).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/pyEQL/solution.py 4.54% 21 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #288      +/-   ##
==========================================
- Coverage   84.89%   83.71%   -1.18%     
==========================================
  Files           9        9              
  Lines        1476     1498      +22     
  Branches      257      261       +4     
==========================================
+ Hits         1253     1254       +1     
- Misses        193      214      +21     
  Partials       30       30              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@rkingsbury rkingsbury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the speedy work @SuixiongTay ! Off to a good start

Comment on lines +2718 to +2728
for solute, amount in self.components.items():
amount = self.get_amount(solute, units).magnitude
if solute in ["H2O(aq)", "H[+1]", "OH[-1]"]:
continue
k = standardize_formula(solute)
spl = k.split("[")
el = spl[0]
chg = spl[1].split("]")[0]
if chg[-1] == "1":
chg = chg[0]
k = el + chg
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I think you will need to specify the total element concentrations via get_total_amount(), because the phreeqc convention is not to specify individual species, right?

Also, any formula that is coming out of components is guaranteed to already be standardized, so it's not necessary to call standardize_formula on it

target_mol = quantity.to("moles", "chem", mw=mw, volume=self.volume, solvent_mass=self.solvent_mass)
self.components[formula] = target_mol.to("moles").magnitude

def to_phreeqc(self, units: str = "mol/L", charge_balance: bool = "False") -> str:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The charge_balance should not be a kwarg here, but rather be read from the Solution.balance_charge attribute which is set on __init__. See here for the documentation.

This will require some careful handling depending on the different cases - the pH case is easy and will work very much like you've coded below.

If 'balance_charge' is another species, you'll have to determine the associated element (e.g., Na+ -> Na) and then append the charge to that line (I think).

the solution.
"""
lines = ["SOLUTION 0"]
lines.append(f" temp {self.temperature.to('degC').magnitude:.2f}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solution also has pressure and volume attributes. How does PHREEQC handle those? If possible, pass them into the input file, too

@rkingsbury
Copy link
Member

One other question / idea I had - we already have Solution.to_file for dumping a solution to .json / .yaml. We could extend that method such that if you supply a filename ending in .pqi, you get the phreeqc-formatted text file.

In that case, the to_phreeqc method you're developing here should return a string (as it currently does) rather than write the file, and the user would rarely if ever need to call to_phreeqc directly. In that case, it might be appropriate to make this a private method e.g. ._to_phreeqc. The advantage of accessing it via to_file is that there is one fewer method for a user to learn.

@SuixiongTay @YitongPan1 @vineetbansal what are your thoughts on this?

@rkingsbury rkingsbury mentioned this pull request Nov 7, 2025
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants