How to set up a simple plot of pH against volume of titrant?

My very first notebook. I have the following equation
Vb = Va * ((Ca/(1 + H/Ka)) - H + Kw/H) / ((Cb/(1 + Kw/(H*Kb))) + H -
Kw/H)
which I have managed to set up in Mathematica. I have tested it by entering different values of pH one at a time.
For given values of Ca, Cb, Ka, Kb, Kw, and Va, I want to plot pH (y-axis) against Vb (x-axis) by specifying a range and increment of pH (e.g., from pH 3.0 to 12.5 in steps of 0.2)
I would also like to tabulate the values of pH and Vb.

My longer-term goal is to use manipulate to illustrate the effects of changes to Ca, Cb, Ka, Kb, and Va

Any help with giving me a kickstart will be much appreciated

What I think you want to do is set up a function that takes pH as an argument. Since H also depends on pH, I suggest you turn that into a function as well. So,

(* parameters *)
Ca = 0.1;
Cb = 0.1;
Ka = 1.75*10^-5;
Kb = 0.63;
Kw = 1.*10^-14;
Va = 10;

(* functions *)
H[pH_] := 10^-pH;
Vb[pH_] := Va*((Ca/(1 + H[pH]/Ka)) - H[pH] + Kw/H[pH])/((Cb/(1 + Kw/(H[pH]*Kb))) + H[pH] - Kw/H[pH])

A quick test:

Vb[11.9]
(* 11.8865 *)

Here is how you could generate some data for pH versus Vb:

Table[{x, Vb[x]}, {x, 3, 12.5, 0.2}]

Okay, now things change a bit. You said

My longer term goal is to use manipulate to illustrate the effects of changes to Ca, Cb, Ka, Kb and Va

Okay, so these other symbols aren’t actually constants. So, you probably want to define Vb as a function of all of these arguments:

Vb[pH_, Ca_, Cb_, Ka_, Kb_, Kw_, Va_] := 
  Va*((Ca/(1 + H[pH]/Ka)) - H[pH] + Kw/H[pH])/((Cb/(1 + Kw/(H[pH]*Kb))) + H[pH] - Kw/H[pH])

You could replace H[pH] with the explicit expression 10^-pH. Now you can plug in whatever values you want:

Vb[11.9, 0.1, 0.1, 1.75*10^-5, 0.63, 1.*^-14, 10]

This should set you up for an easy Manipulate, but I don’t know what ranges you want:

Manipulate[
 Vb[pH, Ca, Cb, Ka, Kb, Kw, Va],
 {pH, 3, 12.5},
 {Ca, < put bounds here >},
 {Cb, < put bounds here >},
 {Ka, < put bounds here >},
 {Kb, < put bounds here >},
 {Kw, < put bounds here >},
 {Va, < put bounds here >}]

Oh, and here’s a plot:

Plot[Vb[pH, 0.1, 0.1, 1.75*10^-5, 0.63, 1.*^-14, 10], {pH, 3, 12.5}] 

VbpHPlot.bmp (945 KB)

Many thanks Eric, that will definitely get me over the next hurdle. I am curious as to what is the purpose or significance of the underscores as in H[pH_] := 10^-pH;
It is getting close to midnight here so I will look at your suggestions tomorrow and takes things from there.

The underscores are a pattern matching construct. Also, the := is SetDelayed, which is a common way to define a function.

Thanks for that explanation - I had read up about SetDelayed but was not familiar with patterns. A couple of things arising:

  1. I would like to use pKa instead of Ka, where pKa = -logKa (or Ka = 10^-Ka). I have attempted this by trying to follow the example used for pH but cannot get it to work. My attempt (commented out) is in the attached notebook.

  2. I started my approach by calculating Vb for a range of values of pH because this seemed to be the quickest way to get started but what I really want to do is calculate pH for a range of values of Vb (this would more closely what happens in the laboratory). I would then plot pH on the y-axis against Vb on the x-axis. I am not sure whether we can use (some) of what we have already or would have to reformulate things to achieve this.

  3. Manipulate is working nicely (as a newcomer to Mathematica, I am blown away by what can be done with it). I have attached Manipulate.PNG - in this screenshot, I don’t really want to see the lower output because the upper input displays the result (11.3973) anyway. Is that possible?
    Also, can the number of decimal places in the result be specified so in this case, it would display as 11.40?

  4. In manipulate, rather than specify a range that results in a slider control, is it possible (for some items at least) to offer the user a choice of three or four predefined values?

  5. Lastly (for now, at least), is it possible to have the table output arranged as two columns rather than a collection of ordered-pair values?

