Mutually orthogonality of the wave functions - Armadillo - c++

Not sure if this is the best place to ask this.
So I'm trying to study the orthogonality of the wave function solutions by calculating the Integral of the product of two solutions of different orders m and n. Now I get to the part where I have to do the product of 2 Hermite matrices of different dimensions, which I can't mathematically perform, one being 3x20 and the other one 4x20. Is there a way around this?
arma::mat Orthonormality::gaussHermiteG(int n, int m, arma::mat Z)
{
Miscellaneous misc;
Calcul *caln = new Calcul(n,Z);
Calcul *calm = new Calcul(m,Z);
double f1;
arma::mat Hnm;
arma::mat res;
f1 = (1 / std::sqrt(std::exp(n * std::log(2)) * misc.factorial(n))) * (1 / std::sqrt(std::exp(m * std::log(2)) * misc.factorial(m))) * std::sqrt(1 / M_PI);
Hnm = caln->calculPolynomeHermite() % calm->calculPolynomeHermite();
res = f1 * Hnm;
return res;
}
Here's my function for getting the quadrature. It this the way to prove the orthogonality, or am I doing it wrong?
long double Orthonormality::quadrature(int n, int m)
{
arma::mat gx;
arma::mat gauss_point = {{
-2.453407083009012499038365306336166239661e-1,
2.453407083009012499038365306336166239661e-1,
-7.374737285453943587056051442521042290772e-1,
7.374737285453943587056051442521042290772e-1,
1.234076215395323007885818346959410229585,
-1.234076215395323007885818346959410229584,
-1.738537712116586206780865662136406442958,
1.738537712116586206780865662136406442953,
2.254974002089275523082333344734565128082,
-2.254974002089275523082333344734565128065,
-2.788806058428130480525033756403185410695,
2.788806058428130480525033756403185410655,
3.347854567383216326914924522996463698566,
-3.347854567383216326914924522996463698495,
-3.94476404011562521037562880052441180715,
3.944764040115625210375628800524411807067,
4.603682449550744273077675248978347585171,
-4.603682449550744273077675248978347585109,
5.387480890011232862016900410681120753981,
-5.387480890011232862016900410681120754003,
}
};
arma::mat gauss_point_weight = {{
4.622436696006100896503286398612081142142e-1,
4.622436696006100896503286398612081142142e-1,
2.866755053628341297196597062280879168236e-1,
2.866755053628341297196597062280879168236e-1,
1.090172060200233200137550335354255770852e-1,
1.090172060200233200137550335354255770846e-1,
2.481052088746361088216495255894039439922e-2,
2.481052088746361088216495255894039440028e-2,
3.24377334223786183218324713235370544232e-3,
3.243773342237861832183247132353705443042e-3,
2.283386360163539672571459179634955394906e-4,
2.283386360163539672571459179634955393512e-4,
7.802556478532063694145991999647569104495e-6,
7.802556478532063694145991999647569095955e-6,
1.086069370769281693999524563447163430255e-7,
1.086069370769281693999524563447163432688e-7,
4.399340992273180553628851455467928211995e-10,
4.399340992273180553628851455467928212879e-10,
2.229393645534151292522500616029095785758e-13,
2.22939364553415129252250061602909578525e-13,
}
};
gx = Orthonormality::gaussHermiteG(n, m, gauss_point);
arma::mat res;
res = gx * gauss_point_weight.t();
long double resDouble = res(0, 0);
return resDouble;
}
Here's the Hermite Polynomial function and its output for the 3 an 4 modes:
mat Calcul::calculPolynomeHermite(int n_max, mat z)
{
mat H(n_max, z.n_elem);
if (n_max == 0)
{
H = z.ones(size(z));
}
else
{
if (n_max == 1)
{
return z.for_each([](arma::mat::elem_type& val)
{
val = 2 * val;
});
}
else {
for(int i = 0; i < z.n_elem; ++i)
{
H(0, i) = 1;
}
rowvec h2 = rowvec(z.n_elem);
h2 = 2 * z;
H.row(1) = h2;
for(int i = 2; i < n_max; i++)
{
rowvec hn = rowvec(z.n_elem);
hn = h2 % H.row(i - 1) - (2 * i) * H.row(i - 2);
H.row(i) = hn;
}
}
}
return H;
}
output :
H(3,z):
1.0000 1.0000 1.0000 1.0000 1.0000
-4.0000 -2.0000 0 2.0000 4.0000
12.0000 0 -4.0000 0 12.0000
H(4,z):
1.0000 1.0000 1.0000 1.0000 1.0000
-4.0000 -2.0000 0 2.0000 4.0000
12.0000 0 -4.0000 0 12.0000
-24.0000 12.0000 0 -12.0000 24.0000

