Q1 Environment Variables in Linux The behaviour of your system can be controlled by what are called environment variables. An important one is call PATH. Check out the value of this environment variable by entering echo $PATH You should see a bunch of directory names separated by colons. These directories are places where the system checks for executables; executables contained in these directories will be available to run wherever you are in the system. The error "command not found" means that the executable that you are trying to run is not in one of these directories. To acknowledge that you've understood the above, please answer True to this question. Q2 Example: Environment variable PS1 The PS1 variable controls how the command line prompt appears. Enter echo $PS1 You might see something like [\u@\h \W]\$ which reads something like "user@hostname, name of directory you are in, dollar sign". Try changing it to something by entering PS1="$(pwd)>" The effect on the prompt should be obvious. The syntax $(command) gives as a string the results of the command inside the parentheses. In this case the string will be the full path to your current directory. A better way to change environment variables is to use "export". Enter export PS1='[\u@\h \W]\$' Using export makes the variable available to all processes in the shell. If you are interested in this particular environment variable, you can check out https://linoxide.com/change-bash-prompt-variable-ps1/ among others. To see other environment variables currently in play, enter env and you should see a whole list. To acknowledge that you've gone through the above, please answer True to this question. Q3 Header files in C Download spring-midpoint-fnc.c spring.dat spring.gnu from website. You can use wget, e.g. wget --no-check-certificate https://www.physics.mun.ca/courses/p3800/LECTURES/L06/spring-midpoint-fnc.c The program contains a line void deriv(double y[], double f[]); This line is a function declaration or function prototype. It tells the compiler that there is a function called "derive", what its arguments are (two double precision arrays) and what type of variable it returns (in this case it does not return a value -- this is what "void" means). If we have many function prototypes, it makes sense to neatly put them into a separate file. Such files are called header files. Create a file called spring.h, with, say nano spring.h that includes the line void deriv(double y[], double f[]); And replace the same line in spring-midpoint-fnc.c with #include "spring.h" The syntax "#include" results in the compiler compiling spring-midpoint-fnc.c as if the contents of spring.h were inserted at the place where the #include is located. The handing of lines beginning with "#" are handled by a "preprocessor". Such lines are called preporcessor directives. This line also tells the compiler to look for the file spring.h in the current directory. Header files contain function prototypes, declarations of (global) variables and preprocessor directives. They are use to handle "built-in" c functions. The line in the code #include is needed to use such math functions as "pow" (raising a number to some power). The "<...>" part means that the file math.h should be located in a directory in the system where the compiler knows to look for header files. Check out math.h with less /usr/include/math.h See if you can find pi. Now create the file deriv.f with, say, cat > deriv.c void deriv(double y[], double f[]) { f[0]=y[1]; // x' = v, x is y0 f[1]=-y[0]; // v' = -x v is y1 return; } ^D (the last line means holding down the CONTROL key while hitting D). This is a funny way to create a file quickly. You can always use nano, gedit, etc. Now that this function definition is contained in a separate file, delete the above lines from spring-midpoint-fnc.c. Confirm that everything works by compiling the code via gcc spring-midpoint-fnc.c deriv.c -lm -o spring-midpoint-fnc (the -lm option tells the compiler to link with the library of math functions). Once this compiles, answer True to this question. Q4 Makefiles -- simplest The following is a minimal Makefile for the code from Q3. Create "Makefile" with an editor of your choice. all: gcc spring-midpoint-fnc.c deriv.c -lm -o spring-midpoint-fnc (don't forget about tab it the line containing actions/commands -- the one with gcc in this case) For this and subsequent questions on Makefiles, you should run "make" to make sure that each Makefile runs properly. Choose all statements that apply to this Makefile. Entering "make" will compile the code There is only on target, and it is called "all" There are no dependencies, and will always (re)compile the code This simple style of Makefile is always the best to use. Q5 Makefiles -- Dependencies In this and the next few questions, you will edit the Makefile, adding more features and functionality. You will need to run the Makefile with make as necessary. Now you shall introduce a dependency. Here is the new Makefile. all: spring-midpoint-fnc spring-midpoint-fnc: gcc spring-midpoint-fnc.c deriv.c -lm -o spring-midpoint-fnc "all" now requires spring-midpoint-fnc, which in turn is a target, with its own body. Note, there are no more instructions in the (absent) body for "all". Note also that since you compiled the executable in Q4, make won't do anything when you run it. In order for it to recompile, you will first need to rm spring-midpoint-fnc and then type "make". True or false, With this Makefile, even if you update, say, deriv.c, it won't recompile so long as "spring-midpoint-fnc" exists. Q6 Makefiles -- split up compilation It is often good to split up the creation of the executable into compilation and linking. By hand this would be gcc -c spring-midpoint-fnc.c (which creates spring-midpoint-fnc.o) gcc -c deriv.c gcc spring-midpoint-fnc.o deriv.o -lm -o spring-midpoint-fnc This compiles each bit of source code to produce object files, and then link object files, together with the math library, into an executable. Making spring-midpoint-fnc depends on having spring-midpoint-fnc.o and deriv.o, each of which need their respective source codes to be made. If a target's dependency is newer than the target, the body lines are executed. We will add the target "clean" to remove the executable and object files. Here is the updated Makefile all: spring-midpoint-fnc spring-midpoint-fnc: spring-midpoint-fnc.o deriv.o gcc spring-midpoint-fnc.o deriv.o -lm -o spring-midpoint-fnc spring-midpoint-fnc.o: spring-midpoint-fnc.c gcc -c spring-midpoint-fnc.c deriv.o: deriv.c gcc -c deriv.c clean: rm *.o spring-midpoint-fnc Check all that apply There is nothing really special about the target "all"; it only gets executed by default with "make" since it is first. If the target "clean" were the first target, one would need to run "make all" or "make spring-midpoint-fnc" in order to compile the code. Q7 Makefiles -- Variables Now make the process a little easier by introducing variables instead of using repetitive typing Here is the updated Makefile # Comment. The following line stores the compiler in the # variable CC CC=gcc # CFLAGS stores options used when compiling source code # -c compile only # -Wall show all warnings CFLAGS=-c -Wall # LFLAGS stores options used when linking object code # -lm include the math library LFLAGS=-lm all: spring-midpoint-fnc spring-midpoint-fnc: spring-midpoint-fnc.o deriv.o ${CC} spring-midpoint-fnc.o deriv.o ${LFLAGS} -o spring-midpoint-fnc spring-midpoint-fnc.o: spring-midpoint-fnc.c ${CC} ${CFLAGS} spring-midpoint-fnc.c deriv.o: deriv.c ${CC} ${CFLAGS} deriv.c clean: rm *.o spring-midpoint-fnc Once this is working of you, answer True to this question. Q8 Makefiles -- Patterns You may have noticed that often every .o file is made from a corresponding .c file. The make utility allows for the use patterns to define a general rule for, say, making an object file from a source code file. In the new Makefile below, the "%" symbol stands for a "stem" of a file name. All the compilations of .c files into .o files are handled through pattern matching. The Makefile also contains "automatic variables" that can take the place of dependencies and targets. # Comment. The following line stores the compiler in the # variable CC CC=gcc # CFLAGS stores options used when compiling source code # -c compile only # -Wall show all warnings CFLAGS=-c -Wall # LFLAGS stores options used when linking object code # -lm include the math library LFLAGS=-lm all: spring-midpoint-fnc spring-midpoint-fnc: spring-midpoint-fnc.o deriv.o ${CC} $^ ${LFLAGS} -o $@ # $^ stands for all the prereq files, # in this case spring-midpoint-fnc.o deriv.o # $@ stands for the name of the target, # in this case spring-midpoint-fnc %.o: %.c ${CC} ${CFLAGS} $< # The $< stands for the first prerequiste input file, # in this case the .c file being compiled. clean: rm *.o spring-midpoint-fnc For a list of variables and more discussion on pattern matching and make in general, see https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables Check all that apply The automatic variable $@ stands for the name of the target The automatic variable $^ stands for all the prerequisites In this example, a .cpp source file will automatically be compiled into a corresponding .o file. Q9 Makefiles -- More variables The use of variables can reduce the number of spots in a file that you need to type and retype things, and so reduces the possibility of errors. Here is the new makefile. To adapt it to a project with the same structure, you may only need to change the TARGET variable and the OBJECTS variable. TARGET=spring-midpoint-fnc OBJECTS=spring-midpoint-fnc.o deriv.o # Comment. The following line stores the compiler in the # variable CC CC=gcc # CFLAGS stores options used when compiling source code # -c compile only # -Wall show all warnings CFLAGS=-c -Wall # LFLAGS stores options used when linking object code # -lm include the math library LFLAGS=-lm all: ${TARGET} ${TARGET}: ${OBJECTS} ${CC} $^ ${LFLAGS} -o $@ # $^ stands for all the prereq files, # in this case spring-midpoint-fnc.o deriv.o # $@ stands for the name of the target, # in this case spring-midpoint-fnc %.o: %.c ${CC} ${CFLAGS} $< # The $< stands for the first prerequiste input file, # in this case the .c file being compiled. clean: rm *.o ${TARGET} However, using variables can make the Makefile a little harder to read, especially for those who aren't used to the syntax. You decide! Now, add a rule for a figure Add/edit the following to the Makefile all: ${TARGET} euler.eps euler.eps: spring.dat spring.gnu gnuplot spring.gnu (Note: gnuplot may throw an error about the "qt" terminal. If this happens, edit the file spring.gnu by commenting the line with "qt" in it and uncomment the line with "x11" in it.) Once you have this Makefile running, answer True to this question. Q10 Makefile -- Fortran Download the Fortran 90 version of this code from https://www.physics.mun.ca/courses/p3800/LECTURES/L06/spring-midpoint-fnf.f90 Here is a Makefile for this code. It is remarkably similar to the Makefile from Q9. TARGET=spring-midpoint-fnf OBJECTS=spring-midpoint-fnf.o CC=gfortran CFLAGS=-c -Wall LFLAGS= all: ${TARGET} ${TARGET}: ${OBJECTS} ${CC} $^ ${LFLAGS} -o $@ %.o: %.f90 ${CC} ${CFLAGS} $< clean: rm *.o ${TARGET} Create a file called Makefile-f90 from the above lines. Execute it by running make -f Makefile-f90 The "-f" option allows you to specify a name. True or false All files processed by make must be called "Makefile". Q11 Fortran modules The Fortran code uses the command "contains" to tell the compiler that the function "energy" and the subroutine "deriv" exist and are usable by the main routine. One of the ways that we can detach functions (which return a value) and subroutines (that don't return a value, like void functions in c), is to use something like a function declaration or prototype, but is called an interface. And just like in c, which has its .h header files, Fortran has modules. Create the file spring_mod.f90 that contains the following. module spring IMPLICIT NONE INTERFACE function energy(y) integer, parameter :: DP = SELECTED_REAL_KIND(14) real( kind=DP ) :: energy real( kind=DP ), dimension(*), intent(in) :: y end function energy subroutine deriv(y,f) integer, parameter :: DP = SELECTED_REAL_KIND(14) real( kind=DP ), dimension(*), intent(in) :: y real( kind=DP ), dimension(*), intent(inout) :: f end subroutine deriv END INTERFACE END module spring Like a header file, it contains information on the subroutines and functions, what arguments they take etc. The interface consists essentially of the declarations taken from the subroutines and functions themselves. A module can also hold variables and parameters. Unlike header files, modules need to be compiled. Enter gfortran -c spring_mod.f90 This should produce an object file (spring_mod.o) and a module file spring.mod (note the name of this file reflects what was declared inside spring_mod.f90 and is not related to the name of the file spring_mod.f90). Now create the file energy.f90 containing function energy(y) implicit none integer, parameter :: DP = SELECTED_REAL_KIND(14) real( kind=DP ) :: energy real( kind=DP ), dimension(*), intent(in) :: y ! dimension(*) means array will take the size of ! array the function was called with ! recall that m=1 and k=1, y(1) is x, and y(2) is vx energy = 0.5_DP*(y(1)**2 + y(2)**2) return end function energy and create deriv.f90, containing subroutine deriv(y,f) IMPLICIT NONE integer, parameter :: DP = SELECTED_REAL_KIND(14) real( kind=DP ), dimension(*), intent(in) :: y real( kind=DP ), dimension(*), intent(inout) :: f f(1) = y(2) f(2) = -y(1) return end subroutine Now we need to edit spring-midpoint-fnf.f90 so that it includes as the first line USE spring so that it sues the module we just created. And we need to delete, the line with "contain" the code for the energy function the code for the deriv subroutine It should look like the following now. program spring_midpoint_fnf USE spring IMPLICIT NONE integer, parameter :: DP = SELECTED_REAL_KIND(14) integer, parameter :: nvars = 2 real( kind=DP ), dimension(nvars) :: y, ymid, f real( kind=DP ) :: vinit = 5.0_DP, xinit = 0.0_DP, time=0.0_DP real( kind=DP ) :: en, step character(20) :: nchar, stepchar !strings for reading commandline integer :: n,i ! Get n and step from command line ! make sure we have both arguments if(command_argument_count() .ne. 2)then write(*,*)'Usage: spring-midpoint-fnf n step' stop endif call get_command_argument(1,nchar) !read first argument call get_command_argument(2,stepchar) !read 2nd argument read(nchar,*)n ! convert string to whatver type n is (integer) read(stepchar,*)step i = 0 ! The loop counter y(1) = xinit ! Initial conditions y(2) = vinit en = energy(y) ! see function definition below write(*,*) time, y(1), y(2), en do while( i < n ) call deriv(y,f) !see subroutine below ymid(1) = y(1) + 0.5_DP*step*f(1) ymid(2)= y(2) + 0.5_DP*step*f(2) call deriv(ymid,f) y(1) = y(1)+step*f(1) y(2) = y(2)+step*f(2) en = energy(y) time = time+step i=i+1 write(*,*) time, y(1), y(2), en enddo call flush() ! On my system, for some reason, not all of the output ! was being captured when I was redirecting standard ! output to a full. Calling this subroutine makes sure ! that anything being written out gets flushed out of ! any buffer that is holding the information temporarily. end program Here is a Makefile that compiles all the parts. TARGET=spring-midpoint-fnf OBJECTS=spring-midpoint-fnf.o deriv.o energy.o spring_mod.o CC=gfortran CFLAGS=-c -Wall LFLAGS= all: ${TARGET} ${TARGET}: spring.mod ${OBJECTS} ${CC} ${OBJECTS} ${LFLAGS} -o $@ %.o: %.f90 ${CC} ${CFLAGS} $< spring.mod: spring_mod.f90 ${CC} ${CFLAGS} $< clean: rm *.o *.mod ${TARGET} When this is all working for you and the Makefile runs, answer True to this question.