The Gaussian Elimination algorithm was taken from the book Gerald, Applied Numerical Analysis, Fifth Edition, Addision-Wesley by downloading it with ftp.
These two functions were taken from the pdec.c program downloaded from the previously mentioned ftp server. The algorithm for Gaussian Elimination is based on the following Applied Numerical Analysis' pseudo-code:
gaussian elimination: to solve a system of n linear
equations: Ax = b
for j = 1 to (n-1)
pvt = abs(a[j,j]);
pivot[j] = j;
for i = j + 1 to n (find pivot row)
if abs(a[i,j]) > pvt
pvt = abs(a[i,j])
ipvt_store = i
end if
end for i
(switch rows if necessary)
if pivot[j] <> ipvt_store then
pivot[j] = ipvt_store
pivot[ipvt_store] = j
for k = 1 to n
temp = a[j,k]
a[j,k] = a[pivot(j),k]
a[pivot(j),k] = temp
end for k
temp = b[j]
b[j] = b[pivot(j)]
b[pivot(j)] = temp
end if
for i = j+1 to n (store multipliers)
a[i,j] = a[i,j]/a[j,j]
end for i
for i = j+1 to n (create zeros below main diagonal)
for k = j+1 to n
a[i,k] = a[i,k] - a[i,j]*a[j,k]
end for
b[i] = b[i] - a[i,j]*b[j]
end for i
end for j
(back substitution part)
x[n] = b[n]/a[n,n]
for j = n-1 downto 1
x[j] = b[j]
for k = n downto j+1
x[j] = x[j] - x[k]*a[j,k]
end for k
x[j] = x[j]/a[j,j]
end for j
Note
No check for singular metrices is included.
float XAMatrixElement(atom_ptr curr_atom, char *orbital_string, int m, double beta)
This function is calculating a matrix element according to the following formulae:
oo j -beta * r
a = integral (P * r * e ) dr
ij 0 i
n -alpha * r
k k k
P = sum (c * r * e )
i k
where i is the shell number of one of the "smaller" orbitals. For example, if you want to create a 3S orbital, then i will have the values 1 and 2.
double** XAMatrix(atom_ptr curr_atom, int dimension, char symbol, double alpha)
XAMatrix builds up the matrix which is necessary for solving the linear equations. A matrix A with (n-1) columns and rows, where n is the shell number of the new orbital, is created by calling the procedure XAMatrixElement for each a_ij.
double *XAVector(atom_ptr curr_atom, int dimension, char symbol, double alpha)
XAVector computes the b vector for the right hand side of the linear equations.
atom_ptr XACreateOrbitalArray(atom_ptr curr_atom, char *orbital_string, double alpha)
This procedure combines all the steps necessary to create a new orbital. To explain these more clearly the following example might be useful:
We want to create a 3S orbital out of an 1S and an 2S orbital. We know:
oo
integral P * P = 0
0 1S 3S
oo
integral P * P = 0
0 2S 3S
oo
integral P * P = 1
0 3S 3S
Let us make the following simplification, that P("3S") is defined as:
-alpha * r
P = c * r * e +
3S 1
2 -alpha * r
+ c * r * e +
2
3 -alpha * r
+ c * r * e
3
where alpha is a previously fixed value. We can use the definition of
P_3S in the first two formulae mentioned above, so we get two linear
equations with three unknown constants c_i. Without loss of generality,
be c_3 equal to 1.0. So we can put
3 -alpha * r
P * r * e
iS
to the right hand side of the equation. For the left hand side XAMatrix is calculated, and the same is done for the right hand side by using XAVector.
By calling XAElim and XASolve the linear equations are solved, the last constant, here c_3, is appended to the solution vector and an array is created which stores all the new values and whose pointer is returned to the calling function.
The next step is to normalize the atom, because we have chosen a fixed c_3 value previously. This is done by calculating
oo
integral P * P
0 3S 3S
which will normally return a value not equal to 1.0. If we divide the new constants by this value, we will get the normalized atom.