Related

Can this Iron Python 2.7 code be sped up?

I have implemented Gray-Scott reaction diffusion in Iron Python 2, mapping grayscale values between 0 and 1.
But since it only gets interesting from about 6400 steps, it takes a lot of time.
So can someone smarter / more proficient in Python than me help me make this code more efficient?
Here is the code:
import random as rnd
dA = 1
dB = 0.5
feed = 0.055
kill = 0.062
wHalb = int(width/2)
hHalb = int(height/2)
#decides if gAA is random or 1
if gAA == 0:
gAA = rnd.random()
def main():
#create base grid of chemical A and B
gridA = [ [gAA for i in range(width)] for i in range(height)]
gridB = [ [0 for i in range(width)] for i in range(height)]
nextA = [ [1 for i in range(width)] for i in range(height)]
nextB = [ [0 for i in range(width)] for i in range(height)]
color = [ [0 for i in range(width)] for i in range(height)]
for x in range (wHalb-baseBlock,wHalb+baseBlock):
for y in range (hHalb-baseBlock,hHalb+baseBlock):
gridB[x][y] = 1
x, y, i, j = 0, 0, 0, 0
for n in range(steps):
for x in range (width):
for y in range (height):
a = gridA[x][y]
b = gridB[x][y]
nextA[x][y] = (a + (dA * laplaceA(x, y, gridA)) - (a * b*b) + (feed * (1 - a)))
nextB[x][y] = (b + (dB * laplaceB(x, y, gridB)) + (a * b*b) - ((kill + feed) * b))
tempA = gridA
gridA = nextA
nextA = tempA
tempB = gridB
gridB = nextB
nextB = tempB
color = [ [(nextA[i][j] - nextB[i][j]) for i in range(width)] for j in range(height)]
return color
def laplaceA(x, y, gridA):
sumA = 0;
xS = x - 1
xE = x + 1
yS = y - 1
yE = y + 1
if (x == 0):
xS = width-1
if (y == 0):
yS = height-1
if (x == width - 1):
xE = 0;
if (y == height - 1):
yE = 0;
sumA = sumA + gridA[x][y] * -1
sumA = sumA + gridA[xS][y] * 0.2
sumA = sumA + gridA[xE][y] * 0.2
sumA = sumA + gridA[x][yE] * 0.2
sumA = sumA + gridA[x][yS] * 0.2
sumA = sumA + gridA[xS][yS] * 0.05
sumA = sumA + gridA[xE][yS] * 0.05
sumA = sumA + gridA[xS][yE] * 0.05
sumA = sumA + gridA[xE][yE] * 0.05
return sumA
def laplaceB(x, y, gridB):
sumB = 0
xS = x - 1
xE = x + 1
yS = y - 1
yE = y + 1
if (x == 0):
xS = width-1
if (y == 0):
yS = height-1
if (x == width - 1):
xE = 0
if (y == height - 1):
yE = 0
sumB = sumB + gridB[x][y] * -1
sumB = sumB + gridB[xS][y] * 0.2
sumB = sumB + gridB[xE][y] * 0.2
sumB = sumB + gridB[x][yE] * 0.2
sumB = sumB + gridB[x][yS] * 0.2
sumB = sumB + gridB[xS][yS] * 0.05
sumB = sumB + gridB[xE][yS] * 0.05
sumB = sumB + gridB[xS][yE] * 0.05
sumB = sumB + gridB[xE][yE] * 0.05
return sumB
aOut = main()

Wrong uv in ray tracer

