Tuesday, July 25, 2023

Using chatGPT to clean up Perl programs on a Linux server (a developing tutorial) using sed and awk

Introduction


When my University decided to upgrade its RedHat server which hosted my teaching material, I expected that this would be a smooth process. I was wrong.
Every Perl script on my sites failed.
The problem had to do with the @INC variable, which tells Perl where modules with the extensiom ".pm" (in my case) reside. The Perl documentation tells us:
Prior to Perl 5.26, . -which represents the current directory, 
was included in @INC; it has been removed. This change in behavior is 
documented in PERL_USE_UNSAFE_INC and it is not recommended that . 
be re-added to @INC. If you need to modify @INC at runtime, 
you should use the use lib pragma to get the machine-dependent 
library properly loaded as well:

use lib '/mypath/libdir/';
use SomeMod;

This seems to imply that I need to change every perl script on this server to include a 'use lib' statement. There are several hundred programs involved. That means we have to use the 'sed' unix utility, a stream editor. But my expertise is limited in sed, and programming it would drive me mad. Hello chatGPT.

My first chatGPT attempt


I wrote: "Write a sed script to insert a line of code above the first instance of the word "use"." in the chatGPT QUERY BOX. It answered:

#!/bin/sed -f

# Add a line of code above the first instance of "use"
/\<use\>/ {
    i\
    # Line of code to insert
}
 Yes, hold on hold on
# Print all lines
1,$ p

with the accompanying text: "To use this script, save it to a file (e.g., 'insert_code.sed'), make it executable ('chmod +x insert_code.sed'), and then run it with 'sed -f insert_code.sed input_file'. Replace 'input_file' with the path to the file you want to modify. Make sure to replace '# Line of code to insert' with the actual code you want to insert. The code should be written in a way that sed can understand it (e.g., escape special characters with a backslash if necessary). The script searches for the first occurrence of the word "use" (separated by word boundaries) and inserts the line of code above it. All other lines are printed unchanged." k

Before rushing in

We will make a safety subfolder containing some test cases and the sed file, test everything there, and then apply the sed program to the contents of the cgi-bin directory which is serving the web. This is the line we have to add: use lib '/home/chem12x/public_html/cgi-bin';

First steps


we start by creating a sub-directory called 'test'

  chem12x@chemphys cgi-bin]$ mkdir test

Next, we copy some code from cgi-bin to cgi-bin/test:

  cp ../sop*.pl .

Then we check that what we did was OK:

 ls 

with output:
  


-rwxr-xr-x. 1 chem12x chem12x  13K Jul 15 19:30 sophiakp1a.pl*
-rwxr-xr-x. 1 chem12x chem12x  15K Jul 15 19:30 sophiakp1.pl*
-rwxr-xr-x. 1 chem12x chem12x  12K Jul 15 19:30 sophiakp1popup.pl*
-rw-r--r--. 1 chem12x chem12x 6.7K Jul 15 19:30 sophiaKp1_PSGI.pl
-rwxr-xr-x. 1 chem12x chem12x  11K Jul 15 19:30 sophiakp1safety2.pl*
-rwxr-xr-x. 1 chem12x chem12x 9.8K Jul 15 19:30 sophiakp1safety3.pl*
-rwxr-xr-x. 1 chem12x chem12x  11K Jul 15 19:30 sophiakp1safety.pl*
-rwxr-xr-x. 1 chem12x chem12x  16K Jul 15 19:30 sophiakp2mail.pl*
-rwxr-xr-x. 1 chem12x chem12x  15K Jul 15 19:30 sophiakp2.pl*

I need to explain. My granddaughter was studying chemical equilibrium in high school, so I wrote some programs to help her learn. By the time I'd finished, she had moved on. Oh well. Anyway, all these programs involve Computer Assisted Testing, which also includes teaching, learning, etc.. I converted sophiakp1.pl to include the lib statement we need (by hand) as proof of cocept. So now it is time to alter chatGPT's suggestion and try it.

  chem12x@chemphys cgi-bin]$ mkdir test

Next, we re-copy some Perl code from cgi-bin to cgi-bin/test as what we had was corrupted. Then chatGPT suggested:

#!/bin/sed -f

# Add a line of code above the first instance of "use"
/\<use\>/ {
    i\
    use lib '/home/chem12x/public_html/cgi-bin';
}
 Yes, hold on hold on
# Print all lines
1,$ p

This failed

  #!/bin/bash

# Save the awk script to a file named 'insert_code.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk -i inplace '
    BEGIN { found=0 }
    /use/ && found==0 {
        print "# Line of code to insert"
        print
        found=1
        next
    }
    { print }
' {} \;

This didn't work either, so, iteration n+1 yields: "Apologies for the confusion. It seems there was a typo in the command. The -i inplace option is specific to sed, and awk does not have an equivalent option for in-place editing. Instead, we'll need to use a temporary file to achieve the desired effect. Here's the updated version using awk:"

#!/bin/bash

# Save the awk script to a file named 'add_use.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk '
    BEGIN { found=0 }
    /use/ && found==0 {
        print "# Line of code to insert"
        found=1
    }
    { print }
' {} > tmpfile && mv tmpfile {} \;

chatCPK wrote the following:

"Replace /path/to/directory with the actual path to the 
directory containing your .pl files. Save the script 
above to a file named add_use.awk. 
Make sure to adjust # Line of code to insert with the 
actual code you want to insert.

This script will use awk to search for the first occurrence 
of "use" in each .pl file and then insert the desired line 
above it. The changes will be written to a temporary file, 
which is then moved back to the original file, effectively 
achieving the in-place editing.

Please give this script a try, and it should work as expected."

Most of this is wrong. I named the file add_use.sh and used "chmod a+x add_use.sh" to make it executable. Then, I copied everything in cgi-bin to a safety directory, chi-bin/safety.
Here is the final result:

#!/bin/bash

