- [Getting Segmentation Fault]
Particularly if this happens when plotting, make the
character string "title" -- which is passed to
routines contr and sfc, larger than
the default size of 25 letters long (e.g. try 50 instead).
- [Getting skewed, very
un-cone-like initial condition plots]
You
likely are passing an array with ghost points to the plot
routine -
and our plot routines are not expecting an array with ghost
points. To fix:
In C, copy your s1[][] or s2 array to a separate array of
[NX][NY] size and call contr or sfc with that, e.g.
float
splot[NX][NY];
for (
j=J1; j<=J2; j++ ) {
for (
i=I1; i<=I2; i++) {
splot[i-I1][j-J1]
= s2[i][j];
}
}
contr(
NX, NY, splot, ... ) (same sort of thing is done for calling sfc)
In
Fortran, be sure and pass the "real" (no ghost zones) part
of your array, i.e. use array subdomains as shown below:
call
contr( nx,ny, s2(1:nx,1:ny), ... )
- [Concerns
over U and V flow array sizes]
Our U
array is (nx+1,ny) and V is (nx,ny+1).
When
doing X-advection, we need to pass the nx+1 values in the
first dimension of U.
When
doing Y-advection, we need to pass the ny+1 values in the
second dimension of V.
C
programmers: Note also that in
advection, you use the i1, i2, j1, j2 when copying
s1 or s2; but u and v have no ghost points.
... so you have to be careful with indices.
- My min/max
values and plot vs. time for the official problem
is very different from the 51x51 test case ...
Yes,
there is much more resolution and the waves are much reduced
and smax(t) looks very different.
- I encountered problems when updating my
history(nx,ny,step-counter) array
There
is no need for a history() array in program 2.
So please delete
the history() array definition, and the loop(s) used to
create it.
- Do the 121x121 dimensions
include ghost points?
No - the ghost points are in
addition to the physical 121x121 (or 51x51 for testing) grid
sizes.
And, only the
scalar S array is 121x121; U and V dimensions
differ due to the staggering.
- Why
do my contour plots have fewer contours than yours?
Check
to make sure you are using the same contour interval when
plotting, if you want to match my results.
I used a contour interval of 0.5 for s1 and s2, and 0.1 for u
and v.
- Do I need to pass 'ghost points' for the
scalar "s" arrays to my advect1d routine?
Yes. Make sure your 1-D
array for s1 is
dimensioned to include ghost points, and have your advection
routine
copy all of
a row or column - including ghost points - to the 1d array
that you pass to advect1d.
Advect1d only
changes the 1:nx (in
Fortran notation) grid points, but it uses 0:nx+1 (again
considering the Fortran case).
- What grid dimensions do I need -
are there ghost points for all arrays?
You only need ghost points for the "s" arrays, s1,
s2, and strue.
The X-velocity is dimensioned u(nx+1,ny), and the Y-velocity
is v(nx,ny+1).
- How we should use the advect1d
subroutine each time?
All the advect1d routine "knows" is that it is
getting a 1-D array of a field "S", and a velocity field -
say, call it "vel1d" (we used to just consider this a
constant "c"). It takes the N-time level values and
returns the N+1 time level (updated) values. It
doesn't actually care whether it is being used in X- or
Y-advection.
- There are two common formulas
for variance. One is: Sum[(X-mean(X))^2] over all X, and
divided by N, the total number of points. The other
possibility is dividing by (N-1) instead of N. I just need
to make sure which to use.
I am using the (sample, biased) variance expression:
variance = 1/N * sum[
(s(i)-smean)**2 ]
For more on the difference between these two types of
variance, see
this page at MathWorld.
- When should I use the subroutine plot1d?
is it used to draw the smax, smin versus the time step?
Do I need to change plot1d to 2-D?
There is no need for plot1d, though you may use it if
you wish as we did in program 1.
A simpler approach: To plot a 1-d array such as the
minimum S values vs. time step (what I call smin), do this:
call
ezy(smin,nstep,'Min value of S vs. time')
In C,
c_ezy(
smin, nstep, title ); (smin is float *, nstep is int, title is char *)
For more on the
ezy
routine, see
this
online documentation.
- My contour plots look the same, with the same
smax and smin values as your examples, our final error values
are slightly different.
It is probably a matter of coding the calculations
slightly differently. As long as they are somewhat
close to mine and your contour plots look the same and your
dissipation + dispersion error adds up to your total error,
don't worry about it.
- [Plotting S array when calling contr routine
in C]
You may recall that the plot routines we are using
expect arrays dimensioned NX (in program 1), and NX,NY in
this program. Thus, I recommend copying your s2 values
(s2 being dimensioned NXDIM,NYDIM) to a new NX,NY array - so
the array passed to contr() is of size [NX][NY] and the
values start at array location [0][0], not [I1][I1].
Here is one way, for the initial condition:
float
plot_s[NX][NY],runtime;
...
sprintf(title,"Contour plot
at n = %d",n);
for (j=I1; j<=I2; j++) {
for (i=I1; i<=I2; i++) {
plot_s[i-I1][j-I1] = s2[i][j];
}
}
contr(NX,NY,plot_s,cint,0.0,title,colors,pltzero);
In Fortran, there is a
shortcut for this: call
contr(nx,ny,s2(1:nx,1:ny),...) but
in C we need to specifically pass an array of NX,NY size.
C programmers: Note
the 'time' expected as an argument to contr() should be float, not
integer - pass "0.0", not 0, and use a float variable or
calculation during the run, e.g. contr(...,dt*(float)n,...) or something along those
lines.
- [Plotting smin and smax time series array at
the end of your program]
In this 2d program you are asked to plot both the min
and max values over time, rather than just the max absolute
value.
I suggest getting rid of
strace() and defining new arrays, smin() and smax(), of size
MAXSTEP - make sure maxstep is at least 600.
Then, in your main
program, in your big n=1,nstep time integration loop, call
your stats routine passing it the location of the one element of the
smin() and smax() arrays that you want to set for the
current time step. In FORTRAN,
call stats(s2,
..., smin(n),smax(n))
in
FORTRAN
--
so smin(1) is first value
stored.
stats(s2, ..., &smin[n],&smax[n]))
in C -- if your time step loop runs (n=0; n<
nstep; n++) -- so smin[0] is first value stored.
stats(s2, ..., &smin[n-1],&smax[n-1]))
in C -- if your time step loop runs (n=1; n<=nstep;
n++) -- so smin[0] is
first value stored.
Then, after your main
time step loop has finished, you calculate your Takacs-style
error statistics, and also plot your smin and smax arrays
using the ezy (or, in C, c_ezy) routines - one call for
smin, and the other for smax - to plot nsteps time steps.
- [Not evolving correctly or S field is not
changing at all with time]
I suggest this.
Comment out all Y
advection steps. Use only X advection.
Set the U array to be 1.0
everywhere (in the real problem, U ranges from -1 to
+1). Set V to zero.
Now run your code for 20
steps, plotting every step. The cone should move to
the right.
Put print statements in
the integration and advect routines to find out what is
happening if it does not move correctly.
Then put Y advection back
and comment out X advection.
Set U to be zero
everywhere. Set V to be -1.0 everywhere.
Run the code; the cone
should move down towards lower Y, towards the center.
Again, if it isn't
working, I would do debugging from the inside out; run one
time step, print out results inside advect1d, and make sure
values are being updated and the one-dimensional S, U (or V)
and dt and dx values are OK. When that is working, go
to your integration step (where advect is called) and make sure you are
updating the 2-d s1 or s2 arrays correctly with the output
from advect1d, and that you are not somehow overwriting your
new (updated) values by doing an incorrect update within the
integration step.