I have a problem with my ray tracer program. The image looks wrong. Here is the output image:
Barycentric coordinates and collision calculation codes are as follows:
bool CTriangle::Intersect(Calculus::CRay& ray, CIntersection* isect) const {
// Möller–Trumbore intersection algorithm
const Calculus::CPoint3<float>& p1 = v_points[0];
const Calculus::CPoint3<float>& p2 = v_points[1];
const Calculus::CPoint3<float>& p3 = v_points[2];
Calculus::CVector3<float> e1 = p2 - p1;
Calculus::CVector3<float> e2 = p3 - p1;
Calculus::CVector3<float> s1 = Calculus::Math::Cross(ray.direction, e2);
float determinant = Calculus::Math::Dot(s1, e1);
if (determinant == 0.0f)
return false;
float inv_determinant = 1.0f / determinant;
Calculus::CVector3<float> s = ray.origin - p1;
float b1 = Calculus::Math::Dot(s, s1) * inv_determinant;
if (b1 < 0.0f || b1 > 1.0f)
return false;
Calculus::CVector3<float> s2 = Calculus::Math::Cross(s, e1);
float b2 = Calculus::Math::Dot(ray.direction, s2) * inv_determinant;
if (b2 < 0.0f || b1 + b2 > 1.0f)
return false;
float b0 = 1 - b1 - b2;
float thit = Calculus::Math::Dot(e2, s2) * inv_determinant;
if (thit < ray.mint || thit > ray.maxt)
return false;
isect->p = ray(thit);
isect->n = Calculus::Math::Normalize(Calculus::CVector3<float>
(v_normals[0].x, v_normals[0].y, v_normals[0].z) * b0 +
Calculus::CVector3<float>(v_normals[1].x, v_normals[1].y,
v_normals[1].z) * b1 +
Calculus::CVector3<float>(v_normals[2].x, v_normals[2].y,
v_normals[2].z) * b2);
isect->uv = v_uvs[0] * b0 + v_uvs[1] * b1 + v_uvs[2] * b2;
isect->tHit = thit;
isect->ray_epsilon = 1e-5f * thit;
return true;
}
Texture i used int the ray trace program:(file type: bmp)
my obj file is as follows. The background shape consists of two triangles. Texture projection is applied only to the background shape:
v -24.1456 -11.1684 -26.2413
v 24.1455 -11.1684 -26.2413
v -24.1456 37.1227 -26.2413
v 24.1455 37.1227 -26.2413
# 4 vertices
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 1.0000
# 6 vertex normals
vt 0.9995 0.0005 0.0000
vt 0.0005 0.0005 0.0000
vt 0.9995 0.9995 0.0000
vt 0.0005 0.9995 0.0000
# 4 texture coords
o back
g back
usemtl default
s 1
f 1/1/1 2/2/2 4/4/3
f 4/4/4 3/3/5 1/1/6
# 2 faces
Here is the interpolated uv draw call.
Here is indexing algorithm, i'm starting from zero:
...
Calculus::CPoint3<unsigned short> p, t, n;
sscanf_s(token, "%hu/%hu/%hu %hu/%hu/%hu %hu/%hu/%hu",
&p.x, &t.x, &n.x, &p.y, &t.y, &n.y, &p.z, &t.z, &n.z);
pi.push_back(p);
ti.push_back(t);
ni.push_back(n);
…
index = ti[i].x - 1;
temp_t[0] = vt[index]; // first uv
index = ti[i].y - 1;
temp_t[1] = vt[index]; // second uv
index = ti[i].z - 1;
temp_t[2] = vt[index]; // third uv
I wonder where I'm making a mistake. Thank you.
isect->uv = v_uvs[0] * b1 + v_uvs[1] * b2;
This is not the correct parametric interpolation of vertex attributes:
The parameters b1, b2 are being applied to the wrong vertices
You are not taking the third vertex v_uvs[2] into account
Correct version:
isect->uv = v_uvs[0] * b0 + v_uvs[1] * b1 + v_uvs[2] * b2;

Implementing 4-dimensional Halton Sequence

The psuedocode for the Halton sequnce can be found here. I wrote a function that does this but for some reason checking the Matlab results for the 4th dimensional Halton sequence my numbers do not match up and I am not sure why. Here is my code:
double Halton_Seq(int index, double base){
double f = 1, r;
while(index > 0){
f = f/base;
r = r + f*(fmod(index,base));
index = index/base;
}
return r;
}
Here are the first 10 results I get:
1
0.25
0.5
0.75
0.0625
0.3125
0.5625
0.8125
0.125
0.375
Here is the first 10 results MATLAB gets:
Columns 1 through 2
0 0.5000
Columns 3 through 4
0.2500 0.7500
Columns 5 through 6
0.1250 0.6250
Columns 7 through 8
0.3750 0.8750
Columns 9 through 10
0.0625 0.5625
You forgot to initialize r in line 2.
r = 0;
double Halton_Seq(int index, int base){
double f = 1, r = 0;
while(index > 0){
f = f/base;
r = r + f* (index% base);
index = index/base;
}
return r;
}
// Output for 10 (base 2)
0.000000
0.500000
0.250000
0.750000
0.125000
0.625000
0.375000
0.875000
0.062500
0.562500

