watertap-org / watertap

The WaterTAP development repository
https://watertap.readthedocs.io/en/latest
Other
60 stars 59 forks source link

Limited recovery range for RO with ERD flowsheet #951

Open arao53 opened 1 year ago

arao53 commented 1 year ago

Description

Conducting certain parameter sweeps using the RO_with_energy_recovery example with a fixed membrane area returns NaN for an unexpectedly wide range of water recovery values (does not solve for 35% water recovery and 35g/kg). This occurred even when initialize_system(m) was called after changing the recovery and before each solve.

Expected Behavior

With a fixed membrane area, we would expect the lower limit of water recovery to be 0% (or near that to account for numerical issues). However in this example, we see the model is not able to handle even reasonable values for recovery (30-35%) with a fixed area.

The solvable lower bound also changes with respect to the feed salinity. For seawater salinity (m.fs.RO.feed_side.properties_in[0].mass_frac_phase_comp["Liq", "NaCl"].fix(0.035)), the system solves for water recovery as low as 39.6%. For a low salinity brackish water case (m.fs.RO.feed_side.properties_in[0].mass_frac_phase_comp["Liq", "NaCl"].fix(0.005) the system is able to solve for water recovery as low as 8%.

This may indicate either an issue with parameter scaling or model formulation.

Steps to Reproduce

  1. In an environment with Watertap version 0.8.dev0 installed,
  2. create a folder in the same directory as setup.py
  3. Unzip the attached zip file (ro_with_erd_sweep.zip) in this folder.
  4. In the file watertap\examples\flowsheets\RO_with_energy_recovery\RO_with_energy_recovery.py place initialize_system(blk, solver=solver) on line 345 (before solver.solve(blk) is called). This ensures that the system is re-initialized before each solve in the parameter sweep.
  5. Run the script titled ro_with_erd_sweep.py
  6. Inspect the created sweep file titled default_sweep.csv

The following parameter changes are made to the default flowsheet:

m.fs.feed.properties[0].flow_mass_phase_comp["Liq","NaCl"].unfix()
m.fs.RO.recovery_mass_phase_comp[0, "Liq", "H2O"].unfix()

m.fs.RO.area.fix(115) # the approximate value from the original solution (seawater salinity @ 50% recovery)
m.fs.RO.feed_side.properties_in[0].mass_frac_phase_comp["Liq", "NaCl"].fix(0.035) # seawater concentration

This results in 1 DOF, which will be reduced to 0 DOF during the parameter sweep on m.fs.RO.recovery_mass_phase_comp[0, "Liq", "H2O"]

Environment

Anything Else?

ro_with_erd_sweep.zip

adam-a-a commented 1 year ago

My immediate thought is that this might be mitigated by using some of the other arguments built into the parameter_sweep tool, such as reinitialize_function and others. I just haven't kept up with all the latest changes with parameter_sweep but would hope that we've documented the latest developments. We could take a deeper dive into this, but I'd first suggest tinkering with parameter_sweep. @k1nshuk and @bknueven are probably most up to date on the tool.

adam-a-a commented 1 year ago

I should also mention that I tried rerunning your code but at a different starting point: 6% recovery. It solves for that low recovery (where it didn't previously) and maybe a couple other points at low recovery, but then fails to solve for higher recoveries that were solved previously in your runs. This indicates to me that it is likely more of a reinitialization issue than a "variables hitting bounds" issue.