anderkve / FYS3150

https://anderkve.github.io/FYS3150
26 stars 14 forks source link

weird initial state probability at t=0, but otherwise fine for the rest of the timesteps? #25

Closed dondondooooon closed 2 years ago

dondondooooon commented 2 years ago

Im getting a huge spike at the start of my probability, and I can't figure out why... This is by the way for the first time I switched on the double slit wall in the box. (Problem 7 part 2)

image

However, I did get a seemingly correct graph for when the slit was switched off... (Problem 7 part 1)

image image

dondondooooon commented 2 years ago

I do have several speculations, but I don't know which one it is, and I'm afraid to change too much stuff permanently before consulting for help... My biggest speculation as to why im getting this issue is that:

In my c++ program, I use a cube matrix to store the different u_ij for a chosen n. When I initialize this cube matrix (i.e. for the first slice) I add in the potential (including the one from the middle wall in the box where the slit is, if the slit is switched on), before I actually initialize and calculate the inner point matrix U using the gaussian wavepacket function. So I was thinking doesn't this mean that the potential is taken into account here as well? since the high potential slit wall is within the inner points? Thus resulting in perhaps a huge probability at the initial state of the system.

(p.s. unsure if I normalize the function properly in the wavepoint function as well, but im pretty sure I did?)...

Anyways, am I suppose to not add the potential to the cube matrix at all? And just have U in the inner points w/o the potential, whilst my A and B matrix will take the potential into account when updating the points in U?

image

dondondooooon commented 2 years ago

Nvm, i think i found out the problem. for a given time slice, I was plotting the probability of the whole matrix instead of only the inner points of the matrix :))) thus giving a weirdly high spike in probability.

Screen Shot 2021-12-13 at 02 17 27

Though would still like to know if we were meant to add the potential to the cube matrix that we are working with...

anderkve commented 2 years ago

Hi @dondondooooon!

Here are some quick comments:

dondondooooon commented 2 years ago

Yeah, I suspected that V and U are suppose to be seperate from one another, but I made a mistake while coding thinking of how the plotting would look like at the end, and thought of adding in V in the main matrix. Thank you for the help and clarification. :))

I dont quite get what you meant by saving the inner points of U vs. the complete U (including the "border" of boundary points). Is the border in this case just 0s according to the boundary conditions?

Did you also mean to have xc and yc as a double in the range [0,1] (i.e. in a vector) or is it only x and y that needs to be in a vector [0,1]? I thought xc and yc were suppose to be a constant double which represents the coordinates of the centre of the initial wave packet?

anderkve commented 2 years ago

I dont quite get what you meant by saving the inner points of U vs. the complete U (including the "border" of boundary points). Is the border in this case just 0s according to the boundary conditions?

Yep! :) So it doesn't matter too much, but personally I find it easier to not get confused with indices etc (especially in making the final plots) if my programs always store the complete state, regardless of what the boundary conditions happen to be in the given problem.

Did you also mean to have xc and yc as a double in the range [0,1] (i.e. in a vector) or is it only x and y that needs to be in a vector [0,1]? I thought xc and yc were suppose to be a constant double which represents the coordinates of the centre of the initial wave packet?

My point was not that anything had to be in a vector, but that the numbers x, xc, y and yc are all floating-point numbers that live on the domain from 0 to 1 (since this is the coordinate system we decided to work with). You are right that xc and yc are simply constants. The main point was that the bracket (i - xc) necessarily would give the wrong results since i would be some large integer while xc would be e.g. xc = 0.25, while mathematically this bracket should have the form (x - xc) where x is some number between 0 and 1 (and similarly for the y coordinate).

dondondooooon commented 2 years ago

My point was not that anything had to be in a vector, but that the numbers x, xc, y and yc are all floating-point numbers that live on the domain from 0 to 1 (since this is the coordinate system we decided to work with). You are right that xc and yc are simply constants. The main point was that the bracket (i - xc) necessarily would give the wrong results since i would be some large integer while xc would be e.g. xc = 0.25, while mathematically this bracket should have the form (x - xc) where x is some number between 0 and 1 (and similarly for the y coordinate).

Am I constructing the wavepacket correctly now?

Screen Shot 2021-12-13 at 16 57 08