rotation matrix to quaternion (and back) what is wrong?

I copied a code for conversion of 3D roation matrix to quaternions and back. The same code is used in jMonkey (I just rewrote it into my C++ class). However, it does not work properly (at least not as I would expect.)
e.g. I made this test:
matrix (a,b,c):
a : 0.707107 0.000000 0.707107
b : 0.000000 -1.000000 0.000000
c : -0.707107 0.000000 0.707107
>>> ortonormality:
a.a b.b c.c 1.000000 1.000000 1.000000
a.b a.c b.c 0.000000 0.000000 0.000000
>>> matrix -> quat
quat: 0.000000 0.594604 0.000000 0.594604 norm(quat) 0.707107
>>> quat -> matrix
matrix (a,b,c):
a: 0.000000 0.000000 1.000000
b: 0.000000 1.000000 0.000000
c: -1.000000 0.000000 0.000000
I think the problem is in matrix -> quat because I have used quat -> matrix procedure before, and it was working fine. Also it is strange that quaternion made from orthonormal matrix is not unitary.
the matrix -> quat procedure
inline void fromMatrix( TYPE m00, TYPE m01, TYPE m02, TYPE m10, TYPE m11, TYPE m12, TYPE m20, TYPE m21, TYPE m22) {
// Use the Graphics Gems code, from
// ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z
TYPE t = m00 + m11 + m22;
// we protect the division by s by ensuring that s>=1
if (t >= 0) { // by w
TYPE s = sqrt(t + 1);
w = 0.5 * s;
s = 0.5 / s;
x = (m21 - m12) * s;
y = (m02 - m20) * s;
z = (m10 - m01) * s;
} else if ((m00 > m11) && (m00 > m22)) { // by x
TYPE s = sqrt(1 + m00 - m11 - m22);
x = s * 0.5;
s = 0.5 / s;
y = (m10 + m01) * s;
z = (m02 + m20) * s;
w = (m21 - m12) * s;
} else if (m11 > m22) { // by y
TYPE s = sqrt(1 + m11 - m00 - m22);
y = s * 0.5;
s = 0.5 / s;
x = (m10 + m01) * s;
z = (m21 + m12) * s;
w = (m02 - m20) * s;
} else { // by z
TYPE s = sqrt(1 + m22 - m00 - m11);
z = s * 0.5;
s = 0.5 / s;
x = (m02 + m20) * s;
y = (m21 + m12) * s;
w = (m10 - m01) * s;
}
}
the quat -> matrix procedure
inline void toMatrix( MAT& result) const {
TYPE r2 = w*w + x*x + y*y + z*z;
//TYPE s = (r2 > 0) ? 2d / r2 : 0;
TYPE s = 2 / r2;
// compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs
// will be used 2-4 times each.
TYPE xs = x * s; TYPE ys = y * s; TYPE zs = z * s;
TYPE xx = x * xs; TYPE xy = x * ys; TYPE xz = x * zs;
TYPE xw = w * xs; TYPE yy = y * ys; TYPE yz = y * zs;
TYPE yw = w * ys; TYPE zz = z * zs; TYPE zw = w * zs;
// using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here
result.xx = 1 - (yy + zz);
result.xy = (xy - zw);
result.xz = (xz + yw);
result.yx = (xy + zw);
result.yy = 1 - (xx + zz);
result.yz = (yz - xw);
result.zx = (xz - yw);
result.zy = (yz + xw);
result.zz = 1 - (xx + yy);
};
sorry for TYPE, VEC, MAT, QUAT it is part of class tepmpltes... should be replaced by double, Vec3d, Mat3d, Quat3d or float, Vec3f, Mat3f, Quat3f.
EDIT:
I also checked if I get the same behaviour with jMonkey directly (in case I made a bug in Java to C++ conversion ). And I do - using this code:
Matrix3f Min = new Matrix3f( 0.707107f, 0.000000f, 0.707107f, 0.000000f, -1.000000f, 0.000000f, -0.707107f, 0.000000f, 0.707107f );
Matrix3f Mout = new Matrix3f( );
Quaternion q = new Quaternion();
q.fromRotationMatrix(Min);
System.out.println( q.getX()+" "+q.getY()+" "+q.getZ()+" "+q.getW() );
q.toRotationMatrix(Mout);
System.out.println( Mout.get(0,0) +" "+Mout.get(0,1)+" "+Mout.get(0,2) );
System.out.println( Mout.get(1,0) +" "+Mout.get(1,1)+" "+Mout.get(1,2) );
System.out.println( Mout.get(2,0) +" "+Mout.get(2,1)+" "+Mout.get(2,2) );
Your matrix:
matrix (a,b,c):
a : 0.707107 0.000000 0.707107
b : 0.000000 -1.000000 0.000000
c : -0.707107 0.000000 0.707107
is orthogonal but it is not a rotation matrix. A rotation matrix has determinant 1; your matrix has determinant -1 and is thus an improper rotation.
I think your code is likely correct and the issue is in your data. Try it with a real rotation matrix.

