This module is currently under development
We will now use the cmdline_helper.py NRPy+ module to create the source directory within the IllinoisGRMHD
NRPy+ directory, if it does not exist yet.
# Step 0: Creation of the IllinoisGRMHD source directory
# Step 0a: Add NRPy's directory to the path
# https://stackoverflow.com/questions/16780014/import-file-from-parent-directory
import os,sys
nrpy_dir_path = os.path.join("..","..")
if nrpy_dir_path not in sys.path:
sys.path.append(nrpy_dir_path)
# Step 0b: Load up cmdline_helper and create the directory
import cmdline_helper as cmd
IGM_src_dir_path = os.path.join("..","src")
cmd.mkdir(IGM_src_dir_path)
# Step 0c: Create the output file path
outfile_path__eigen__C = os.path.join(IGM_src_dir_path,"eigen.C")
In this tutorial notebook we will implement an algorithm to evaluate the eigenvalues of a 3×3 symmetric matrix. Our method will be analytical and will follow closely this discussion.
Let M be a 3×3 symmetric matrix,
M=(M11M12M13M12M22M23M13M23M33) .To obtain the eigenvalues of M, we must solve the characteristic equation
det(λI3×3−M)=0 ,where λ represents the eigenvalues of M and I3×3=diag(1,1,1) is the 3×3 identity matrix. For this particular case, the characteristic equation of M is then given by
λ3−tr(M)λ2+[tr(M2)−tr(M)22]λ−det(M)=0 .Now let M=nN+mI3×3, so that the matrices M and N have the same eigenvectors. Then, κ is an eigenvalue of N if, and only if, λ=nκ+m is an eigenvalue of M. Now, let us look at the following identities:
N=1n(M−mI3×3) .Choosing m≡13tr(M), we get
tr(N)=1n(M−3m)=0 .Also,
tr(N2)=1n2[N211+N222+N233+2(N212+N213+N223)] ,so that if we choose n≡√N211+N222+N233+2(N212+N213+N223)6 we get
tr(N2)=6 .Then, if we look at the characteristic equation for the matrix N,
κ3−tr(N)κ2+[tr(N2)−tr(N)22]κ−det(N)=0 ,we see that it can be greatly simplified with our choices of m and n,
κ3−3κ−det(N)=0 .Further simplification of this characteristic equation can be obtained by using
κ≡2cosϕ ,cos(3ϕ)=4cos3ϕ−3cosϕ ,so that
0=8cos3ϕ−6cosϕ−det(N)=2cos(3ϕ)−det(N)⟹ϕ=13arccosdet(N)2+2kπ3 , k=0,1,2 ,which, finally, yields
κ(k)=2cos(13arccosdet(N)2+2kπ3) .Once we have κ, we can find the eigenvectors of M doing
λ1=m+2nκ(0)λ2=m+2nκ(1)λ3=3m−λ1−λ2 ,where we have used the fact that tr(M)=λ1+λ2+λ3 to compute λ3.
eigen.C
[Back to top]¶eigen.C
[Back to top]¶In the algorithm below, we define the following quantities
K=M−mI3×3m=tr(M)3q=det(K)2p=n2=tr(K2)6 .We these definitions, we have the following quantities to be implemented:
m=(M11+M22+M33)3 .The matrix K is simply
K=(M11−mM12M13M12M22−mM23M13M23M33−m) .Straightforwardly, we have
q=K11K22K33+K12K23K13+K13K12K23−K13K22K13−K12K12K33−K11K23K232 .Since K is symmetric as well, we have
p=K211+K222+K233+2(K212+K213+K223)6 .%%writefile $outfile_path__eigen__C
//
// This subroutine calcualtes the eigenvalues of a real, symmetric 3x3
// matrix M={{M11,M12,M13},{M12,M22,M23},{M13,M23,M33}} based on the
// algorithm described in
// http://en.wikipedia.org/wiki/Eigenvalue_algorithm#Eigenvalues_of_3.C3.973_matrices
// which simply solve the cubic equation Det( M - lamnda I)=0 analytically.
// The eigenvalues are stored in lam1, lam2 and lam3.
//
void eigenvalues_3by3_real_sym_matrix(CCTK_REAL & lam1, CCTK_REAL & lam2, CCTK_REAL & lam3,
CCTK_REAL M11, CCTK_REAL M12, CCTK_REAL M13, CCTK_REAL M22, CCTK_REAL M23, CCTK_REAL M33)
{
CCTK_REAL m = (M11 + M22 + M33)/3.0;
CCTK_REAL K11 = M11 - m, K12 = M12, K13 = M13, K22 = M22-m, K23 = M23, K33=M33-m;
CCTK_REAL q = 0.5* (K11*K22*K33 + K12*K23*K13 + K13*K12*K23 - K13*K22*K13
- K12*K12*K33 - K11*K23*K23);
CCTK_REAL p = ( SQR(K11) + SQR(K22) + SQR(K33) + 2.0*(SQR(K12) + SQR(K13) + SQR(K23) ) )/6.0;
Writing ../src/eigen.C
%%writefile -a $outfile_path__eigen__C
CCTK_REAL phi;
CCTK_REAL p32 = sqrt(p*p*p);
if (fabs(q) >= fabs(p32) ) {
phi = 0.0;
} else {
phi = acos(q/p32)/3.0;
}
if (phi<0.0) phi += M_PI/3.0;
Appending to ../src/eigen.C
%%writefile -a $outfile_path__eigen__C
CCTK_REAL sqrtp = sqrt(p);
CCTK_REAL sqrtp_cosphi = sqrtp*cos(phi);
CCTK_REAL sqrtp_sqrt3_sinphi = sqrtp*sqrt(3.0)*sin(phi);
lam1 = m + 2.0*sqrtp_cosphi;
lam2 = m - sqrtp_cosphi - sqrtp_sqrt3_sinphi;
lam3 = m - sqrtp_cosphi + sqrtp_sqrt3_sinphi;
}
Appending to ../src/eigen.C
# Verify if the code generated by this tutorial module
# matches the original IllinoisGRMHD source code
# First download the original IllinoisGRMHD source code
import urllib
from os import path
original_IGM_file_url = "https://bitbucket.org/zach_etienne/wvuthorns/raw/5611b2f0b17135538c9d9d17c7da062abe0401b6/IllinoisGRMHD/src/eigen.C"
original_IGM_file_name = "eigen-original.C"
original_IGM_file_path = os.path.join(IGM_src_dir_path,original_IGM_file_name)
# Then download the original IllinoisGRMHD source code
# We try it here in a couple of ways in an attempt to keep
# the code more portable
try:
original_IGM_file_code = urllib.request.urlopen(original_IGM_file_url).read().decode("utf-8")
# Write down the file the original IllinoisGRMHD source code
with open(original_IGM_file_path,"w") as file:
file.write(original_IGM_file_code)
except:
try:
original_IGM_file_code = urllib.urlopen(original_IGM_file_url).read().decode("utf-8")
# Write down the file the original IllinoisGRMHD source code
with open(original_IGM_file_path,"w") as file:
file.write(original_IGM_file_code)
except:
# If all else fails, hope wget does the job
!wget -O $original_IGM_file_path $original_IGM_file_url
# Perform validation
Validation__eigen__C = !diff $original_IGM_file_path $outfile_path__eigen__C
if Validation__eigen__C == []:
# If the validation passes, we do not need to store the original IGM source code file
!rm $original_IGM_file_path
print("Validation test for eigen.C: PASSED!")
else:
# If the validation fails, we keep the original IGM source code file
print("Validation test for eigen.C: FAILED!")
# We also print out the difference between the code generated
# in this tutorial module and the original IGM source code
print("Diff:")
for diff_line in Validation__eigen__C:
print(diff_line)
Validation test for eigen.C: FAILED! Diff: 16a17 > 24a26 > 31a34 >
The following code cell converts this Jupyter notebook into a proper, clickable LATEX-formatted PDF file. After the cell is successfully run, the generated PDF may be found in the root NRPy+ tutorial directory, with filename Tutorial-IllinoisGRMHD__eigen.pdf (Note that clicking on this link may not work; you may need to open the PDF file through another means).
latex_nrpy_style_path = os.path.join(nrpy_dir_path,"latex_nrpy_style.tplx")
#!jupyter nbconvert --to latex --template $latex_nrpy_style_path --log-level='WARN' Tutorial-IllinoisGRMHD__eigen.ipynb
#!pdflatex -interaction=batchmode Tutorial-IllinoisGRMHD__eigen.tex
#!pdflatex -interaction=batchmode Tutorial-IllinoisGRMHD__eigen.tex
#!pdflatex -interaction=batchmode Tutorial-IllinoisGRMHD__eigen.tex
!rm -f Tut*.out Tut*.aux Tut*.log