I do hope I am not asking too much all at once. My revised notebook shows my attempts referred to above.

I would like to use pKa instead of Ka…

The expression

Ka[pKa_] := 10^-pKa

was evaluated after

Ka = 1.75 * 10^-5

and you can’t set DownValues for a constant number. You can either clear definitions for Ka (e.g. ClearAll[Ka]) before your new definition, or just remove the first expression entirely if you’re not going to depend on it as a constant anymore (although you’ll still need to clear the symbol or restart the kernel because that definition will still be in Mathematica’s “memory” even if you don’t see it in the notebook anymore).

…what I really want to do is calculate pH for a range of values of Vb…

If you can rewrite the equation in terms of ph = , then sure, that’s doable. I’m not going to try to do it myself :). Then we’ll just write a definition like ph[<arguments go here>]:=<new definition goes here>.

3A.

…I don’t really want to see the lower output because the upper input displays the result…

You somehow ended up with the output of the Manipulate as an input (or something like that). Just delete all of the output cells and re-evaluate. But before re-evaluating, remove the semi-colon from after the Manipulate expression. That semi-colon is suppressing the output.

3B.

…Also can the number of decimal places in the result be specified…

Look at the various *Form methods:

Try NumberForm, for example.

a choice of three or four pre-defined values

Yes. This is documented for Manipulate: Manipulate: Create an Interactive User Interface—Wolfram Documentation

Specifically, you could use this form for (to take one example) Cb:

{Cb, {0.05, 0.1, 0.15}}

which will give you a setter bar with three choices.

is it possible to have the table output arranged as two columns

TableForm[Table[{x, Vb[x]}, {x, 3, 12.5, 0.2}]]

If you’re going to want to do further processing on that data, then I suggest you first save the data in a variable:

dataPairs = Table[{x, Vb[x]}, {x, 3, 12.5, 0.2}];
TableForm[dataPairs]

The various *Form functions are just special wrappers that the front end knows how to interpret to give certain visualizations. You rarely want to use form-wrapped expressions in computations. In other words, you probably do NOT want to do this:

dataPairs = TableForm[Table[{x, Vb[x]}, {x, 3, 12.5, 0.2}]]

TableForm has a bunch of options if you want to tweak further.

Many thanks, Eric. Best if I reply like you, referring to numbered sections/paragraphs

  1. That’s now sorted, and something else I’ve learned

  2. Rewriting the equation would be a problem (at least for me). In Excel, I was able to use the equation as given (Vb = …) and use GoalSeek. You have to specify an initial guess value, give it the value sought, and the cell to adjust in order to achieve that value. Might there be a way to do something similar with Mathematica?

3A I followed your instructions, and all is well, BUT when first run, there is a problem (see attached screenshot). This must be because one of the ranges starts at 0. Ideally, can we specify a range (say 0-5) and a default value (say 2.5)?

3B I will study the reference you provided and see whether it helps

4 That’s what I wanted, and again will follow up on the reference

5 I’ll start following up on your suggestions tomorrow, but I presume Table will now look something like

Table[{x, Vb[x, 0.1, 0.1, 4.76, 0.63, 1.*^-14, 10]}, {x, 3, 12.5, 0.2}]

Can you tell me what each of the symbols is?
Or provide a reference to the formula you’re using?

Sure. Sorry about the units (can’t do superscripts here)
Ca and Cb are the concentrations in mol dm-3 of an acid and a base
Va and Vb are the volumes in cm3 of the acid and base
Ka and Kb are the dissociation constants of the acid and base in mol dm-3
Kw is the ionic product of water in mol2 dm-6

The equation comes from an article in the journal School Science Review

Greatorex, D., ‘Exact algorithms for acid/base titration curves’, S.S.R. 1979, 214, 61, 94

I eventually got hold of a copy (attached) with help of a very kind ladyn at the Association for Science Education (the publishers of S.S.R.)

Greatorex, D., ‘Exact algorithms for acid-base titration curves’, S.S.R. 1979, 214, 61, 94.pdf (2.68 MB)

Vis-a-vis the divide by zero range error, it’s a shame that instead of (for example)
{Kb,0,1} which means 0 <= Kb <= 1
there could be way of stating the range as 0 < Kb <= 1

Okay, sorry for the back-and-forth…

So, what we have is a relation between acid-volume and base-volume. It’s expressed as acid-volume = base-volume * (some big hairy mess based on the other measurements/parameters). Is that correct?