How to make a complete matrix with 2 loops in c++

I have a string in c++ and it represents an upper triangular matrix, What I want to do is meake a complete matrix from this string
std::string input = "1,2,1,3,6,1,4,7,9,1";
//this represents
//1 2 3 4
//2 1 6 7
//3 6 1 9
//4 7 9 1
std::replace(input.begin(), input.end(), ',', ' ');
std::vector<double> Matrix;
std::istringstream inputStream(input);
double value;
int rowNum = 0;
int colNum = 0;
while (inputStream >> value){
for (colNum = 0; colNum < 2; colNum++){
if (colNum >= rowNum){
Matrix.push_back( value );
}
else{
Matrix.push_back( Matrix[colNum * 2 + rowNum]);
}
}
rowNum++;
}
inputStream >> std::ws;
Instead of getting
1 2 3 4
2 1 6 7
3 6 1 9
4 7 9 1
But I am getting
1.0000 1.0000 1.0000 2.0000
1.0000 1.0000 2.0000 1.0000
1.0000 2.0000 1.0000 1.0000
2.0000 1.0000 1.0000 2.0000
What is it my error? I can not see it...
You should show the indexing scheme used for printing the output (i.e. how do you expect the indexes works): your choice of using a vector instead of a matrix make hard to correct the code. For sure, I see the following points that have no clear connection with the input pattern:
1) each number you read you increment the rowNum index. The row should be incremented instead at 'steps' 1, 1+2, 1+2+3,...
2) colNum should range from 0 to current rowNum, instead assumes just 0,1
3) there is no chance to fill a row (say the first) before you read (say the last). You could do if the input would be 1 2 3 4 1 6 7 1 9 1
all these points are related, and origin from the wrong data representation, that make difficult a trivial task.
In C++, a very effective way to tackle these problems is data hiding: consider how easily we can write a class that gives the correct logical representation and doesn't waste space:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
template <class T = double>
class upper_triangular_matrix
{
std::vector<T> Matrix;
public:
upper_triangular_matrix(std::string input)
{
// trade time for space: store the values, compute indexing
std::replace(input.begin(), input.end(), ',', ' ');
std::istringstream inputStream(input);
T value;
while (inputStream >> value)
Matrix.push_back(value);
// validate size: ok 1,1+2,1+2+3 etc
}
T operator()(int r, int c) const
{
// compute indexing accounting for miss duplicated
if (c > r)
std::swap(c, r);
int p = 0, n = 1;
while (r > 0)
{
p += n++;
r--;
}
return Matrix[p + c];
}
};
int main()
{
upper_triangular_matrix<> m("1,2,1,3,6,1,4,7,9,1");
for (int r = 0; r < 4; ++r)
{
for (int c = 0; c < 4; ++c)
std::cout << m(r, c) << ' ';
std::cout << std::endl;
}
}
when run, this prints
1 2 3 4
2 1 6 7
3 6 1 9
4 7 9 1
It is hard to tell exactly where the error is but here is where it starts:
std::vector<double> Matrix;
Yes, a non-empty std::vector<double> with n elements is a matrix: either a 1xn or a nx1 matrix (or both). In your context this view is, however, utterly unhelpful.
Let's look at the for-loop when you read the first element:
colNum == 0, rowNum == 0 => (1, 1) = Matrix[0] = 1
colNum == 1, rowNum == 0 => (2, 1) = Matrix[1] = 1
This start is clearly wrong. After this rowNum becomes 1:
colNum == 0, rowNum == 1 => (3, 1) = Matrix[2] = Matrix[colNum * 2 + rowNum] = Matrix[1] = 1
colNum == 1, rowNum == 1 => (4, 1) = Matrix[3] = 2
Well, I guess you can write the remainder up yourself. Of course, I could quickly write the code to solve your problem but I think this little exercise is for you. The way to do it is to fill the first row columns (where row is the current row being processed, using conventional index starting with 0) with the values from the transposed matrix and then read the remaining n - row columns (where n is the size of the matrix) from the file.