where xvec and yvec is defined in the constructor:

Screen Shot 2021-12-13 at 17 03 08
anderkve commented 2 years ago

I think so -- at least I can't spot anything wrong right away :)

dondondooooon commented 2 years ago

Since we're working with dimensionless variables, should I just have "t" on the x axis without specifying what t is (i.e. it is time). Also is the labelling on the y-axis alright considering I had to scale them. Is there a cleaner way, if this isn't acceptable?

sim1_prob.pdf

sim1_dev.pdf

anderkve commented 2 years ago

(I'll write p^n_total instead of the sum over i,j, but the sum notation is perfectly fine.)

When using bracket notation, a bracket "[X]" is typically read as "in units X". So in your sim1_dev.pdf plot I would have read your current y axis as "1 - p^n_total, in units 10^15", which is not what you wanted to convey. I suspect what you wanted so say was either

Either of those would be correct. (Though, if you just set something like plt.xlim([-8e-15, 8e-15]) I think you don't have to worry about any manual scaling, since Matplotlib will show the factor 10^{-15} automatically either directly in the tick numbers or on top of the axis.)

Similarly, the axis label "t [time]" would be read as "t in units time", which doesn't make sense. Here I'd simply go with "t" or "time", and if you want to stress that it is dimensionless you could put something like "t [1]" or "t [dimensionless]" or something similar. But I'd say it's perfectly fine to just say "t" and point out elsewhere in the report that "t" is a dimensionless time variable.

dondondooooon commented 2 years ago

Last thing... is setting up the a & b vector values for the diagonal values of A and B matrices used in the Crank Nicolson method correct here?

Screen Shot 2021-12-14 at 10 17 53

if i vectorize (translate my V matrix into v vector) using V.as_col like this

Screen Shot 2021-12-14 at 10 18 13

instead of using my function that specifically does this in accordance to Problem 2 image

anderkve commented 2 years ago

The easiest way to double-check code like this is simply to print the matrix to screen (you can print Armadillo matrices with cout) and see if the values are what you expect. (To make the output fit in the terminal, either print a subset of the matrix or set a very large step size, which gives small matrices, and make the terminal font size sufficiently small.) Or in this case, you could simply print the diagonal as a vector. If you at the same time print the values of the variables k, r, dt_half and v(k) it's easy to check if the resulting diagonal looks like it should.

Looking at the code above, I'm worried about this line in quantum:af (and the corresponding one in quantum::bf`):

cx_double send( 1.0, 4*imag(r) + imag(dt_half) * v(k) ); 

In particular, I wouldn't expect the variable dt_half to have an imaginary component -- the time step should simply be a real number. So in that case imag(dt_half) would return 0 and thus make the diagonal wrong.

Personally I find it easier to use the complex number "i" directly in my code, rather than using the cx_double (in reality the std::complex<double>) constructor with the real and imaginary parts as separate arguments. At least I find that I make fewer mistakes when I write code that looks more similar to the math. So I would do something like this

cx_double send = 1.0 + 4 * r + 1.0i * dt_half * v(k); 

where r is of type cx_double while dt_half is of type double.

If you encounter compilation problems when using the "i" notation, take a look at this page: https://stackoverflow.com/questions/17925904/how-to-use-complex-number-i-in-c

Concerning the ordering in your vectorized potential: Look at the documentation of the as_col() function: http://arma.sourceforge.net/docs.html#as_col_row There it says that the vector is created "by concatenating all columns". Whether or not that corresponds to your function for translating from (i.j) --> (k) is something you need to figure out, so I won't give a straight yes/no answer. :)

(And if you're unsure, remember that you can always just test it by setting up a small example matrix, e.g. a random 3x3 matrix, and checking the resulting .as_col() vector against the element ordering you get with your index translation function.)

dondondooooon commented 2 years ago

In particular, I wouldn't expect the variable dt_half to have an imaginary component -- the time step should simply be a real number. So in that case imag(dt_half) would return 0 and thus make the diagonal wrong.

I initialized dt_half as a complex double with only imaginary...

Screen Shot 2021-12-14 at 13 34 22

So when I do imag(dt_half) it will return dt/2. In hindsight it's a bit roundabout way of doing it, but I started with this and just continued accordingly.