And what you’d like is a formula that outputs pH based on the various acid/base measurements/parameters. Correct?

If my understanding is correct, then I think we might be able to coerce Mathematica into solving the big hairy formula for pH. But I’m heading out, away from my computer, for a bit. So, I can’t set this up right now.

That would be brilliant. There is absolutely no hurry -as it is, I’m going to be quite busy trying out your various suggestions. I thought you might like some background, so here goes:

Basically, this is an acid-base titration. We start off with a volume Va of an acid of “strength” Ka and (unknown) concentration Ca in a conical flask. Ka is a property of the acid in question. We can decide on what volume of acid Va we want to use. (typically 10, 20, or 25 cm3)

We then add from a burette incremental volumes Vb of the base of “strength” Kb. Kb is a property of the base, and we can decide on what (known) concentration of base Cb we want to use.

Experimentally, we don’t need to know anything about Ka or Kb. For example, we place volume Va of acid of unknown concentration in the flask and then add the base of known concentration from the burette until the “end-point” is reached. Then note the volume of base Vb that was added to reach the end-point. From that, we can calculate the concentration of the acid in the flask.

Okay, I think I understand that. What I’m confused about is what you’re trying to find. Previously, it sounded like you were solving for pH, but now it sounds like you’re solving for Ca. And when we started, we were solving for Vb. I guess I’m also confused about this: “we don’t need to know anything about Ka or Kb”. Either we have values for Ka & Kb, or we don’t. They seem to be present in the formula you referenced, so I don’t know how to set this up for the case where we don’t know those values.

Here’s what it sounds like to me. We have some acid solution. We must know some of its properties, but I’m confused about which ones. What we don’t know but would like to know is its concentration, Ca. We have some base solutions, and we know some of their properties. If we can get to a neutral solution (I assume that’s the “endpoint”, but maybe it’s some other pH) by adding a known amount of the base, we can calculate Ca with this complicated formula. So, we’re solving for Ca, and we need a formula where Ca is defined in terms of all of these other independent variables. It sounds like the goal is to solve that complicated formula for Ca. Am I on the right track?

Sorry for the confusion - “we don’t need to know anything about Ka or Kb” applies in the laboratory situation when we are dealing with real solutions and glassware. Again, we are only solving for Ca in the laboratory.

So to clarify (and this will make more sense when you look at my latest version of the notebook which I have attached and to which I have added a number of enhancements)

Kw is always a constant 1.0 E-14

Ka, Kb are dependent on the acid and base respectively and will always be known

Ca, Cb are the concentrations of the acid and base respectively - and in the case of our Mathematica approach will be determined by the user

Va is the volume of acid to which we are adding the base - the user sets this value, usually to 5, 10, 20 or 25

What we are trying to achieve is a plot of pH vs Vb. We can do this in one of two ways;

The first way (which we have been working on) is to calculate Vb from pH. The resulting graph has Vb on the y-axis and pH on the x-axis - I don’t know if the axes can be transposed, but it would be nice if they could

The second way (which is what we want to do next) is to calculate pH from Vb and then plot pH (y-axis) against Vb (x-axis). You said that you might find a way " I think we might be able to coerce Mathematica into solving the big hairy formula for pH." It might be a good idea to do this in a separate notebook.

I hope all this now makes sense but, if not, please let me know.

Titration _OP_Rev 2_CP_.nb (43.8 KB)

So, just as a sanity check, H is really hydrogen ions, and pH is based on that somehow, so solving for H is equivalent to solving for pH. That is, solving for H and scaling appropriately is what we mean by solving for pH.

More sanity checks:

  • Kw is a fixed constant
  • parameters for the experiment are Ka, Kb (i.e. we might let the user specify these, but they represent using completely different acid/base combinations)
  • the free variables, what we want the user to be able to manipulate, are Ca, Cb, and Va (i.e. having pre-determined Ka, Kb, these are the variables that the user “plays” with)
  • we want to show the relationship between pH (or H) and Vb (i.e. having values for all of the aforementioned variables, we just crank out the arithmetic).
  • we want to show this in either orientation (i.e. for a target pH we want to see what Vb volume we need, or alternatively for a given Vb volume we want to know the pH we achieve)

If this is all true, I actually think this is pretty easy (assuming the choices for the variables produce valid numerical answers) and we were almost there. Later today I’ll put something together and try to answer your questions. In the meantime, if you look at the things I sent you about number formatting you can probably answer some of them yourself. Also, the default-value-for-manipulate-controls is answered in the documentation for Manipulate. You might be able to finish this before I get back to it.