# Save the awk script to a file named 'add_use.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk '
    BEGIN { found=0 }
    /use/ && found==0 {
        print "use lib '/home/chem12x/public_html/cgi-bin';"
        found=1
    }
    { print }
' {} > tmpfile && mv tmpfile {} \;

There's one last problem here, which had to be fixed.

#!/bin/bash

# Save the awk script to a file named 'add_use.awk'
# with the desired code to insert above the word 'use'.

# Find all files with .pl extension and execute the awk script on each of them
find /path/to/directory -type f -name '*.pl' -exec awk '
    BEGIN { found=0 }
    /use/ && found==0 {
        print qw(use lib '/home/chem12x/public_html/cgi-bin';)
        found=1
    }
    { print }
' {} > tmpfile && mv tmpfile {} \;

Without the qw code, the single apostrophes are not reproduced into the final Perl programs. To see the result try this link.

Tuesday, November 29, 2022

Computer AssistedTesting/Learning using php

The following php programs are presented to aid educators in developing interactive modules for their students on the world wide web. Where teachers have access solely to the public_html directory, and no access to the cgi-bin directory, php is a method of writing interactive material without using Perl. The following code, 2 programs, one a question (test.php), and one a grading module called "process.php", are presented. I am no expert in php, and cobbled this together just to show the reader that it can be done.

test.php

<?php
// Start the session
session_start();
?>
<!DOCTYPE html>
<html>
<body>
   <title>Prototype php Computer Assisted Learning/Testing</title>
 </head>
<?php
//global $root2;
$true = "true";
$false = "false";
$debug = $false;
function sigFig($value, $digits)
{
    if ($value == 0) {
        $decimalPlaces = $digits - 1;
    } elseif ($value < 0) {
        $decimalPlaces = $digits - floor(log10($value * -1)) - 1;
    } else {
        $decimalPlaces = $digits - floor(log10($value)) - 1;
    }

    $answer = round($value, $decimalPlaces);
    return $answer;
}


