diff --git a/advanced_lab/README.pdf b/advanced_lab/README.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..7e1b046a337f3fc8809487904ddc36ad07634832
Binary files /dev/null and b/advanced_lab/README.pdf differ
diff --git a/intro_lab/OpenMPlab-assigment.pdf b/intro_lab/OpenMPlab-assigment.pdf
deleted file mode 100644
index 925e8cf0ae90a6eac8cc8ec611e8ce01bdf2546b..0000000000000000000000000000000000000000
Binary files a/intro_lab/OpenMPlab-assigment.pdf and /dev/null differ
diff --git a/intro_lab/README.pdf b/intro_lab/README.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..a9988a97b64cc46b1cff42c65b5ce9b8a9197aa7
Binary files /dev/null and b/intro_lab/README.pdf differ
diff --git a/intro_lab/stream-triad.c b/intro_lab/stream-triad.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ee42ac9c73b6a68ea69f2b919202c6798fae045
--- /dev/null
+++ b/intro_lab/stream-triad.c
@@ -0,0 +1,31 @@
+/*
+ * This program implements the operation a <- b + s * c where
+ * a, b, c are arrays of doubles of length N and s is a double
+ */
+ 
+#define N (1024*1024)
+#define M 100
+
+double a[N];
+double b[N];
+double c[N];
+
+int main() {
+    int i, j;
+    double s;
+
+     /* Initialise b, c and s */
+    s = 0.1;
+    for (i = 0; i < N; i++) {
+        b[i] = (double) i;
+        c[i] = (double) i;
+    }
+
+     /* Run benchmark loop M times */
+     for (j = 0; j < M; j++) {
+        for (i = 0; i < N; i++)
+            a[i] = b[i] + s * c[i];
+    }
+
+    return 0;
+}
\ No newline at end of file
diff --git a/intro_lab/stream-triad.f90 b/intro_lab/stream-triad.f90
new file mode 100644
index 0000000000000000000000000000000000000000..4679f26b799bae0ff30974633fc0f390a4b23738
--- /dev/null
+++ b/intro_lab/stream-triad.f90
@@ -0,0 +1,32 @@
+! This program implements the operation a <- b + s * c where
+! a, b, c are arrays of doubles of length N and s is a double
+
+program triad
+
+use omp_lib
+
+implicit none
+
+integer(kind=8), parameter :: N = 1024 * 1024
+integer(kind=8), parameter :: M = 100
+
+real(kind=8), dimension(N) :: a, b, c
+real(kind=8) :: s
+
+integer(kind=8) :: i, j
+
+! Initialise b, c and s
+s = 0.1;
+do i = 1, N
+    b(i) = i
+    c(i) = i
+end do
+
+! Run benchmark loop M times
+do j = 1, M
+    do i = 1, N
+        a(i) = b(i) + s * c(i)
+    end do
+end do
+
+end program
\ No newline at end of file
diff --git a/old_intro_lab/README.md b/old_intro_lab/README.md
deleted file mode 100644
index f461701d77fd647a90a93a60f909678f0175f163..0000000000000000000000000000000000000000
--- a/old_intro_lab/README.md
+++ /dev/null
@@ -1,132 +0,0 @@
-# About this exercise
-
-The aim of this exercise is to give an introduction to OpenMP programming. The test examples are all written in both C and Fortran90.
-
-The exercise consists of three parts. The goal of the first part is to give you some familiarity to the OpenMP syntax by successively adding directives to a small test program. In the second part there is a small dummy program that you will parallelize in a guided manner. Finally, in the third part there are two programs to parallelize. Both are dealing with the issue of race conditions and the parallelization is of a more non-trivial nature.
-
-## Location of the examples
-
-A Makefile for the Cray nodes is to be found together with the source codes. You should copy this tarfile to a work directory of your own choice. The command below will untar the exercises into a directory omplab in your working directory.
-
-```bash
-$ tar xvf omplab.tar 
-```
-
-## Answers to the exercises
-
-All exercises have suggestions to how they can be solved. Compare your solution to ours. What are the good things and bad things for the different solutions? If you were not able to solve the exercise, make sure you understand how our suggested solution work. The answers will appear below towards the end of the exercise session.
-
-If you'd like to try our suggested solution, it is probably most easy to use the "Save As..." function in your web browser. Save the frame with the solution in "Text" mode to make sure that only the program is saved and not any information about font types etc. The solutions have the relevant changes made to the original program marked in bold face.
-
-# The first set of exercises
-
-You will start with the file part1.(c/f90) and make changes to it in this exercise. There are four different sections in the code you will work on. Do your changes to your copy of the file without changing its name. You can then recompile it using the make utility after each change you make.
-
-## part1ex1 -- Controlling a parallel section
-
-Thus exercise tries to illustrate a simple parallel OpenMP program.
-
-Compile the exercise by executing the command
-
-```bash
-$ make part1ex1
-```
-
-Run the resulting program:
-
-```bash
-export OMP_NUM_THREADS=<number of threads>
-srun -n 1 ./part1ex1
-```
-
-Remember that on the Cray you need to set the environment variable OMP_NUM_THREADS to the number of threads as described in the general instructions.
-Execute the program several times. Sometimes the output is incorrect. What is, and why? Fix the parallelization directive so that the program always prints the expected output.
-
-## part1ex2 -- Data-sharing
-
-The default storage type in OpenMP is shared. In many instances it is very useful to add the clause default(none) to the directives. If you take this as a habit you will always be reminded of what variables are in use and not forget to decide if a variable is to be shared or private. Furthermore, in OpenMP private data is also undefined on entry to a parallel section. Hence, this causes problems with pre-initialized private variable upon entry/exit to the parallel section.
-
-Compile the next example:
-
-```bash
-make part1ex2
-```
-
-The resulting program is named part1ex2. Run the program (using aprun as described above), is the output correct? Try to make the program print the correct value of n for both parallel sections.
-Hint: Look at the OpenMP standard subroutines and functions. A copy of the standard document is available if you open http://www.openmp.org/mp-documents/spec30.pdf in your web browser
-
-## part1ex3 -- Rudimentary synchronization
-
-This exercise tries to illustrate the usage of rudimentary OpenMP synchronization constructs. Compile make part1ex3 and run the example part1ex3. Try to make all the threads end at the same time.
-
-## Prog1Ex4 -- Scheduling
-The workload distribution for a loop can be controlled by a scheduling clause in OpenMP. It can be controlled either by a directive or by an environment variable. In this exercise we will use the later approach to control the scheduling of a simple loop. The scheduling policy is controlled by:
-
-```bash
-$ export OMP_SCHEDULE=type,chunk_size
-```
-
-where type can be any of static,dynamic,guided and chunk_size is an optional argument controlling the granularity of the workload distribution. The program stores the workload distribution to a file such that it can be visualized later.
-Compile the program with make part1ex4. Run the program with OMP_SCHEDULE=static. After it has completed, execute gnuplot schedule.gp, and look at the result with xview schedule.png (Require X-forwarding).
-
-The x-axis of the plot corresponds to loop iterations, and the y-axis represents the threads. Can you figure out what the static scheduling does? Experiment with different values of OMP_SCHEDULE and try to figure out what static, dynamic, guided does. Also, try to change the chunk_size, for example OMP_SCHEDULE=static,2 and observe what happens.
-
-# The second set of exercises
-
-We will in this section go through a guided parallelization of a simulated application. The application first creates three matrices according to a recursive secret formula. The program then multiplies the matrices with each other a few times. First compile a serial version of the program that you can use to check your results against:
-
-```bash
-$ make part2serial
-```
-
-Run the serial program (part2Serial) and save the results in a file so that you can compare your parallel program to this.
-
-## part2ex1 -- Parallel matrix generation
-
-Look at the section in the code marked Exercise 1. Three matrices are generated. Try to think of a way to parallelize this. Implement this parallelization. Compile your program with the command:
-
-```bash
-$ make part2ex1
-```
-
-Does it produce the same check sums for the matrices and the same output for x? If not, try again. Hint: The parallelization I think of will not scale beyond three threads.
-
-## part2ex2 -- Parallelizing a do loop
-
-Compile the second example make part2ex2. This loop makes a matrix multiplication. Parallelize the outer-most loop. Make sure the output is correct when you are done. Run your program several times to try to verify it is correct. Compare your solution to ours (there are several correct ways to do this exercise).
-
-## part2ex3 -- Parallelizing a do loop
-
-Continue to the section of the code marked Exercise 3. This time try to parallelize the second outer-most loop (the j-loop). Make sure the output is not changed from the output in the serial version.  
-
-If this had been a real application, which parallelization would you prefer? part2ex2 or part2ex3? Why?
-
-# Non-trivial parallelization
-
-Reality is usually less attractive than lab exercises. Now that you have become familiar with the directives in OpenMP, you might feel up to a slightly more challenging task.
-
-## part3a -- Cumulative sum
-
-In the example program part3a.(c/f90) a cumulative sum is computed. Compile the serial version of the program using the command make part3serial. Run the program part3serial and save the results in a file so that you can compare your parallel program to this.
-
-The core in this program consists of the loop:
-
-```fortran
-do i=2,N 
-  A(i,1)=A(i-1,1)+A(i,1)
-end do
-```
-
-In this example N is a large number so parallelizing it should be beneficial. Try to make this loop parallel. Run it several times to make sure the result is the same each time you run and that it is the same as for the serial program. You can compile the OpenMP version of the same program using the command make part3a.
-
-The suggested solution contains two slightly different ways to accomplish the task, but uses the same parallelization. Both have about the same performance. The first one is the most appealing since it is most straight forward. The second solution is not the preferred way of accomplishing the task in a real application, but is a good exercise in some of the less often used functions in OpenMP.
-
-## part3b -- Generating graphs
-
-In this example part3b.(c/f90) a graph is generated, represented as an adjacency list. Compile the program using the command make part3b and run the program part3b. Is the given program correct? Does it crash? And if so why?
-
-*Hint*: Look at the push subroutine, what happens if several threads modify the adjacency list concurrently?
-There are several solutions for this problem, each with various amounts of synchronization overhead. Try to fix the program without too much overhead.
-
-# Solutions
-The solutions can be found here towards the end of the lab session.
diff --git a/old_intro_lab/c/Makefile b/old_intro_lab/c/Makefile
deleted file mode 100644
index 0b6e65ae274538a4d2e024a7c7594817a3d21c39..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-CC = cc
-CFLAGS = -g -O2
-OMPFLAGS = -openmp
-LIBS = -lm
-
-
-all: part1 part2 part3
-
-part1: part1ex1 part1ex2 part1ex3 part1ex4
-	
-
-part2: part2ex1 part2ex2 part2ex3
-	
-
-part3: part3a part3b
-	
-
-part1ex1: part1.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=1 part1.c -o $@ $(LIBS)
-
-part1ex2: part1.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=2 part1.c -o $@ $(LIBS)
-
-part1ex3: part1.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=3 part1.c -o $@ $(LIBS)
-
-part1ex4: part1.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=4 part1.c -o $@ $(LIBS)
-
-part2ex1: part2.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=1 part2.c -o $@ $(LIBS)
-
-part2ex2: part2.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=2 part2.c -o $@ $(LIBS)
-
-part2ex3: part2.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) -DEXAMPLE=3 part2.c -o $@ $(LIBS)
-
-part3a:	part3a.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) $< -o $@ $(LIBS)
-
-part3b:	part3b.c
-	$(CC) $(CFLAGS) $(OMPFLAGS) $< -o $@ $(LIBS)
-
-part2serial: part2.c
-	$(CC) $(CFLAGS) -DSERIAL part2.c -o $@ $(LIBS)
-
-part3serial: part3a.c
-	$(CC) $(CFLAGS) -DSERIAL part3a.c -o $@ $(LIBS)
-
-clean:
-	rm -fr part1ex1 part1ex2 part1ex3 part1ex4\
-	part2ex1 part2ex2 part2ex3 part3a part3b *.o
diff --git a/old_intro_lab/c/part1.c b/old_intro_lab/c/part1.c
deleted file mode 100644
index fddb31ddbfdc0fb07f8c0d24aff0e3bcdc150cb0..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/part1.c
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <omp.h>
-
-
-/*
-  This set of exercises aims at showing some basic OpenMP directives and how
-  they affect the order (and correctness) of execution
-*/
-
-int main(int argc, char **argv) {
-
-  int i, j, tid, n, *buffer;
-  time_t ts;
-  FILE *fp;
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 1)
-  printf("\n   ----- Exercise 1 ------\n\n");
-
-  /*
-    This exercise tries to illustrate a simple parallel OpenMP
-    program.  Run it several times. At some occasions the printed
-    output is "wrong". Why is that? Correct the program so that it is
-    "correct"
-  */
-
-#pragma omp parallel private(i, j)
-{
-  for (i = 0; i < 1000; i++) 
-    for (j = 0; j < 1000; j++) 
-      tid = omp_get_thread_num();
-  
-  printf("Thread %d : My value of tid (thread id) is %d\n", omp_get_thread_num(), tid);
-}
-  
-
-  printf("\n   ----- End of exercise 1 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 2)
-  printf("\n   ----- Exercise 2 ------\n\n");
-
-  /*
-    This exercise illustrates some of the data-sharing clauses in
-    OpenMP. Run the program, is the output correct? Try to make the
-    program print the correct value for n for both  parallel sections
-  */
-
-  n = 10;
-#pragma omp parallel private(n)
-{
-  n += omp_get_thread_num();
-  printf("Thread %d : My value of n is %d \n", omp_get_thread_num(), n);
-}
-
- j = 100000;
-#pragma omp parallel for private(n)
- for (i = 1; i <= j; i++)
-   n = i;
-
- printf("\nAfter %d iterations the value of n is %d \n\n", j, n);
- 
- printf("\n   ----- End of exercise 2 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 3)
-  printf("\n   ----- Exercise 3 ------\n\n");
-
-  /*
-   This exercise tries to illustrate the usage of rudimentary OpenMP
-   synchronization constructs. Try to make all the threads end at the
-   same time
-  */
-
-#pragma omp parallel private(ts, tid) 
-{
-  tid = omp_get_thread_num();
-  time(&ts);
-
-  printf("Thread %d spawned at:\t %s", tid, ctime(&ts));  
-  sleep(1); 
-  if(tid%2 == 0)
-    sleep(5);
-
-  time(&ts);
-  printf("Thread %d done at:\t %s", tid, ctime(&ts));
- }
-  printf("\n   ----- End of exercise 3 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 4)
-  printf("\n   ----- Exercise 4 ------\n\n");
-  
-  /* 
-     This exercise illustrate the different scheduling algorithms in
-     OpenMP. Run the program several times, with different values for
-     OMP_SCHEDULE. 
-
-     After each run, execute gnuplot schedule.gp, and look at
-     schedule.png to see how the schedule assigned parts of the
-     iteration to different threads
-  */
-
-  n = 1000;
-  buffer = malloc(n * sizeof(int));
-
-  printf("Computing...");
-  fflush(stdout);
-#pragma omp parallel for schedule(runtime)
-  for (i = 0; i < n; i++) {
-    buffer[i] = omp_get_thread_num();    
-    usleep(random()%2000); 
-  }
-  printf("Done\n");
-  fp = fopen("schedule.dat","w");
-
-  for (i = 0; i < n; i++)
-    fprintf(fp, "%d\t%d\n", i, buffer[i]);
-
-  fclose(fp);
-
-  printf("Now, run 'gnuplot schedule.gp' to visualize the scheduling policy\n");
-  free(buffer);
-
-
-  printf("\n   ----- End of exercise 4 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-  return 0;
-}
diff --git a/old_intro_lab/c/part1_roman.c b/old_intro_lab/c/part1_roman.c
deleted file mode 100644
index 5449584823cc0bacad9e000fbb9bc30a234b5a93..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/part1_roman.c
+++ /dev/null
@@ -1,145 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <omp.h>
-
-
-/*
-  This set of exercises aims at showing some basic OpenMP directives and how
-  they affect the order (and correctness) of execution
-*/
-
-int main(int argc, char **argv) {
-
-  int i, j, tid, n, *buffer;
-  time_t ts;
-  FILE *fp;
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 1)
-  printf("\n   ----- Exercise 1 ------\n\n");
-
-  /*
-    This exercise tries to illustrate a simple parallel OpenMP
-    program. Observe that the output is "wrong" (thread IDs do not match).
-    Why is that? Correct the program so that it is
-    "correct"
-  */
-
-#pragma omp parallel private(i, j, tid)
-{
-  for (i = 0; i < 1000; i++) 
-    for (j = 0; j < 1000; j++) 
-      tid = omp_get_thread_num();
-  
-#pragma omp barrier
-
-  printf("Thread %d : My value of tid (thread id) is %d\n", omp_get_thread_num(), tid);
-}
-  
-
-  printf("\n   ----- End of exercise 1 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 2)
-  printf("\n   ----- Exercise 2 ------\n\n");
-
-  /*
-    This exercise illustrates some of the data-sharing clauses in
-    OpenMP. Run the program, is the output correct? Try to make the
-    program print the correct value for n for both  parallel sections
-  */
-
-  n = 10;
-#pragma omp parallel firstprivate(n)
-{
-  n += omp_get_thread_num();
-  printf("Thread %d : My value of n is %d \n", omp_get_thread_num(), n);
-}
-
- j = 100000;
-#pragma omp parallel for lastprivate(n)
- for (i = 1; i <= j; i++)
-   n = i;
-
- printf("\nAfter %d iterations the value of n is %d \n\n", j, n);
- 
- printf("\n   ----- End of exercise 2 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 3)
-  printf("\n   ----- Exercise 3 ------\n\n");
-
-  /*
-   This exercise tries to illustrate the usage of rudimentary OpenMP
-   synchronization constructs. Try to make all the threads end at the
-   same time
-  */
-
-#pragma omp parallel private(ts, tid) 
-{
-  tid = omp_get_thread_num();
-  time(&ts);
-
-  printf("Thread %d spawned at:\t %s", tid, ctime(&ts));  
-  sleep(1); 
-  if(tid%2 == 0)
-    sleep(5);
-  #pragma omp barrier
-
-  time(&ts);
-  printf("Thread %d done at:\t %s", tid, ctime(&ts));
- }
-  printf("\n   ----- End of exercise 3 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE == 4)
-  printf("\n   ----- Exercise 4 ------\n\n");
-  
-  /* 
-     This exercise illustrate the different scheduling algorithms in
-     OpenMP. Run the program several times, with different values for
-     OMP_SCHEDULE. 
-
-     After each run, execute gnuplot schedule.gp, and look at
-     schedule.png to see how the schedule assigned parts of the
-     iteration to different threads
-  */
-
-  n = 1000;
-  buffer = malloc(n * sizeof(int));
-
-  printf("Computing...");
-  fflush(stdout);
-#pragma omp parallel for schedule(runtime)
-  for (i = 0; i < n; i++) {
-    buffer[i] = omp_get_thread_num();    
-    usleep(random()%2000); 
-  }
-  printf("Done\n");
-  fp = fopen("schedule.dat","w");
-
-  for (i = 0; i < n; i++)
-    fprintf(fp, "%d\t%d\n", i, buffer[i]);
-
-  fclose(fp);
-
-  printf("Now, run 'gnuplot schedule.gp' to visualize the scheduling policy\n");
-  free(buffer);
-
-
-  printf("\n   ----- End of exercise 4 ------\n\n");
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-  return 0;
-}
diff --git a/old_intro_lab/c/part2.c b/old_intro_lab/c/part2.c
deleted file mode 100644
index dbf9d6dfcc5f3d9e1daa5634110f7d1cc8ba082d..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/part2.c
+++ /dev/null
@@ -1,178 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <omp.h>
-#include <sys/time.h>
-
-#define MATSIZE 900
-
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-double check_sum(double **mat) {
-  int i, j;
-  double sum = 0.0;
-
-  for(i = 0; i < MATSIZE; i++) 
-    for(j = 0; j < MATSIZE; j++) 
-      sum += mat[i][j];
-  return sum;
-}
-
-/*
-  This program generates some vectors and matrices
-  It manipulates them and finally computes some global
-  things that are printed
-*/
-
-int main(int argc, char **argv) {
-
-  int i,j, k, iptr;
-  double **mat_a, **mat_b, **mat_c, **mat_d;
-  double  x, scal;
-  double dtime;
-
-  
-  mat_a = (double **) malloc(MATSIZE * sizeof(double *));
-  mat_b = (double **) malloc(MATSIZE * sizeof(double *));
-  mat_c = (double **) malloc(MATSIZE * sizeof(double *));
-  mat_d = (double **) malloc(MATSIZE * sizeof(double *));
-  
-  mat_a[0] = (double *) malloc(MATSIZE * MATSIZE * sizeof(double));
-  mat_b[0] = (double *) malloc(MATSIZE * MATSIZE * sizeof(double));
-  mat_c[0] = (double *) malloc(MATSIZE * MATSIZE * sizeof(double));
-  mat_d[0] = (double *) malloc(MATSIZE * MATSIZE * sizeof(double));
-
-  for (i = 0; i < MATSIZE; i++) {
-    mat_a[i] = mat_a[0] + i*MATSIZE;
-    mat_b[i] = mat_b[0] + i*MATSIZE;
-    mat_c[i] = mat_c[0] + i*MATSIZE;
-    mat_d[i] = mat_d[0] + i*MATSIZE;
-  }
-  
-  /*--------------------------------------------------------------------------*/
-
-  printf("\n   ----- Exercise 1 ------\n\n");
-
-  /*
-    The code below generates three matrices. Try to think of a way in which
-    this can be made parallel in any way. Make sure that the printed output
-    x is correct in your parallel version
-  */
-
-
-  dtime = gettime();
-  x = 0.35;
-  for (j = 0; j < MATSIZE; j++) {
-    for (i = 0; i < MATSIZE; i++) {
-      x = 1 - frexp(sin(x), &iptr);
-      mat_a[i][j] = x;
-    }
-  }
-
-  x = 0.68;
-    for (j = 0; j < MATSIZE; j++) {
-      for (i = 0; i < MATSIZE; i++) {	
-      x = 1 - frexp(sin(x), &iptr);
-      mat_b[i][j] = x;
-    }
-  }
-
-  x = 0.24;
-  for (j = 0; j < MATSIZE; j++) {      
-    for (i = 0; i < MATSIZE; i++) {
-      x = 1 - frexp(sin(x), &iptr);
-      mat_c[i][j] = x;
-    }
-  }
-  dtime = gettime() - dtime;
-  printf("The sum of the matrices evaluates to:\n"
-	 "Matrix A:%12.4f\t Matrix B:%12.4f\t Matrix C:%12.4f \n",
-	 check_sum(mat_a), check_sum(mat_b), check_sum(mat_c));
-  printf("Time for the exercise: %9.5f seconds\n", dtime);
-
-  printf("\n   ----- End of exercise 1 ------\n\n");
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE > 1 && EXAMPLE < 3 || SERIAL)
-
-  printf("\n   ----- Exercise 2 ------\n\n");
-
-  /*
-    This code makes a simple attempt at computing a matrix multiply. Try
-    to parallelize it without changing the results (more than negligible)
-    In this exercise parallelize the outer-most loop
-  */
-
-  dtime = gettime();
-  for (i = 0; i < MATSIZE; i++) {
-    for (j = 0; j < MATSIZE; j++) {
-      scal = 0.0;
-      for (k = 0; k < MATSIZE; k++) {
-	scal += mat_a[i][k] * mat_b[k][j];
-      }
-      mat_d[i][j] = scal;
-    }
-  }
-  dtime = gettime() - dtime;
-  printf("The sum of matrix D evaluates to: %12.4f\n", check_sum(mat_d));
-  printf("The value of scal is: %f\n", scal);
-  printf("Time for the exercise: %9.5f seconds\n", dtime);
-
-  printf("\n   ----- End of exercise 2 ------\n\n");
-
-#endif
-
-  /*--------------------------------------------------------------------------*/
-
-#if (EXAMPLE > 2 || SERIAL)
-
-  printf("\n   ----- Exercise 3 ------\n\n");
-
-  /*
-    This code makes a simple attempt at computing a matrix multiply. Try
-    to parallelize it without changing the results (more than negligible)
-    In this exercise parallelize the second outer-most loop
-  */
-
-  dtime = gettime();
-
-  for (i = 0; i < MATSIZE; i++) {
-    for (j = 0; j < MATSIZE; j++) {
-      scal = 0.0;
-      for (k = 0; k < MATSIZE; k++) {
-	scal += mat_a[i][k] * mat_b[k][j];
-      }
-      mat_d[i][j] = scal;
-    }
-  }
-
-  dtime = gettime() - dtime;
-
-  printf("The sum of matrix D evaluates to: %12.4f\n", check_sum(mat_d));
-  printf("The value of scal is: %f\n", scal);
-  printf("Time for the exercise: %9.5f seconds\n", dtime);
-
-  printf("\n   ----- End of exercise 3 ------\n\n");
-#endif  
-
-  /*--------------------------------------------------------------------------*/
-
-
-  free(mat_d[0]); 
-  free(mat_c[0]); 
-  free(mat_b[0]);
-  free(mat_a[0]);
-
-  free(mat_d);
-  free(mat_c);
-  free(mat_b);
-  free(mat_a);
-  
-
-  return 0;
-}
diff --git a/old_intro_lab/c/part3a.c b/old_intro_lab/c/part3a.c
deleted file mode 100644
index a407886923f088d38616b376043063ac06e9c9b7..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/part3a.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <math.h>
-#include <omp.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-
-/* Row-major order macro */
-#define RM(row,col) ((row) + ((2)*(col)))
-
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-int main(int argc, char **argv) {
-
-  int i, j, dN, tid, Nthrds, start, end, MaxNthrds;
-  double dw, fprt, locsum, dtime;
-  double *A;
-  double *blocksum;
-  int N = 12123123;
-  
-  omp_lock_t *locks;
-
-#ifdef _OPENMP
-  MaxNthrds = omp_get_max_threads();
-#else
-  MaxNthrds = 1;
-#endif
-
-  A = calloc(2 * N, sizeof(double));
-  blocksum = calloc(MaxNthrds, sizeof(double));
-
-  dw = M_PI / (double) N;
-
-  for (i = 0; i < N; i++) 
-    A[ RM(1, i) ] = i * dw;
-
-  for (i = 0; i < N; i++) 
-    A[ RM(2, i) ] = A[ RM(1, i) ];
-  
-  dtime = gettime();
-  for (i = 1; i < N; i++)
-    A[ RM(1, i) ] = A[ RM(1, i - 1) ] + A[ RM(1, i) ] ;
-  printf("First summation loop took  %9.5f seconds\n", gettime() - dtime);
-
-  /*--------------------------------------------------------------------------*/
-
-  dtime = gettime();
-  for (i = 1; i < N; i++)
-    A[ RM(2, i) ] = A[ RM(2, i - 1) ] + A[ RM(2, i) ] ;
-  printf("Second summation loop took %9.5f seconds\n", gettime() - dtime);
-
-  printf("%e %e\n", A[RM(1, N - 1)], A[ RM(2, N -1 )] );
-
-  free(blocksum);
-  free(A);
-
-
-  return 0;
-}
diff --git a/old_intro_lab/c/part3b.c b/old_intro_lab/c/part3b.c
deleted file mode 100644
index 31ef0beec7b77ca2da8681208d12851d9503de66..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/part3b.c
+++ /dev/null
@@ -1,126 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <omp.h>
-#include <sys/time.h>
-
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-#define GRAPH_SIZE 1000
-#define ADJLIST_SIZE 4
-
-/*
-  This exercise aims at showing the mutual exclusion clauses in
-  OpenMP. The program generates a graph, represented as an adjacency
-  list. Is the given program correct? Try to fix it without too much
-  parallel overhead.
-*/
-
-
-typedef struct {
-  int *adj;
-  int top;
-  int size;
-} node_t;
-
-
-typedef struct {
-  node_t *n;
-} graph_t;
-
-void init_graph(graph_t *g) {
-  int i;
-  
-  printf("Initialize graph data structure...");
-
-  /* Allocate space for each node */
-  g->n = malloc(GRAPH_SIZE * sizeof(node_t));
-
-  /* Initialize each node's adjacency list */
-  for (i = 0; i < GRAPH_SIZE; i++) {
-    g->n[i].size = ADJLIST_SIZE;
-    g->n[i].top = 0;
-    g->n[i].adj = calloc(g->n[i].size ,sizeof(int));
-  }
-
-  printf("Done\n");
-}
-
-void free_graph(graph_t *g){
-  int i;
-
-  printf("Cleaning up...");
-
-  for (i = 0; i < GRAPH_SIZE; i++) 
-    free(g->n[i].adj);
-  free(g->n);
-
-  printf("Done\n");
-
-}
-
-
-/* 
- * Push a new node to the adjacency list
- */
-void push(int i, node_t *n) {
-  int *tmp;
-  
-  if (n->top >= n->size) {
-    n->size += ADJLIST_SIZE;
-    tmp = n->adj;
-    n->adj = realloc(tmp, n->size * sizeof(int));    
-  }
-  
-  n->adj[(n->top++)] = i;
-}
-
-/*
- * Add node j as neighbour to node i
- */
-void add(int i, int j, graph_t *g) {
-  int k;
-
-  for (k = 0; k < g->n[i].top; k++) 
-    if (g->n[i].adj[k] == j)
-      return;
-
-  push(j, &g->n[i]);
-  
-}
-
-
-
-int main(int argc, char **argv) {
-  int i;
-  graph_t g;
-  double stime;
-
-
-  init_graph(&g);
-
-  stime = gettime();
-#pragma omp parallel shared(g)
-  {
-#pragma omp master
-    {
-      printf("Inserting nodes using %d threads...", omp_get_num_threads());
-      fflush(stdout);
-
-    }
-    #pragma omp barrier
-#pragma omp for 
-  for (i = 0; i < (GRAPH_SIZE * GRAPH_SIZE) ; i++) 
-    add(random()%GRAPH_SIZE, random()%GRAPH_SIZE, &g);
-
-  }
-  printf("Done\nGraph generated in %.5f seconds\n", gettime() - stime);
-
-  free_graph(&g);
-
-  return 0;
-}
diff --git a/old_intro_lab/c/schedule.gp b/old_intro_lab/c/schedule.gp
deleted file mode 100644
index 76714e3510ee40c07be67582d360e75959b92ec6..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/schedule.gp
+++ /dev/null
@@ -1,7 +0,0 @@
-set terminal png 
-set autoscale
-set output "schedule.png" 
-set xlabel "Iteration"
-set ylabel "Thread ID"
-unset key
-plot "schedule.dat" using 1:2 ls 4
\ No newline at end of file
diff --git a/old_intro_lab/c/sol/part1ex1.c b/old_intro_lab/c/sol/part1ex1.c
deleted file mode 100644
index c817aa7099763af16ca426100a2bd66a876904d2..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part1ex1.c
+++ /dev/null
@@ -1,20 +0,0 @@
-printf("\n   ----- Exercise 1 ------\n\n");
-
-/*
-    This exercise tries to illustrate a simple parallel OpenMP
-    program.  Run it several times. At some occasions the printed
-    output is "wrong". Why is that? Correct the program so that it is
-    "correct"
-*/
-
-#pragma omp parallel private(i, j, tid)
-{
-  for (i = 0; i < 1000; i++) 
-    for (j = 0; j < 1000; j++) 
-      tid = omp_get_thread_num();
-  
-  printf("Thread %d : My value of tid (thread id) is %d\n", omp_get_thread_num(), tid);
-}
-  
-
-printf("\n   ----- End of exercise 1 ------\n\n");
diff --git a/old_intro_lab/c/sol/part1ex2.c b/old_intro_lab/c/sol/part1ex2.c
deleted file mode 100644
index 3c9352da86a89c3cc9df1bb39d4a86edadfc782d..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part1ex2.c
+++ /dev/null
@@ -1,23 +0,0 @@
-printf("\n   ----- Exercise 2 ------\n\n");
-
-/*
-    This exercise illustrates some of the data-sharing clauses in
-    OpenMP. Run the program, is the output correct? Try to make the
-    program print the correct value for n for both  parallel sections
-*/
-
-n = 10;
-#pragma omp parallel private(n), firstprivate(n)
-{
-  n += omp_get_thread_num();
-  printf("Thread %d : My value of n is %d \n", omp_get_thread_num(), n);
-}
-
-j = 100000;
-#pragma omp parallel for private(n), lastprivate(n)
-for (i = 1; i <= j; i++)
-  n = i;
-
-printf("\nAfter %d iterations the value of n is %d \n\n", j, n);
- 
-printf("\n   ----- End of exercise 2 ------\n\n");
diff --git a/old_intro_lab/c/sol/part1ex3.c b/old_intro_lab/c/sol/part1ex3.c
deleted file mode 100644
index 3eb9e79542325435634615e89719c04550eadb0c..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part1ex3.c
+++ /dev/null
@@ -1,22 +0,0 @@
-printf("\n   ----- Exercise 3 ------\n\n");
-
-/*
-   This exercise tries to illustrate the usage of rudimentary OpenMP
-   synchronization constructs. Try to make all the threads end at the
-   same time
-*/
-
-#pragma omp parallel private(ts, tid) 
-{
-  tid = omp_get_thread_num();
-  time(&ts;);
-
-  printf("Thread %d spawned at:\t %s", tid, ctime(&ts;));  
-  sleep(1); 
-  if(tid%2 == 0)
-    sleep(5);
-#pragma omp barrier
-  time(&ts;);
-  printf("Thread %d done at:\t %s", tid, ctime(&ts;));
-}
-printf("\n   ----- End of exercise 3 ------\n\n");
diff --git a/old_intro_lab/c/sol/part3a.sol.2.c b/old_intro_lab/c/sol/part3a.sol.2.c
deleted file mode 100644
index 704a37c2bdf35d62b8e56adb8c16d4baf384a6a4..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part3a.sol.2.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#include <math.h>
-#include <omp.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-
-/* Row-major order macro */
-#define RM(row,col) ((row) + ((2)*(col)))
-/* MIN macro */
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-int main(int argc, char **argv) {
-  
-  int i, j, dN, tid, Nthrds, start, end, MaxNthrds;
-  double dw, fprt, locsum, dtime;
-  double *A;
-  double *blocksum;
-  int N = 12123123;
-  
-  omp_lock_t *locks;
-  
-#ifdef _OPENMP
-  MaxNthrds = omp_get_max_threads();
-#else
-  MaxNthrds = 1;
-#endif
-  
-  A = calloc(2 * N, sizeof(double));
-  blocksum = calloc(MaxNthrds, sizeof(double));
-  
-  dw = M_PI / (double) N;
-  
-  for (i = 0; i < N; i++)
-    A[ RM(0, i) ] = i * dw;
-  
-  for (i = 0; i < N; i++)
-    A[ RM(1, i) ] = A[ RM(0, i) ];
-  
-  dtime = gettime();
-#pragma omp parallel shared(blocksum,A), private(locsum,i,start,end,Nthrds,tid,dN)
-  {
-#ifdef _OPENMP
-    Nthrds = omp_get_num_threads();
-    dN=ceil((double) N/Nthrds); tid = omp_get_thread_num();
-    start = tid*dN; end = MIN((tid+1)*dN,N);
-#else
-    start=0; end=N; tid=0; Nthrds=1;
-#endif
-    locsum = A[ RM(0,start) ];
-    for (i = start+1; i < end; i++) {
-      locsum += A[ RM(0, i)];
-      A[ RM(0, i) ] += A[ RM(0, i - 1) ];
-    }
-    blocksum[tid] = locsum;
-    
-#pragma omp barrier
-    locsum = 0;
-    for(i = 0; i < tid; i++)
-      locsum += blocksum[i];
-    
-    for (i = start; i < end; i++)
-      A[ RM(0,i) ] += locsum;
-  }
-  printf("First summation loop took  %9.5f seconds\n", gettime() - dtime);
-  
-  /*--------------------------------------------------------------------------*/
-#ifdef _OPENMP
-  locks = calloc(MaxNthrds, sizeof(omp_lock_t));
-  for (tid=0; tid<MaxNthrds; tid++)
-    omp_init_lock(&(locks[tid]));
-#endif
-  
-  dtime = gettime();
-#pragma omp parallel shared(blocksum, A, locks), private(locsum,i,start,end,Nthrds,tid,dN)
-  {
-#ifdef _OPENMP
-    Nthrds = omp_get_num_threads();
-    dN=ceil((double) N/Nthrds); tid = omp_get_thread_num();
-    start = tid*dN; end = MIN((tid+1)*dN,N);
-    omp_set_lock(&locks[tid]); /* protect my local sum with a lock */
-#else
-    start=0; end=N; tid=0; Nthrds=1;
-#endif
-    
-    locsum=A[ RM(1,start) ];
-    
-    for(i=start+1;i<end;i++) {
-      locsum+=A[ RM(1,i) ];
-      A[ RM(1,i) ] += A[ RM(1,i-1) ];
-    }
-    blocksum[tid]=locsum;
-    
-#ifdef _OPENMP
-    omp_unset_lock(&locks[tid]); /* Allow others to read my value */
-#endif
-    
-    locsum=0;
-    for (i=tid-1;i>=0;i--){
-#ifdef _OPENMP
-      omp_set_lock(&locks[i]); /* Make sure the value is available for reading */
-      omp_unset_lock(&locks[i]);
-#endif
-      locsum+=blocksum[i];
-    }
-    
-    for(i=start;i<end;i++) {
-      A[ RM(1,i) ]+=locsum;
-    }
-    
-    
-  }
-  printf("Second summation loop took %9.5f seconds\n", gettime() - dtime);
-  
-  printf("%e %e\n", A[RM(0, N - 1)], A[ RM(1, N -1 )] );
-  
-  free(blocksum);
-  free(A);
-  
-  return 0;
-}
diff --git a/old_intro_lab/c/sol/part3a.sol.c b/old_intro_lab/c/sol/part3a.sol.c
deleted file mode 100644
index 3ec453418ea89b010b34e7ba88513319c5daa3fd..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part3a.sol.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <math.h>
-#include <omp.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-
-/* Row-major order macro */
-#define RM(row,col) ((row) + ((2)*(col)))
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-int main(int argc, char **argv) {
-  int i, j, dN, tid, Nthrds, start, end, MaxNthrds;
-  double dw, fprt, locsum, dtime;
-  double *A;
-  double *blocksum;
-  int N = 12123123;
-  
-  omp_lock_t *locks;
-
-#ifdef _OPENMP
-  MaxNthrds = omp_get_max_threads();
-#else
-  MaxNthrds = 1;
-#endif
-
-  A = calloc(2 * N, sizeof(double));
-  blocksum = calloc(MaxNthrds, sizeof(double));
-
-  dw = M_PI / (double) N;
-
-  for (i = 0; i < N; i++)
-    A[ RM(0, i) ] = i * dw;
-
-  for (i = 0; i < N; i++)
-    A[ RM(1, i) ] = A[ RM(0, i) ];
-  
-  double n=0;
-  dtime = gettime();
-#pragma omp parallel for reduction(+:n)
-  for (i = 0; i < N; i++)
-    n += A[ RM(0, i) ] ;
-  printf("First summation loop took  %9.5f seconds\n", gettime() - dtime);
-  
-  /*--------------------------------------------------------------------------*/
-  
-  dtime = gettime();
-  for (i = 1; i < N; i++)
-    A[ RM(1, i) ] = A[ RM(1, i - 1) ] + A[ RM(1, i) ] ;
-  printf("Second summation loop took %9.5f seconds\n", gettime() - dtime);
-  printf("%e %e\n", n, A[ RM(1, N -1 )] );
-  free(blocksum);
-  free(A);
-  
-  
-  
-  return 0;
-  
-}
diff --git a/old_intro_lab/c/sol/part3b.sol.1.c b/old_intro_lab/c/sol/part3b.sol.1.c
deleted file mode 100644
index b8f54551d335609e9085743ec9b23a8b1e952fd0..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part3b.sol.1.c
+++ /dev/null
@@ -1,129 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <omp.h>
-#include <sys/time.h>
-
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-#define GRAPH_SIZE 1000
-#define ADJLIST_SIZE 4
-
-/*
-  This exercise aims at showing the mutual exclusion clauses in
-  OpenMP. The program generates a graph, represented as an adjacency
-  list. Is the given program correct? Try to fix it without too much
-  parallel overhead.
-*/
-
-
-typedef struct {
-  int *adj;
-  int top;
-  int size;
-} node_t;
-
-
-typedef struct {
-  node_t *n;
-} graph_t;
-
-void init_graph(graph_t *g) {
-  int i;
-  
-  printf("Initialize graph data structure...");
-  
-  /* Allocate space for each node */
-  g->n = malloc(GRAPH_SIZE * sizeof(node_t));
-  
-  /* Initialize each node's adjacency list */
-  for (i = 0; i < GRAPH_SIZE; i++) {
-    g->n[i].size = ADJLIST_SIZE;
-    g->n[i].top = 0;
-    g->n[i].adj = calloc(g->n[i].size ,sizeof(int));
-  }
-  
-  printf("Done\n");
-}
-
-void free_graph(graph_t *g){
-  int i;
-  
-  printf("Cleaning up...");
-  
-  for (i = 0; i < GRAPH_SIZE; i++) 
-    free(g->n[i].adj);
-  free(g->n);
-  
-  printf("Done\n");
-  
-}
-
-
-/* 
- * Push a new node to the adjacency list
- */
-void push(int i, node_t *n) {
-  int *tmp;
-  
-  if (n->top >= n->size) {
-    n->size += ADJLIST_SIZE;
-    tmp = n->adj;
-    n->adj = realloc(tmp, n->size * sizeof(int));    
-  }
-  
-  n->adj[(n->top++)] = i;
-}
-
-/*
- * Add node j as neighbour to node i
- */
-void add(int i, int j, graph_t *g) {
-  int k, found=0;
-#pragma omp critical
-  { 
-    for (k = 0; k < g->n[i].top; k++) {
-      if (g->n[i].adj[k] == j) {
-	found=1;
-	break;
-      }
-    }
-    if (found!=1) {
-      push(j, &g->n[i]);
-    }
-  }
-}
-
-
-
-int main(int argc, char **argv) {
-  int i;
-  graph_t g;
-  double stime;
-  
-  
-  init_graph(&g);
-  
-  stime = gettime();
-#pragma omp parallel shared(g)
-  {
-#pragma omp master
-    {
-      printf("Inserting nodes using %d threads...", omp_get_num_threads());
-      fflush(stdout);
-      
-    }
-#pragma omp barrier
-#pragma omp for 
-    for (i = 0; i < (GRAPH_SIZE * GRAPH_SIZE) ; i++) 
-      add(random()%GRAPH_SIZE, random()%GRAPH_SIZE, &g);
-  }
-  printf("Done\nGraph generated in %.5f seconds\n", gettime() - stime);
-  
-  free_graph(&g);
-  
-  return 0;
-}
diff --git a/old_intro_lab/c/sol/part3b.sol.2.c b/old_intro_lab/c/sol/part3b.sol.2.c
deleted file mode 100644
index 289ccffd21caa1fd3fc3b8ca2b892cdd74849f46..0000000000000000000000000000000000000000
--- a/old_intro_lab/c/sol/part3b.sol.2.c
+++ /dev/null
@@ -1,137 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <omp.h>
-#include <sys/time.h>
-
-double gettime(void) {
-  struct timeval tv;
-  gettimeofday(&tv,NULL);
-  return tv.tv_sec + 1e-6*tv.tv_usec;
-}
-
-#define GRAPH_SIZE 1000
-#define ADJLIST_SIZE 4
-
-/*
-  This exercise aims at showing the mutual exclusion clauses in
-  OpenMP. The program generates a graph, represented as an adjacency
-  list. Is the given program correct? Try to fix it without too much
-  parallel overhead.
-*/
-
-
-typedef struct {
-  int *adj;
-  int top;
-  int size;
-  omp_lock_t mutex; /* node mutex */
-} node_t;
-
-
-typedef struct {
-  node_t *n;
-} graph_t;
-
-void init_graph(graph_t *g) {
-  int i;
-  
-  printf("Initialize graph data structure...");
-  
-  /* Allocate space for each node */
-  g->n = malloc(GRAPH_SIZE * sizeof(node_t));
-  
-  /* Initialize each node's adjacency list */
-  for (i = 0; i < GRAPH_SIZE; i++) {
-    g->n[i].size = ADJLIST_SIZE;
-    g->n[i].top = 0;
-    g->n[i].adj = calloc(g->n[i].size ,sizeof(int));
-    omp_init_lock(&g->n[i].mutex);
-  }
-  
-  printf("Done\n");
-}
-
-void free_graph(graph_t *g){
-  int i;
-  
-  printf("Cleaning up...");
-  
-  for (i = 0; i < GRAPH_SIZE; i++) {
-    free(g->n[i].adj);
-    omp_destroy_lock(&g->n[i].mutex);
-  }
-  free(g->n);
-  
-  printf("Done\n");
-  
-}
-
-
-/* 
- *  * Push a new node to the adjacency list
- *   */
-void push(int i, node_t *n) {
-  int *tmp;
-  
-  if (n->top >= n->size) {
-    n->size += ADJLIST_SIZE;
-    tmp = n->adj;
-    n->adj = realloc(tmp, n->size * sizeof(int));    
-  }
-  
-  n->adj[(n->top++)] = i;
-}
-
-/*
- *  * Add node j as neighbour to node i
- *   */
-void add(int i, int j, graph_t *g) {
-  int k;
-  
-  omp_set_lock(&g->n[i].mutex);
-  for (k = 0; k < g->n[i].top; k++) 
-    if (g->n[i].adj[k] == j) {
-      omp_unset_lock(&g->n[i].mutex);
-      return;
-    }
-  
-  
-  
-  push(j, &g->n[i]);
-  
-  omp_unset_lock(&g->n[i].mutex);
-  
-}
-
-
-
-int main(int argc, char **argv) {
-  int i;
-  graph_t g;
-  double stime;
-  
-  
-  init_graph(&g);
-  
-  stime = gettime();
-#pragma omp parallel shared(g)
-  {
-#pragma omp master
-    {
-      printf("Inserting nodes using %d threads...", omp_get_num_threads());
-      fflush(stdout);
-      
-    }
-#pragma omp barrier
-#pragma omp for 
-    for (i = 0; i < (GRAPH_SIZE * GRAPH_SIZE) ; i++) 
-      add(random()%GRAPH_SIZE, random()%GRAPH_SIZE, &g);
-    
-  }
-  printf("Done\nGraph generated in %.5f seconds\n", gettime() - stime);
-  
-  free_graph(&g);
-  
-  return 0;
-}
-
diff --git a/old_intro_lab/f90/Makefile b/old_intro_lab/f90/Makefile
deleted file mode 100644
index 5af3578b292b53dfb288d27a85852eebdd67205c..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-FC = ftn
-FFLAGS = -g -O2 -Mpreprocess 
-OMPFLAGS = -mp
-LIBS = -lm
-
-all: part1 part2 part3
-
-part1: part1ex1 part1ex2 part1ex3 part1ex4
-	
-
-part2: part2ex1 part2ex2 part2ex3
-	
-
-part3: part3a part3b
-	
-
-part1ex1: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=1 part1.f90 -o $@ $(LIBS)
-
-part1ex2: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=2 part1.f90 -o $@ $(LIBS)
-
-part1ex3: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=3 part1.f90 -o $@ $(LIBS)
-
-part1ex4: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=4 part1.f90 -o $@ $(LIBS)
-
-part2ex1: part2.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=1 part2.f90 -o $@ $(LIBS)
-
-part2ex2: part2.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=2 part2.f90 -o $@ $(LIBS)
-
-part2ex3: part2.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=3 part2.f90 -o $@ $(LIBS)
-
-part3a:	part3a.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) part3a.f90 -o $@ $(LIBS) 
-
-part3b:	part3b.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) part3b.f90 -o $@ $(LIBS) 
-
-part2serial: part2.f90
-	$(FC) $(FFLAGS) -DSERIAL part2.f90 -o $@ $(LIBS)
-
-part3serial: part3a.f90
-	$(FC) $(FFLAGS) -DSERIAL part3a.f90 -o $@ $(LIBS)
-
-clean:
-	rm -fr part1ex1 part1ex2 part1ex3 part1ex4\
-	 part2ex1 part2ex2 part2ex3 part3a part3b *.o 
-
diff --git a/old_intro_lab/f90/part1.f90 b/old_intro_lab/f90/part1.f90
deleted file mode 100644
index ca9344707e58a602ebff532f50ca0cca42101b6e..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/part1.f90
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-!!! This set of exercises aims at showing some basic OpenMP directives and how
-!!! they affect the order (and correctness) of execution
-
-program part1
-  use omp_lib
-  use, intrinsic :: iso_c_binding
-  implicit none
-  integer :: i, j, tid, n, ts
-  integer, dimension(:), allocatable :: buffer
-  double precision rand
-  integer*8 time
-  character*20 ctime 
-  external time
-  external ctime
-
-  interface
-     subroutine usleep(u) bind(c)
-       use, intrinsic :: iso_c_binding
-       integer(kind=c_long), value :: u
-     end subroutine usleep     
-  end interface
-
-
-#if (EXAMPLE == 1)
-  write(*,"(//a/)") "   ----- Exercise 1 ------"
-
-!!! This exercise tries to illustrate a simple parallel OpenMP
-!!! program.  Run it several times. At some occasions the printed
-!!! output is "wrong". Why is that? Correct the program so that it is
-!!! "correct"
-
-
-!$omp parallel private(i, j)
-
-  do i = 1, 1000
-     do j = 1, 1000
-        tid = omp_get_thread_num()
-     end do
-  end do
-
-  print *," Thread ", omp_get_thread_num(),": My value of tid (thread id) is ", tid
-
-!$omp end parallel
-
-  write(*,"(/a/)") "   ----- End of exercise 1 ------"
-#endif
-
-#if (EXAMPLE == 2)
-  write(*,"(//a/)") "   ----- Exercise 2 ------"
-
-!!! This exercise illustrates some of the data-sharing clauses in
-!!! OpenMP. Run the program, is the output correct? Try to make the
-!!! program print the correct value for n for both  parallel sections
-  
-n = 10;
-
-!$omp parallel private(n)
-
-n = n + omp_get_thread_num()
-print *,"Thread ", omp_get_thread_num(), ": My value of n is ", n
-
-!$omp end parallel
-
-j = 100000
-!$omp parallel do private(n)
-do i = 1,j
-   n = i
-end do
-!$omp end parallel do
-print *, "After ", j, "iterations the value of n is ", n
-
-  write(*,"(/a/)") "   ----- End of exercise 2 ------"
-#endif
-
-#if (EXAMPLE == 3)
-  write(*,"(//a/)") "   ----- Exercise 3 ------"
-
-!!! This exercise tries to illustrate the usage of rudimentary OpenMP
-!!! synchronization constructs. Try to make all the threads end at the
-!!! same time
-
-!$omp parallel private(ts, tid)
-
-tid = omp_get_thread_num()
-ts = time()
-
-print *, "Thread", tid, " spawned at: ", ctime(ts)
-call sleep(1)
-
-if (mod(tid,2) .eq. 0) then
-   call sleep(5)
-end if
-
-ts = time()
-print *, "Thread", tid, " done at: ", ctime(ts)
-
-!$omp end parallel
-
-  write(*,"(/a/)") "   ----- End of exercise 3 ------"
-#endif
-
-#if (EXAMPLE == 4)
-  write(*,"(//a/)") "   ----- Exercise 4 ------"
-
-  n = 1000
-  allocate(buffer(n))
-  
-  print *, "Computing..."
-  
-!$omp parallel do schedule(runtime)
-  do i = 1,n
-     buffer(i) = omp_get_thread_num()
-     call usleep(int(rand(buffer(i))*2000, kind=c_long))
-  end do
-!$omp end parallel do
-
-  print *, "Done"
-  open(1, file="schedule.dat")
-  
-  do i = 1, n
-     write(1, *) i, buffer(i)
-  end do
-  close(1)
-
-  print *, "Now, run 'gnuplot schedule.gp' to visualize the scheduling policy"
-
-  deallocate(buffer)
-
-  write(*,"(/a/)") "   ----- End of exercise 4 ------"
-#endif
-end program part1
diff --git a/old_intro_lab/f90/part2.f90 b/old_intro_lab/f90/part2.f90
deleted file mode 100644
index 014d2483ebc44e5b0011c7fcef8aeea9c8cf4673..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/part2.f90
+++ /dev/null
@@ -1,152 +0,0 @@
-!!! This program generates some vectors and matrices
-!!! It manipulates them and finally computes some global
-!!! things that are printed
-
-
-program part2
-  implicit none
-  integer, parameter:: MATSIZE=900
-  double precision, dimension(:,:), allocatable :: Mat_A, Mat_B, Mat_C, Mat_D
-  double precision :: x, y, scal, Sum_A, Sum_B, Sum_C, Sum_D
-  integer :: i, j, k
-
-  double precision :: dtime, dtime2
-  double precision, external :: rtc
-
-  allocate(Mat_A(MATSIZE, MATSIZE),Mat_B(MATSIZE, MATSIZE), &
-       Mat_C(MATSIZE, MATSIZE), MAT_D(MATSIZE, MATSIZE))
-
-  write(*,"(//a/)") "   ----- Exercise 1 ------"
-!!! The code below generates three matrices. Try to think of a way in which
-!!! this can be made parallel in any way. Make sure that the printed output
-!!! x is correct in your parallel version
-
-
-  dtime = rtc()
-
-  x=0.35d0
-  do j=1,MATSIZE
-    do i=1,MATSIZE
-      x=1-fraction(sin(x))
-      Mat_A(i,j)=x
-    end do
-  end do
-
-  x=0.68d0
-  do j=1,MATSIZE
-    do i=1,MATSIZE
-      x=1-fraction(sin(x))
-      Mat_B(i,j)=x
-    end do
-  end do
-      
-  x=0.24d0
-  do j=1,MATSIZE
-    do i=1,MATSIZE
-      x=1-fraction(sin(x))
-      Mat_C(i,j)=x
-    end do
-  end do
-
-  dtime = rtc() - dtime
-  Sum_A=check_sum(Mat_A)
-  Sum_B=check_sum(Mat_B)
-  Sum_C=check_sum(Mat_C)
-
-  print *," The check sum of the matrices evaluates to:"
-  print 100,"A",Sum_A
-  print 100,"B",Sum_B
-  print 100,"C",Sum_C
-  print 110, dtime
-
-  print 101,"The variable x evaluates to",x
-100 format("Sum of matrix ",a,g25.16)
-101 format(a,g37.25)
-110 format("Time for the exercise: ",f9.5," seconds")
-  write(*,"(/a/)") "   ----- End of exercise 1 ------"
-
-#if (EXAMPLE > 1 && EXAMPLE < 3 || SERIAL)
-
-  write(*,"(//a/)") "   ----- Exercise 2 ------"
-!!! This code makes a simple attempt at computing a matrix multiply. Try
-!!! to parallelize it without changing the results (more than negligible)
-!!! In this exercise parallelize the outer-most loop
-  
-  dtime = rtc()
-  do i=1,MATSIZE
-    do j=1,MATSIZE
-      scal=0.0d0
-      do k=1,MATSIZE
-        scal=scal+Mat_A(i,k)*Mat_B(k,j)
-      end do
-      Mat_D(i,j)=scal
-    end do
-  end do
-
-  dtime = rtc() - dtime
-
-  Sum_D=check_sum(Mat_D)
-  print *," The check sum of the matrices evaluates to:"
-  print 100,"D",Sum_D
-  print 101,"The value of scal is:",scal
-  print 110, dtime  
-  write(*,"(/a/)") "   ----- End of exercise 2 ------"
-#endif
-
-#if (EXAMPLE > 2 || SERIAL)
-
-  write(*,"(//a/)") "   ----- Exercise 3 ------"
-!!! This code makes a simple attempt at computing a matrix multiply. Try
-!!! to parallelize it without changing the results (more than negligible)
-!!! In this exercise parallelize the second outer-most loop
-
-  dtime = rtc()
-  do i=1,MATSIZE
-    do j=1,MATSIZE
-      scal=0.0d0
-      do k=1,MATSIZE
-        scal=scal+Mat_A(i,k)*Mat_B(k,j)
-      end do
-      Mat_D(i,j)=scal
-    end do
-  end do
-
-  dtime = rtc() - dtime
-
-  Sum_D=check_sum(Mat_D)
-  print *," The check sum of the matrices evaluates to:"
-  print 100,"D",Sum_D
-  print 101,"The value of scal is:",scal
-  print 110, dtime  
-  write(*,"(/a/)") "   ----- End of exercise 3 ------"
-
-#endif
-
-  deallocate(Mat_A, Mat_B, Mat_C, Mat_D)
-
-contains
-  function check_sum(Mat)
-    implicit none
-    double precision :: check_sum
-    double precision :: Mat(:,:)
-    check_sum=sum(Mat)
-  end function check_sum
-
-  double precision function rtc()
-  implicit none
-  integer:: icnt,irate
-  real, save:: scaling
-  logical, save:: scale = .true.
-  
-  call system_clock(icnt,irate)
-  
-  if(scale)then
-     scaling=1.0/real(irate)
-     scale=.false.
-  end if
-  
-  rtc = icnt * scaling
-
-end function rtc
-
-end program part2
diff --git a/old_intro_lab/f90/part3a.f90 b/old_intro_lab/f90/part3a.f90
deleted file mode 100644
index 8336c33bb61d47c7dabd35af48ceb8196e6e6520..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/part3a.f90
+++ /dev/null
@@ -1,74 +0,0 @@
-module realtypes
-  integer, parameter:: SINGLE=kind(1.0), DOUBLE=kind(1.0d0)
-end module realtypes
-
-program prog4
-  use realtypes
-  use omp_lib
-  implicit none
-
-  integer, parameter:: N=12123123
-  real(DOUBLE), parameter :: PI=3.141592653589793238462643383279506d0
-  integer :: i,j,dN,tid
-  real(DOUBLE), allocatable, dimension(:,:) :: A
-  real(DOUBLE), allocatable, dimension(:) :: blocksum
-  real(DOUBLE) :: dw, fprt, locsum
-  integer :: Nthrds,start,end,MaxNthrds
-
-!  type(omp_lock_t), allocatable :: locks(:)
-
-  real(DOUBLE) :: dtime
-  real(DOUBLE), external :: rtc
-
-  MaxNthrds=1
-  !$ MaxNthrds=omp_get_max_threads()
-
-  allocate(A(N,2),blocksum(0:MaxNthrds-1))
-
-  dw=PI/real(N,kind=DOUBLE)
-  
-  do i=1,N
-    A(i,1)=i*dw
-  end do
-
-  do i=1,N
-    A(i,2)=A(i,1)
-  end do
-
-  dtime=rtc()
-  do i=2,N
-    A(i,1)=A(i-1,1)+A(i,1)
-  end do
-  print *, "First summation loop took ", rtc() - dtime, "seconds"
-
-
-!!!-------------------------------------------------------
-
-  dtime=rtc()
-  do i=2,N
-    A(i,2)=A(i-1,2)+A(i,2)
-  end do
-  print *,"Second summation loop took",rtc() - dtime,"seconds"
-
-  print *,A(N,1),A(N,2)
-
-contains
-
-  double precision function rtc()
-    implicit none
-    integer:: icnt,irate
-    real, save:: scaling
-    logical, save:: scale = .true.
-    
-    call system_clock(icnt,irate)
-    
-    if(scale)then
-       scaling=1.0/real(irate)
-       scale=.false.
-    end if
-    
-    rtc = icnt * scaling
-    
-  end function rtc
-  
-end program prog4
diff --git a/old_intro_lab/f90/part3b.f90 b/old_intro_lab/f90/part3b.f90
deleted file mode 100644
index 57ea66a92a758e356f173eed94f0014022ed73ce..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/part3b.f90
+++ /dev/null
@@ -1,132 +0,0 @@
-
-!!! This exercise aims at showing the mutual exclusion clauses in
-!!! OpenMP. The program generates a graph, represented as an adjacency
-!!! list. Is the given program correct? Try to fix it without too much
-!!! parallel overhead.
-
-program part3b
-  use omp_lib
-  implicit none
-
-  integer, parameter :: GRAPH_SIZE = 1000
-  integer, parameter :: ADJLIST_SIZE = 4
-  double precision rand, stime
-  double precision, external :: rtc
-
-  type node_t
-     integer, pointer :: adj(:)
-     integer top, size
-  end type node_t
-
-  type graph_t
-     type(node_t), pointer :: n(:)     
-  end type graph_t
-
-  integer i
-  type(graph_t) g
-
-
-  call init_graph(g)
-
-  stime = rtc()
-!$omp parallel shared(g)
-!$omp master
-  print *, "Inserting nodes using", omp_get_num_threads(), "threads"
-!$omp end master
-!$omp do
-  do i = 1, GRAPH_SIZE**2
-     call add(mod(int(rand(0)*(2**31 -1)), GRAPH_SIZE) + 1, &
-          mod(int(rand(0)*(2**31 -1)), GRAPH_SIZE) + 1, g)
-  end do
-!$omp end do
-!$omp end parallel
-  print *, "Done, graph generated in", rtc()-stime, "seconds"
-  
-  call free_graph(g)
-
-contains
-  subroutine init_graph(g)
-    integer i
-    type(graph_t), intent(inout) :: g
-
-    print *,"Initialize graph data structure..."
-
-    allocate(g%n(GRAPH_SIZE))
-    
-    do i = 1, GRAPH_SIZE
-       allocate(g%n(i)%adj(ADJLIST_SIZE))
-       g%n(i)%adj(:) = 0
-       g%n(i)%top = 1
-       g%n(i)%size = 0
-    end do
-    
-    print *, "Done"
-
-  end subroutine init_graph
-  
-  subroutine free_graph(g)
-    integer i
-    type(graph_t), intent(inout) :: g
-    
-    print *,"Cleaning up..."
-    
-    do i = 1,GRAPH_SIZE
-       deallocate(g%n(i)%adj)       
-    end do
-    deallocate(g%n)
-
-    print *,"Done"
-
-  end subroutine free_graph
-
-!! Push a new node to the adjacency list
-  subroutine push(i, n)
-    integer, intent(in) :: i
-    type(node_t), intent(inout) :: n
-    integer, pointer :: tmp(:)
-
-    if (n%top .ge. n%size) then
-       n%size = n%size + ADJLIST_SIZE
-       allocate(tmp(n%size))
-       tmp(1:n%top) = n%adj(:)
-       deallocate(n%adj)
-       n%adj => tmp
-    end if
-
-    n%adj(n%top) = i
-    n%top = n%top + 1   
-  end subroutine push
-
-!! Add node j as neighbour to node i
-  subroutine add(i, j, g)
-    integer, intent(in) :: i, j
-    type(graph_t), intent(inout) :: g
-    integer k
-
-    do k = 1, (g%n(i)%top - 1)
-       if (g%n(i)%adj(k) .eq. j) then
-          return
-       end if
-    end do
-
-    call push(j, g%n(i)) 
-  end subroutine add
-
-  double precision function rtc()
-    implicit none
-    integer:: icnt,irate
-    real, save:: scaling
-    logical, save:: scale = .true.
-    
-    call system_clock(icnt,irate)
-    
-    if(scale)then
-       scaling=1.0/real(irate)
-       scale=.false.
-    end if
-    
-    rtc = icnt * scaling
-    
-  end function rtc
-  
- end program part3b
diff --git a/old_intro_lab/f90/schedule.gp b/old_intro_lab/f90/schedule.gp
deleted file mode 100644
index 76714e3510ee40c07be67582d360e75959b92ec6..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/schedule.gp
+++ /dev/null
@@ -1,7 +0,0 @@
-set terminal png 
-set autoscale
-set output "schedule.png" 
-set xlabel "Iteration"
-set ylabel "Thread ID"
-unset key
-plot "schedule.dat" using 1:2 ls 4
\ No newline at end of file
diff --git a/old_intro_lab/f90/sol/Makefile b/old_intro_lab/f90/sol/Makefile
deleted file mode 100644
index bf44d576de8a82f2a11fa3c5260aa0961bec05d3..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/sol/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-FC = ftn
-FFLAGS = -fpp -O2
-OMPFLAGS = -openmp
-LIBS = -lm
-
-all: part1 part2 part3
-
-part1: part1ex1 part1ex2 part1ex3 part1ex4
-	
-
-part2: part2ex1 part2ex2 part2ex3
-	
-
-part3: part3a part3b
-	
-
-part1ex1: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=1 part1.f90 -o $@ $(LIBS)
-
-part1ex2: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=2 part1.f90 -o $@ $(LIBS)
-
-part1ex3: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=3 part1.f90 -o $@ $(LIBS)
-
-part1ex4: part1.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=4 part1.f90 -o $@ $(LIBS)
-
-part2ex1: part2.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=1 part2.f90 -o $@ $(LIBS)
-
-part2ex2: part2.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=2 part2.f90 -o $@ $(LIBS)
-
-part2ex3: part2.f90
-	$(FC) $(FFLAGS) $(OMPFLAGS) -DEXAMPLE=3 part2.f90 -o $@ $(LIBS)
-
-part3a:	part3a.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) part3a.f90 -o $@ $(LIBS) 
-
-part3b:	part3b.f90 
-	$(FC) $(FFLAGS) $(OMPFLAGS) part3b.f90 -o $@ $(LIBS) 
-
-part2serial: part2.f90
-	$(FC) $(FFLAGS) -DSERIAL part2.f90 -o $@ $(LIBS)
-
-part3serial: part3a.f90
-	$(FC) $(FFLAGS) -DSERIAL part3a.f90 -o $@ $(LIBS)
-
-clean:
-	rm -fr part1ex1 part1ex2 part1ex3 part1ex4\
-	 part2ex1 part2ex2 part2ex3 part3a part3b *.o 
-
diff --git a/old_intro_lab/f90/sol/part2.f90 b/old_intro_lab/f90/sol/part2.f90
deleted file mode 100644
index cd938d02b218566454541e5b28adb95f5ef39589..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/sol/part2.f90
+++ /dev/null
@@ -1,160 +0,0 @@
-!!! This program generates some vectors and matrices
-!!! It manipulates them and finally computes some global
-!!! things that are printed
-
-
-program part2
-  implicit none
-  integer, parameter:: MATSIZE=900
-  double precision, dimension(:,:), allocatable :: Mat_A, Mat_B, Mat_C, Mat_D
-  double precision :: x, y, scal, Sum_A, Sum_B, Sum_C, Sum_D
-  integer :: i, j, k
-
-  double precision :: dtime, dtime2
-
-  allocate(Mat_A(MATSIZE, MATSIZE),Mat_B(MATSIZE, MATSIZE), &
-       Mat_C(MATSIZE, MATSIZE), MAT_D(MATSIZE, MATSIZE))
-
-  write(*,"(//a/)") "   ----- Exercise 1 ------"
-!!! The code below generates three matrices. Try to think of a way in which
-!!! this can be made parallel in any way. Make sure that the printed output
-!!! x is correct in your parallel version
-
-
-  dtime = rtc()
-!$omp parallel sections private(i,j) lastprivate(x)
-!$omp section
-  x=0.35d0
-  do j=1,MATSIZE
-    do i=1,MATSIZE
-      x=1-fraction(sin(x))
-      Mat_A(i,j)=x
-    end do
-  end do
-
-!$omp section
-  x=0.68d0
-  do j=1,MATSIZE
-    do i=1,MATSIZE
-      x=1-fraction(sin(x))
-      Mat_B(i,j)=x
-    end do
-  end do
-      
-!$omp section
-  x=0.24d0
-  do j=1,MATSIZE
-    do i=1,MATSIZE
-      x=1-fraction(sin(x))
-      Mat_C(i,j)=x
-    end do
-  end do
-!$omp end parallel sections
-
-  dtime = rtc() - dtime
-  Sum_A=check_sum(Mat_A)
-  Sum_B=check_sum(Mat_B)
-  Sum_C=check_sum(Mat_C)
-
-  print *," The check sum of the matrices evaluates to:"
-  print 100,"A",Sum_A
-  print 100,"B",Sum_B
-  print 100,"C",Sum_C
-  print 110, dtime
-
-  print 101,"The variable x evaluates to",x
-100 format("Sum of matrix ",a,g25.16)
-101 format(a,g37.25)
-110 format("Time for the exercise: ",f9.5," seconds")
-  write(*,"(/a/)") "   ----- End of exercise 1 ------"
-
-#if (EXAMPLE > 1 && EXAMPLE < 3 || SERIAL)
-
-  write(*,"(//a/)") "   ----- Exercise 2 ------"
-!!! This code makes a simple attempt at computing a matrix multiply. Try
-!!! to parallelize it without changing the results (more than negligible)
-!!! In this exercise parallelize the outer-most loop
-  
-  dtime = rtc()
-!$omp parallel do private(j,k) lastprivate(scal)
-  do i=1,MATSIZE
-    do j=1,MATSIZE
-      scal=0.0d0
-      do k=1,MATSIZE
-        scal=scal+Mat_A(i,k)*Mat_B(k,j)
-      end do
-      Mat_D(i,j)=scal
-    end do
-  end do
-!$omp end parallel do
-
-  dtime = rtc() - dtime
-
-  Sum_D=check_sum(Mat_D)
-  print *," The check sum of the matrices evaluates to:"
-  print 100,"D",Sum_D
-  print 101,"The value of scal is:",scal
-  print 110, dtime  
-  write(*,"(/a/)") "   ----- End of exercise 2 ------"
-#endif
-
-#if (EXAMPLE > 2 || SERIAL)
-
-  write(*,"(//a/)") "   ----- Exercise 3 ------"
-!!! This code makes a simple attempt at computing a matrix multiply. Try
-!!! to parallelize it without changing the results (more than negligible)
-!!! In this exercise parallelize the second outer-most loop
-
-  dtime = rtc()
-  do i=1,MATSIZE
-!$omp parallel do private(k) lastprivate(scal)
-    do j=1,MATSIZE
-      scal=0.0d0
-      do k=1,MATSIZE
-        scal=scal+Mat_A(i,k)*Mat_B(k,j)
-      end do
-      Mat_D(i,j)=scal
-    end do
-!$omp end parallel do
-  end do
-
-  dtime = rtc() - dtime
-
-  Sum_D=check_sum(Mat_D)
-  print *," The check sum of the matrices evaluates to:"
-  print 100,"D",Sum_D
-  print 101,"The value of scal is:",scal
-  print 110, dtime  
-  write(*,"(/a/)") "   ----- End of exercise 3 ------"
-
-#endif
-
-  deallocate(Mat_A, Mat_B, Mat_C, Mat_D)
-
-contains
-  function check_sum(Mat)
-    implicit none
-    double precision :: check_sum
-    double precision :: Mat(:,:)
-    check_sum=sum(Mat)
-  end function check_sum
-
-  function rtc()
-    implicit none
-    double precision :: rtc
-    integer:: icnt,irate
-    real, save:: scaling
-    logical, save:: scale = .true.
-    
-    call system_clock(icnt,irate)
-    
-    if(scale)then
-       scaling=1.0/real(irate)
-       scale=.false.
-    end if
-    
-    rtc = icnt * scaling
-
-  end function rtc
-
-end program part2
diff --git a/old_intro_lab/f90/sol/part3a.f90 b/old_intro_lab/f90/sol/part3a.f90
deleted file mode 100644
index 730241e4d5ce7d3d9f4796ef153ed76efb804fb7..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/sol/part3a.f90
+++ /dev/null
@@ -1,129 +0,0 @@
-module realtypes
-  integer, parameter:: SINGLE=kind(1.0), DOUBLE=kind(1.0d0)
-end module realtypes
-
-program prog3a
-  use realtypes
-  use omp_lib
-  implicit none
-
-  integer, parameter:: N=12123123
-  real(DOUBLE), parameter :: PI=3.141592653589793238462643383279506d0
-  integer :: i,j,dN,tid
-  real(DOUBLE), allocatable, dimension(:,:) :: A
-  real(DOUBLE), allocatable, dimension(:) :: blocksum
-  real(DOUBLE) :: dw, fprt, locsum
-  integer :: Nthrds,start,end,MaxNthrds
-
-  integer(kind=omp_lock_kind) , allocatable :: locks(:)
-
-  real(DOUBLE) :: dtime
-
-  MaxNthrds=1
-  !$ MaxNthrds=omp_get_max_threads()
-
-  allocate(A(N,2),blocksum(0:MaxNthrds-1))
-
-  dw=PI/real(N,kind=DOUBLE)
-  
-  do i=1,N
-    A(i,1)=i*dw
-  end do
-
-  do i=1,N
-    A(i,2)=A(i,1)
-  end do
-
-  dtime=rtc()
-  !$omp parallel default(none) &
-  !$omp  shared(blocksum,A), private(locsum,i,start,end,Nthrds,tid,dN)
-  
-  start=1 ; end=N ; tid=0 ; Nthrds=1  ! Defaults for non-OpenMP
-  !!! OpenMP task work division
-  !$ Nthrds=omp_get_num_threads()
-  !$ dN=ceiling(real(N)/Nthrds) ; tid=omp_get_thread_num()
-  !$ start=1+tid*dN ; end=min((tid+1)*dN,N)
-  
-  locsum=A(start,1)  !!! Compute sum of my local elements
-  do i=start+1,end
-     locsum=locsum+A(i,1)
-     A(i,1)=A(i-1,1)+A(i,1)
-  end do
-  blocksum(tid)=locsum !!! Store the sum in shared variable
-  
-  !$omp barrier   !!! Wait for all sums to be ready and flushed
-  
-  locsum=0.0      !!! Find out what to add to my local values
-  do i=tid-1,0,-1
-     locsum=locsum+blocksum(i)
-  end do
-  
-  do i=start,end  !!! Add this to my values
-     A(i,1)=A(i,1)+locsum
-  end do
-  
-  !$omp end parallel
-  print *, "First summation loop took ", rtc() - dtime, "seconds"
-  
-
-!!!-------------------------------------------------------
-
-  !$ allocate(locks(0:MaxNthrds-1))
-  !$ do tid=0,MaxNthrds-1
-  !$   call omp_init_lock(locks(tid))
-  !$ end do
-  
-  dtime=rtc()
-  !$omp parallel default(none) &
-  !$omp  shared(blocksum,A,locks), private(locsum,i,start,end,Nthrds,tid,dN)
-  start=1 ; end=N ; tid=0 ; Nthrds=omp_get_num_threads()
-  
-  !$ dN=ceiling(real(N)/Nthrds) ; tid=omp_get_thread_num()
-  !$ start=1+tid*dN ; end=min((tid+1)*dN,N)
-  !$ call omp_set_lock(locks(tid))  ! Protect my local sum with a lock
-  
-  locsum=A(start,2)
-  do i=start+1,end
-     locsum=locsum+A(i,2)
-     A(i,2)=A(i-1,2)+A(i,2)
-  end do
-  blocksum(tid)=locsum
-  
-  !$ call omp_unset_lock(locks(tid)) ! Allow for others to read my value
-  
-  locsum=0.0
-  do i=tid-1,0,-1
-     !$ call omp_set_lock(locks(i))  ! Make sure the value is available for reading
-     !$ call omp_unset_lock(locks(i))
-     locsum=locsum+blocksum(i)
-  end do
-  
-  do i=start,end
-     A(i,2)=A(i,2)+locsum
-  end do
-  
-  !$omp end parallel
-  print *,"Second summation loop took",rtc() - dtime,"seconds"
-  
-  print *,A(N,1),A(N,2)
-  
-contains
-
-  double precision function rtc()
-    implicit none
-    integer:: icnt,irate
-    real, save:: scaling
-    logical, save:: scale = .true.
-    
-    call system_clock(icnt,irate)
-    
-    if(scale)then
-       scaling=1.0/real(irate)
-       scale=.false.
-    end if
-    
-    rtc = icnt * scaling
-    
-  end function rtc
-  
-end program prog3a
diff --git a/old_intro_lab/f90/sol/part3b_critical.f90 b/old_intro_lab/f90/sol/part3b_critical.f90
deleted file mode 100644
index 77bd8f6b4546a09a17cf1e540ff364a9621236b3..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/sol/part3b_critical.f90
+++ /dev/null
@@ -1,143 +0,0 @@
-!!! This exercise aims at showing the mutual exclusion clauses in
-!!! OpenMP. The program generates a graph, represented as an adjacency
-!!! list. Is the given program correct? Try to fix it without too much
-!!! parallel overhead.
-
-program part3b
-  use omp_lib
-  implicit none
-
-  integer, parameter :: GRAPH_SIZE = 1000
-  integer, parameter :: ADJLIST_SIZE = 4
-  double precision :: rand, stime
-  real :: r1,r2
-
-  type node_t
-     integer, pointer :: adj(:)
-     integer top, size
-  end type node_t
-
-  type graph_t
-     type(node_t), pointer :: n(:)     
-  end type graph_t
-
-  integer i,ii,jj
-  type(graph_t) g
-
-  call random_seed()
-  call init_graph(g)
-
-  stime = rtc()
-!$omp parallel shared(g) private(ii,jj,r1,r2)
-!$omp master
-  print *, "Inserting nodes using", omp_get_num_threads(), "threads"
-!$omp end master
-!$omp do
-  do i = 1, GRAPH_SIZE**2
-      call random_number(r1)
-      call random_number(r2)   
-      ii=mod(int(r1*(2**15 -1)), GRAPH_SIZE) + 1
-      jj=mod(int(r2*(2**15 -1)), GRAPH_SIZE) + 1
-      call add(ii,jj,g)
-  end do
-!$omp end do
-!$omp end parallel
-  print *, "Done, graph generated in", rtc()-stime, "seconds"
-  
-  call free_graph(g)
-
-contains
-  subroutine init_graph(g)
-    integer i
-    type(graph_t), intent(inout) :: g
-
-    print *,"Initialize graph data structure..."
-
-    allocate(g%n(GRAPH_SIZE))
-    
-    do i = 1, GRAPH_SIZE
-       allocate(g%n(i)%adj(ADJLIST_SIZE))
-       g%n(i)%adj(:) = 0
-       g%n(i)%top = 1
-       g%n(i)%size = 0
-    end do
-    
-    print *, "Done"
-
-  end subroutine init_graph
-  
-  subroutine free_graph(g)
-    integer i
-    type(graph_t), intent(inout) :: g
-    
-    print *,"Cleaning up..."
-    
-    do i = 1,GRAPH_SIZE
-       deallocate(g%n(i)%adj)       
-    end do
-    deallocate(g%n)
-
-    print *,"Done"
-
-  end subroutine free_graph
-
-!! Push a new node to the adjacency list
-  subroutine push(i, n)
-    integer, intent(in) :: i
-    type(node_t), intent(inout) :: n
-    integer, pointer :: tmp(:)
-
-    if (n%top .ge. n%size) then
-       n%size = n%size + ADJLIST_SIZE
-       allocate(tmp(n%size))
-       tmp(1:n%top) = n%adj(:)
-       deallocate(n%adj)
-       n%adj => tmp
-    end if
-
-    n%adj(n%top) = i
-    n%top = n%top + 1   
-  end subroutine push
-
-!! Add node j as neighbour to node i
-  subroutine add(i, j, g)
-    integer, intent(in) :: i, j
-    type(graph_t), intent(inout) :: g
-    integer k
-    logical flag
-    flag = .false.
-
-    !$omp critical
-    do k = 1, (g%n(i)%top - 1)
-       if (g%n(i)%adj(k) .eq. j) then
-           flag = .true.
-           exit
-       end if
-    end do
-
-    if (flag .eqv. .false.) then
-        call push(j, g%n(i)) 
-    end if
-    !$omp end critical
-
-  end subroutine add
-
-  function rtc()
-    implicit none
-    double precision :: rtc
-    integer:: icnt,irate
-    real, save:: scaling
-    logical, save:: scale = .true.
-    
-    call system_clock(icnt,irate)
-    
-    if(scale)then
-       scaling=1.0/real(irate)
-       scale=.false.
-    end if
-    
-    rtc = icnt * scaling
-    
-  end function rtc
-  
- end program part3b
diff --git a/old_intro_lab/f90/sol/part3b_locks.f90 b/old_intro_lab/f90/sol/part3b_locks.f90
deleted file mode 100644
index d5fcf9ad854fc744a571be4abfd223df299a04c3..0000000000000000000000000000000000000000
--- a/old_intro_lab/f90/sol/part3b_locks.f90
+++ /dev/null
@@ -1,142 +0,0 @@
-!!! This exercise aims at showing the mutual exclusion clauses in
-!!! OpenMP. The program generates a graph, represented as an adjacency
-!!! list. Is the given program correct? Try to fix it without too much
-!!! parallel overhead.
-
-program part3b
- use omp_lib
- implicit none
-
- integer, parameter :: GRAPH_SIZE = 1000
- integer, parameter :: ADJLIST_SIZE = 4
- double precision :: rand, stime
- real :: r1,r2
-
- type node_t
-   integer, pointer :: adj(:)
-   integer top, size
-   integer(kind=omp_lock_kind) :: mutex
- end type node_t
-
- type graph_t
-   type(node_t), pointer :: n(:)     
- end type graph_t
-
- integer i,ii,jj
- type(graph_t) g
-
- call random_seed()
- call init_graph(g)
-
- stime = rtc()
-!$omp parallel shared(g) private(ii,jj,r1,r2)
-!$omp master
- print *, "Inserting nodes using", omp_get_num_threads(), "threads"
-!$omp end master
-!$omp do
- do i = 1, GRAPH_SIZE**2
-   call random_number(r1)
-   call random_number(r2)   
-   ii=mod(int(r1*(2**15 -1)), GRAPH_SIZE) + 1
-   jj=mod(int(r2*(2**15 -1)), GRAPH_SIZE) + 1
-   call add(ii,jj,g)
- end do
-!$omp end do
-!$omp end parallel
- print *, "Done, graph generated in", rtc()-stime, "seconds"
- 
- call free_graph(g)
-
-contains
-  subroutine init_graph(g)
-    integer i
-    type(graph_t), intent(inout) :: g
-
-    print *,"Initialize graph data structure..."
-
-    allocate(g%n(GRAPH_SIZE))
- 
-    do i = 1, GRAPH_SIZE
-      allocate(g%n(i)%adj(ADJLIST_SIZE))
-      g%n(i)%adj(:) = 0
-      g%n(i)%top = 1
-      g%n(i)%size = 0
-!$ call omp_init_lock(g%n(i)%mutex)
-    end do
- 
-    print *, "Done"
-
-  end subroutine init_graph
- 
-  subroutine free_graph(g)
-    integer i
-    type(graph_t), intent(inout) :: g
- 
-    print *,"Cleaning up..."
- 
-    do i = 1,GRAPH_SIZE
-      deallocate(g%n(i)%adj)       
-!$ call omp_destroy_lock(g%n(i)%mutex)
-    end do
-    deallocate(g%n)
-
-    print *,"Done"
-
-  end subroutine free_graph
-
-!! Push a new node to the adjacency list
-  subroutine push(i, n)
-    integer, intent(in) :: i
-    type(node_t), intent(inout) :: n
-    integer, pointer :: tmp(:)
-
-    if (n%top .ge. n%size) then
-      n%size = n%size + ADJLIST_SIZE
-      allocate(tmp(n%size))
-      tmp(1:n%top) = n%adj(:)
-      deallocate(n%adj)
-      n%adj => tmp
-    end if
-
-    n%adj(n%top) = i
-    n%top = n%top + 1   
-  end subroutine push
-
-!! Add node j as neighbour to node i
-  subroutine add(i, j, g)
-    integer, intent(in) :: i, j
-    type(graph_t), intent(inout) :: g
-    integer k
-
-!$ call omp_set_lock(g%n(i)%mutex)
-    do k = 1, (g%n(i)%top - 1)
-      if (g%n(i)%adj(k) .eq. j) then
-!$ call omp_unset_lock(g%n(i)%mutex)
-        return
-      end if
-    end do
-
-    call push(j, g%n(i)) 
-
-!$ call omp_unset_lock(g%n(i)%mutex)
-  end subroutine add
-
-  function rtc()
-    implicit none
-    double precision :: rtc
-    integer:: icnt,irate
-    real, save:: scaling
-    logical, save:: scale = .true.
- 
-    call system_clock(icnt,irate)
- 
-    if(scale)then
-      scaling=1.0/real(irate)
-      scale=.false.
-    end if
- 
-    rtc = icnt * scaling
- 
-  end function rtc
- 
-end program part3b