ekwan / PyPlate

Apache License 2.0
5 stars 7 forks source link

Container.create_solution() Issue with Solids #22

Open jlw387 opened 2 months ago

jlw387 commented 2 months ago

Hello!

I believe I've encountered a fairly substantial problem with the logic of the create_solution() function. The problem is this: it seems like the function uses the volumes of solutes as contributing factors to the overall volume of the solution. Here is an example of what I mean:

image

Here I have added 20 grams of salt to a solvent of water with the goal of creating a solution that is 100 mL. I have indeed achieved that outcome, but the volumes of the substances added are 20 mL of salt and 80 mL of water. This seemed obviously wrong to me, as adding a solute should, for the most part, leave the volume of the solution unchanged, as it dissolves in the solvent, and so the final volume of a solution formed by adding 20 g of salt to 80 mL of water should be 80 mL, not 100 mL.

I can make this even more extreme, ignoring realistic solubility for a moment, and create an even more farfetched example:

image

Here, we would create a 100 mL brine solution with only 10 mL of water and 90 g of salt. Again, in reality, most of the salt would likely not dissolve, but it helps make the issue clearer.

Because solubility is not a parameter of the Substance class, it should allow you to create as concentrated of a solution as you'd like. However, if I push the mass too high, I get the following error:

image

This is because the 150 g of salt is assumed to take up 150 mL, and so it would be impossible to create a solution with only 100 mL. In reality, salt has a density of 2.16 g/mL, so it should be possible to make even if the two substances (salt and water) remained completely separate.

I dug down into this further, and noticed a few discrepancies in the Substance class. The Substance attribute density has the following description: density: Density if 'Substance' is a liquid (g/mL). This would imply the field is only supposed to be used when the substance is a liquid, and by default it is set to infinity when a substance is initialized. However, when looking through Substance.solid(), the function I used to create the solid substances, I found this line:

https://github.com/ekwan/PyPlate/blob/f2047cc44cb9b8e725e524c2483e3cff2e1726b9/pyplate/pyplate.py#L570C9-L570C57

The default value for the solid density in pyplate.yaml is 1, which explains why salt was assumed to have a density of 1 g/mL, but the important thing to note here is that the density is being set for solids, not just liquids, in spite of the comment at the top of the class.

Looking back at the create_solution() logic, the code sets up a linear system of equations and calls numpy.linalg.solve(). As far as I can tell, the source of the issue I'm encountering is here:

https://github.com/ekwan/PyPlate/blob/f2047cc44cb9b8e725e524c2483e3cff2e1726b9/pyplate/pyplate.py#L1155-L1159

To get the A entries, the function calls the convert_one() function with the unit of the 'total_quantity' entry. If a volume quantity is entered, it results in the function computing volumes of one mole of all the other compounds using the Unit.convert_from() function, which uses density, which is where the 1 g/mL conversion is coming from. This means that the resulting equation is (for the first salt example):

0.1 L = [58.55 g/mol (1 g/mL)^(-1) 0.001 L / mL] x_salt + [18.015 g/mol (1 g/mL)^(-1) 0.001 L / mL] x_water

where x_salt is the moles of salt and x_water is the moles of water. In reality, if we assume for simplicity that solutes take up no volume, the equation should be:

0.1 L = 0 x_salt + [18.015 g/mol (1 g/mL)^(-1) 0.001 L / mL] x_water

This would result in the correct amount of water being added. Thus, unless you are currently trying to support instances where solutes take up non-zero volumes, I would recommend adjusting the logic in this function to simply zero out all the solute entries in this final equation if the total quantity unit is a volume.

ekwan commented 2 months ago

These are really good points! I was just looking at this:

https://chemistry.stackexchange.com/questions/54111/does-solute-add-to-volume-of-solution

Clearly, we need to be more thoughtful here. Can we have an offline discussion about this? ekwan16@gmail.com