function randomFloat($min = 0, $max = 1) {
    return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
$r_no_a = randomFloat(1,2);
$r_no_a = sigFig($r_no_a,3);
$r_no_c = sigFig(randomFloat(1,2),3);
$r_no_b = sigFig(randomFloat(4*$r_no_a*$r_no_c, 4.3*$r_no_a*$r_no_c),3);
$root1 = (-$r_no_b +sqrt( pow($r_no_b,2)-4*$r_no_a*$r_no_c))/(2*$r_no_a);
$root1 =  sigFig($root1,3);
$text = "
<h2>A php protypical computer assisted learning/testing module</h2>
<br> For the equaton <br>
<center>
<h2>
 $r_no_a  x<sup>2</sup> +   $r_no_b x +   $r_no_c  = 0 
</h2>
</center>
one root is $root1. What is the second root?";
$root2 = (-$r_no_b - sqrt( pow($r_no_b,2)-4*$r_no_a*$r_no_c))/(2*$r_no_a);
$root2 =sigFig($root2,3);
echo $text;
if ($debug == $true){
echo "<br> debug::: root2 = $root2<br>";
echo sigFig($root1,3);}
?>
<body>
  <form action="process.php" method="post">
   <fieldset>
     <table>
      <tr>
       <td>First Name: </td>
       <td><input type="text" name="fname" value="John"></td>
      </tr>
      <tr>
       <td>Last Name: </td>
       <td><input type="text" name="lname" value="Smith"></td>
      </tr>
      <tr>
       <td>e-mail address: </td>
       <td><input type="text" name="email address" value="john.smith@university.edu"></td>
      </tr>
     </table>
   </fieldset>
   <fieldset>
<input type="hidden" name="root2" value="<?php echo $root2;?>" />
<input type="hidden" name="a" value="<?php echo $r_no_a;?>" />
<input type="hidden" name="b" value="<?php echo $r_no_b;?>" />
<input type="hidden" name="c" value="<?php echo $r_no_c;?>" />
<input type="hidden" name="text" value="
<?php echo $text;?>"/>
<font size="+3">
<select name="firstSign">
  <option value="+">+</option>
  <option value="-"> -</option>
</select>
<select name="firstDigit">
  <option value="1">1</option>
  <option value="2"> 2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
</select>
.
<select name="secondDigit">
  <option value="0">0</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
</select>
<select name="thirdDigit">
  <option value="0">0</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
</select>
x 10
</font>
<sup>
<select name="firstExpSign">
  <option value="+">+</option>
  <option value="-">-</option>
</select>
<select name="firstExpDigit">
  <option value="0">0</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
</select>
<select name="secondExpDigit">
  <option value="0">0</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
</select>
<input type="hidden" name="correctAnswer" value='<?php "$root2";?>' />
       <input type="submit"  name="submit" value="Submit Your  Answer">
   </fieldset>
   </sup>
  </form>
 </body>
 </html>
process.php
The process module starts here:
<?php
$true = "true";
$false = "false";
$debug = $false;
   if (isset($_POST['submit']))
   {
     echo "<big/><big/>";
     echo "Your First Name is: " . $_POST["fname"] . "<br>";
     echo "Your Last Name is: " . $_POST["lname"] . "<br>";
/*     echo "Your e-mail address is: " . $_POST["email address"] . "<br>";
/*     echo "Your State is: " . $_POST["state"] . "<br>";*/
     echo "<br>";
     $correctAnswer = $_POST["correctAnswer"];
/*var_dump($_POST["correctAnswer"]);*/
     $text = $_POST["text"];
/*var_dump($_POST["text"]);*/
     $root2 = $_POST["root2"];
/*var_dump($_POST["correctAnswer"]);*/
     $firstDigit = $_POST["firstDigit"];
     $secondDigit = $_POST["secondDigit"];
     $thirdDigit = $_POST["thirdDigit"];
    $firstExpSign = $_POST['firstExpSign'];
    $firstExpDigit = $_POST['firstExpDigit'];
    $secondExpDigit = $_POST['secondExpDigit'];
    $power = $firstExpDigit*10+$secondExpDigit;
    if ($firstExpSign == "-"){$power=-$power;}
    $studentAnswer = $firstDigit+$secondDigit/10+$thirdDigit/100;
    if ($firstSign == "-"){-$studentAnswer = -$studentAnswer;}
    $studentAnswer = $studentAnswer*pow(10,$power);
    echo $text;
    echo "<br> Your answer was = ".$studentAnswer;
    if($studentAnswer == $root2){
       echo "Right! <img src=./icons/check.gif> ";
    }else{
    echo "<br>
    Wrong! <img src=./icons/checkno.gif><br>";}
    echo "<h2>Use back arrow to return to question</h2>";
   }
?>
The above text can be executed at my physical chemistry site

Friday, July 22, 2022

Revisiting educational value of educational journal articles

Revisiting educational value of educational articles

There is a powerful belief amongst us that teaching and learning are coupled in some magical way.


Recently, while searching for an article I'd written and had accepted, I came across a letter to the editor referring to earlier work of mine. How wonderful; an indication that someone had actually read something I'd written.


But, in thinking about it, I was apalled that the editor had not told me about this letter. I refer to J. Chem. Ed. 61,268(1984), by F. O. Ellison. Ellison objected to my using Cartesian coördinates to show that an LCAO-MO for the hydrogen molecule cation was not an eigenfunction of the appropriate Hamilonian. Instead, Ellison showed symbolically that this was the case. Of course, we were both "correct", but the question in my mind then, and now, is- what pedagogically works for students of physical chemistry.

 Three coördinate systems, cartesian, spherical polar and elliptical, are shown

In teaching valence bond or molecular orbital theory, one needs to deal explicitly with coördinate systems, so that one can locate the nuclei. The figure shows three coördinate systems applicable to the problem at hand. Which should one use? How should it be used? What does using it do for the student?


The typical chemistry student has ended his/her mathematical formal instruction with differential equations. Thus partial differential equations in two or more independent variables is not usually included in the curriculum. So a Hamiltonian of the form
$$ -\frac{\hbar^2}{2m_e} \left ( \frac{\partial^2}{\partial x^2}+ \frac{\partial^2}{\partial y^2}+ \frac{\partial^2}{\partial z^2} \right ) -\frac{Ze^2}{r} $$ can not be referring to $r_A$ or $r_B$, but to $r = \sqrt{x^2+y^2+z^2}$. That is the radius from the origin in spherical polar coördinates, viz., $r,\vartheta,\varphi$. So, when Ellison writes $$ H\psi_{trial}=\left [ -\frac{\hbar^2}{2m}\nabla^2 -\frac{ Ze^2}{r_A} - \frac{ Ze^2}{r_B} \right ](1s_A+1s_B) $$one has the right to ask, does the student understand the difference between $r$ and $r_A$?

As one traces backwards the accumulated learning that was required to get to these points the student/reader has the right to ask 'what does this symbolism mean?'. After all, $r_A = \sqrt{x^2 + y^2 + (z- R/2)^2}$ and $r_B= \sqrt{x^2 + y^2 + (z+R/2)^2}$ so the LCAO proposed is a little complicated.

So, we return to the idea of third year chemistry majors studying physical chemistry for the first time and dealing with mathematics based on two years of standard calculus instruction. Having been out of classrooms for more that 12 years, I can no longer attest to what students have been exposed to, but my guess is that $\nabla$ is not one of symbols they've seen.

But I'm sure that they've never seen an equation of the form $Operator$ operating on $function$ yields a $number$ times $the\ same\ function$, i.e., $H\psi = E \psi$. Actually, most likely they've "seen" it, but never actually used it.


Following backwards the accumulated knowledge that these students have acquired is an amazing journey. Consider the gradient $$ \vec{\nabla} = \hat{i}\frac{\partial}{\partial x}+ \hat{j}\frac{\partial}{\partial y}+ \hat{k}\frac{\partial}{\partial z} $$ Does the student know this operator? Is it related to $\nabla^2$?
Where did we learn this?

And, relative to the diagram, what is $\nabla$ and $ \nabla^2$ in elliptical coördinates?

And what is an LCAO-MO in these elliptical coördinates?

As we trace backwards from the current state of the art, looking at the assumed knowledge required for understanding, we see the reverse process of educational curriculum development through the lens of practitioners. This enormous pyramid of learned techniques and facts has to be reverse engineered so that children can absorb this material and incorporate this knowledge into their armamentarium.

How we do this is the task of educators who do not know what their charges will need; the material they are presenting or the material they are omitting. The future will unfold, and leaving out a topic could easily warp understanding many years hence.

On the other hand, most of their charges will never use any of the mathematics they are taught!

Consider the backwards path from partial differential equations, through calculus, through advanced algebra, solid geometry, intermediate algebra, trigonometry, plane geometry, elementary algebra, arithmetic, and finally numbers, and more than finally, fingers and toes.

Can we really truncate this learning path?

It seems doubtful we can; but instead, we leave it to the child to drop off of the heirarchical tree. That seems to work in most cases, but the doors that are closed for these children are rarely re-opened. Perhaps this is the best a civilization can do.

Thursday, June 23, 2022

The ground state wavefunction expansion for Helium's electrons

On the Exact Helium Wave Function Expansion

Abstract

A $^1S$ wave function's expansion for 2 electron atoms and ions is obtained and the leading coëfficients are reported.

Introduction

The ground electronic state of Helium (and its isoelectronic ions) has been studied extensively since the original work of Hylleraas (E. A. Hylleraas, Uber den Grundzustand des Heliumatoms, Zeits. f. Physik 48, 469 (1928)). Absent an exact solution, efforts have been expended to find compact approximate wave functions which give increasingly better energy eigenvalues for the energy ( K. Rodriguez, G. Gasaneo, and D. Mitnik, Accurate and simple wavefunctions for the Helium isoelectronic sequence with correct cusp conditions, Journal of Physics B: Atomic, Molecular and Optical Physics 40, 3923 (2007).).

The $^1S$ wave function for Helium's two electrons is not a power series in $r_1, r_2$ and $r_{12}$, as shown by Bartlett, Gibbons and Dunn ( J. H. Bartlett Jr., J. J. Gibbons Jr., and C. G. Dunn, Phys. Rev. 47, 679 (1935)). who demonstrated that a unique solution for $\psi(r_1,r_2,r_{12})$ of the form $$ \psi = \sum_{i,j,k}C_{i,j,k}r_1^ir_2^jr_{12}^k $$ does not exist. They showed that the coëfficient of $\frac{r_2^2}{r_1r_{12}} \hookrightarrow C_{101} = 0$, that the coëfficients of $\frac{1}{r_1} \hookrightarrow 2C_{100}+C_{010}= 0$ and that the coëfficients of $\frac{r_{1}}{r_{12}} \hookrightarrow 5C_{101}-\frac{1}{2} C_{100} = 0$.

Fock (V. A. Fock, Izv. Akad. Nauk SSSR, Ser. Fiz. 18, 161 (1954).,V. A. Fock, On the Schrödinger equation of the Helium atom, Det Koneglige Norske Videnskabers Selskabs Forhandlinger 31, 138 (1958)., E. Z. Liverts and N. Barnea, Angular fock coefficients: Refinement and further development, Phys. Rev. A92, 42512 (2015).) showed that there must be logarithmic terms in the expansion, and gave the form the expansion had to take. Defining $R=\sqrt{r_1^2+r_2^2}$, he wrote (in current but mixed notation) \begin{eqnarray} \psi = 1 -Z (r_1+r_2) +\frac{1}{2}r_{12}+ \nonumber \\ R \left (\psi_{2,1} \ell n R + \psi _{2,0} \right ) + \nonumber \\ R^{1/2} \left (\psi_{5/2}R \ell n R + R\psi _{5/2,0} \right ) + \nonumber \\ R^2 \left (\psi_{3,2}\ell n^2 R + \psi_{3,1} \ell n R +\psi_{3,0} \right ) +\dots \end{eqnarray} with $Z=2$ for Helium. $\psi_{2,1}$ was shown by Fock to be a linear combination of $\cos \alpha$ and $\sin \alpha \cos \vartheta$ where $\cos \alpha \hookrightarrow r_1^2-r_2^2$ and $\sin \alpha \cos \vartheta \hookrightarrow 1-\frac{r_{12}^2}{r_1^2+r_2^2}$. Here $R^{1/2}\cos(\alpha/2)$ and $R^{1/2}\sin(\alpha/2)$ are equal to $r_1$ and $r_2$ respectively, while $r_{12}$ is equal to $R^{1/2}\sqrt{(1-\sin\alpha\cos\vartheta)}$.

It is hard to fit the Fock form coherently into the Bartlet et al. formulation of an $ Ansatz$ for the Schrödinger Equation's possible solution.

The idea that the coëfficients of $\psi_{2,1} $ are a linear combination of $\sin \alpha \sin \vartheta$ and $\cos\alpha$ is worrisome, as $\cos{\alpha}$ is an odd function of $r_1$ and $r_2$ and the ground state of 2-electron systems should be even with respect to these two variables. If the coëfficient of $\cos \alpha$ in $\psi_{2,1} $ is indeed zero, then $\psi_{2,1} =\frac{ r_1^2+r_2^2 - r_{12}^2}{r_1^2+r_2^2}$.

The $Ansatz$

The following expansion is proposed: \begin{eqnarray} 1 + C_{1,0,0}r_1 + C_{0,1,0}r_2 + C_{0,0,1}r_{12} + \nonumber \\ +C_{1,1,0}r_1r_2 + C_{1,0,1}r_1r_{12} + C_{0,1,1}r_2r_{12}+ \\ \nonumber constant* \left ( r_1r_{12}\ell n r_1r_{12} + r_2r_{12}\ell n r_2r_{12} \right ) +\dots \label{eqone} \end{eqnarray} as the first few terms. The last term shown in (Eqn. 1) mitigates the Bartlett, Gibbons and Dunn conundrum. This suggests the following $Ansatz$: \begin{eqnarray} \psi = \sum_{i,j,k,\ell}C_{i,j,k,\ell}r_1^ir_2^jr_{12}^k \left [ \left (r_1r_{12} \ell n r_1r_{12} \right)^\ell + \left (r_1r_{12} \ell n r_2r_{12} \right)^\ell \right ] \end{eqnarray} (with restrictions on $i,j,k$ and $\ell$), but it fails the Bartlett Gibbons and Dunn criterion. Instead, the following is proposed: \begin{eqnarray} \psi = \sum_{i,j,k=0}C_{i,j,k,0}r_1^ir_2^jr_{12}^k \nonumber \\ + \sum_{\{i,j,k\}=0,\ell=1}C_{i,j,k,\ell}r_1^ir_2^jr_{12}^k \left ( r_1r_{12}\left ( \ell n r_1r_{12} \right)^\ell + r_2r_{12} \left ( \ell n r_2r_{12} \right)^\ell \right ) \label{ansatz} \end{eqnarray} with $C_{0,0,0,0}=1$.

The Hamiltonian and Leading Terms in the Expansion

The Hamiltonian Operator used in the best calculation to date ( H. Nakashima and H. Nakatsujja, J. Chem. Phys. 127, 224104 (2007).) applicable to the ground state of the Helium-like atom's/ion's two electrons is: \begin{eqnarray} -\frac{1}{2 } \left ( \frac{1}{r_1^2} \frac{\partial \left (r_1^2\frac{\partial}{\partial r_1}\right ) }{\partial r_1} + \frac{1}{r_2^2} \frac{\partial\left ( r_2^2\frac{\partial}{\partial r_2}\right ) }{\partial r_2} \right )- \frac{1}{r_{12}^2} \frac{\partial\left ( r_{12}^2\frac{\partial}{\partial r_{12}}\right ) }{\partial r_{12}} \nonumber \\ - \frac{r_1^2-r_2^2+r_{12}^2}{2r_1r_{12}} \frac{\partial^2}{\partial r_{1}\partial r_{12}} - \frac{r_2^2-r_1^2+r_{12}^2}{2r_2r_{12}} \frac{\partial^2}{\partial r_{2}\partial r_{12}} \nonumber \\ -\frac{Z}{r_1} -\frac{Z}{r_2} +\frac{\lambda}{r_{12}} \label{ham} \end{eqnarray} where $\lambda = 1$ and $Z$ is the atomic number of the nucleus.

Substituting our $Ansatz$ into the Hamiltonian of the Schrödinger Equation $H\psi=E\psi$ and setting coëfficients to zero sequentially, we obtain $C_{1,0,0,0}=C_{0,1,0,0} = -Z$, and $C_{0,0,1,0}= \lambda /2$ as expected.

Results and Discussion

Table 1, Sequential coëfficients
Term Coëfficient
$\frac{r_1^2}{r_2r_{12}}$ $ C_{1,0,1,0}= -2*(C_{0,0,0,1}+C_{0,0,0,2})$
$\frac{r_2^2}{r_1r_{12}}$ $ C_{0,1,1,0}= -2*(C_{0,0,0,1}+C_{0,0,0,2})$
$\frac{1}{r_1}$, $\frac{1}{r_2}$ $C_{1,1,0,0}=Z^2$
$\frac{r_2^2\ell n(r_1r_{12})}{r_1r_{12}}$, $\frac{r_1^2\ell n(r_2r_{12})}{r_2r_{12}}$ $C_{0,0,0,1}=-(4C_{0,0,0,2}+6C_{0,0,0,3}) $
$\frac{r_2r_{12}}{r_1}$, $\frac{r_1r_{12}}{r_2}$ $C_{1,1,1,0}=-(12ZC_{0,0,0,2}+24ZC_{0,0,0,3})/3$
$\frac{r_{12}}{r_1}$,$\frac{r_{12}}{r_2}$ $ C_{0,0,0,2}=2(Z\lambda/2+3C_{0,0,0,3})$
Table 1 indicates the beginning sequence of coëfficients determined sequentially substituting terms of the expansion of the wave function $Ansatz$ (Eqn. \ref{ansatz}) into the Hamiltonian (Eqn. \ref{ham}) of the Schrödinger equation.

Demurral

The continuation of developments with respect to coëfficient recursion relationships, variational calculations based on wave function choices shaped by the results shown here, and the ultimate finding of simple functional forms for which this series is the expansion, exceeds the ability and timeline of the author.

It is not apparent what sequence one needs to solve the succeeding equations.


However, approximate calculations which include logarithmic terms such as those indicated above, should allow smaller expansions with increased accuracy and a well defined path for improvement. It is worth noting that literature statements that equate more accurate energy values (to more digits) to more accurate wave functions is not, in fact, true. The contrary is expected to be true however, i.e., the more accurate the wave function the better the eigenenergy.

Acknowledgements

The mathematics employed herein was done in part using SageMath/CoCalc.

SageMath/CoCalc code

code
Send email

Thursday, December 2, 2021

Navigator

The Navigator Object

The appName property returns the application name of the browser:

Strange enough, "Netscape" is the application name for IE11, Chrome, Firefox, and Safari.

Wednesday, October 20, 2021

Computer Assisted Learning revisited

Web pages devoted to problems which are clones of hard copy pages, are just as likely to be successful in enhancing learning as their predecessors, i.e., not very effective. Learning from the written word is not part of current dogma, hence teachers, tutors, etc..


Videos of chalk boards should be as effective as lectures in affecting learning i.e., not very effective. Passive web instruments are little better than last century text books in enhancing self learning. Passive web instruments are little better than lectures. 


Pedagogically, one should be searching for problems on web pages which require reader input to achieve solutions, with instantaneous grading of student inputs, and possible help in overcoming error inputs. Interactive web pages make the motivated learner learn, while leaving the unmotivated learner in stupid city. 


Those interactive web pages that exist are primarily multiple-choice queries, a scheme invented to ease the burden of hand grading examinations, and not subject to part credit variances in grading schemes. But multiple-choice responses warp the thinking of students, i.e., enhance gamesmanship, and rarely guarantee that students know what they claim to know. In a world which never presents multiple-choice problems to anything in reality, training children to pass such examinations is tantamount to malpractice. 


Clearly, constructed responses are preferable to multiple choice ones, as they offer no subliminal hints concerning the “right” answer. Constructed response questions are the closest thing to perfect assessment tools as exist. 


Using cgi-bin programming (in my case using Perl, and chemistry examples), I have created pages and pages of constructed response questions in physical chemistry and freshman chemistry including some  new chemical equilibrium problems which illustrate the constructed response question approach. These examples are just the tip of the iceberg, as better handling of potential student incorrect responses offers unlimited possibilities for improvement. See:

https://chemphys.uconn.edu/~chem12x/cgi-bin/sophiakp1a.pl

and

https://chemphys.uconn.edu/~chem12x/cgi-bin/sophiakp2.pl


At this time of the covid remote learning environment we have exactly the right time to create tools for self learning which will enhance future self learning especially when our students have left school. No graduates/adults can expect teachers to answer their questions and grade their learning. Adulthood demands a modus operandi of self learning and self validation of learning which far exceeds what is available today. 


These ideas are offered in the hope of encouraging Computer Assisted Learning as a primary way of using remote on-line STEM instruction for interactive problem solving everywhere in the quantitative domain. 


For web authors of teaching materials who have public_html access but not cgi-bin access, php alternatives to Perl should be easy to develop. My attempt is currently underway.

Tuesday, November 10, 2020

Sophiakp1.pl source code

Sophiakp1.pl; constructed response Kp problem source code

This is the code for one of the chemical equilibrium problems presented on the web site: https://chemphys.uconn.edu/~chem12x/cgi-bin/sophiakp1.pl. It goes without saying (althought it is being said) that I am not a professional programmer, and that therefore the code presented is not a template. It is loaded with debugging detrious which may or may not be relevant.

The purpose of releasing the code is to suggest a scheme whereby a professional programmer can create computer assisted learning modules. S/he should regard the following lines as an effort to suggest approaches, rather than a prescription.

The code is centered on CGI.pm, which has been declared obsolete by Perl authors and managers. I have yet to find a substitute for CGI.pm for allowing perl code to be included in web forms in a transparent manner, and suggest that anyone preparing to use the following code as a suggeestion, should have his/her system administratopr install CGI.pm, since it is no longer included in the standard Perl library.

To make it abundently clear, CGI.pm allows one to write Perl code, which resides in the executable directory public_html/cgi-bin/ on a standard Unix server of web pages. The public_html directory contains (HTML sourced) web pages which can be loaded directly, while Perl programs located in cgi-bin need to be executed.

We start with the preliminary code:

#!/usr/local/bin/perl -- -*-perl-*-
#
# This is sophiakp1(Computer Assisted Learning, CAL1)
#
require  "CleanUp.pl";
require "top.pl";
require "JSCRIPT.js";
use CGI;
use CGI qw/:standard *table start_ul/;
use CGI::Carp qw(fatalsToBrowser);
#
use CAT2p4pchem;
use CGRutils3;
use lib '/home/cdavid/perl5/lib/perl5';
use Mail::Mailer;

$query = new CGI;
$qCAT = new CAT2p4pchem;
$qCGR = new CGRutils3;
$debug = 1;# set to zero to remove print statements

The real work starts here

$first = 1;#ignore box check first time
prin
print $query-&header;
$title = "Sophia's K<sub>p</sub> I. C. E. page";
print $query-&start_html($title);

$global_debug="false";
srand;
top();
$redz = "<font color=red>z</font>";
print "<h1>$title</h1>";
$scriptname = $query->script_name();#this gives the question name

$rnoby3 = $qCAT->rno(3)/3;
$temp_rno = $qCAT->rno(3)/3;
$qCAT->save_vars($query,'rnoby3',\$rnoby3);#save list for this variable
$qCAT->save_vars($query,'temp_rno',\$temp_rno);#save list for this variable

We have defined peripheral constants and we are ready to start the form which will be used to

  1. get the student's e-mail address, which we use to lock the screen until something is given,
  2. create the Perl variables for the problem at hand,
  3. state the problem,
  4. accept a student's response.

print $query->start_form();
$student_id = "?";
print <<EOD;
Messages for the author concerning errors, mistakes, bad grammar, etc., can be sent
<a href="mailto:my.name\@uni.edu?subject=Sophiakp1%comment.">to my.name\@uni.edu using your own mail handler.</a> .
EOD
print "<hr>";

$var11 = 10*$qCAT->rno(3)+5;#create random number with two digits behind decimal point
$qCAT->save_vars($query,'var11',\$var11);#save list for this variable
$var12 = 10*$qCAT->rno(3)+$var11;#create random number with two digits behind decimal point
$qCAT->save_vars($query,'var12',\$var12);#save list for this variable
$var13 = 10*$qCAT->rno(3)+$var12;#create random number with two digits behind decimal point
$qCAT->save_vars($query,'var13',\$var13);#save list for this variable


$var11string = sprintf "%5.2f", $var11;
$var12string = sprintf "%5.2f", $var12;
$var13string = sprintf "%5.2f", $var13;
$var21 = "2*z";
$var23 = "-2*z";
$var31 = $var11string."+2*z";
$var32 = $var12string."+z";
$var33 = $var13string."-2*z";


$varz = $var13*$qCAT->rno(3)/3;
$qCAT->save_vars($query,'varz',\$varz);#save list for this variable
$varzstring = sprintf "%5.2f", $varz;
$answerKpusingQp = Qp(($var13-2*$varz), ($var11+2*$varz),($var12+$varz));
$error = 0;
$student_id = "?";
print "To unlock this page, please enter your e-mail address:",  $query->textfield( -name=>'student_id',-default=>'?',-size=>40,-maxlength=>50);
$qCAT->save_vars($query,'student_id',\$student_id);#save
print <<EOF;
<br>
The equilibrium constant for the reaction of NO(g) with O<sub>2</sub>(g) to
form NO<sub>2</sub>(g) is unknown.
EOF

The following code gives the Kp expression as long as this site (sciweavers)  stays alive.

print <<EOF;
<center>
<img src="http://www.sciweavers.org/tex2img.php?eq=NO%28g%29%20%2B%20%0A%20%5Cfrac%7B1%7D%7B2%7DO_2%28g%29%20%5Crightleftharpoons%0ANO_2%28g%29%20&bc=White&fc=Black&im=jpg&fs=12&ff=arev&edit=0" align="center" border="0" alt="NO(g) +  \frac{1}{2}O_2(g) \rightleftharpoonsNO_2(g) " width="221" height="43" />
</center>
In a recent experiment,  the initial pressure of NO(g) was $var11, while the initial pressure of
O<sub>2</sub>(g) was $var12, and the initial pressure of NO<sub>2</sub>(g) was
$var13.
Please fill in the following tableau (remember to include the '*' sign when multiplying): 
EOF

We've stated the problem (at least part of it) and now we are going to switch from text to a table, i.e., use HTML explicitly. Here is where the discussion of separating the HTML from the Perl makes no sense to me. The HTML flows perfectly, and templating it makes no sense, since the next problem will require a different kind of table, with its own coding.

The tableau code follows, with the table entries indicating the box indexing scheme which will be lost as the student fills in the boxes. Perhaps coding these (x,y) couples into the table with persistence, would be preferable, but this works as the simplest way of beginning.

print  "<center>";
print table({-border=>undef},
  caption('I.C.E. Table'),
  Tr({-align=>'CENTER',-valign=>'TOP'},
    [
    th(['', 'P<sub>NO</sub>','P<sub>O<sub>2</sub></sub>','P<sub>NO<sub>2</sub></sub>']),
    td(['Initial' ,
      $query->textfield( -name=>'box11',
        -default=>'1,1',
        -size=>5,
        -maxlength=>7
      ),
      $query->textfield(-name=>'box12',
        -default=>'1,2',
        -size=>5,
      -maxlength=>7),
      $query->textfield(-name=>'box13',
        -default=>'1,3',
        -size=>5,
      -maxlength=>7),
    ]),
    td(['Change' ,
      $query->textfield(-name=>'box21',
        -default=>'2,1',
        -size=>5,
      -maxlength=>7),
      $redz,
      $query->textfield(-name=>'box23',
        -default=>'2,3',
        -size=>5,
      -maxlength=>7),
    ]),
    td(['Equilibium'   ,
      $query->textfield(-name=>'box31',
        -default=>'3,1',
        -size=>5,
      -maxlength=>9),
      $query->textfield(-name=>'box32',
        -default=>'3,2',
        -size=>5,
      -maxlength=>9),
      $query->textfield(-name=>'box33',
        -default=>'3,3',
        -size=>5,
      -maxlength=>9)
    ])
  ] )
);

When the submit button is pressed, the contents of the boxes are assigned to Perl variables:

$ans11 = $query->param('box11');
$ans12 = $query->param('box12');
$ans13 = $query->param('box13');
$ans21 = $query->param('box21');
$ans22 = $query->param('box22');
$ans23 = $query->param('box23');
$ans31 = $query->param('box31');
$ans32 = $query->param('box32');
$ans33 = $query->param('box33');

#begin judging box answers:
if($query->param('student_id') ne "?"){

In order to unlock the screen, we force the "?" to have been changed.

Then each box is checked and the error messages printed.

  if (grade_student_txt_against_correct($ans11,$var11,"Does not seem right ","z") == 0){
    print "<br>box 1,1 appears to be wrong";
    $error = 1;
  }else{print"box 1,1 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans12,$var12,"Does not seem right ","z") == 0){
    print "<br>box 1,2 appears to be wrong ";
    $error = 1;
  }else{print"box 1,2 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans13,$var13,"Does not seem right ","z") == 0){
    print "<br>box 1,3 appears to be wrong ";
    $error = 1;
  }else{print"box 1,3 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans21,$var21,"Does not seem right ","z") == 0){
    print "<br>box 2,1 appears to be wrong ";
    $error = 1;
  }else{print"box 2,1 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans23,$var23,"Does not seem right ","z") == 0){
    print "<br>box 2,3 appears to be wrong ";
    $error = 1;
  }else{print"box 2,3 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans31,$var31,"Does not seem right ","z") == 0){
    print "<br>box 3,1 appears to be wrong ";
    $error = 1;
  }else{print"box 3,1 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans32,$var32,"Does not seem right ","z") == 0){
    print "<br>box 3,2 appears to be wrong ";
    $error = 1;
  }else{print"box 3,2 appears to be right <br>";}
  if (grade_student_txt_against_correct($ans33,$var33,"Does not seem right ","z") == 0){
    print "<br>box 3,3 appears to be wrong ";
    $error = 1;
  }else{print"box 3,3 appears to be right<br> ";}
  $first = 0;#enable box checking
#
  print "<hr>";
  
  
  $ans11 = $query->param('box11');
  $ans12 = $query->param('box12');
  $ans13 = $query->param('box13');
  $ans21 = $query->param('box21');
  $ans22 = $query->param('box22');
  $ans23 = $query->param('box23');
  $ans31 = $query->param('box31');
  $ans32 = $query->param('box32');
  $ans33 = $query->param('box33');
  $NO2_eq = $ans13-2*$varz;
  $NO_eq = $ans11+2*$varz;
  $O2_eq = $ans12+$varz;
# NO_2 then NO and then O_2
  $Kp_correct = &Qp($NO2_eq,$NO_eq,$O2_eq);
  $ans = $Kp_correct;

When all boxes are correct, we present the real problem.

  if ($error == 0) {
    print "<br>If the value of  $redz  = $varzstring , what is the value of
    K<sub>p</sub>?  ";
#=========start
    my $ret = $qCAT->qnd($query,'t0',$ans,2,$filename,'');#to be extended

Above is the request for a student numerical answer. The function qnd is a 3 significant figure comparer.  $qCAT points at CAT2p4pchem.pm which contains a set of support subroutines that are commonly used in this kind of work. The text for CAT2p4pchem.pm is included in these posts elsewhere.

    if($ret == 0){ #here if answer wrong
      print "<img src=../icons/RAIN_LINE.gif>";
      print "
      <br>Do you want to see how this problem is done (or at least a hint)?
      If so, please check this box (and resubmit) ",$query->checkbox('to')," enable this feature.
      ";

The text of help, is solely in the programmer's discretion.

      if ($query->param('to') eq 'on'){
        print <<EOF;
        <br>
        Once the boxes are correctly filled in, the
        the equilibrium pressure of NO<sub>2</sub> = $NO2_eq,
        the equilibrium pressure of NO = $NO_eq,
        and the equilibrium pressure of O<sub>2</sub>  = $O2_eq.
        Knowing $redz one can compute these values, and substitute them into
        the K<sub>p</sub> expression to finish the problem.
EOF
      }
      
    }
    else {
#here if answer right

Again, when the student gets the answer correct, the programmer can "reward" him/her as s/he sees fit. In our case here, while the question is being circulated in a campaign to get Perl based cgi-bin modules to be added to all computer assisted learning modules, the "reward" text is aimed at educators rather than students.

      print "Great";
      print <<EOF;
      <br>This is the ultimate formulation of computer assisted learning that I can produce.
      It offers no help whatsoever in terms of filling in the boxes in the tableau, but tells students when they are wrong.
      Suggestions about interventions when students make mistakes would certainly be appreciated.
EOF
$student_id = $query->param('student_id');
    print "<br><img src=../icons/RAIN_LINE.gif><br>";

When the student gets the right answer, the programmer needs to record this event. This can be done by adding remarks to a database of student activity, (as one `can record wrong responses, for analysis and improvement purposes).

In this case, I wanted to monitor whether or not anyone (i.e., an educator visiting the site) had actually carried out the computation required to finish the problem, hence the use of an e-mail to me.

    $mailer = new Mail::Mailer;
    $email = 'carl.david@uconn.edu';
    $mailer->open( {
        To       => $email,
        From     => 'The Webmaster <chem12x@chemphys.uconn.edu>',
        Subject  => 'Web Site Feedback using Mail::Mailer'
    } );
    
    print $mailer <<END_OF_MESSAGE;
    This is the Mail::Mailer message sent by $student_id using the page $scriptname.
END_OF_MESSAGE
    };
  }
}
$first = 0;
$qCAT->save_vars($query,'first',\$first);#save list for this variable
print $query->submit;

print $qusery->end_form;

This calculator (below) can easily be omitted.

&JSCRIPT();
print $query->end_html;


This is specific to the chemistry problem.

sub Qp{
# NO_2 then NO and then O_2
#print "dump  = ";print Dumper(@_);print "<br>";
  
  return(($_[0])/(($_[1])*sqrt($_[2])));
}

This is a constructed response evaluating subroutine, which in our case is being used for the box fillin section of the problem.

sub grade_student_txt_against_correct
#note no input in this subroutine
# calling sequence, required!!!!!
{
#      my ($query) = $_[1];# this seems to work only in the newer version of CGI.pm
# this is a subroutine which gets a query, an answer, a student answer, and a list
# of variables and returns 1 (True) if the student answer is OK, and 0 (False) otherwise.
#      my $q = $_[2];#passing unique textual identifier
#
  $total_args = scalar(@_);
  
  my $student = $_[0];#passing a student answwer
  my $correct = $_[1];#passing the correct answer
  my $error_response = $_[2];#response for a wrong answer
  my $variables1 = $_[3];#passing list of variables
  my $dump = 0;
  $variables = $variables1;
#print "<br>inside subroutine, global_debug = $global_debug";
  if ( $global_debug eq "true"){$dump = 1};
  if($dump){
    print "<br> total_args = $total_args";
    print "<br> student = $student";
    print "<br> correct = $correct";
    print "<br> variables = $variables";
  }
#      if ($query->param($q)ne ''){
  my $ans1 = $student;
  
  my $saved_stu_ans1 = $ans1;
  if($dump){
    print "<br> ans1 = $ans1";
    print "<br> saved_stu_ans1= $saved_stu_ans1";
  }
  $escape = '?!';
  if(substr($ans1,0,length($escape)) eq $escape){print "<br> test mode, answer expected = $correct";}
  
  &CleanUp($ans1);
  &CleanUp2($ans1);#someone else's attempt, lost reference
  &CleanUp($correct);
  if($dump){
    print "<br> ans1 (after CleanUp)   = $ans1";
    print "<br> saved_stu_ans1 (after CleanUp)  = $correct";
  }
  $var = $variables1;
  if($dump){
    print "<br> substitution variable var = $var";
  }
  $rno = 1+rand();
  $ans1 =~ s/$var/$rno/gi;
  $correct =~ s/$var/$rno/g;
  if($dump){
    print "<br> rno = $rnob";
    print "<br> after substitution variable var = $var";
    print "<br> after a cycle of substitutions, ans1 = $ans1, and correct = $correct";
  }
  if($dump){
    print "<br> criterion = ",abs(eval($correct)-eval($ans1));
    print "<br> correct = ",eval($correct);
    print "<br> ans1 = ",eval($ans1);
  }

This is the core of the scheme. The expressions, with the same random variable in both the student's and the author's answer are compared.

  if(abs(eval($correct) -eval( $ans1)) < 0.0001){
    print "<img src=../icons/check.gif>";
    return 1
  }
  else{
    print "<br><img src=../icons/checkno.gif>";
#print "<br>You did not submit a correct answer.<br>";
    print $error_response;
    return 0
  }
#      }#end of if param
  if($global_debug eq "true"){ $dump = 0; $global_debug = "false"};
}#end of subroutine  grade_student_txt_against_correct

sub CleanUp2{#Author's name and address unfortunately lost. Not my code.
  $_ = shift;
  s/\-+(.*)/\1/g;
  s/(.*)[ \t]+\-(.*)/\1\2/g;
  tr/\$\'\`\"\<\>\/\;\!\|/_/;
  return($_);
}


The above code, along with libraries found here, is sufficient to get a programmer started on coding Computer Assisted Learning/Testing materials in any STEM subject. 


 That the work is harder than composing passive html pages is obvious. I have failed repeatedly over the past 20 years in interesting anyone in doing this, despite papers written, examples displayed, and blog posts/linkedin/facebook propaganda intended to incite someone, anyone, to join in rigorizing STEM education.


As usual, the mathematicians are ahead of us;   ixl.com is a site offering constructed math problems.

Our offering is https://chemphys.uconn.edu/~chem12x/cgi-bin/sophiakp1.pl which is one of several of these problems which illustrate how rigorous CAT/L is. The last of them in essence presents a spreadsheet to the student for exploration of the approach to equilibrium:https://chemphys.uconn.edu/~chem12x/cgi-bin/sophiakp2.pl. These are freshman chemistry specific, but illustrative of what can be done.

https://chemphys.uconn.edu/~cdavid/book.html is a site with Perl code, intended to teach how to write CAT/L programs on the web for teachers.