Spencer,

Rather than try and pull this off my machine from the aeronautics dept, I 
thought I'd just send you the patch.

This is the full, unadulterated patch to the source as I have it here. It 
includes all the trial and error changes to the global variables as well as 
the genuine leak fixes.

Angus
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Basis.C clean2/Hlib/src/Basis.C
--- dirty/Hlib/src/Basis.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Basis.C	Wed May  1 17:51:41 2002
@@ -603,142 +603,205 @@ static double norm(int np, double *d, ch
 
 
 /* interpolation matrix */
 
-static double   ***BasisA_G,  ***BasisA_GL, ***BasisA_GR;
-static double  ****BasisB_G, ****BasisB_GR;
-static double  ****BasisC_GR, ****BasisC_G;
-
-/* This function initialises the orthogonal basis statically defined
-   matrices based on QGmax. These arrays may be accessed form [1-QGmax]*/
-
-void init_ortho_basis(void){
-  BasisA_G  = (double ***) calloc(QGmax, sizeof(double **));
-  BasisA_G -= 1;
-  BasisA_GL = (double ***) calloc(QGmax, sizeof(double **));
-  BasisA_GL-= 1;
-  BasisA_GR = (double ***) calloc(QGmax, sizeof(double **));
-  BasisA_GR-= 1;
+// This class initialises the orthogonal basis matrices based on QGmax. 
+// These arrays may be accessed from [1-QGmax]
+class OBMatrices {
+public:
+  // This is a singleton class. Get the instance.
+  static OBMatrices & get();
+
+  // Some compilers don't like the d-tor being private.
+  ~OBMatrices();
+
+  double *** A_G;
+  double *** A_GL;
+  double *** A_GR;
+  double **** B_G;
+  double **** B_GR;
+  double **** C_GR;
+  double **** C_G;
+
+private:
+  // Make the c-tor private so we can control how many objects
+  // are instantiated.
+  OBMatrices();
+};
+
+OBMatrices & OBMatrices::get()
+{
+  static OBMatrices singleton;
+  return singleton;
+}
+
+OBMatrices::OBMatrices()
+{
+  A_G  = (double ***) calloc(QGmax, sizeof(double **));
+  A_G -= 1;
+  A_GL = (double ***) calloc(QGmax, sizeof(double **));
+  A_GL-= 1;
+  A_GR = (double ***) calloc(QGmax, sizeof(double **));
+  A_GR-= 1;
  
-  BasisB_G  = (double ****)calloc(QGmax, sizeof(double ***));
-  BasisB_G -= 1;
-  BasisB_GR = (double ****)calloc(QGmax, sizeof(double ***));
-  BasisB_GR-= 1;
+  B_G  = (double ****)calloc(QGmax, sizeof(double ***));
+  B_G -= 1;
+  B_GR = (double ****)calloc(QGmax, sizeof(double ***));
+  B_GR-= 1;
 
-  BasisC_GR = (double ****)calloc(QGmax, sizeof(double ***));
-  BasisC_GR-= 1;
+  C_GR = (double ****)calloc(QGmax, sizeof(double ***));
+  C_GR-= 1;
 
-  BasisC_G = (double ****)calloc(QGmax, sizeof(double ***));
-  BasisC_G-= 1;
+  C_G = (double ****)calloc(QGmax, sizeof(double ***));
+  C_G-= 1;
+}
 
+OBMatrices::~OBMatrices()
+{
+  // i starts at 1 because of the offset, above.
+  for (int i = 1; i <= QGmax; ++i) {
+    if (A_G[i]) {
+      free_dmatrix(A_G[i],  0, 0);
+    }
+    if (A_GL[i]) {
+      free_dmatrix(A_GL[i], 0, 0);
+    }
+    if (A_GR[i]) {
+      free_dmatrix(A_GR[i], 0, 0);
+    }
+    if (B_G[i]) {
+      free(B_G[i][0][0]);  free(B_G[i][0]);  free(B_G[i]);
+    }
+    if (B_GR[i]) {
+      free(B_GR[i][0][0]); free(B_GR[i][0]); free(B_GR[i]);
+    }
+    if (C_G[i]) {
+      free(C_G[i][0][0]);  free(C_G[i][0]);  free(C_G[i]);
+    }
+    if (C_GR[i]) {
+      free(C_GR[i][0][0]); free(C_GR[i][0]); free(C_GR[i]);
+    }
+  }
+  // The increment is needed to return to the address of the allocation.
+  free(++A_G);
+  free(++A_GL);
+  free(++A_GR);
+  free(++B_G);
+  free(++B_GR);
+  free(++C_GR);
+  free(++C_G);
 }
 
+// Now that we use a singleton class to store the Matrices, this function is
+// redundant.
+void init_ortho_basis()
+{}
+
 /* Gets the values of "mode" (0..LGmax) degree Leg. poly on "size"
-   Gauss points, stores the result in BasisA_G[size][mode] array */
-void get_moda_G  (int size, double ***mat){
+   Gauss points, stores the result in OBMatrices::get().A_G[size][mode] array */void get_moda_G  (int size, double ***mat){
 
-  if (!BasisA_G[size]){
+  if (!OBMatrices::get().A_G[size]){
     double *w, *z;
     int i;
 
-    BasisA_G[size] = dmatrix(0,LGmax-1,0,size-1);
+    OBMatrices::get().A_G[size] = dmatrix(0,LGmax-1,0,size-1);
     getzw(size,&z,&w,'g');
     
     for (i=0; i < LGmax; ++i){
-      jacobf(size, z, BasisA_G[size][i], i, 0.0, 0.0);
+      jacobf(size, z, OBMatrices::get().A_G[size][i], i, 0.0, 0.0);
       /* normalise so that  (g,g)=1*/
 #ifndef NONORM
-      dscal(size,sqrt(0.5*(2.0*i+1.0)),BasisA_G[size][i],1);
+      dscal(size,sqrt(0.5*(2.0*i+1.0)),OBMatrices::get().A_G[size][i],1);
 #endif
     }
   }
     
-  *mat = BasisA_G[size];
+  *mat = OBMatrices::get().A_G[size];
   return;
 }
 
 /* computes the values of a_mode[mode_a][j], mode_a=0..LGmax,
    j=0..size-1, at size Gauss-Lob. points, stores the result in
-   BasisA_GL[size][mode_a] array */
+   OBMatrices::get().A_GL[size][mode_a] array */
 void get_moda_GL (int size, double ***mat){
 
-  if (!BasisA_GL[size]){
+  if (!OBMatrices::get().A_GL[size]){
     double *w, *z;
     int i;
     double *tmp = dvector(0, size-1);
-    BasisA_GL[size] = dmatrix(0,LGmax-1,0,size-1);
+    OBMatrices::get().A_GL[size] = dmatrix(0,LGmax-1,0,size-1);
     getzw(size,&z,&w,'a');
     
     for (i=0; i < LGmax; ++i){
-      jacobf(size, z, BasisA_GL[size][i], i, 0.0, 0.0);
+      jacobf(size, z, OBMatrices::get().A_GL[size][i], i, 0.0, 0.0);
 
 #ifndef NONORM
       /* normalise so that (g,g)=1*/
-      dscal(size,sqrt(0.5*(2.0*i+1.0)),BasisA_GL[size][i],1);
+      dscal(size,sqrt(0.5*(2.0*i+1.0)),OBMatrices::get().A_GL[size][i],1);
 #endif
     }
     free(tmp);
 
   }
-  *mat = BasisA_GL[size];
+  *mat = OBMatrices::get().A_GL[size];
   return;
 }
 
 
 /* computes the values of a_mode[mode_a][j], mode_a=0..LGmax,
    j=0..size-1, at size Gauss-Lob. points, stores the result in
-   BasisA_GL[size][mode_a] array */
+   OBMatrices::get().A_GL[size][mode_a] array */
 void get_moda_GR (int size, double ***mat){
 
-  if (!BasisA_GR[size]){
+  if (!OBMatrices::get().A_GR[size]){
     double *w, *z;
     int i;
     double *tmp = dvector(0, size-1);
-    BasisA_GR[size] = dmatrix(0,LGmax-1,0,size-1);
+    OBMatrices::get().A_GR[size] = dmatrix(0,LGmax-1,0,size-1);
     getzw(size,&z,&w,'b');
     
     for (i=0; i < LGmax; ++i){
-      jacobf(size, z, BasisA_GR[size][i], i, 0.0, 0.0);
+      jacobf(size, z, OBMatrices::get().A_GR[size][i], i, 0.0, 0.0);
 #ifndef NONORM
       /* normalise so that (g,g)=1*/
-      dscal(size,sqrt(0.5*(2.0*i+1.0)),BasisA_GR[size][i],1);
+      dscal(size,sqrt(0.5*(2.0*i+1.0)),OBMatrices::get().A_GR[size][i],1);
 #endif
     }
     free(tmp);
 
   }
-  *mat = BasisA_GR[size];
+  *mat = OBMatrices::get().A_GR[size];
   return;
 }
 
 /* computes the values of b dependent modes at either the gauss or
    gauss radau points depending on the function and stores the result
-   in BasisB_G array */
+   in OBMatrices::get().B_G array */
 
 static double ***get_Bmodes(int size, double *z);
 static double ***get_Cmodes(int size, double *z);
 
 void get_modb_G (int size, double ****mat){
   
-  if (!BasisB_G[size]){
+  if (!OBMatrices::get().B_G[size]){
     double *w,*z;
     getzw (size,&z,&w,'h');
-    BasisB_G[size] = get_Bmodes(size,z);
+    OBMatrices::get().B_G[size] = get_Bmodes(size,z);
   }
   
-  *mat = BasisB_G[size];
+  *mat = OBMatrices::get().B_G[size];
   return;
 }
 
 void get_modb_GR (int size, double ****mat){
   
-  if (!BasisB_GR[size]){
+  if (!OBMatrices::get().B_GR[size]){
     double *w,*z;
     getzw (size,&z,&w,'b');
-    BasisB_GR[size] = get_Bmodes(size,z);
+    OBMatrices::get().B_GR[size] = get_Bmodes(size,z);
   }
   
-  *mat = BasisB_GR[size];
+  *mat = OBMatrices::get().B_GR[size];
   return;
 }
 
 static double ***get_Bmodes(int size, double *z){
@@ -792,27 +855,27 @@ static double ***get_Bmodes(int size, do
 }
 
 void get_modc_GR (int size, double ****mat){
   
-  if (!BasisC_GR[size]){
+  if (!OBMatrices::get().C_GR[size]){
     double *w,*z;
     getzw (size,&z,&w,'c');
-    BasisC_GR[size] = get_Cmodes(size,z);
+    OBMatrices::get().C_GR[size] = get_Cmodes(size,z);
   }
   
-  *mat = BasisC_GR[size];
+  *mat = OBMatrices::get().C_GR[size];
   return;
 }
 
 void get_modc_G (int size, double ****mat){
   
-  if (!BasisC_G[size]){
+  if (!OBMatrices::get().C_G[size]){
     double *w,*z;
     getzw (size,&z,&w,'h');
-    BasisC_G[size] = get_Cmodes(size,z);
+    OBMatrices::get().C_G[size] = get_Cmodes(size,z);
   }
   
-  *mat = BasisC_G[size];
+  *mat = OBMatrices::get().C_G[size];
   return;
 }
 
 		  
@@ -884,31 +947,75 @@ void reset_bases(){
   Hex_reset_basis();
 }
 
 
-static double   ***Mod_BasisA, ****Mod_BasisB, ****Mod_BasisC;
-
-void init_mod_basis(void){
-  Mod_BasisA  = (double ***) calloc(QGmax, sizeof(double **));
-  Mod_BasisA -= 1;
+// This class initialises the modified basis matrices based on QGmax. 
+// These arrays may be accessed from [1-QGmax]
+class MBMatrices {
+public:
+  // This is a singleton class. Get the instance.
+  static MBMatrices & get();
+
+  // Some compilers don't like the d-tor being private.
+  ~MBMatrices();
+
+  double ***A;
+  double ****B;
+
+private:
+  // Make the c-tor private so we can control how many objects
+  // are instantiated.
+  MBMatrices();
+};
+
+MBMatrices & MBMatrices::get()
+{
+  static MBMatrices singleton;
+  return singleton;
+}
+
+MBMatrices::MBMatrices()
+{
+  A  = (double ***) calloc(QGmax, sizeof(double **));
+  A -= 1;
  
-  Mod_BasisB  = (double ****)calloc(QGmax, sizeof(double ***));
-  Mod_BasisB -= 1;
+  B  = (double ****)calloc(QGmax, sizeof(double ***));
+  B -= 1;
+}
 
-  Mod_BasisC  = (double ****)calloc(QGmax, sizeof(double ***));
-  Mod_BasisC -= 1;
+MBMatrices::~MBMatrices()
+{
+  // i starts at 1 because of the offset, above.
+  for (int i = 1; i <= QGmax; ++i) {
+    if (A[i]) {
+      free_dmatrix(A[i],  0, 0);
+    }
+    if (B[i]) {
+      free(B[i][0][0]);  free(B[i][0]);  free(B[i]);
+    }
+  }
+  // The increment is needed to return to the address of the allocation.
+  free(++A);
+  free(++B);
 }
 
+// Now that we use a singleton class to store the Matrices, this function is
+// redundant.
+void init_mod_basis()
+{}
+
 /* Computes the values of modified a_mode[mode_a][j], mode_a=0..LGmax,
    j=0..size-1, at size Gauss-Lob. points, stores the result in
-   Mod_BasisA[size][mode_a] array 
+   MBMatrics::get().A[size][mode_a] array 
    (1+a)/2                         
    (1-a)/2                         
    (1-a)/2 (1+a)/2                 
    (1-a)/2 (1+a)/2 P_1^{1,1}(a)    
    (1-a)/2 (1+a)/2 P_{l-2}^{1,1}(a)*/
 
-void get_modA(int size, double ***mat){
+void get_modA(int size, double ***mat)
+{
+  double *** Mod_BasisA = MBMatrices::get().A;
 
   if (!Mod_BasisA[size]){
     double *w, *z;
     int i;
@@ -940,9 +1047,12 @@ void get_modA(int size, double ***mat){
   return;
 }
 
 static double ***get_Mod_Bmodes(int size, double *z);
-void get_modB(int size, double ****mat){
+
+void get_modB(int size, double ****mat)
+{
+  double **** Mod_BasisB = MBMatrices::get().B;
 
   if (!Mod_BasisB[size]){
     double *w,*z;
     getzw (size,&z,&w,'b');
@@ -1010,9 +1120,33 @@ static double ***get_Mod_Bmodes(int size
   return mat;
 }
 
 
-static Basis ****Tri_bbase=NULL;
+struct Tri_bbase_singleton {
+  static Tri_bbase_singleton & get();
+  ~Tri_bbase_singleton();
+  
+  Basis **** Tri_bbase;
+private:
+  Tri_bbase_singleton();
+};
+Tri_bbase_singleton & Tri_bbase_singleton::get()
+{
+    static Tri_bbase_singleton singleton;
+    return singleton;
+}
+
+Tri_bbase_singleton::Tri_bbase_singleton()
+  : Tri_bbase(0)
+{}
+
+Tri_bbase_singleton::~Tri_bbase_singleton()
+{
+
+  Tri_reset_basis();
+}
+
+
 static Basis ****Quad_bbase=NULL;
 static Basis  *Tet_bbinf=NULL,*Tet_bbase=NULL;
 static Basis  *Pyr_bbinf=NULL,*Pyr_bbase=NULL;
 static Basis  *Prism_bbinf=NULL,*Prism_bbase=NULL;
@@ -1045,17 +1179,22 @@ Function Notes:
 
 
 Basis *Tri::getbasis(){ 
 
-  int i,j;
-  if(!Tri_bbase){
-    Tri_bbase = (Basis****) calloc(LGmax+1, sizeof(Basis***));
+  if(!Tri_bbase_singleton::get().Tri_bbase){
+    Tri_bbase_singleton::get().Tri_bbase = 
+      (Basis****) calloc(LGmax+1, sizeof(Basis***));
+
+    Basis **** Tri_bbase = Tri_bbase_singleton::get().Tri_bbase;
+    int i,j;
+
     for(i=0;i<LGmax+1;++i){
       Tri_bbase[i] = (Basis***) calloc(QGmax+1, sizeof(Basis**));
       for(j=0;j<QGmax+1;++j)
 	Tri_bbase[i][j] = (Basis**) calloc(QGmax+1, sizeof(Basis*));
     }
   }
+  Basis **** Tri_bbase = Tri_bbase_singleton::get().Tri_bbase;
   if(!Tri_bbase[lmax][qa][qb])
     Tri_bbase[lmax][qa][qb] = Tri_addbase(lmax,qa,qb,qc);
   return Tri_bbase[lmax][qa][qb];
 }
@@ -1322,32 +1461,31 @@ static Basis *Hex_addbase(int L, int qa,
   return b;
 }
 
 
-void Tri_reset_basis(void){
+void Tri_reset_basis(Basis *B);
+
+void Tri_reset_basis(void)
+{
+  Basis **** Tri_bbase = Tri_bbase_singleton::get().Tri_bbase;
+  if(!Tri_bbase)
+    return;
 
   int i,j,k;
-  if(Tri_bbase){
-    for(i=0;i<LGmax+1;++i)
-      for(j=0;j<QGmax+1;++j)
-	for(k=0;k<QGmax+1;++k)
-	  if(Tri_bbase[i][j][k]){
-	    free(Tri_bbase[i][j][k]->vert[2].a);
-	    free(Tri_bbase[i][j][k]->vert[2].b);
-	    
-	    free(Tri_bbase[i][j][k]->vert);
-	    free(Tri_bbase[i][j][k]->edge);
-	    free(Tri_bbase[i][j][k]->face);
-	    free(Tri_bbase[i][j][k]);
-	  }
-    for(i=0;i<LGmax+1;++i){
-      for(j=0;j<QGmax+1;++j)
-	free(Tri_bbase[i][j]);
-      free(Tri_bbase[i]);
-    }
-    free(Tri_bbase);
-    Tri_bbase = NULL;
+
+  for(i=0;i<LGmax+1;++i)
+    for(j=0;j<QGmax+1;++j)
+      for(k=0;k<QGmax+1;++k)
+	Tri_reset_basis(Tri_bbase[i][j][k]);
+
+  for(i=0;i<LGmax+1;++i){
+    for(j=0;j<QGmax+1;++j)
+      free(Tri_bbase[i][j]);
+    free(Tri_bbase[i]);
   }
+  free(Tri_bbase);
+  Tri_bbase = NULL;
+
 }
 
 void Tri_reset_basis(Basis *B){
 
@@ -1356,8 +1494,12 @@ void Tri_reset_basis(Basis *B){
     free(B->vert[2].b);
     
     free(B->vert);
     free(B->edge);
+    if (B->face) {
+      for(int i = 0; i < NTri_faces; ++i)
+	free(B->face[i]);
+    }
     free(B->face);
     free(B);
   }
 }
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Boundary.C clean2/Hlib/src/Boundary.C
--- dirty/Hlib/src/Boundary.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Boundary.C	Wed May  1 17:51:41 2002
@@ -1962,10 +1962,10 @@ void Tri::Add_Surface_Contrib(Element *E
   Element *E = this;
   double   *za,*zb,*wa,*wb;
   double   **ima, **imb;
   double one = 1.0e0 , two = 2.0e0;
-  double *f  = Tri_wk;
-  double *fi = Tri_wk+QGmax;
+  double *f  = Tri_wk.get();
+  double *fi = f+QGmax;
 
   getzw(qa,&za,&wa,'a'); // ok
   getzw(qb,&zb,&wb,'b'); // ok
     
@@ -2796,60 +2796,61 @@ Function Notes:
 void Tri::fill_edges(double *ux, double *uy, double *){
   double **im;
 
   // one field case
+  double * wk = Tri_wk.get();
 
   if(!uy){
     getim(qa,edge[0].qedg,&im,a2g);
-    GetFace(ux,0,Tri_wk);
-    Interp(*im,Tri_wk,qa,edge[0].h,edge[0].qedg);
+    GetFace(ux,0,wk);
+    Interp(*im,wk,qa,edge[0].h,edge[0].qedg);
 
     getim(qa,edge[1].qedg,&im,b2g);
-    GetFace(ux,1,Tri_wk);
-    Interp(*im,Tri_wk,qb,edge[1].h,edge[1].qedg);
+    GetFace(ux,1,wk);
+    Interp(*im,wk,qb,edge[1].h,edge[1].qedg);
 
     getim(qa,edge[2].qedg,&im,b2g);
-    GetFace(ux,2,Tri_wk);
-    Interp(*im,Tri_wk,qb,edge[2].h,edge[2].qedg);
+    GetFace(ux,2,wk);
+    Interp(*im,wk,qb,edge[2].h,edge[2].qedg);
   }
   else{
-    double *wka = Tri_wk+QGmax;
-    double *wkb = Tri_wk+2*QGmax;
+    double *wka = wk+QGmax;
+    double *wkb = wk+2*QGmax;
     int qedg;
     Edge   *e;
     e    = edge;
     qedg = e->qedg;
 
     getim(qa,qedg,&im,a2g);
-    GetFace(ux,0,Tri_wk);
-    Interp(*im,Tri_wk,qa,wka,qedg);
+    GetFace(ux,0,wk);
+    Interp(*im,wk,qa,wka,qedg);
 
-    GetFace(uy,0,Tri_wk);
-    Interp(*im,Tri_wk,qa,wkb,qedg);
+    GetFace(uy,0,wk);
+    Interp(*im,wk,qa,wkb,qedg);
 
     dvmul (qedg, e->norm->x, 1, wka, 1, e->h, 1);
     dvvtvp(qedg, e->norm->y, 1, wkb, 1, e->h, 1, e->h, 1);
 
     e = edge+1;
     qedg = e->qedg;
     getim(qb,qedg,&im,b2g);
-    GetFace(ux,1,Tri_wk);
-    Interp(*im,Tri_wk,qb,wka,qedg);
+    GetFace(ux,1,wk);
+    Interp(*im,wk,qb,wka,qedg);
 
-    GetFace(uy,1,Tri_wk);
-    Interp(*im,Tri_wk,qb,wkb,qedg);
+    GetFace(uy,1,wk);
+    Interp(*im,wk,qb,wkb,qedg);
 
     dvmul (qedg, e->norm->x, 1, wka, 1, e->h, 1);
     dvvtvp(qedg, e->norm->y, 1, wkb, 1, e->h, 1, e->h, 1);
 
     e = edge+2;
     qedg = e->qedg;
     getim(qb,qedg,&im,b2g);
-    GetFace(ux,2,Tri_wk);
-    Interp(*im,Tri_wk,qb,wka,qedg);
+    GetFace(ux,2,wk);
+    Interp(*im,wk,qb,wka,qedg);
 
-    GetFace(uy,2,Tri_wk);
-    Interp(*im,Tri_wk,qb,wkb,qedg);
+    GetFace(uy,2,wk);
+    Interp(*im,wk,qb,wkb,qedg);
 
     dvmul (qedg, e->norm->x, 1, wka, 1, e->h, 1);
     dvvtvp(qedg, e->norm->y, 1, wkb, 1, e->h, 1, e->h, 1);
   }
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/ChangeLog clean2/Hlib/src/ChangeLog
--- dirty/Hlib/src/ChangeLog	Thu Jan  1 01:00:00 1970
+++ clean2/Hlib/src/ChangeLog	Wed May  1 17:51:41 2002
@@ -0,0 +1,13 @@
+2002-10-04  Angus Leeming <[EMAIL PROTECTED]>
+
+	* Basis.C (OBMatrices): a new singleton class. Used to encapsulate the
+	orthogonal basis matrices BasisA_G etc. No other change of code at all;
+	E.g., matrix BasisA_G is now accessed as OBMatrices::get().A_G.
+	Why do this? Because the allocated memory is now cleaned-up when the 
+	instance of OBMatrices goes out of scope at program end, removing
+	a heap of valgrind error messages.
+
+	* Tri.C (Tri_setup_iprodlap): free Tri * "T" and its member pointers.
+
+	* Memory.C (Tri::Mem_shift): check whether h and face[0].hj have been
+	allocated memory already and, if so, free it.
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Element.C clean2/Hlib/src/Element.C
--- dirty/Hlib/src/Element.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Element.C	Wed May  1 17:51:41 2002
@@ -74,8 +74,32 @@ Element::Element(const Element &E){
   face = (Face *)calloc(Nfaces,sizeof(Face));
   memcpy (face,E.face,Nfaces*sizeof(Face));
 }
 
+
+Element::~Element()
+{
+  free(vert);
+  free(edge);
+  free(h);
+
+  if (face && face[0].hj) 
+    free(face[0].hj);
+
+  free(face);
+
+  // Looks to me like curve, curvX and geom should be stored by a
+  // boost::shared_ptr, as multiple elements reference the same block of memory.
+  // Angus
+//    double  **h;
+//    double  ***h_3d;
+//    double  ***hj_3d;
+//    Curve   *curve;
+//    Cmodes  *curvX;
+//    Geom    *geom;
+//    Element *next;
+}
+
 void Element::EdgeJbwd(double *d, int edg){
   Basis *b = getbasis();
   int   va = vnum(edg,0);
   int   vb = vnum(edg,1), i;
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Element_List.C clean2/Hlib/src/Element_List.C
--- dirty/Hlib/src/Element_List.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Element_List.C	Wed May  1 17:51:41 2002
@@ -63,8 +63,22 @@ Element_List::Element_List(Element **hea
   nztot   = 1;
   flevels = (Element_List**)NULL;
 }
 
+Element_List::~Element_List()
+{
+  for (int i = 0; i < nel; ++i) {
+    delete flist[i];
+  }
+  free(flist);
+
+  if (base_h)
+    free(base_h);
+  if (base_hj)
+    free(base_hj);
+}
+
+
 Element *Element_List::operator()(int i){
 #ifdef DEBUG
   if(i>nel-1) 
     fprintf(stderr,"Element_List::operator() bounds error\n");
@@ -80,8 +94,22 @@ Element *Element_List::operator[](int i)
   return flist[i];
 }
 
 void Element_List::Cat_mem(){
+  if (base_h) {
+    fprintf(stderr, "Element_List::Cat_mem(): base_h is set already: %d\n", 
+	    base_h);
+    free(base_h);
+    base_h = 0;
+  }
+
+  if (base_hj) {
+    fprintf(stderr, "Element_List::Cat_mem(): base_hj  is set already: %d\n", 
+	    base_hj);
+    free(base_hj);
+    base_hj = 0;
+  }
+
   htot = 0;
   hjtot = 0;
   Eloop(fhead){
     htot  += el->qtot;
@@ -90,20 +118,19 @@ void Element_List::Cat_mem(){
 
   base_h  = dvector(0, nz*htot-1);
   base_hj = dvector(0, nz*hjtot-1);
 
+  dzero(nz*htot,  base_h, 1);
+  dzero(nz*hjtot, base_hj, 1);
+  
   double *tmp_base_h  = base_h;
   double *tmp_base_hj = base_hj;
   
-  dzero(nz*htot,   base_h, 1);
-  dzero(nz*hjtot, base_hj, 1);
-  
   Eloop(fhead){
     el->Mem_shift(tmp_base_h, tmp_base_hj, 'n');
     tmp_base_h  += el->qtot;
     tmp_base_hj += el->Nmodes;
   }
-
 }
 
 void Element_List::Trans(Element_List *EL, Nek_Trans_Type ntt){
   // Treat FFT as a global operation
@@ -1199,9 +1226,8 @@ static void  add_pf(int elmt, int side);
 Element_List *Part_elmt_list(Element_List *GEL, char trip){
   int           i,k;
   int           lnel = pllinfo.nloop, ig;
 
-  Element_List *EL = (Element_List*) new Element_List();
   Element**  new_E = (Element**) malloc(lnel*sizeof(Element*));
   Element *Eg, *E;
 
   //  fprintf(stderr, "Entering: Part_elmt_list\n");
@@ -1449,9 +1475,10 @@ Element_List *Part_elmt_list(Element_Lis
     }
   }
   free(inc);
 
-  EL = (Element_List*) new Element_List(new_E, lnel);
+  Element_List * EL = (Element_List*) new Element_List(new_E, lnel);
+
   EL->Cat_mem();
   for(E=EL->fhead;E;E=E->next){
     E->geom = (Geom*)0;
     E->set_geofac();
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Geofac.C clean2/Hlib/src/Geofac.C
--- dirty/Hlib/src/Geofac.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Geofac.C	Wed May  1 17:51:41 2002
@@ -77,11 +77,11 @@ void Tri::set_edge_geofac(){
   Edge     *e;
   Vert     *v;
   double   **mat,*wk1,**im,nx,ny,fac;
 
-  double *wk = Tri_wk;
+  double *wk = Tri_wk.get();
 
-  wk1 = Tri_wk+QGmax;
+  wk1 = wk+QGmax;
 
   v = vert;
 
   for(i = 0; i < Nedges; ++i){
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Gradient.C clean2/Hlib/src/Gradient.C
--- dirty/Hlib/src/Gradient.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Gradient.C	Wed May  1 17:51:41 2002
@@ -236,9 +236,9 @@ void Tri::Grad_h(double *H, double *ux, 
   Geom      *G = geom;
   Mode      *v = getbasis()->vert;
   double    *u = H; // fix ??
 //  double    *wk = dvector(0,QGmax*QGmax-1);
-  double    *ur = Tri_wk;
+  double    *ur = Tri_wk.get();
 
   uz=uz; // compiler fix
 
   getD(&da,&dat,&db,&dbt,NULL,NULL);
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/InnerProd.C clean2/Hlib/src/InnerProd.C
--- dirty/Hlib/src/InnerProd.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/InnerProd.C	Wed May  1 17:51:41 2002
@@ -103,8 +103,10 @@ void Tri::Iprod_d(Element *T, Basis *ba,
   Edge    *e = T->edge;
   Face    *f = T->face;
   size_t  d = sizeof(double);
 
+  double *wk = Tri_wk.get();
+
   T->state = 't';
   
   getzw(T->qa,&wa,&wa,'a');
   getzw(T->qb,&wb,&wb,'b');
@@ -117,24 +119,24 @@ void Tri::Iprod_d(Element *T, Basis *ba,
 
   for(i = 0; i < qb; ++i) dvmul(qa,wa,1, T->h[i],1, T->h[i],1);
   for(i = 0; i < qb; ++i) dscal(qa,wb[i],T->h[i],1);
 
-  dgemm('T','N',qb,lmax,qa,1.0,T->h[0],qa,ba->vert[1].a,qa,0.0,Tri_wk,qb);
+  dgemm('T','N',qb,lmax,qa,1.0,T->h[0],qa,ba->vert[1].a,qa,0.0,wk,qb);
 
 #if 0
   H = *T->h;
-  dgemv('T',qb,lmax,1.0,bb->vert[2].b,qb,Tri_wk   ,1,0.0,H     ,1);
-  dgemv('T',qb,lmax,1.0,bb->vert[2].b,qb,Tri_wk+qb,1,0.0,H+lmax,1);
+  dgemv('T',qb,lmax,1.0,bb->vert[2].b,qb,wk   ,1,0.0,H     ,1);
+  dgemv('T',qb,lmax,1.0,bb->vert[2].b,qb,wk+qb,1,0.0,H+lmax,1);
   H  += 2*lmax;
-  Tri_wk_a = Tri_wk+2*qb;
-  for(i = 0; i < lmax-2; Tri_wk_a+=qb,H+=lmax-2-i, ++i)
-    dgemv('T',qb,lmax-2-i,1.0,bb->edge[0][i].b,qb,1,Tri_wk_a,1,0.0,H,1);
+  wk_a = wk+2*qb;
+  for(i = 0; i < lmax-2; wk_a+=qb,H+=lmax-2-i, ++i)
+    dgemv('T',qb,lmax-2-i,1.0,bb->edge[0][i].b,qb,1,wk_a,1,0.0,H,1);
 #else
   H = *T->h;
-  mxva(bb->vert[2].b,qb,1,Tri_wk   ,1,H     ,1,lmax,qb);
-  mxva(bb->vert[2].b,qb,1,Tri_wk+qb,1,H+lmax,1,lmax,qb);
+  mxva(bb->vert[2].b,qb,1,wk   ,1,H     ,1,lmax,qb);
+  mxva(bb->vert[2].b,qb,1,wk+qb,1,H+lmax,1,lmax,qb);
   H  += 2*lmax;
-  wk_a = Tri_wk+2*qb;
+  wk_a = wk+2*qb;
   for(i = 0; i < lmax-2; wk_a+=qb,H+=lmax-2-i, ++i)
     mxva(bb->edge[0][i].b,qb,1,wk_a,1,H,1,lmax-2-i,qb);
 #endif  
 
@@ -974,11 +976,13 @@ void Tri::HelmHoltz(Metric *lambda){
   Basis *b,*db;
   double *store,*u1,*u2;
   static int SVV = dparam("SVVfactor") ? 1:0;
 
-  store = Tri_wk+QGmax*QGmax;
-  u1    = Tri_wk+2*QGmax*QGmax;
-  u2    = Tri_wk+3*QGmax*QGmax;
+  double *wk = Tri_wk.get();
+
+  store = wk+QGmax*QGmax;
+  u1    = wk+2*QGmax*QGmax;
+  u2    = wk+3*QGmax*QGmax;
 
   Nm = Nmodes;
   b  = getbasis(); 
   db = derbasis();
@@ -1612,9 +1616,9 @@ void Tri::form_diprod(double *u1, double
 {
   register int i;
   const    int qt = qa*qb;
   Geom     *G = geom;
-  double *tmp = Tri_wk+4*QGmax*QGmax; // sort out later
+  double *tmp = Tri_wk.get()+4*QGmax*QGmax; // sort out later
   double *Ur = tmp;
   
   //  Grad_d(u1,u2,(double*)NULL,'a');
   
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Interp_point.C clean2/Hlib/src/Interp_point.C
--- dirty/Hlib/src/Interp_point.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Interp_point.C	Wed May  1 17:51:41 2002
@@ -13,8 +13,9 @@
 #include <math.h>
 #include <veclib.h>
 #include "polylib.h"
 #include "hotel.h"
+#include <smart_ptr.hpp>
 
 static int Find_elmt_coords_2d(Element_List *U, 
 		      double xo, double yo, 
 		      int *eid, double *a, double *b, char trip);
@@ -207,9 +208,9 @@ double eval_field_at_pt_3d(int qa, int q
 }
 
 
 
-class BoundBox{
+class BoundBox {
 public:
   int nel;
   int dim;
   double *lx;
@@ -220,31 +221,41 @@ public:
   double *uy;
   double *uz;
 };
 
-BoundBox *Bbox = NULL;
+namespace {
+
+struct DestroyBoundBox {
+  void operator()(BoundBox * Bbox)
+  {
+    free(Bbox->lx);
+    free(Bbox->ly);
+    free(Bbox->ux);
+    free(Bbox->uy);
+    if (Bbox->dim == 3) {
+      free(Bbox->lz);
+      free(Bbox->uz);
+    }
+    free (Bbox);
+    Bbox = 0;
+  }
+};
+
+} // namespace anon
+
+nektar::scoped_ptr<BoundBox, DestroyBoundBox> Bbox;
 
 #define TOLBOX 1.1  // scaling factor of box 
+
 void setup_elmt_boxes(Element_List *U){
   Element *E;
   double mean;
   int i,k;
   
   if(U->fhead->dim() == 3){
 
-    if(Bbox){
-      free(Bbox->lx);
-      free(Bbox->ly);
-      free(Bbox->lz);
-      
-      free(Bbox->ux);
-      free(Bbox->uy);
-      free(Bbox->uz);
-
-      free(Bbox);
-    }
+    Bbox.reset((BoundBox*) calloc(1, sizeof(BoundBox)));
 
-    Bbox = (BoundBox*) calloc(1, sizeof(BoundBox));
     Bbox->dim = U->fhead->dim();
     Bbox->nel = U->nel;
     Bbox->lx = dvector(0, U->nel-1);
     Bbox->ly = dvector(0, U->nel-1);
@@ -257,9 +268,9 @@ void setup_elmt_boxes(Element_List *U){
     Coord X;
     X.x = dvector(0, QGmax*QGmax*QGmax-1);
     X.y = dvector(0, QGmax*QGmax*QGmax-1);
     X.z = dvector(0, QGmax*QGmax*QGmax-1);
-    
+
     for(k=0;k<U->nel;++k){
       E = U->flist[k];
       E->coord(&X);
       Bbox->lx[k] = X.x[idmin(E->qtot, X.x, 1)];
@@ -297,19 +308,11 @@ void setup_elmt_boxes(Element_List *U){
     free(X.y);
     free(X.z);
   }
   else{
-    if(Bbox){
-      free(Bbox->lx);
-      free(Bbox->ly);
-      
-      free(Bbox->ux);
-      free(Bbox->uy);
 
-      free(Bbox);
-    }
+    Bbox.reset((BoundBox*) calloc(1, sizeof(BoundBox)));
 
-    Bbox = (BoundBox*) calloc(1, sizeof(BoundBox));
     Bbox->dim = U->fhead->dim();
     Bbox->nel = U->nel;
     Bbox->lx = dvector(0, U->nel-1);
     Bbox->ly = dvector(0, U->nel-1);
@@ -349,19 +352,19 @@ void setup_elmt_boxes(Element_List *U){
     free(X.y);
   }
 }
 
-int point_in_box_2d(double x, double y, int boxid){
-
+int point_in_box_2d(double x, double y, int boxid)
+{
   if( x <= Bbox->ux[boxid] && x >= Bbox->lx[boxid] &&
       y <= Bbox->uy[boxid] && y >= Bbox->ly[boxid])
     return 1;
 
   return 0;
 }
 
-int point_in_box_3d(double x, double y, double z, int boxid){
-
+int point_in_box_3d(double x, double y, double z, int boxid)
+{
   if( x <= Bbox->ux[boxid] && x >= Bbox->lx[boxid] &&
       y <= Bbox->uy[boxid] && y >= Bbox->ly[boxid] && 
       z <= Bbox->uz[boxid] && z >= Bbox->lz[boxid])
     return 1;
@@ -372,43 +375,48 @@ int point_in_box_3d(double x, double y, 
 #define MAXIT    101         /* maximum iterations for convergence   */
 #define EPSILON  1.e-8       /* |x-xp| < EPSILON  error tolerance    */
 #define GETRSDIV 15.0        /* |r,s|  > GETRSDIV stop the search    */
 
-
-
-Coord **meshX = NULL;
 int     meshX_nel;
 int     meshX_dim;
-void set_mesh_coord(Element_List *EL){
-  Element *E;
 
-  if(!meshX){
-    meshX = (Coord**) calloc(EL->nel, sizeof(Coord*));
-    
-    for(E=EL->fhead;E;E=E->next){
-      meshX[E->id] = (Coord*) calloc(1, sizeof(Coord));
-      meshX[E->id]->x = dvector(0, E->qtot-1);
-      meshX[E->id]->y = dvector(0, E->qtot-1);
-      if(E->dim() == 3)
-	meshX[E->id]->z = dvector(0, E->qtot-1);
-      E->coord(meshX[E->id]);
-    }
-    meshX_nel = EL->nel;
-    meshX_dim = EL->fhead->dim();
-  }
-  else{
-    int k;
-    for(k=0;k<EL->nel;++k){
-      free(meshX[k]->x);
-      free(meshX[k]->y);
+namespace {
+
+struct DestroyMeshX {
+  void operator()(Coord ** ptr) 
+  { 
+    for(int i = 0; i < meshX_nel; ++i) {
+      free(ptr[i]->x);
+      free(ptr[i]->y);
       if(meshX_dim == 3)
-	free(meshX[k]->z);
-      free(meshX[k]);
+	free(ptr[i]->z);
+      free(ptr[i]);
     }
-    free(meshX);
-    meshX = NULL;
-    set_mesh_coord(EL);
+    free(ptr);
+    ptr = 0;
+  }
+};
+
+} // namespace anon
+
+nektar::scoped_ptr<Coord *, DestroyMeshX> meshX_ptr;
+
+void set_mesh_coord(Element_List *EL){
+  Element *E;
+
+  meshX_ptr.reset((Coord**) calloc(EL->nel, sizeof(Coord*)));
+  Coord ** meshX = meshX_ptr.get();
+
+  for(E=EL->fhead;E;E=E->next){
+    meshX[E->id] = (Coord*) calloc(1, sizeof(Coord));
+    meshX[E->id]->x = dvector(0, E->qtot-1);
+    meshX[E->id]->y = dvector(0, E->qtot-1);
+    if(E->dim() == 3)
+      meshX[E->id]->z = dvector(0, E->qtot-1);
+    E->coord(meshX[E->id]);
   }
+  meshX_nel = EL->nel;
+  meshX_dim = EL->fhead->dim();
 }
 
 int Find_coords_2d(Element *E, double xo, double yo, 
 		double *a, double *b, char trip){
@@ -440,8 +448,10 @@ int Find_coords_2d(Element *E, double xo
     hr    = dvector (0, QGmax-1);
     hs    = dvector (0, QGmax-1);
   }
 
+  Coord ** meshX = meshX_ptr.get();
+
   gX = meshX[E->id];
   gridx = gX->x;
   gridy = gX->y;
 
@@ -618,8 +628,10 @@ int Find_coords_3d(Element *E, double xo
     hs    = dvector (0, QGmax-1);
     ht    = dvector (0, QGmax-1);
   }
   
+  Coord ** meshX = meshX_ptr.get();
+
   gX = meshX[E->id];
   gridx = gX->x;
   gridy = gX->y;
   gridz = gX->z;
@@ -911,9 +923,9 @@ void Prt_find_local_coords(Element_List 
 			   int *Eid, Coord *A, char status){  
   int i;
   int dim = U->fhead->dim();
   
-  if(!Bbox){
+  if(!Bbox.get()){
     setup_elmt_boxes(U);
     set_mesh_coord(U);
   }
 
@@ -1162,9 +1174,9 @@ void Find_local_coords(Element_List *U, 
   
   int i;
   int dim = U->fhead->dim();
 
-  if(!Bbox){
+  if(!Bbox.get()){
     setup_elmt_boxes(U);
     set_mesh_coord(U);
   }
 
@@ -1202,9 +1214,9 @@ void find_local_coords(Element_List *U, 
   
   int i;
   int dim = U->fhead->dim();
 
-  if(!Bbox){
+  if(!Bbox.get()){
     setup_elmt_boxes(U);
     set_mesh_coord(U);
   }
 
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Memory.C clean2/Hlib/src/Memory.C
--- dirty/Hlib/src/Memory.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Memory.C	Wed May  1 17:51:41 2002
@@ -18,11 +18,13 @@
 #include <math.h>
 #include <polylib.h>
 #include "veclib.h"
 #include "hotel.h"
+#include <smart_ptr.hpp>
 
 
- double *Tri_wk = (double*)0;
+
+nektar::scoped_c_ptr<double> Tri_wk;
 
  double *Quad_wk = (double*)0;
  double *Quad_Jbwd_wk = (double*)0;
  double *Quad_Iprod_wk = (double*)0;
@@ -61,11 +63,9 @@
  double *Hex_InterpToGaussFace_wk = (double*)0;
 
 
 void Tri_work(){
-  if(Tri_wk)
-    free(Tri_wk);
-  Tri_wk = dvector(0,5*QGmax*QGmax-1);
+  Tri_wk.reset(dvector(0,5*QGmax*QGmax-1));
 }
 
 void Quad_work(){
   
@@ -608,9 +608,14 @@ Function Notes:
 */
 
 void Tri::Mem_shift(double *new_h, double *new_hj, char Trip){
 
+  if (h) 
+    free(h);
   h = (double**) calloc(qb,sizeof(double*));
+
+  if (face[0].hj) 
+    free(face[0].hj);
   face[0].hj = (double**) calloc(face[0].l,sizeof(double*));
   
   // Physical memory
   int i;
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Transforms.C clean2/Hlib/src/Transforms.C
--- dirty/Hlib/src/Transforms.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Transforms.C	Wed May  1 17:51:41 2002
@@ -249,13 +249,15 @@ void Tri::Jbwd(Element *T, Basis *b){
   for(i = 0; i < lmax-2; H+=lmax-2-i, ++i)
     dgemv('N',Qb,lmax-2-i,1.0,b->edge[0][i].b,Qb,H,1,0.0,wk+2+i,lmax); 
   dgemm('N','N',Qa,Qb,lmax,1.0,b->vert[1].a,Qa,wk,lmax,0.0,T->h[0],Qa);
 #else /* mxv and mxm vertions */
-  mxva(b->vert[2].b,1,Qb,H,1,Tri_wk  ,lmax,Qb,lmax); H+=lmax; 
-  mxva(b->vert[2].b,1,Qb,H,1,Tri_wk+1,lmax,Qb,lmax); H+=lmax; 
+  double *wk = Tri_wk.get();
+
+  mxva(b->vert[2].b,1,Qb,H,1,wk  ,lmax,Qb,lmax); H+=lmax; 
+  mxva(b->vert[2].b,1,Qb,H,1,wk+1,lmax,Qb,lmax); H+=lmax; 
   for(i = 0; i < lmax-2; H+=lmax-2-i, ++i)
-    mxva(b->edge[0][i].b,1,Qb,H,1,Tri_wk+2+i,lmax,Qb,lmax-2-i);
-  mxm(Tri_wk,Qb,b->vert[1].a,lmax,T->h[0],Qa);
+    mxva(b->edge[0][i].b,1,Qb,H,1,wk+2+i,lmax,Qb,lmax-2-i);
+  mxm(wk,Qb,b->vert[1].a,lmax,T->h[0],Qa);
 #endif
 }
 
 
@@ -1295,21 +1297,22 @@ void Tri::Obwd(double *in, double *out, 
   register int i;
   double   **ba,***bb;
   int      mode;
 
+  double *wk = Tri_wk.get();
 
   get_moda_GL (qa, &ba);
   get_modb_GR (qb, &bb); 
 
   mode = 0;
   /* bwd trans w.r.t. b modes */
   for (i= 0; i < L; ++i){
-    mxva (bb[i][0],1,qb,in+mode,1,Tri_wk+i*qb,1,qb,L-i);
+    mxva (bb[i][0],1,qb,in+mode,1,wk+i*qb,1,qb,L-i);
     mode += L-i;
   }
   
   /* bwd trans w.r.t. a modes */
-  dgemm('N','T',qa,qb,L,1.0,*ba,qa,Tri_wk,qb,0.0,out,qa);
+  dgemm('N','T',qa,qb,L,1.0,*ba,qa,wk,qb,0.0,out,qa);
 }
 
 
 
@@ -1464,8 +1467,10 @@ void Tri::Ofwd(double *in, double *out, 
   register int i;
   double   **ba,***bb,*wa,*wb;
   int      mode;
   
+  double *wk = Tri_wk.get();
+
   getzw (qa,&wa,&wa,'a');
   getzw (qb,&wb,&wb,'b');
   get_moda_GL (qa, &ba);
   get_modb_GR (qb, &bb); 
@@ -1484,20 +1489,20 @@ void Tri::Ofwd(double *in, double *out, 
   for(i = 0; i < qa; ++i)
     dscal(qb,wa[i],in+i,qa);
   
   /* Inner product trans w.r.t. a modes */
-  dgemm('T','N',qb,L,qa,1.0,in,qa,*ba,qa,0.0,Tri_wk,qb); 
+  dgemm('T','N',qb,L,qa,1.0,in,qa,*ba,qa,0.0,wk,qb); 
 #ifdef NONORM
   for(i=0;i<L;++i)
-    dscal(qb, 0.5*(2.*i+1.), Tri_wk+qb*i, 1);
+    dscal(qb, 0.5*(2.*i+1.), wk+qb*i, 1);
 
   double fac = 1.;
 #endif
 
   mode = 0;
   for (i= 0; i < L; ++i){ /* Inner product trans w.r.t. b modes */
-    dvmul (qb,wb,1,Tri_wk+i*qb,1,Tri_wk+i*qb,1);
-    mxva (bb[i][0],qb,1,Tri_wk+i*qb,1,out+mode,1,L-i,qb);
+    dvmul (qb,wb,1,wk+i*qb,1,wk+i*qb,1);
+    mxva (bb[i][0],qb,1,wk+i*qb,1,out+mode,1,L-i,qb);
 #ifdef NONORM
     for(j = 0; j < L-i; ++j)    
       out[mode+j] *= fac*(i+j+1.);
     fac *= 0.25;
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Hlib/src/Tri.C clean2/Hlib/src/Tri.C
--- dirty/Hlib/src/Tri.C	Fri Feb  1 13:26:29 2002
+++ clean2/Hlib/src/Tri.C	Wed May  1 17:51:41 2002
@@ -30,9 +30,10 @@ Tri::Tri(){
 }
 
 
 Tri::Tri(Element *E){
-  if(!Tri_wk)
+
+  if(!Tri_wk.get())
     Tri_work();
   id      = E->id;
   type    = E->type;
   state   = 'p';
@@ -74,9 +75,9 @@ Tri::Tri(Element *E){
 
 Tri::Tri(int i_d, char ty, int L, int Qa, int Qb, int Qc, Coord *X){
   int i;
 
-  if(!Tri_wk)
+  if(!Tri_wk.get())
     Tri_work();
 
   id = i_d;
   type = ty;
@@ -414,11 +415,16 @@ void Tri_setup_iprodlap(){
   free_mvec(gb1[0]); free((char *) gb1);
   free((char*)w);
 
   free(tmp);
+
+  // These should really, really be free-d in the Element d-tor
+  // but I don't know enough to know what side effects writing this 
+  // d-tor would have.
+  // Angus 11 April 2002.
+  free(T->vert);
+  free(T->edge);
+  free(T->face);
+  free(T);
 }
 
 #endif
-
-
-
-
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Nektar2d/src/ChangeLog clean2/Nektar2d/src/ChangeLog
--- dirty/Nektar2d/src/ChangeLog	Thu Jan  1 01:00:00 1970
+++ clean2/Nektar2d/src/ChangeLog	Wed May  1 17:51:41 2002
@@ -0,0 +1,24 @@
+2002-10-04  Angus Leeming <[EMAIL PROTECTED]>
+
+	* nektar.C (main): initilise "step". 
+	Valgrind reports "Use of uninitialised value of size 4" in 
+	writeHeader(_IO_FILE *, Field *) (../src/Fieldfiles.C:1486) 
+	that propogates from here!
+
+	* analyser.C (Analyser): free the pointer "V" (but not its contents).
+
+	* bwoptim.C (free_Fctcon): add the all-imporatant braces to the for-loop
+	so that we actually free some memory!
+
+	* prepost.C (PreProcess): Don't free already free'd memory; wrap the 
+	free(P->base_h) call inside an if-statement. Ditto for P->base_hj.
+
+	* io.C (ReadMesh): free Coord X's member dvectors.
+
+	* io.C (bsort): Fix one memory leak caused by not free-ing the array, 
+	tmp.
+	Attempt to fix memory leaks caused by not free-ing the original 
+	bndry_list, but ultimately fail. I fail here because memory is 
+	allocated in one of two different ways and we cannot resolve which in 
+	order to free it cleanly. See the routine for details.
+	
\ No newline at end of file
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Nektar2d/src/analyser.C clean2/Nektar2d/src/analyser.C
--- dirty/Nektar2d/src/analyser.C	Tue Jan  9 18:38:14 2001
+++ clean2/Nektar2d/src/analyser.C	Wed May  1 17:51:41 2002
@@ -145,8 +145,11 @@ void Analyser (Domain *omega, int step, 
   V[0]->Set_state('t');
   V[1]->Set_state('t');
   //  V[2]->Set_state('t');
   
+  // free the pointer
+  free(V);
+
   return;		
 }
     
 
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Nektar2d/src/bwoptim.C clean2/Nektar2d/src/bwoptim.C
--- dirty/Nektar2d/src/bwoptim.C	Tue Jun 29 11:03:26 1999
+++ clean2/Nektar2d/src/bwoptim.C	Wed May  1 17:51:41 2002
@@ -345,15 +345,16 @@ void addfct(Fctcon *con, int *pts, int n
 void  free_Fctcon(Fctcon *con, int n){
   register int i;
   Facet *f,*f1;
   
-  for(i = 0; i < n; ++i)
+  for(i = 0; i < n; ++i) {
     f = con[i].f;
     while(f){
       f1 = f->next;
       free(f);
       f = f1;
     }      
+  }
   
   free(con);
 }
 
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Nektar2d/src/io.C clean2/Nektar2d/src/io.C
--- dirty/Nektar2d/src/io.C	Tue Feb 13 19:05:10 2001
+++ clean2/Nektar2d/src/io.C	Wed May  1 17:51:41 2002
@@ -271,8 +271,11 @@ Element_List *ReadMesh(FILE *fp, char *s
       new_E[k] = new Nodal_Tri (k,'u', L,qa,qb,0, &X);
 #endif
   }
 
+  free(X.x);
+  free(X.y);
+
   for(k = 0; k < nel-1; ++k)     new_E[k]->next = new_E[k+1];
   new_E[k]->next = (Element*) NULL;
   
   Element_List* E_List = new Element_List(new_E, nel);			   
@@ -979,30 +982,53 @@ Bndry *bsort(Bndry *bndry_list, int nbcs
 
   tmp = (Bndry**) malloc(nbcs*sizeof(Bndry*));
   
   /* Copy the linked list into a regular array and sort it */
-
   for(i = 0 ; i < nbcs; ++i, bedg = bedg->next) tmp[i] = bedg;
   qsort(tmp, nbcs, sizeof(Bndry*), bedgcmp);
 
   /* Create a new version of the ordered list */
-  
   bedg  = (Bndry*) malloc (nbcs * sizeof(Bndry));
   for(i = 0; i < nbcs; ++i) {
-//    memcpy (bedg + i, tmp[i], sizeof(Bndry));
     bedg[i] = *(tmp[i]);
     bedg[i].id         = i;
     bedg[i].next = bedg + i + 1;
   }
   bedg[nbcs-1].next   = (Bndry*) NULL;
   
-  /* Free up the space occupied by the old list */
-  bndry_list = bedg;
-//  for(i = 0; i < nbcs; ++i) free (tmp[i]);
+  /* Free up the memory occupied by the temporary array */
+  free (tmp);
+
+  // Free up the memory occupied by the old list.
+  // Ahhhhhhhhhhhhhh! (Scream for help!)
+
+  // The memory allocated to the linked list bndry_list is allocated in 
+  // one of two different ways.
 
-//  free (tmp);
+  // In ReadBCs, above, the memory is allocated in piecewise fashion to each 
+  // new element of the linked list. The following therefore frees the memory:
+
+  // (Commented out for now until a proper solution is decided upon.)
+//    Bndry * ptr = bndry_list;
+//    Bndry * next;
+//    while(ptr) {
+//      next = ptr->next;
+//      free(ptr);
+//      ptr = next;
+//    }
+
+  // In BuildPBCs in pressure.C, the memory is allocated in one lump at the 
+  // start. The following, therefore, frees the memory in this case.
+  free(bndry_list);
+
+  // Three solutions present themselves.
+  // 1. Use the STL list and leave such worries behind you.
+  // 2. Decide on a consistent memory allocation strategy.
+  // 3. Pass an addition parameter to bsort that flags how the memory should
+  //    be free-d.
 
-  return bndry_list;
+  // return the new, sorted list
+  return bedg;
 }
 
 /*
  * Boundaries are sorted by their ASCII character values except for
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Nektar2d/src/nektar.C clean2/Nektar2d/src/nektar.C
--- dirty/Nektar2d/src/nektar.C	Fri Jan 19 21:12:13 2001
+++ clean2/Nektar2d/src/nektar.C	Wed May  1 17:51:41 2002
@@ -12,12 +12,16 @@
 #include <time.h>
 #include "nektar.h"
 
 
+//void free_Domain(Domain * omega);
+
 main(int argc, char *argv[]){
-  Domain      *Omega;             /* Solution Domain            */
-  int          step, nsteps;      /* Discrete time (step)       */
-  double       dt,time = 0.0;        /* Continuous time            */
+  Domain      *Omega;             /* Solution Domain      */
+  int          step = 0;          /* Discrete time (step) */
+  int          nsteps;            /* Number of steps      */
+  double       time = 0.0;        /* Continuous time      */
+  double       dt;
 
 #ifdef DEBUG
 /*  mallopt(M_DEBUG,1); */
   init_debug();
@@ -31,6 +35,7 @@ main(int argc, char *argv[]){
   Navier_Stokes(Omega,time,time+dt*nsteps);
 
   PostProcess(Omega, step, time+dt*nsteps);
   
+  //free_Domain(Omega);
   exit(0);
 }
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Nektar2d/src/prepost.C clean2/Nektar2d/src/prepost.C
--- dirty/Nektar2d/src/prepost.C	Tue Apr 17 14:04:34 2001
+++ clean2/Nektar2d/src/prepost.C	Wed May  1 17:51:41 2002
@@ -196,9 +196,9 @@ void parse_args(int argc, char *argv[]){
  * ------------------------------------------------------------------------ */
 void CorrectRobinFluxes(Bndry *B);
  
 static void Set_Oseen(FILE *rea_file,Bsystem *PB, Bsystem *B, Element_List *U);
- 
+
 Domain *PreProcess(int argc, char **argv)
 {
   FILE     *rea_file;
   Element_List  *U,*P;
@@ -287,9 +287,16 @@ Domain *PreProcess(int argc, char **argv
     P = U->gen_aux_field('p');    
 
     option_set("variable",1);
     /* set pressure field to L-1 */
-     free(P->base_h);  free(P->base_hj);
+    if (P->base_h) {
+      free(P->base_h);
+      P->base_h = 0;
+    }
+    if (P->base_hj) {
+      free(P->base_hj);
+      P->base_hj = 0;
+    }
 
     for(E=P->fhead;E;E=E->next){
       for(i=0;i<E->Nedges;++i)
 	size[i] = max(0,E->edge[i].l-2);
@@ -411,9 +418,9 @@ Domain *PreProcess(int argc, char **argv
   }
 
   if(slvtype == TurbCurr){
     omega->Lfx = U->gen_aux_field('l');
-    omega->Lfy = U->gen_aux_field('l');
+    omega->Lfy =    U->gen_aux_field('l');
   
     omega->lfx  = (double**) malloc(Je*sizeof(double*));
     for(k = 0; k < Je; ++k){
       omega->lfx[k] = dvector(0,U->htot*U->nz-1);
@@ -580,8 +587,9 @@ void PostProcess(Domain *omega, int step
 
   Writefld(fp, omega->name, step, time, nfields, V);
   fflush(fp[0]);
 
+  free(V);
   free(size);
 
   //fclose(fp[0]);
   //fclose(omega->his_file);
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/ChangeLog clean2/Particle/src/ChangeLog
--- dirty/Particle/src/ChangeLog	Thu Jan  1 01:00:00 1970
+++ clean2/Particle/src/ChangeLog	Wed May  1 17:51:41 2002
@@ -0,0 +1,16 @@
+2002-04-23  Angus Leeming <[EMAIL PROTECTED]>
+
+	* PC_makestep.C (PC_Make_step_hybrid): initialise double shear. 
+	Initialise matrices h and J. Together these resolve valgrind "Use of 
+	uninitialised value" reports.
+
+	* particle.h: give class Butcher_arrays a default c-tor and d-tor.
+
+	* PC_accessories.C (~Butcher_arrays): free memory.
+
+	* PC_accessories.C (~Particle_Cluster): Vcsi was free-d and then
+	delete []-ed!
+
+	* Pre_interpolation.C (Prt_Interp_field_in_time): move creation
+	of dmatrix data closer to where it's used and after those return 
+	statements.
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/PC_accessories.C clean2/Particle/src/PC_accessories.C
--- dirty/Particle/src/PC_accessories.C	Fri Feb  1 17:14:03 2002
+++ clean2/Particle/src/PC_accessories.C	Wed May  1 17:51:41 2002
@@ -8,12 +8,24 @@
 
 /* These functions are accessory functions for class Particle_Cluster */
 /* Their puorpose is to access the member functions of this class     */
 
+Butcher_arrays::~Butcher_arrays()
+{
+  if (ai+1)
+    free_dmatrix(ai, 1, 0);
+  if (bi)
+    free_dmatrix(bi, 0, 0);
+  if (ci+1)
+    free_dvector(ci, 1);
+}
+
 
 /* Default constructor */
 
-Particle_Cluster::Particle_Cluster(){
+Particle_Cluster::Particle_Cluster() 
+  : nel(0), mesh(0)
+{
   dim = 0;
   npts = 0;
   xyz = NULL;
   csi = NULL;
@@ -53,9 +65,11 @@ Coord *alloc_coord(int npts, int dim){
 //#define  dealloc_coord(c) {delete [] c->x; delete [] c;}
 #define  dealloc_coord(c) {delete [] c->x; free (c);}
 
 
-Particle_Cluster::Particle_Cluster(int dimin, int nptsin){
+Particle_Cluster::Particle_Cluster(int dimin, int nptsin)
+  : nel(0), mesh(0)
+{
   int p;
 
   dim = dimin;
   npts = nptsin;
@@ -85,16 +99,21 @@ Particle_Cluster::Particle_Cluster(int d
 }
 
 /* Destructor: free memory */
 
-Particle_Cluster::~Particle_Cluster(){
+Particle_Cluster::~Particle_Cluster()
+{
   dealloc_coord(xyz);
   dealloc_coord(csi);
   dealloc_coord(Vxyz);
   dealloc_coord(xyzstart);
   dealloc_coord(Vcsi);
 
-  delete [] Vcsi;
+  for(int i = 0; i < nel; ++i){
+    free(mesh[i].x);
+  }
+
+  delete [] mesh;
   delete [] k;
   delete [] colour;
   delete [] s;
   delete [] restime;
@@ -104,9 +123,11 @@ Particle_Cluster::~Particle_Cluster(){
 }
 
 /* Copy constructor */
 
-Particle_Cluster::Particle_Cluster(const Particle_Cluster *cluster){
+Particle_Cluster::Particle_Cluster(const Particle_Cluster *cluster)
+  : nel(0), mesh(0)
+{
   int p;
 
   //sort out copy constructor 
 
@@ -165,8 +186,11 @@ void Particle_Cluster::PC_Check_MaxTime(
 
 void Particle_Cluster::Set_ai_Butcher_array(){
   double **ai;
   
+  if (aibici.ai)
+    fprintf(stderr, "ai is set already!\n");
+
   if(RKstg > 1){
     ai = dmatrix(1,RKstg-1,0,RKstg-2);
     dzero((RKstg-1)*(RKstg-1),&ai[1][0],1);
   }
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/PC_makestep.C clean2/Particle/src/PC_makestep.C
--- dirty/Particle/src/PC_makestep.C	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/PC_makestep.C	Wed May  1 17:51:41 2002
@@ -203,8 +203,9 @@ void Particle_Cluster::PC_Make_step_hybr
   Element *E;
 
 
 #ifdef SHEAR
+  shear = 0.0;
   nvar = dim + 1;
 #else
   nvar = dim;
 #endif
@@ -223,8 +224,11 @@ void Particle_Cluster::PC_Make_step_hybr
     }
     
     h = dmatrix(0,dim-1,0,QGmax-1);
     J = dmatrix(0,dim-1,0,dim-1);
+
+    dzero(dim * QGmax, h[0], 1);
+    dzero(dim * dim,   J[0], 1);
 
     Tol = dparam("P_COOR_TOL");
     init = 0;
   }
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/Prt_interpolation.C clean2/Particle/src/Prt_interpolation.C
--- dirty/Particle/src/Prt_interpolation.C	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/Prt_interpolation.C	Wed May  1 17:51:41 2002
@@ -4,8 +4,9 @@
 #include <veclib.h>
 #include <hotel.h>
 #include <gen_utils.h>
 #include "particle.h"
+#include <smart_ptr.hpp>
 
 void Particle_Cluster::Prt_Interp_geom_fact(Element *E, Coord A, double **J,
 				    double **h){
   if(dim == 2) {
@@ -111,10 +112,13 @@ void Particle_Cluster::Prt_Interp_field_
   int      nekdumps   = fdata->nekdumps;
   int     *dataskip   = fdata->dataskip;
   double  *dtime      = fdata->dumptime, **data,dt;
   Element  *E         = Vel[0]->flist[eid];
-  static   double     last_tlevel = 0, *time, *mode;
-  static   int        *Interp_done;
+
+  static double last_tlevel = 0;
+  static nektar::scoped_c_ptr<double> scoped_time;
+  static nektar::scoped_c_ptr<double> scoped_mode;
+  static nektar::scoped_c_ptr<int> scoped_Interp_done;
 
 #ifdef ANALYTIC_SOL
   for(i = 0; i < E->qa*E->qb*E->qc; ++i){
     Vel[0]->flist[eid]->h_3d[0][0][i] = -mesh[eid].x[i];
@@ -123,18 +127,20 @@ void Particle_Cluster::Prt_Interp_field_
   }
   return;
 #endif
 
+  if(!scoped_Interp_done.get()){
+    scoped_Interp_done.reset(ivector(0,Vel[0]->nel-1));
+    izero(Vel[0]->nel,scoped_Interp_done.get(),1);
 
-  if(!Interp_done){
-    Interp_done = ivector(0,Vel[0]->nel-1);
-    izero(Vel[0]->nel,Interp_done,1);
-    time = dvector(0,nload-1);
-    mode = dvector(0,nload-1);
+    scoped_time.reset(dvector(0,nload-1));
+    scoped_mode.reset(dvector(0,nload-1));
   }
 
-  data = dmatrix(0,dim-1,0,E->Nmodes-1);
-  
+  int * Interp_done = scoped_Interp_done.get();
+  double * time = scoped_time.get();
+  double * mode = scoped_mode.get();
+
   // make sure tlevel is in nektar field dump interval 
   if(fdata->periodic)
     tlevel = fmod(fmod(tlevel,fdata->periodic) + fdata->periodic,
 		  fdata->periodic) + dtime[0];
@@ -171,8 +177,10 @@ void Particle_Cluster::Prt_Interp_field_
       Field_Dump = i;
       break;
     }
 
+  data = dmatrix(0,dim-1,0,E->Nmodes-1);
+  
   if(Field_Dump+1)
     copyelfield(fld_dump[Field_Dump][0],dim,eid,Vel);
   else{ // interpolate 
     for(f=0;f < dim;++f){
@@ -186,8 +194,10 @@ void Particle_Cluster::Prt_Interp_field_
     }
     copyelfield(fld_dump[0][0],dim,eid,data,Vel);
   }
 
+  free_dmatrix(data,0,0);
+
   // put data in physical space 
   for(f=0;f<dim;++f) 
     Vel[f]->flist[eid]->Trans(Vel[f]->flist[eid], J_to_Q);
 
@@ -196,10 +206,8 @@ void Particle_Cluster::Prt_Interp_field_
   else{
     izero(Vel[0]->nel,Interp_done,1);  
     last_tlevel = tlevel;
   }
-
-  free_dmatrix(data,0,0);
 
   return;
 }
 
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/misc/ChangeLog clean2/Particle/src/misc/ChangeLog
--- dirty/Particle/src/misc/ChangeLog	Thu Jan  1 01:00:00 1970
+++ clean2/Particle/src/misc/ChangeLog	Wed May  1 17:51:41 2002
@@ -0,0 +1,5 @@
+2002-04-23  Angus Leeming <[EMAIL PROTECTED]>
+
+	* io.C (ReadMesh): initialise components of Coord X to prevent 
+	valgrind reporting a subsequent use of an uninitialised value.
+	On exitting loop, free these components.
\ No newline at end of file
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/misc/gen_utils.C clean2/Particle/src/misc/gen_utils.C
--- dirty/Particle/src/misc/gen_utils.C	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/misc/gen_utils.C	Wed May  1 17:51:41 2002
@@ -114,8 +114,10 @@ int generic_args (int argc, char *argv[]
 	    fprintf(stderr, "%s: unable to open the mesh file -- %s or %s\n", 
 		    prog, *argv, fname);
 	    exit(1);
 	  }
+	if (f->mesh.name)
+	  free(f->mesh.name);
 	f->mesh.name = strdup(fname);
 	break;
 
       case 'r':                           /* read the session file */
@@ -130,16 +132,20 @@ int generic_args (int argc, char *argv[]
 	    fprintf(stderr,"%s: unable to open the session file -- %s or %s\n",
 		    prog, *argv, fname);
 	    exit(1);
 	  }
+	if (f->rea.name)
+	  free(f->rea.name);
 	f->rea.name = strdup(fname);
 
 	/* Try to open the connectivity file.  This file is usually *
 	 * optional, so the application is responsible for error    *
 	 * checking.                                                */
 	
 	strcpy(fname + strlen(fname)-3, "mor");
 	f->mor.fp   = fopen (fname,"r");
+	if (f->mor.name)
+	  free(f->mor.name);
 	f->mor.name = strdup(fname);
 	break;
 
       case 'o':                         /* direct the output to a file */
@@ -153,8 +159,10 @@ int generic_args (int argc, char *argv[]
 	  fprintf(stderr, "%s: unable to open the output file -- %s\n", 
 		  prog, fname);
 	  exit(1);
 	}
+	if (f->out.name)
+	  free(f->out.name);
 	f->out.name = strdup(fname);
 	break;
 
       case 'v': {               /* be verbose and echo the version */
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/misc/io.C clean2/Particle/src/misc/io.C
--- dirty/Particle/src/misc/io.C	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/misc/io.C	Wed May  1 17:51:41 2002
@@ -229,8 +229,11 @@ Element_List *ReadMesh (FILE *fp, char* 
   Coord X;
   X.x = dvector(0,Max_Nverts-1);
   X.y = dvector(0,Max_Nverts-1);
   X.z = dvector(0,Max_Nverts-1);
+  dzero(Max_Nverts-1, X.x, 1);
+  dzero(Max_Nverts-1, X.y, 1);
+  dzero(Max_Nverts-1, X.z, 1);
 
   /* Read in mesh information */
   for(k = 0; k < nel; k++) {
     fgets(buf, BUFSIZ, fp);  /* element header */
@@ -277,8 +280,12 @@ Element_List *ReadMesh (FILE *fp, char* 
       fgets(buf_a, BUFSIZ, fp);  /* finish the line */
     }
   }
   
+  free_dvector(X.x, 0);
+  free_dvector(X.y, 0);
+  free_dvector(X.z, 0);
+
   for(k = 0; k < nel-1; ++k)     new_E[k]->next = new_E[k+1];
   new_E[k]->next = (Element*) NULL;
   
   Element_List* E_List = (Element_List*) new Element_List(new_E, nel);	 
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/misc/prepost.C clean2/Particle/src/misc/prepost.C
--- dirty/Particle/src/misc/prepost.C	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/misc/prepost.C	Wed May  1 17:51:41 2002
@@ -696,8 +696,10 @@ Gmap *GlobalNumScheme(Element_List *UL, 
   for(E = U; E; E = E->next)
     for(i = 0; i < E->Nedges; ++i)
       E->edge[i].gid = gbmap[E->edge[i].gid];
   
+  free(gsolve); free(gbmap);
+
   if(U->dim() == 3){
     /*------------------*/
     /* Face re-ordering */
     /*------------------*/
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/particle.C clean2/Particle/src/particle.C
--- dirty/Particle/src/particle.C	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/particle.C	Wed May  1 17:51:41 2002
@@ -56,8 +56,36 @@ static int  PG_set_nmb_of_RK_stages();
 #define Timing(s) \
  /* Nothing */
 #endif
 
+FieldData::FieldData()
+  : steady(0), nload(0), nekdumps(0), dmpid(0), backwards(0), 
+  dataskip(0), periodic(0), dumptime(0), fld_dump(0)
+{}
+
+FieldData::~FieldData()
+{
+  delete [] dataskip;
+  delete [] dumptime;
+
+  for (int i = 0; i < nload; ++i) {
+    freeField(fld_dump[i]);
+  }
+
+  // The field data ptrs are shifted around in Transient_Field. However, we
+  // know that they were created in a block by operator new [], so we just 
+  // need to check their addresses to ascertain which one to pass to 
+  // operator delete [].
+  Field * allocated_field = fld_dump[0];
+  for (int i = 0; i < nload; ++i) {
+    if (allocated_field > fld_dump[i])
+      allocated_field = fld_dump[i];
+  }
+  delete [] allocated_field;
+
+  free(fld_dump);
+}
+
 /** 
 This is the main routine for particle tracker
  */
 main (int argc, char *argv[]){
@@ -75,8 +103,10 @@ main (int argc, char *argv[]){
 
   outfile    = file.out.fp;
 
   setup_field     (&file,&U,&fld);
+  int const dim = fld.dim;
+
   setup_particles (&file,U,&pclust,fld.dim);
   P_summary       (pclust,file.in.name);
   setup_fdata     (*U,&fdata,&fld,pclust);
 
@@ -124,17 +154,16 @@ main (int argc, char *argv[]){
   }
 
   for(i = 0; i < pclust->npts; ++i)  pclust->bnd[i] = BndInit;
   pclust->PC_output(step,outfile);
+  fclose(outfile);
 
   // calculate error 
   double err;
   for(i = 0; i < 3*pclust->npts; ++i)  
     err += (pclust->xyz[0].x[i]- pclust->xyzstart[0].x[i])*
       (pclust->xyz[0].x[i]- pclust->xyzstart[0].x[i]);
   fprintf(stderr,"Error: %lg\n",sqrt(err));
-  
-
 #endif
 
 
   // -----------------------------------------------------------------
@@ -143,8 +172,27 @@ main (int argc, char *argv[]){
   
   fprintf(stderr,"%d particle paths have been traced in %d step(s)\n", 
 	 pclust->npts,step);
   
+  // -----------------------------------------------------------------
+  for(int i = 0; i < dim; ++i) {
+    delete U[i];
+  }
+  free(U);
+
+  delete pclust;
+
+  if (file.in.name)
+    free(file.in.name);
+  if (file.rea.name)
+    free(file.rea.name);
+  if (file.mesh.name)
+    free(file.mesh.name);
+  if (file.mor.name)
+    free(file.mor.name);
+  if (file.out.name)
+    free(file.out.name);
+
   return 0;
 }
 
 static int PG_set_nmb_of_RK_stages(){
@@ -259,10 +307,47 @@ static void Calc_data_skip(Element_List 
   return;
 }
 
 
-Element_List *GMesh;
-Gmap *gmap;
+// We create this store for gmesh and gmap so that they can be free-d 
+// when the program ends.
+// In turn, we do this to make it easier to debug genuine memory leaks.
+class GlobalVars {
+public:
+  // This is a singleton class. Get the instance.
+  static GlobalVars & get();
+
+  // Some compilers don't like the d-tor being private.
+  ~GlobalVars();
+
+  Element_List *gmesh;
+  Gmap *gmap;
+  
+private:
+  // Make the c-tor private so we can control how many objects
+  // are instantiated.
+  GlobalVars();
+};
+
+GlobalVars & GlobalVars::get()
+{
+  static GlobalVars singleton;
+  return singleton;
+}
+
+GlobalVars::GlobalVars() 
+  : gmesh(0), gmap(0) 
+{}
+
+GlobalVars::~GlobalVars()
+{
+  delete gmesh;
+
+  free(gmap->vgid);
+  free(gmap->egid);
+  free(gmap->fgid);
+  free(gmap);
+}
 
 static void setup_field(FileList *file, Element_List ***U, Field *fld){
   int i;
   int nfields,dump;
@@ -280,11 +365,12 @@ static void setup_field(FileList *file, 
 
   iparam_set("MODES", fld->lmax);
 
   /* Generate the list of elements */
-  GMesh = ReadMesh(file->rea.fp, strtok(file->rea.name,".")); 
-  gmap  = GlobalNumScheme(GMesh, (Bndry *)NULL);
-  U[0][0] = LocalMesh(GMesh,strtok(file->rea.name,".")); 
+  GlobalVars & gvars = GlobalVars::get();
+  gvars.gmesh = ReadMesh(file->rea.fp, strtok(file->rea.name,".")); 
+  gvars.gmap  = GlobalNumScheme(gvars.gmesh, (Bndry *)NULL);
+  U[0][0] = LocalMesh(gvars.gmesh,strtok(file->rea.name,".")); 
 
   init_ortho_basis();
 
   /* load field structures to element_list */
@@ -353,11 +439,11 @@ static void setup_particles(FileList *fi
     break;
   }
     
   // setup mesh coordinates
-  nel = U[0]->nel;
-  pclust[0]->mesh = new Coord[nel];
-  for(i = 0; i < nel; ++i){
+  pclust[0]->nel = U[0]->nel;
+  pclust[0]->mesh = new Coord[pclust[0]->nel];
+  for(i = 0; i < pclust[0]->nel; ++i){
     qt = U[0]->flist[i]->qa*U[0]->flist[i]->qb;
     if(dim == 3) qt *= U[0]->flist[i]->qc;
     pclust[0]->mesh[i].x = dvector(0,dim*qt-1);
     pclust[0]->mesh[i].y = pclust[0]->mesh[i].x + qt;
@@ -616,15 +702,14 @@ static void setup_fdata(Element_List *U,
     }
     
     for(i = 0; i < fld_dump->nel; ++i) // ensure field is at correct time
       pclust->Prt_Interp_field_in_time(fdata,i,pclust->abstime[0]);
-    
+
     // set up global velocities
     pclust->PC_set_glob_vel();
 
     freeField(startfld);
   }
-
 }
 
 static void P_summary (Particle_Cluster *pc, char *name ){
   fprintf(stderr,"Input Information\n");
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/Particle/src/particle.h clean2/Particle/src/particle.h
--- dirty/Particle/src/particle.h	Fri Feb  1 13:26:29 2002
+++ clean2/Particle/src/particle.h	Wed May  1 17:51:41 2002
@@ -1,8 +1,11 @@
 #include <veclib.h>
 #include <hotel.h>
 
 struct Butcher_arrays{
+  Butcher_arrays() : ai(0), bi(0), ci(0) {}
+  ~Butcher_arrays();
+
   double **ai;
   double **bi;
   double *ci;
 };
@@ -15,8 +18,11 @@ enum BndAct{
   BndInit        = -10
 };
 
 struct FieldData {
+  FieldData();
+  ~FieldData();
+
   int    steady;    // data is steady if set to 1
   int    nload;     // number of fields to load 
   int    nekdumps;  // number of nektar fields dumps available
   int    dmpid;     // id of starting field currently stored in fld_dump
@@ -70,8 +76,9 @@ class Particle_Cluster {
    int          dim;        /* dimensions of the problem        */
    int          npts;       /* number of particles              */
    int          kopt;       /* use optimised time step          */
    char         status;     /* scheme type 'H', 'P' or 'E'      */
+   int          nel;        /* The number of elements in the mesh */
    Coord        *mesh;      /* Mesh coordinates                 */
    Coord        *xyz;       /* physical coords                  */
    Coord        *csi;       /* cartesian local coords           */
    Coord        *xyzstart;  /* initial coordinates of particles */
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/include/nekstruct.h clean2/include/nekstruct.h
--- dirty/include/nekstruct.h	Fri Feb  1 13:26:29 2002
+++ clean2/include/nekstruct.h	Wed May  1 17:51:41 2002
@@ -391,8 +391,11 @@ class Element{
   Element();                                         // default constructor
   Element(const Element&);                           // copy constructor
   Element(Element*);                                 // copy constructor
 
+  // A base class without a virtual d-tor? You're mad and bad.
+  virtual ~Element();
+
   // Local Matrix builders
   virtual void MassMat (LocMat *);                   // return mass-matri(ces)
   virtual void MassMatC(LocMat *);
   virtual void HelmMatC(LocMat *, Metric *lambda);           // return Helmholtz op.
@@ -602,8 +605,9 @@ public:
   int           nztot; 
 
   Element_List();
   Element_List(Element **hea, int n);
+  ~Element_List();
 
   virtual Element *operator()(int i);
   virtual Element *operator[](int i);
 
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/include/smart_ptr.hpp clean2/include/smart_ptr.hpp
--- dirty/include/smart_ptr.hpp	Thu Jan  1 01:00:00 1970
+++ clean2/include/smart_ptr.hpp	Wed May  1 17:51:41 2002
@@ -0,0 +1,104 @@
+/**
+ * \file smart_ptr.hpp
+ * \author Angus Leeming, [EMAIL PROTECTED]
+ * \date April 2002
+ *
+ * class nektar::scoped_ptr is a small extension of the boost::scoped_ptr idea.
+ * See www.boost.org for more about boost.
+ *
+ * The original, boost smart_ptr.hpp file contains the following notice:
+ *
+ *  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
+ *  use, modify, sell and distribute this software is granted provided this
+ *  copyright notice appears in all copies. This software is provided "as is"
+ *  without express or implied warranty, and with no claim as to its
+ *  suitability for any purpose.
+ *
+ * nektar::scoped_ptr can be used in identical fashion to the boost class, 
+ * but can also be used to invoke an arbitrary functor when it goes out of 
+ * scope.
+ *
+ * A simple example:
+ *
+ *   void example() 
+ *   {
+ *      nektar::scoped_c_ptr<Foo> scoped_foo((Foo*)malloc(sizeof(Foo)));
+ *      Foo * foo = scoped_foo.get();
+ *      ...
+ *      // scoped_foo calls free(foo) automatically as it goes out of scope
+ *   }
+ *
+ * The additional power lies in being able to define arbitrary functors to
+ * perform the destruction. Great with c-style structs that have no d-tor.
+ */
+
+#ifndef NEKTAR_SMART_PTR_HPP
+#define NEKTAR_SMART_PTR_HPP
+
+namespace nektar {
+
+class noncopyable {
+protected:
+        noncopyable(){}
+        ~noncopyable(){}
+private:
+        noncopyable( const noncopyable& );
+        const noncopyable& operator=( const noncopyable& );
+};
+
+template< typename T >
+struct DeletePtr {
+	void operator()(T * x) { delete x; }
+};
+	
+template< typename T, typename Destroyer=DeletePtr<T> >
+class scoped_ptr : noncopyable {
+
+	T* ptr;
+
+	void destroy_ptr() {
+		if (ptr) {
+			Destroyer destroy;
+			destroy(ptr);
+		}
+	}
+
+public:
+	typedef T element_type;
+
+	explicit scoped_ptr( T* p=0 ) : ptr(p) {}
+	~scoped_ptr() { destroy_ptr(); }
+	void reset( T* p=0 )  { if ( ptr != p ) { destroy_ptr(); ptr = p; } }
+	T& operator*()  const { return *ptr; }
+	T* operator->() const { return ptr; }
+	T* get() const        { return ptr; }
+};
+
+// and some shorthand helpers...
+template< typename T >
+struct DeleteArrayPtr {
+	void operator()(T * x) { delete [] x; }
+};
+	
+
+template< typename T >
+struct FreePtr {
+	void operator()(T * x) { free(x); }
+};
+	
+
+template< typename T >
+struct scoped_array_ptr : public scoped_ptr<T, DeleteArrayPtr<T> > {
+	explicit scoped_array_ptr( T* p=0 )
+		: scoped_ptr<T, DeleteArrayPtr<T> >(p) {}
+};
+
+template< typename T >
+struct scoped_c_ptr : public scoped_ptr<T, FreePtr<T> > {
+	explicit scoped_c_ptr( T* p=0 )
+		: scoped_ptr<T, FreePtr<T> >(p) {}
+};
+
+} // namespace nektar
+
+#endif // NEKTAR_SMART_PTR_HPP
========================================================================
diff -p -N -r -U 4 -X excl.tmp dirty/include/work.h clean2/include/work.h
--- dirty/include/work.h	Fri Feb  1 13:26:29 2002
+++ clean2/include/work.h	Wed May  1 17:51:41 2002
@@ -1,6 +1,8 @@
 #ifndef NEKWORK
-extern double *Tri_wk;
+#include <smart_ptr.hpp>
+
+extern nektar::scoped_c_ptr<double> Tri_wk;
 
 extern double *Quad_wk;
 extern double *Quad_Jbwd_wk;
 extern double *Quad_Iprod_wk;

Reply via email to