[test-suite] r312488 - Revert "Revert "[test-suite] Adding the CLAMR mini-app""

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 4 07:25:36 PDT 2017


Author: hfinkel
Date: Mon Sep  4 07:25:36 2017
New Revision: 312488

URL: http://llvm.org/viewvc/llvm-project?rev=312488&view=rev
Log:
Revert "Revert "[test-suite] Adding the CLAMR mini-app""

This reverts commit r312482 with fixes for ODR violations (at least one of
which was manifesting as a linking error on AArch64).

Commit message from r312482:

Revert "[test-suite] Adding the CLAMR mini-app"

This reverts commit r312465, r312463, as they broke the AArch64
test-suite:

http://lab.llvm.org:8011/builders/clang-cmake-aarch64-quick/builds/8141

Reported in: PR34453

Added:
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CLAMR.reference_output
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CMakeLists.txt
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Globals.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/LICENSE
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Makefile
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.cc
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.hh
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/clamr_cpuonly.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfcsort.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/mesh.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/mesh.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/partition.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/partition.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/reduce.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/reduce.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/s7.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/s7.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/state.cpp
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/state.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/timer.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/timer.h
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/zorder.c
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/zorder.h
Modified:
    test-suite/trunk/LICENSE.TXT
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CMakeLists.txt
    test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/Makefile

Modified: test-suite/trunk/LICENSE.TXT
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/LICENSE.TXT?rev=312488&r1=312487&r2=312488&view=diff
==============================================================================
--- test-suite/trunk/LICENSE.TXT (original)
+++ test-suite/trunk/LICENSE.TXT Mon Sep  4 07:25:36 2017
@@ -86,6 +86,7 @@ smg2000:            llvm-test/MultiSourc
 miniAMR:            llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C/miniAMR
 Pathfinder:         llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C/Pathfinder
 XSBench:            llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C/XSBench
+CLAMR:              llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR
 HPCCG:              llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C++/HPCCG
 PENNANT:            llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C++/PENNANT
 miniFE:             llvm-test/MultiSource/Benchmarks/DOE-ProxyApps-C++/miniFE

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Bounds.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ *           Other LANL authors
+ * 
+ */
+#include "Bounds.h"
+
+#define MEMCPY(s,d,n,t) {memcpy((void*)d, (void*)s, n * sizeof(t)); }
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+void Bounds_Copy(TBounds* src, TBounds* dest) {
+   assert(src && dest);
+   MEMCPY(src, dest, 1, TBounds);
+}
+
+void Bounds_Infinite(TBounds* b){
+   assert(b);
+   b->min.x = POSITIVE_INFINITY;
+   b->min.y = POSITIVE_INFINITY;
+   b->max.x = NEGATIVE_INFINITY;
+   b->max.y = NEGATIVE_INFINITY;
+}
+
+void Bounds_AddBounds(TBounds* b, TBounds* add) {
+   assert(b && add);
+   b->min.x = MIN(b->min.x, add->min.x);
+   b->min.y = MIN(b->min.y, add->min.y);
+   b->max.x = MAX(b->max.x, add->max.x);
+   b->max.y = MAX(b->max.y, add->max.y);
+}
+
+void Bounds_AddEpsilon(TBounds* b, double add) {
+   assert(b);
+   b->min.x = b->min.x - add;
+   b->min.y = b->min.y - add;
+   b->max.x = b->max.x + add;
+   b->max.y = b->max.y + add;
+}
+
+bool Bounds_IsOverlappingBounds(TBounds* b, TBounds* tst) {
+   assert(b && tst);
+   if((tst->max.x < b->min.x) || (tst->min.x > b->max.x))
+      return(false);
+   if((tst->max.y < b->min.y) || (tst->min.y > b->max.y))
+      return(false);
+   return(true);
+}
+
+double Bounds_WidthAxis(TBounds* b, unsigned int axis)
+{
+   double width;
+   
+   assert(b);
+   if(axis == XAXIS)
+      width = b->max.x - b->min.x;
+   else if(axis == YAXIS)
+      width = b->max.y - b->min.y;
+   else
+      assert(NULL);
+   return(width);
+}
+
+double Bounds_CenterAxis(TBounds* b, unsigned int axis)
+{
+   double center;
+   
+   assert(b);
+   if(axis == XAXIS)
+      center = (b->min.x + b->max.x) * 0.5;
+   else if(axis == YAXIS)
+      center = (b->min.y + b->max.y) * 0.5;
+   else
+      assert(NULL);
+   return(center);
+}

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Bounds.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Bounds.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ *           Other LANL authors
+ * 
+ */
+
+#include <stdbool.h>
+
+#ifndef _Bounds_
+#define _Bounds_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+   
+#include "Globals.h"
+
+typedef struct {
+   TVector min, max;
+} TBounds;
+
+extern void Bounds_Copy(TBounds* src, TBounds* dest);
+extern void Bounds_Infinite(TBounds* b);
+extern void Bounds_AddBounds(TBounds* b, TBounds* add);
+extern void Bounds_AddEpsilon(TBounds* b, double add);
+extern bool Bounds_IsOverlappingBounds(TBounds* b, TBounds* tst);
+extern double Bounds_WidthAxis(TBounds* b, unsigned int axis);
+extern double Bounds_CenterAxis(TBounds* b, unsigned int axis);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CLAMR.reference_output
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/CLAMR.reference_output?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CLAMR.reference_output (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CLAMR.reference_output Mon Sep  4 07:25:36 2017
@@ -0,0 +1,19 @@
+Mass of initialized cells equal to  31290.8709635
+Iteration   0 timestep      n/a Sim Time      0.0 cells 4412 Mass Sum  31290.8709635
+Iteration 100 timestep 0.000349 Sim Time 0.045244 cells 4652 Mass Sum  31290.8709635 Mass Change            0
+Iteration 200 timestep 0.000386 Sim Time 0.080903 cells 4760 Mass Sum  31290.8709635 Mass Change            0
+Iteration 300 timestep 0.000442 Sim Time 0.121853 cells 4892 Mass Sum  31290.8709635 Mass Change            0
+Iteration 400 timestep 0.000502 Sim Time 0.169292 cells 4976 Mass Sum  31290.8709635 Mass Change -3.63798e-12
+Iteration 500 timestep 0.000614 Sim Time 0.224092 cells 5096 Mass Sum  31290.8709635 Mass Change -3.63798e-12
+Iteration 600 timestep 0.000701 Sim Time 0.288037 cells 5372 Mass Sum  31290.8709635 Mass Change -3.63798e-12
+Iteration 700 timestep 0.000787 Sim Time 0.362393 cells 5780 Mass Sum  31290.8709635 Mass Change -7.27596e-12
+Iteration 800 timestep 0.000922 Sim Time 0.449275 cells 6152 Mass Sum  31290.8709635 Mass Change -1.09139e-11
+Iteration 900 timestep 0.001131 Sim Time 0.551298 cells 6704 Mass Sum  31290.8709635 Mass Change -1.09139e-11
+Iteration 1000 timestep 0.001318 Sim Time 0.672188 cells 7208 Mass Sum  31290.8709635 Mass Change -1.09139e-11
+Using hash tables to calculate neighbors
+hash table size  bytes 278784
+Initial order is Hilbert sort.   No cycle reorder.   Local Stencil is on.
+CPU:  rezone frequency                	  17.1000	percent
+CPU:  calc neigh frequency            	  17.2000	percent
+CPU:  refine_smooth_iter per rezone   	   0.0000	
+exit 0

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/CMakeLists.txt?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CMakeLists.txt (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/CMakeLists.txt Mon Sep  4 07:25:36 2017
@@ -0,0 +1,3 @@
+set(PROG CLAMR)
+set(RUN_OPTIONS -n 64 -t 1000)
+llvm_multisource()

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Cmd.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,3972 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds command lines broken up into words.
+// The term command is used in a general sense, it includes variable
+// assignments, do loops, usual commands, etc.
+// ***************************************************************************
+// ***************************************************************************
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <deque>
+#include <sstream>
+#include <map>
+#include <algorithm>
+#include <math.h>
+#include <assert.h>
+
+#include "Parser_utils.hh"
+#include "Variable.hh"
+#include "Function.hh"
+#include "Word.hh"
+#include "Parser_math.hh"
+#include "Cmd.hh"
+
+namespace PP
+{
+using std::cout;
+using std::endl;
+using std::string;
+using std::deque;
+using std::vector;
+using std::stringstream;
+using std::pair;
+using std::ifstream;
+using std::ios;
+using std::setw;
+
+// index base, generally 1 for Fortran style and 0 for C/C++, default 1
+static int index_base = 1;
+static bool case_sensitive = false;
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Cmd::Cmd() 
+{
+    init();
+}
+
+
+// ===========================================================================
+// Constructor including map of variables.
+// ===========================================================================
+Cmd::Cmd(string s, map<string, Variable> *v, map<string, Function> *f,
+         deque<string> *lstr, int lnum, int file_lnum, string fname,
+         stringstream &serr, int &ierr)
+{
+    init();
+    vmap = v;
+    fmap = f;
+    original_str = s;
+    line_number = lnum;
+    file_line_number = file_lnum;
+    filename = fname;
+    lines = lstr;
+    process_string(s, serr, ierr);
+}
+
+
+// ===========================================================================
+// Add a word to this cmd.
+// ===========================================================================
+void Cmd::add_word(string str, int lnum, int file_lnum, string fname)
+{
+    Word w(str, lnum, file_lnum, fname, lines);
+    words.push_back(w);
+}
+
+
+// ===========================================================================
+// Erase a word from this cmd.
+// ===========================================================================
+void Cmd::erase_word(int iw)
+{
+    words.erase(words.begin()+iw);
+}
+void Cmd::erase_last_word()
+{
+    words.erase(words.begin()+(int)words.size()-1);
+}
+
+
+// ===========================================================================
+// Remove words that are commas.
+// ===========================================================================
+void Cmd::remove_commas()
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].is_comma()) {
+            words.erase(words.begin()+i);
+            i -= 1;
+        }
+    }
+}
+
+
+// ===========================================================================
+// Initialize various private data.
+// ===========================================================================
+void Cmd::init()
+{
+    original_str = "";
+    //processed = false;
+    white_space = " \t";
+    delims = " \t()[],*/+-=!#";
+    vmap = NULL;
+    fmap = NULL;
+    line_number = 0;
+    file_line_number = 0;
+    filename = "";
+}
+
+
+// ===========================================================================
+// Set index base for input file indexing. 1 -- Fortran like, 0 -- Other
+//   languages
+// ===========================================================================
+void Cmd::set_index_base(int base)
+{
+    //cout << "Info:: Setting index base to " << base << endl;
+    index_base = base;
+}
+
+// ===========================================================================
+// Set case sensitivity for input file commands.
+// ===========================================================================
+void Cmd::set_case_sensitive(bool case_sensitive_in)
+{
+    case_sensitive = case_sensitive_in;
+}
+
+// ===========================================================================
+// Process a string.
+// Break the string into words and copy each word to a double ended queue.
+// ===========================================================================
+void Cmd::process_string(string in_str, stringstream &serr, int &ierr)
+{
+    //cout << "&&&&& Original line = " << endl;
+    //cout << in_str << endl;
+    //cout << "01234567890123456789012345678901234567890123456789" << endl;
+    //cout << "0         1         2         3         4         " << endl;
+
+    string s;
+    int istart = 0;
+    bool found = false;
+    //int plevel = 0;
+    for (;;) {
+        delims = " \t()[],*/+-=!#";
+
+        // Extract the next word from the line.
+        found = extract_next_word(istart, in_str, s, serr, ierr);
+        if (!found) break;
+
+        // Create a new word using the word that was found.
+        // This removes quotes if there are any and types the word.
+        Word w(s, line_number, file_line_number, filename, lines);
+
+        // Copy the word to the end of the queue.
+        words.push_back(w);
+    }
+
+    // Set the command name and type.
+    reset_name_type();
+}
+
+
+// ===========================================================================
+// Given a string, str, and a starting position in
+// that string, istart, extract the next word and
+// pass it back as a string.
+// ===========================================================================
+bool Cmd::extract_next_word(int &istart, string &str, string &word,
+                            stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    //assert(serr == serr);
+    assert(ierr == ierr);
+
+    // If istart is out of bounds then there is nothing to do.
+    if (istart < 0) return false;
+    if (istart >= (int)str.size()) return false;
+
+    // Find the next non blank character.
+    int i1 = str.find_first_not_of(white_space, istart);
+
+    // If a non whitespace character was not found then there are no more
+    // words to extract.
+    if (i1 == (int)string::npos) return false;
+
+    // If the non blank character that was found is a delimiter, like
+    // ()[]+-/* ... then it needs to be a word by itself.
+    if (delims.find(str[i1], 0) != string::npos) {
+        word = str[i1];
+        istart = i1+1;
+        return true;
+    }
+
+    // At this point we have found the start of a word. The end of the
+    // word will be one of the delimiters like ()[]+=-*/spacetab ...
+    string wend = delims;
+
+    // A word delimited by quotes is handled differently. If the i1
+    // position in the string is a beginning quotes then we need to search
+    // for an ending quotes. Anything between quotes is part of the word
+    // including delimters.
+    bool quotes = false;
+    if (str[i1] == '"') {
+        quotes = true;
+        wend = "\"";
+    }
+    if (str[i1] == '\'') {
+        quotes = true;
+        wend = "\'";
+    }
+
+    // Search for the end of the word by finding the next delimiter. The
+    // delimiter is one index past the end of the word.
+    // But if the next delimiter is + or - then we have to consider that
+    // this could be a floating point number in which case we continue
+    // past the + or - to find the next delimiter.
+    int i2;
+    int i1_start = i1+1;
+    for(;;) {
+        i2 = str.find_first_of(wend, i1_start);
+
+        // If a delimiter was not found then the word extends to the end
+        // of the line.
+        if (i2 == (int)string::npos) {
+            i2 = str.size();
+            break;
+        }
+        else {
+            // Check for a floating point number (fpn). For example
+            //       1.34e+14  or -3.8E-19
+            // i2 might point to the + or - in e+14 or E-19, so we check
+            // for that case. Note that if the + or - is not found, then it
+            // could be a number like 1.e14 but then i2 would point to
+            // something after e14 and we would be ok.
+            // If we do find +e or -e, then everything in front of it needs
+            // to be a digit, if not then this is not a number.
+            bool fpn = false;
+            if (str[i2] == '+' || str[i2] == '-') {
+                if (str[i2-1] == 'e' || str[i2-1] == 'E' ||
+                    str[i2-1] == 'd' || str[i2-1] == 'D') {
+                    fpn = true;
+                    for (int j=i1; j<=i2-2; j++) {
+                        if (!isdigit(str[j]) && str[j] != '.') {
+                            fpn = false;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (!fpn) break;
+            i1_start = i2+1;
+        }
+    }
+
+    // If the word is quoted then it should end in quotes.
+    // We do not check for quotes matching here because at this
+    // point we might be in a comment region where quotes mismatch
+    // is allowed. We check for quotes mismatch later.
+    if (quotes) {
+        if (i2 >= (int)str.size()) i2 = (int)str.size() - 1;
+    }
+    /*
+    if (quotes) {
+        bool missing = false;
+        if (i2 >= (int)str.size()) missing = true;
+        else if (str[i1] == '\"' && str[i2] != '\"') missing = true;
+        else if (str[i1] == '\'' && str[i2] != '\'') missing = true;
+        else if (str[i1] == '\"' && str[i2] == '\'') missing = true;
+        else if (str[i1] == '\'' && str[i2] == '\"') missing = true;
+        if (missing) {
+            fatal_error2(serr, ierr);
+            serr << "Quotes mismatch found." << endl;
+            serr << "A starting quotes must have a closing quotes." << endl;
+            serr << "Double quotes, \", must be matched with double quotes." << endl;
+            serr << "Single quotes, \', must be matched with single quotes." << endl;
+            ierr = 2;
+            return false;
+        }
+    }
+    */
+
+    // We include the quotes symbols in the word. The quote symbols will
+    // be removed elsewhere.
+    if (quotes) i2 += 1;
+
+    // The word is now delimited by i1 and i2-1, return it in word.
+    word = str.substr(i1, i2 - i1);
+
+    // Update the starting point for finding the next word.
+    istart = i2;
+
+    // A word was successfully found so return true.
+    return true;
+}
+
+
+// ===========================================================================
+// Reset the command name and type. Consider the following command:
+//      * lasdkj */ cmd = 5.0
+// The original command name is "*", but after the multi-line comment is
+// removed, the command name should be "cmd".
+// ===========================================================================
+void Cmd::reset_name_type()
+{
+    if ((int)words.size() == 0) {
+        cmd_name = " ";
+        cmd_type = " ";
+        return;
+    }
+    cmd_name = words[0].get_string();
+    if (! case_sensitive) {
+       transform(cmd_name.begin(), cmd_name.end(), cmd_name.begin(), tolower);
+    }
+    cmd_type = "command";
+    if (words[0].is_variable()) cmd_type = "assignment";
+    if (cmd_name == "parser_list_variables") cmd_type = "debug";
+    if (cmd_name == "parser_list_functions") cmd_type = "debug";
+    if (cmd_name == "parser_print_fbuffer")  cmd_type = "debug";
+    if (cmd_name == "if")      cmd_type = "internal_cmd";
+    if (cmd_name == "elseif")  cmd_type = "internal_cmd";
+    if (cmd_name == "endif")   cmd_type = "internal_cmd";
+    if (cmd_name == "do")      cmd_type = "internal_cmd";
+    if (cmd_name == "return")  cmd_type = "internal_cmd";
+    if (cmd_name == "enddo")   cmd_type = "internal_cmd";
+    if (cmd_name == "stop")    cmd_type = "internal_cmd";
+    if (cmd_name == "when")    cmd_type = "internal_cmd";
+    if (cmd_name == "endwhen") cmd_type = "internal_cmd";
+}
+
+
+// ===========================================================================
+// Given a line like
+//    include filename1 filename2 filename3 ...
+// Find the first filename that exists and return that.
+// This should only be called on the io processor.
+// ===========================================================================
+string Cmd::get_cmd_filename(stringstream &ssfiles)
+{
+    for (int i=1; i<(int)words.size(); i++) {
+        string fn = words[i].get_string();
+
+        // The quotes may still be on the word, strip them off if they are
+        // present.
+        int len = (int)fn.size();
+        if ((fn[len-1] == '\"') || (fn[len-1] == '\'')) {
+            fn.erase(fn.end() - 1);
+        }
+        if ((fn[0] == '\"') || (fn[0] == '\'')) {
+            fn.erase(fn.begin());
+        }
+
+        ssfiles << "    " << fn << endl;
+
+        // Open the file to test if it exists.
+        ifstream instm(fn.c_str(), ios::in);
+        instm.close();
+        if( instm.fail() ) continue;
+        return fn;
+    }
+    return "";
+}
+
+
+// ===========================================================================
+// Handle unary minus in a command line (not in math(..))
+// ===========================================================================
+void Cmd::handle_cmd_unary_minus(stringstream &serr, int &ierr)
+{
+    int ipstart = 0;
+    for (;;) {
+        int ip = find(ipstart, (int)words.size()-1, "-");
+
+        // If we do not find any more minus signs then we are done.
+        if (ip == -1) return;
+
+        // The word after the minus sign must be a number.
+        if (!words[ip+1].is_number()) {
+            words[ip+1].fatal_error(serr, ierr);
+            serr << "Expected the object following the unary - to"
+                " be a number." << endl;
+            serr << "Instead, it was " << words[ip+1].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+
+        // Actually do the negate operation.
+        do_unary_op(ip, "-");
+        ipstart = ip+1;
+        continue;
+    }
+}
+         
+
+// ===========================================================================
+// Handle unary plus in a command line (not in math(..))
+// ===========================================================================
+void Cmd::handle_cmd_unary_plus(stringstream &serr, int &ierr)
+{
+    int ipstart = 0;
+    for (;;) {
+        int ip = find(ipstart, (int)words.size()-1, "+");
+
+        // If we do not find any more minus signs then we are done.
+        if (ip == -1) return;
+
+        // The word after the plus sign must be a number.
+        if (!words[ip+1].is_number()) {
+            words[ip+1].fatal_error(serr, ierr);
+            serr << "Expected the object following the unary + to"
+                " be a number." << endl;
+            serr << "Instead, it was " << words[ip+1].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+
+        // The + sign is not needed.
+        delete_words(ip, ip);
+        ipstart = ip+1;
+        continue;
+    }
+}
+         
+
+// ===========================================================================
+// The following type of command is allowed:
+//      a(1) = 15*3.0
+// meaning that 3.0 is to be replicated 15 times and thus a(1)-a(15) is set
+// by this command.
+// ===========================================================================
+void Cmd::handle_cmd_multiplicity(stringstream &serr, int &ierr)
+{
+    int ipstart = 0;
+    for (;;) {
+        int ip = find(ipstart, (int)words.size()-1, "*");
+
+        // If we do not find any more asterisks then we are done.
+        if (ip == -1) return;
+
+        if (ip==0) {
+            fatal_error2(serr, ierr);
+            serr << "Asterisk cannot be at the start of a line." << endl;
+            ierr = 2;
+            return;
+        }
+
+        if (ip == (int)words.size()-1) {
+            words[ip].fatal_error(serr, ierr);
+            serr << "Asterisk cannot be at the end of a line." << endl;
+            ierr = 2;
+            return;
+        }
+
+        // The word after the asterisk must be a number or a boolean.
+        // Wait, why is this? We actually allow strings also, really
+        // we allow anything.
+        //if (!words[ip+1].is_number() && !words[ip+1].is_bool()) {
+        //    words[ip+1].fatal_error(serr, ierr);
+        //    serr << "Expected the object following the * to"
+        //        " be a number or a logical." << endl;
+        //    serr << "Instead, it was " << words[ip+1].get_string() << endl;
+        //    ierr = 2;
+        //    return;
+        //}
+
+        // The word before the asterisk must be a number.
+        if (!words[ip-1].is_number()) {
+            words[ip-1].fatal_error(serr, ierr);
+            serr << "Expected the object before the * to"
+                " be a number." << endl;
+            serr << "Instead, it was " << words[ip-1].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+
+        // Set the multiplicity.
+        int imult = words[ip-1].get_int(serr, ierr);
+        words[ip+1].set_multiplicity(imult);
+        Word w = words[ip+1];
+        replace_words(ip-1, ip+1, w);
+        ipstart = ip;
+    }
+}
+         
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Functions for getting values from the commands.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Get boolean values. This gets all the words past the = sign,
+// converts them to bool (and then to int), and puts them in the output arrays.
+//
+// The expected commands are:
+//    cmdname = .true.                    0d
+//    cmdname(5) = false true false       1d
+//    cmdname(5,9) = true false true      2d
+//    etc.
+//
+// We also allow
+//    cmdname = false true false
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// But note that the , is gone at this point, so the 2d command is
+//    cmdname ( 5 9 ) = true false true      2d
+//
+// This function works for any dimension, 0,1,2,3,...
+//
+// We pass the result back as an int because of the incompatibility between
+// fortran logical and c++ bool.
+// ===========================================================================
+void Cmd::get_bool_int(string &cname, int *array_vals, const vector<int> &size,
+                       vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                       int dup_fatal, vector<int> &dup_vals,
+                       bool skip, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, for example an equals sign must be present, and set istart.
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // If skipping, we don't need to get array values.
+    if (skip) {
+        set_processed(true);
+        return;
+    }
+
+    // Get the number of values past the = sign.
+    // Also mark the words up to and including the = sign as processed.
+    int nvals = 0;
+    if (!get_nvals(istart, size, nvals, serr, ierr)) return;
+
+    // 0d is a special case.
+    if (dim == 0) {
+        bool b = words[2].get_bool(serr, ierr);
+        int cvalue = 0;
+        if (b) cvalue = 1;
+        *array_vals = cvalue;
+        return;
+    }
+
+    // Get the values and return.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+    Parser_utils putils(index_base);
+    int k = putils.start_dex(istart, size);
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        bool b = words[i].get_bool(serr, ierr);
+        int cvalue = 0;
+        if (b) cvalue = 1;
+        int imult = words[i].get_multiplicity();
+        for (int j=1; j<=imult; j++) {
+            error_dup_line(cname, i, k, dup_wdex1, dup_cmd1, dup_vals, 
+                           size, dup_fatal, serr, ierr);
+            array_vals[k++] = cvalue;
+        }
+    }
+}
+
+// ===========================================================================
+// Get boolean values. This gets all the words past the = sign,
+// converts them to bool and puts them in the output arrays.
+//
+// The expected commands are:
+//    cmdname = .true.                    0d
+//    cmdname(5) = false true false       1d
+//    cmdname(5,9) = true false true      2d
+//    etc.
+//
+// We also allow
+//    cmdname = false true false
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// But note that the , is gone at this point, so the 2d command is
+//    cmdname ( 5 9 ) = true false true      2d
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Cmd::get_bool(string &cname, bool *array_vals, const vector<int> &size,
+                   vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                   int dup_fatal, vector<int> &dup_vals,
+                   bool skip, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, for example an equals sign must be present, and set istart.
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // If skipping, we don't need to get array values.
+    if (skip) {
+        set_processed(true);
+        return;
+    }
+
+    // Get the number of values past the = sign.
+    // Also mark the words up to and including the = sign as processed.
+    int nvals = 0;
+    if (!get_nvals(istart, size, nvals, serr, ierr)) return;
+
+    // 0d is a special case.
+    if (dim == 0) {
+        bool b = words[2].get_bool(serr, ierr);
+        *array_vals = b;
+        return;
+    }
+
+    // Get the values and return.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+    Parser_utils putils(index_base);
+    int k = putils.start_dex(istart, size);
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        bool b = words[i].get_bool(serr, ierr);
+        int imult = words[i].get_multiplicity();
+        for (int j=1; j<=imult; j++) {
+            error_dup_line(cname, i, k, dup_wdex1, dup_cmd1, dup_vals, 
+                           size, dup_fatal, serr, ierr);
+            array_vals[k++] = b;
+        }
+    }
+}
+
+
+// ===========================================================================
+// Get integer values. This gets all the words past the = sign,
+// converts them to int, and puts them in the output arrays.
+//
+// The expected commands are:
+//    cmdname = some_int                  0d
+//    cmdname(5) = 3, 5, -15, 10          1d
+//    cmdname(5,9) = 3, 7, -20, 154       2d
+//    etc.
+//
+// We also allow
+//    cmdname = 3, 5, -15, 10
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// But note that the , is gone at this point, so the 2d command is
+//    cmdname ( 5 9 ) = 3  7  -20  154 ...
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Cmd::get_int(string &cname, int *array_vals, const vector<int> &size,
+                  vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                  int dup_fatal, vector<int> &dup_vals,
+                  bool skip, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, for example an equals sign must be present, and set istart.
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // If skipping, we don't need to get array values.
+    if (skip) {
+        set_processed(true);
+        return;
+    }
+
+    // Get the number of values past the = sign.
+    // Also mark the words up to and including the = sign as processed.
+    int nvals = 0;
+    if (!get_nvals(istart, size, nvals, serr, ierr)) return;
+
+    // 0d is a special case.
+    if (dim == 0) {
+        *array_vals = words[2].get_int(serr, ierr);
+        return;
+    }
+
+    // Get the values and return.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+    Parser_utils putils(index_base);
+    int k = putils.start_dex(istart, size);
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        int iw = words[i].get_int(serr, ierr);
+        int imult = words[i].get_multiplicity();
+        for (int j=1; j<=imult; j++) {
+            error_dup_line(cname, i, k, dup_wdex1, dup_cmd1, dup_vals, 
+                           size, dup_fatal, serr, ierr);
+            array_vals[k++] = iw;
+        }
+    }
+}
+
+
+// ===========================================================================
+// Get int64_t values. This gets all the words past the = sign,
+// converts them to int, and puts them in the output arrays.
+//
+// The expected commands are:
+//    cmdname = some_int                  0d
+//    cmdname(5) = 3, 5, -15, 10          1d
+//    cmdname(5,9) = 3, 7, -20, 154       2d
+//    etc.
+//
+// We also allow
+//    cmdname = 3, 5, -15, 10
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// But note that the , is gone at this point, so the 2d command is
+//    cmdname ( 5 9 ) = 3  7  -20  154 ...
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Cmd::get_int(string &cname, int64_t *array_vals, const vector<int> &size,
+                  vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                  int dup_fatal, vector<int> &dup_vals,
+                  bool skip, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, for example an equals sign must be present, and set istart.
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // If skipping, we don't need to get array values.
+    if (skip) {
+        set_processed(true);
+        return;
+    }
+
+    // Get the number of values past the = sign.
+    // Also mark the words up to and including the = sign as processed.
+    int nvals = 0;
+    if (!get_nvals(istart, size, nvals, serr, ierr)) return;
+
+    // 0d is a special case.
+    if (dim == 0) {
+        *array_vals = words[2].get_int64_t(serr, ierr);
+        return;
+    }
+
+    // Get the values and return.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+    Parser_utils putils(index_base);
+    int k = putils.start_dex(istart, size);
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        int64_t iw = words[i].get_int64_t(serr, ierr);
+        int imult = words[i].get_multiplicity();
+        for (int j=1; j<=imult; j++) {
+            error_dup_line(cname, i, k, dup_wdex1, dup_cmd1, dup_vals, 
+                           size, dup_fatal, serr, ierr);
+            array_vals[k++] = iw;
+        }
+    }
+}
+
+// ===========================================================================
+// Get the real (double) values. This gets all the words past the = sign,
+// converts them to doubles, and puts them in the output arrays.
+//
+// The expected commands are:
+//    cmdname = some_double                         0d
+//    cmdname(5) = 3.0, 35, -15e20, 10.154          1d
+//    cmdname(5,9) = 3.0, 35, -15e20, 10.154        2d
+//    etc.
+//
+// We also allow
+//    cmdname = 3.0, 35, -15e20, 10.154
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// But note that the , is gone at this point, so the 2d command is
+//    cmdname ( 5 9 ) = 3.0  35  -15e20  10.154  ...
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Cmd::get_real(string &cname, double *array_vals, const vector<int> &size,
+                   vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                   int dup_fatal, vector<int> &dup_vals,
+                   bool skip, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, for example an equals sign must be present, and set istart.
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // If skipping, we don't need to get array values.
+    if (skip) {
+        set_processed(true);
+        return;
+    }
+
+    // Get the number of values past the = sign.
+    // Also mark the words up to and including the = sign as processed.
+    int nvals = 0;
+    if (!get_nvals(istart, size, nvals, serr, ierr)) return;
+
+    // 0d is a special case.
+    // Note that we do not increment dup_vals for 0d because duplicate scalar
+    // commands are handled differently from array commands.
+    if (dim == 0) {
+        *array_vals = words[2].get_double(serr, ierr);
+        return;
+    }
+
+    // All other dimensions.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+    Parser_utils putils(index_base);
+    int k = putils.start_dex(istart, size);
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        double d = words[i].get_double(serr, ierr);
+        int imult = words[i].get_multiplicity();
+        for (int j=1; j<=imult; j++) {
+            error_dup_line(cname, i, k, dup_wdex1, dup_cmd1, dup_vals, 
+                           size, dup_fatal, serr, ierr);
+            array_vals[k++] = d;
+        }
+    }
+}
+
+
+// ===========================================================================
+// Get the character values. This gets all the words past the = sign,
+// converts them to chars, and puts them in the output arrays.
+//
+// The expected commands are:
+//    cmdname = q                                   0d single character
+//    cmdname = char_string                         0d character string
+//    cmdname(3) = "May" "the", "force", "be"       1d array of strings
+//    cmdname(5,9) = "11" "21" "31"                 2d
+//    etc.
+//
+// We also allow
+//    cmdname = "May" "the", "force", "be"
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// But note that the , is gone at this point, so the 2d command is
+//    cmdname ( 5 9 ) = "11" "21" "31"
+//
+// This function works for any dimension, 0,1,2,3,...
+// For 0d, it has an extra flag to distinguish between single characters
+// and a character string.
+// ===========================================================================
+void Cmd::get_char(string &cname, vector<string> &vstr, const vector<int> &size,
+                   bool single_char, vector<Cmd *> &dup_cmd1,
+                   vector<int> &dup_wdex1, int dup_fatal,
+                   vector<int> &dup_vals, bool skip,
+                   stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, for example an equals sign must be present, and set istart.
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // If skipping, we don't need to get array values.
+    if (skip) {
+        set_processed(true);
+        return;
+    }
+
+    // Get the number of values past the = sign.
+    // Also mark the words up to and including the = sign as processed.
+    int nvals = 0;
+    if (!get_nvals(istart, size, nvals, serr, ierr)) return;
+
+    // 0d is a special case - get a single char
+    if (dim == 0 && single_char) {
+        vstr[0] = words[2].get_single_char(serr, ierr);
+        return;
+    }
+
+    // 0d is a special case - get a single string
+    if (dim == 0) {
+        vstr[0] = words[2].get_stringp();
+        return;
+    }
+
+    // Get the value and return, dim > 0.
+    // get_stringp is the same as get_string except get_stringp also marks
+    // the word as being processed.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+    Parser_utils putils(index_base);
+    int k = putils.start_dex(istart, size);
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        string s = words[i].get_stringp();
+        int imult = words[i].get_multiplicity();
+        for (int j=1; j<=imult; j++) {
+            error_dup_line(cname, i, k, dup_wdex1, dup_cmd1, dup_vals, 
+                           size, dup_fatal, serr, ierr);
+            vstr[k++] = s;
+        }
+    }
+
+}
+
+
+// ===========================================================================
+// Get sizes of arrays, this works for dimensions 1,2,3,...
+//
+// The size vector contains the sizes (or bounds) of each array dimensions.
+// It is assumed in this routine that all but the last size is known (this
+// is input) and that this routine will determine the last size. See the
+// get_sizeb function below where a different assumption is made.
+//
+// Suppose, for example, we have a 3d array called a3d which is dimensioned
+// a3d(5,3,:). The first two dimensions are known, 5 and 3, the last dimension
+// is unknown and will be determined by this routine.
+//
+// size is a vector of ints of size 3, with elements 5,3,? where the ? is
+// to be determined.
+//
+// Note that this routine is called in a loop over all the lines in the
+// input which is why we set the size using maximum.
+// ===========================================================================
+void Cmd::get_size(vector<int> &size, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // Check syntax, also sets istart.
+    // istart   Position in array where we start filling it.
+    //          Example command might be a3d(3,2,2) = ...  In this case istart
+    //          would be a vector of length 3 contining 3,2,2
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // Get the number of values past the = sign.
+    int nvals = 0;
+    vector<int> size0(dim,0);
+    if (!get_nvals(istart, size0, nvals, serr, ierr)) return;
+
+    int sm = 1;
+    for (int i=0; i<dim-1; i++) {
+        sm *= size[i];
+    }
+
+    // Set the size.
+    int maxval = istart[dim-1] + (nvals-1)/sm;
+    if (maxval > size[dim-1]) {
+        size[dim-1] = maxval;
+    }
+}
+
+
+// ===========================================================================
+// This is a special purpose routine to get sizes for certain 2d arrays.
+//
+// Suppose we have the following input
+//      mults(1,1) = 0. 0.  1. 5.  6. 9.
+//      mults(1,2) = 3. 5.  8. 9.  10. 11. 20. 10
+//      mults(1,3) = 30. 5. 38. 3.
+// In this case we don't know the size of either of the array dimensions, and
+// of course the user does not know the size either and thus cannot somehow
+// merge the above two lines. 
+//
+// The purpose of this function is to obtain sizes for both the array
+// dimensions so memory allocation of the array can be done.
+//
+// The size vector contains the sizes (or bounds) of each array dimensions.
+// For the above example, this function would determine size[0] to be 8 and
+// size[1] to be 3. 8 is just the max of the number of values put in per
+// entry and 3 is just the max of the second index.
+//
+// Note that this routine is called in a loop over all the lines in the
+// input which is why we set the size using maximum.
+//
+// This routine only works for 2d arrays.
+// ===========================================================================
+void Cmd::get_sizeb(vector<int> &size, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)size.size();
+
+    // This is a special purpose routine, dim must be 2.
+    if (dim != 2) {
+        fatal_error2(serr, ierr);
+        serr << "Cmd.cc, get_sizeb, internal error." << endl;
+        serr << "dim != 2, dim=" << dim << endl << endl;
+        ierr = 2;
+        return;
+    }
+
+    // Check syntax, also sets istart.
+    // istart   Position in array where we start filling it.
+    //          Example command might be a3d(3,2,2) = ...  In this case istart
+    //          would be a vector of length 3 contining 3,2,2
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    vector<int> istart(dim,0);
+    if (!check_syntax(istart, serr, ierr)) return;
+
+    // Get the number of values past the = sign.
+    int nvals = 0;
+    vector<int> size0(dim,0);
+    if (!get_nvals(istart, size0, nvals, serr, ierr)) return;
+
+    // Set the size vector
+    int maxval = istart[0] + nvals - 1;
+    if (maxval > size[0]) {
+        size[0] = maxval;
+    }
+
+    maxval = istart[1];
+    if (maxval > size[1]) {
+        size[1] = maxval;
+    }
+}
+
+
+// ===========================================================================
+// Check command syntax for any dimension array. The expected command is:
+//    cmdname = .true.                          0d
+//    cmdname(5) = 1, 3, -4                     1d
+//    cmdname(3,4) = 1.e19, 23., -45.           2d
+//    etc.
+//
+// We also allow
+//    cmdname = "May" "the", "force", "be"
+// and we will supply the starting indices of (1) or (1,1), etc.
+//
+// Note that at this point, the commas have been removed so the 2d command
+// is actually
+//    cmdname ( 3 4 ) = 1.e19 23. -45. 
+// ===========================================================================
+bool Cmd::check_syntax(vector<int> &istart, stringstream &serr, int &ierr)
+{
+    // Get the dimension of the array, 0,1,2,3,...
+    int dim = (int)istart.size();
+
+    bool skip_check = false;
+    if (dim > 0) {
+        int ieqt = find_equals();
+        if (ieqt == 1) skip_check = true;
+    }
+
+    // Must be at least a certain number of words on the line.
+    int nw_min = 3;
+    int nw_min_wc = 3;
+    if (dim > 0 && (!skip_check)) {
+        nw_min = 6 + dim - 1;
+        nw_min_wc = nw_min + dim - 1;
+    }
+    if ((int)words.size() < nw_min) {
+        fatal_error2(serr, ierr);
+        serr << "Expected number words in this line >= " << nw_min_wc << endl;
+        serr << "Actual number words = " << words.size() << endl << endl;
+        ierr = 2;
+        // If there aren't enough words on the line, then it is hopeless.
+        return false;
+    }
+
+
+    // Word at index ieq must be an = sign.
+    int ieq = 1;
+    int ieq_wc = 2;
+    if (dim > 0 && (!skip_check)) {
+        ieq = 4 + dim -1;
+        ieq_wc = ieq + 1 + dim - 1;
+    }
+    if (words[ieq].get_string() != "=") {
+        words[ieq].fatal_error(serr, ierr);
+        serr << "Expected an equals sign for symbol " << ieq_wc << endl;
+        serr << "Instead symbol " << ieq_wc << " is: " <<
+            words[ieq].get_string() << endl << endl;
+        ierr = 2;
+    }
+
+    // The value must not have any multiplicity, i.e. be just a single value.
+    // This only applies to 0d, values for arrays can have multiplicity.
+    if (dim == 0) {
+        if (words[2].get_multiplicity() != 1) {
+            words[2].fatal_error(serr, ierr);
+            serr << "Multiplicity not equal 1 for " << words[2].get_string() << endl;
+            serr << "Multiplicity is: " << words[2].get_multiplicity() << endl << endl;
+            ierr = 2;
+        }
+    }
+
+    // Nothing more to check for 0d.
+    if (dim == 0) return true;
+
+    if (!skip_check) {
+        // Word at index 1 must be a "(".
+        if (words[1].get_string() != "(") {
+            words[1].fatal_error(serr, ierr);
+            serr << "Expected an open parenthesis ,(, following the command name"
+                " in this line," << endl;
+            serr << "For example: " << cmd_name << "(...) = ..." << endl;
+            serr << "Instead found: " << words[1].get_string() << endl << endl;
+            ierr = 2;
+        }
+
+        // There must be a closing parenthses.
+        int irp = 3 + dim - 1;
+        if (words[irp].get_string() != ")") {
+            words[irp].fatal_error(serr, ierr);
+            serr << "Expected a close parenthesis ,), following the array indices"
+                " in this line," << endl;
+            serr << "For example: " << cmd_name << "(...) = ..." << endl;
+            serr << "Instead found: " << words[irp].get_string() << endl << endl;
+            ierr = 2;
+        }
+    }
+
+
+    // istart   Position in array_vals where we start filling it.
+    //          Note that istart starts from index base (default 1, Fortran style)
+    //          Use set_index_base_zero for C/C++ index convention
+    if (skip_check) {
+        for (int i=0; i<dim; i++) {
+            istart[i] = index_base;
+        }
+    }
+    else {
+        int ierr2 = 0;
+        for (int i=0; i<dim; i++) {
+            int iloc = 2 + i;
+            istart[i] = words[iloc].get_int(serr, ierr);
+            if (ierr < 2  &&  istart[i] < index_base) {
+                words[iloc].fatal_error(serr, ierr);
+                serr << "The index for the array must be an integer that is >= " << index_base << endl;
+                serr << "Integer includes numbers like 3, 3., 3.0, but not 3.5" << endl;
+                serr << "The index input is: " << istart[i] << endl << endl;
+                ierr2 = 2;
+            }
+        }
+        if (ierr2 == 2) ierr = 2;
+    }
+
+    for (int i=0; i<dim; i++) {
+        if (istart[i] < index_base) return false;
+    }
+    return true;
+}
+
+
+// ===========================================================================
+// Get the number of values (nvals) past the = sign.
+// Check that nvals does not exceed array size.
+// Also mark the words up to and including the = sign as processed.
+//
+// Works for any array dimension = 0,1,2,3,...
+// ===========================================================================
+bool Cmd::get_nvals(vector<int> &istart, const vector<int> &size,
+                    int &nvals, stringstream &serr, int &ierr)
+{
+    int nvals_cur;
+    // Get the array dimension, 0,1,2,3,...
+    int dim = (int)istart.size();
+
+    // 0d is a special case.
+    if (dim == 0) {
+        nvals = 1;
+        //if (size[0] == 0) return true;        
+        words[0].set_processed(true);
+        words[1].set_processed(true);
+        return true;
+    }
+
+    // Index of word after equals sign.
+    //int ieqp1 = 5 + dim - 1;
+    int ieqp1 = find_equals() + 1;
+
+    // nvals    Number of values after the = sign.
+    nvals = 0;
+    for (int i=ieqp1; i<(int)words.size(); i++) {
+        nvals_cur = words[i].get_multiplicity();
+        if( nvals_cur <= 0 ){
+            fatal_error2(serr, ierr);
+            serr << "Count must be positive [" << nvals_cur << "]" << endl;
+            ierr = 2;
+        }
+        nvals += nvals_cur;
+    }
+
+    // This is for the get size function. We just want nvals and do not want
+    // to do the check or marking as processed.
+    if (size[0] == 0) return true;
+
+    // Get the max size of the array.
+    //int maxvals = size1*size2;
+    int maxvals = size[0];
+    for (int i=2; i<=dim; i++) {
+        maxvals *= size[i-1];
+    }
+
+    //int ip = istart[0]-1;
+    //if (dim == 2) {
+    //    ip = istart[0]-1 + (istart[1]-1)*size[0];
+    //}
+    //if (dim == 3) {
+    //    ip = istart[0]-1 + (istart[1]-1)*size[0] + (istart[2]-1)*size[0]*size[1];
+    //}
+    //if (dim == 4) {
+    //    ip = istart[0]-1 + (istart[1]-1)*size[0] + (istart[2]-1)*size[0]*size[1] +
+    //        (istart[3]-1)*size[0]*size[1]*size[2];
+    //}
+    //ip += nvals - maxvals;
+
+    // Find the excess, i.e. the max array position the user is trying to
+    // fill compared with the max size allowed. 
+    Parser_utils putils(index_base);
+    int ix = putils.start_dex(istart, size);
+    int excess = ix + nvals - maxvals;
+
+    //cout << "&&&&&cw ip = " << ip << "  excess = " << excess << endl;
+
+    // Check that the number of values input by the user does not exceed
+    // the array size.
+    //int excess = istart1 - 1 + (istart2-1)*size1 + nvals - maxvals;
+    if (excess > 0) {
+        fatal_error2(serr, ierr);
+        serr << "Maximum number of values allowed = " << maxvals << endl;
+        serr << "(for multi-dimension arrays this max number is" << endl;
+        serr << "     max_dim1 * max_dim2 * ...)" << endl;
+        serr << "This command exceeds that value by " <<
+             excess << endl << endl;
+        ierr = 2;
+    }
+    
+    // If fatal errors, then do not attempt further processing.
+    if (ierr == 2) return false;
+
+    // Mark as processed.
+    for (int i=0; i<ieqp1; i++) {
+        words[i].set_processed(true);
+    }
+
+    return true;
+}
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Handle variables.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Check for the user defining variable dimensions for multi-dimensional
+// arrays.
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+bool Cmd::check_for_dimension(stringstream &serr, int &ierr)
+{
+    // First do some checks.
+    string varname = words[0].get_string();
+    if (!words[0].is_variable()) return false;
+
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].get_string() == "=") {
+            return false;
+        }
+    }
+
+    if (words[1].get_string() != "dimension") return false;
+
+    // Find the variable, if not found, then create it.
+    map<string, Variable>::iterator p;
+    p = vmap->find(varname);
+    if (p == vmap->end()) {
+        Variable v(varname);
+        vmap->insert(pair<string, Variable>(v.get_varname(), v));
+    }
+    p = vmap->find(varname);
+
+    // Extract the bounds from the line.
+    vector<int> bounds;
+    for (int i=2; i<(int)words.size(); i++) {
+        if (words[i].get_string() == "(") continue;
+        if (words[i].is_comma())          continue;
+        if (words[i].get_string() == ":") continue;
+        if (words[i].get_string() == ")") break;
+
+        // Get the bounds, note that this also makes sure it is an integer.
+        bounds.push_back(words[i].get_int(serr, ierr));
+    }
+
+    // Actually set the bounds for the variable.
+    int lnum = words[0].get_line_number();
+    int file_lnum = words[0].get_file_line_number();
+    string fname = words[0].get_filename();
+    p->second.set_bounds(bounds, lnum, file_lnum, fname,
+                         lines, serr, ierr);
+
+    return true;
+}
+
+
+// ===========================================================================
+// Check for the command
+//    variable_description variable_name description
+// If found, then set the description for the variable.
+// Create the variable if necessary.
+// ===========================================================================
+bool Cmd::check_for_var_description(stringstream &serr, int &ierr)
+{
+    if (words[0].get_string() != "variable_description") return false;
+
+    // Must be 3 words in the line.
+    if (words.size() != 3) {
+        words[0].fatal_error(serr, ierr);
+        serr << "The variable_description command must have 3 words on the"
+            " line" << endl;
+        serr << "First word =  variable_description" << endl;
+        serr << "Second word =  name of the variable" << endl;
+        serr << "Third word =  description (usually some phrase in quotes)" << endl;
+        serr << "This command has " << words.size() <<
+            " words instead of 3 words." << endl;
+        ierr = 2;
+        return true;
+    }
+
+    // The variable name is word 1.
+    string varname = words[1].get_string();
+    if (!words[1].is_variable()) {
+        words[0].fatal_error(serr, ierr);
+        serr << "Expected a variable name as word 2" << endl;
+        serr << "Variable names must begin with the $ character." << endl;
+        serr << "This variable name does not begin with a $ character." << endl;
+        serr << "Note that putting quotes around a variable name makes it" << endl;
+        serr << "a string, not a variable." << endl;
+        serr << "Variable name = " << varname << endl;
+        ierr = 2;
+        return true;
+    }
+
+    // Get the description.
+    string vardes = words[2].get_string();
+
+    // Find the variable, if not found, then create it.
+    map<string, Variable>::iterator p;
+    p = vmap->find(varname);
+    if (p == vmap->end()) {
+        Variable v(varname);
+        vmap->insert(pair<string, Variable>(v.get_varname(), v));
+    }
+    p = vmap->find(varname);
+
+    // Cannot change pre-defined variables.
+    if (p->second.is_pre_defined()) {
+        words[0].fatal_error(serr, ierr);
+        serr << "Cannot change the description for a pre-defined"
+             " variable" << endl;
+        serr << "Variable name = " << varname << " is pre-defined." << endl;
+        ierr = 2;
+        return true;
+    }
+    
+    // Actually set the description.
+    p->second.set_description(vardes);
+
+    return true;
+}
+
+
+// ===========================================================================
+// Go through each word on the line (starting after the equals sign if
+// present), and replace each variable with its value.
+// This is for scalar variables only.
+// ===========================================================================
+void Cmd::substitute_variables(stringstream &serr, int &ierr)
+{
+    int irstart = 0;
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].get_string() == "=") {
+            irstart = 1;
+            break;
+        }
+    }
+    int nw1 = (int)words.size()-1;
+    subvar_w0(irstart, nw1, serr, ierr);
+}
+
+
+// ===========================================================================
+// Scan words i1 through i2 inclusive, replace any variables found with
+// their value.
+// If the variable is followed by ++ or --, handle that also.
+// This is for scalar variables only.
+// ===========================================================================
+void Cmd::subvar_w0(int i1, int &i2, stringstream &serr, int &ierr)
+{
+    for (int i=i1; i<=i2; i++) {
+        string s = words[i].get_string();
+        if (words[i].is_variable()) {
+            int increment = 0;
+            if (i < i2) {
+                string ppmm = words[i+1].get_string();
+                if (ppmm == "++") increment = 1;
+                if (ppmm == "--") increment = -1;
+            }
+            subvar0(i, s, increment, serr, ierr);
+            if (increment != 0) {
+                delete_words(i+1,i+1);
+                i2 -= 1;
+            }
+        }
+    }
+}
+
+
+// ===========================================================================
+// Given a variable name, varname, and its index in the words array, vardex,
+// replace it with its value.
+// This is for scalar variables only.
+// ===========================================================================
+void Cmd::subvar0(int vardex, string &varname, int increment,
+                  stringstream &serr, int &ierr)
+{
+    vector<int> adex;
+
+    map<string, Variable>::iterator p;
+    p = vmap->find(varname);
+    if (p != vmap->end()) {
+        int lnum = words[vardex].get_line_number();
+        int file_lnum = words[vardex].get_file_line_number();
+        string fname = words[vardex].get_filename();
+        string svalue = p->second.get_var_value(adex, words[vardex].get_string(),
+                                                lnum, file_lnum, fname,
+                                                lines, serr, ierr);
+        //int increment = words[vardex].get_increment();
+        if (increment != 0) p->second.bump_var(adex, increment,
+                                               lnum, file_lnum, fname,
+                                               lines, serr, ierr);
+        //words[vardex].set_increment(0);
+        words[vardex].set_value(svalue);
+    }
+    else {
+        // The variable has not been defined yet.
+        words[vardex].fatal_error(serr, ierr);
+        serr << "Attempted to use a variable before it was defined."
+             << endl;
+        serr << "Undefined variable = " << varname << endl;
+        ierr = 2;
+    }
+}
+
+
+// ===========================================================================
+// Store the variable value(s), define if needed.
+// Examples:
+//    $radius = 3.0                         0d
+//    $radius(1) = 3.0 4. 5.6e19            1d
+//    $radius(3,4) = 3.0 4. 5.6e19 4 5 9    2d
+//    ...
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Cmd::set_variables(stringstream &serr, int &ierr)
+{
+    //cout << "&&&&&cw Enter set_variables, words[0] = " << words[0].get_string() << endl;
+    int ieq = -1;
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].get_string() == "=") {
+            ieq = i;
+            break;
+        }
+    }
+
+    // If an equals sign was not found on the line, then this is not a
+    // variable assignment.
+    if (ieq == -1) return;
+
+    // If the first character of the first word is not a $, then this is not
+    // a variable assignment.
+    string vname = words[0].get_string();
+    if (!words[0].is_variable()) return;
+
+    // Define a few common things.
+    int lnum = words[0].get_line_number();
+    int file_lnum = words[0].get_file_line_number();
+    string fname = words[0].get_filename();
+    vector<string> valvec;
+
+    int dim = 0;
+    if (ieq >= 4) dim = ieq - 3;
+    //cout << "&&&&&cw vname=" << vname << "  ieq=" << ieq << "  dim=" << dim << endl;
+
+    // Do some checking.
+    if (dim == 0) {
+        // Must be 3 words in the line (for example: $radius = 3.0)
+        if (words.size() != 3) {
+            fatal_error2(serr, ierr);
+            serr << "Expected number words in this line = 3" << endl;
+            serr << "Actual number words = " << words.size() << endl << endl;
+            ierr = 2;
+            // If there aren't enough words on the line, then it is hopeless.
+            if (words.size() < 3) return;
+        }
+
+        // The value must not have any multiplicity, i.e. be just a single value.
+        // This only applies to 0d, values for arrays can have multiplicity.
+        if (words[2].get_multiplicity() != 1) {
+            words[2].fatal_error(serr, ierr);
+            serr << "Multiplicity not equal 1 for " << words[2].get_string() << endl;
+            serr << "Multiplicity is: " << words[2].get_multiplicity() << endl << endl;
+            ierr = 2;
+        }
+    }
+
+    if (dim > 0) {
+        int nw_min = dim + 5;
+        int nw_min_wc = nw_min + dim - 1;
+        if ((int)words.size() < nw_min) {
+            fatal_error2(serr, ierr);
+            serr << "Expected number of symbols in this line >= " << nw_min_wc << endl;
+            serr << "Actual number of symbols is less than expected." << endl << endl;
+            ierr = 2;
+            // If there aren't enough words on the line, then it is hopeless.
+            return;
+        }
+
+        // Word at index 1 must be a "(".
+        if (words[1].get_string() != "(") {
+            words[1].fatal_error(serr, ierr);
+            serr << "Expected an open parenthesis ,(, following the variable name"
+                " in this line," << endl;
+            serr << "For example: " << vname << "(...) = ..." << endl;
+            serr << "Instead found: " << words[1].get_string() << endl << endl;
+            ierr = 2;
+            return;
+        }
+
+        // There must be a closing parenthses.
+        int irp = 3 + dim - 1;
+        if (words[irp].get_string() != ")") {
+            words[irp].fatal_error(serr, ierr);
+            serr << "Expected a close parenthesis ,), following the array indices"
+                " in this line," << endl;
+            serr << "For example: " << vname << "(...) = ..." << endl;
+            serr << "Instead found: " << words[irp].get_string() << endl << endl;
+            ierr = 2;
+            return;
+        }
+    }
+
+    // Store the values in a vector.
+    for (int i=ieq+1; i<(int)words.size(); i++) {
+        int imult = words[i].get_multiplicity();
+        string s = words[i].get_string();
+        for (int j=1; j<=imult; j++) {
+            valvec.push_back(s);
+        }
+    }
+
+    // Store the array indices in a vector.
+    vector<int> istart(dim,0);
+    int ierr2 = 0;
+    for (int d=0; d<dim; d++) {
+        istart[d] = words[d+2].get_int(serr, ierr);
+        if (istart[d] <= 0) {
+            words[d+2].fatal_error(serr, ierr);
+            serr << "The index for the array must be an integer that is >= " << index_base << endl;
+            serr << "Integer includes numbers like 3, 3., 3.0, but not 3.5" << endl;
+            serr << "The index input is: " << istart[d] << endl << endl;
+            ierr2 = 2;
+        }
+    }
+    if (ierr2 == 2) {
+        ierr = 2;
+        return;
+    }
+
+    // Find the variable name in the variable map.
+    map<string, Variable>::iterator p;
+    p = vmap->find(vname);
+
+    // If the variable is found in the variable map, then replace
+    // its value with the new value. If the variable is not found
+    // in the variable map, then add it as a new variable.
+    if (p != vmap->end()) {
+        p->second.set_var_value(istart, valvec, lnum, file_lnum, fname,
+                                lines, serr, ierr);
+    }
+    else {
+        Variable v(vname, istart, valvec, lnum, file_lnum, fname, lines,
+                   serr, ierr);
+        vmap->insert(pair<string, Variable>(v.get_varname(), v));
+    }
+}
+
+
+
+// ===========================================================================
+// Evaluate a variable.
+// We have a word followed by multiple arguments. Find out if the word is
+// a variable, use the arguments to get the variable value, replace the
+// variable and arguments with its value.
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+bool Cmd::evaluate_variable(int iw1, int &i2, int &nargs,
+                            stringstream &serr, int &ierr)
+{
+    // If there is no map of variables, then we do nothing.
+    if (vmap == NULL) return false;
+
+    // Do nothing if the word is not a variable (begins with $).
+    if (!words[iw1].is_variable()) return false;
+
+    // Get the variable name.
+    string varname = words[iw1].get_string();
+
+    // Find the variable.
+    map<string, Variable>::iterator p;
+    p = vmap->find(varname);
+
+    // The variable was not found.
+    if (p == vmap->end()) {
+        words[iw1].fatal_error(serr, ierr);
+        serr << "Trying to use a variable before it is defined." << endl;
+        serr << "Undefined variable = " << varname << endl;
+        serr << "The list of defined variables (at this point) is:" << endl;
+        for (p=vmap->begin(); p!=vmap->end(); p++) {
+            serr << p->second.get_varname() << endl;
+        }
+        ierr = 2;
+        return true;
+    }
+
+    // The variable was found, do the evaluation and replace the words.
+
+    // Check to see if all the variable arguments have a value.
+    bool has_value = true;
+    for (int i=0; i<nargs; i++) {
+        int j = iw1 + 1 + i;
+        if (!words[j].is_number()) {
+            has_value = false;
+            words[j].fatal_error(serr, ierr);
+            serr << "Expected a number for variable index " <<
+                i+1 << endl;
+            serr << "Instead found:   " << words[j].get_string() << endl;
+            ierr = 2;
+        }
+    }
+    if (!has_value) return true;
+
+    // Check to see if all the variable arguments are integer.
+    bool all_int = true;
+    for (int i=0; i<nargs; i++) {
+        int j = iw1 + 1 + i;
+        if (!words[j].is_integer()) {
+            all_int = false;
+            words[j].fatal_error(serr, ierr);
+            serr << "Expected an integer for variable index " <<
+                i+1 << endl;
+            serr << "Instead found:   " << words[j].get_string() << endl;
+            ierr = 2;
+        }
+    }
+    if (!all_int) return true;
+
+    // All the indices have values and are ints.
+    // Load all the arguments into a vector of ints.
+    vector<int> vdex;
+    for (int i=0; i<nargs; i++) {
+        int j = iw1 + 1 + i;
+        int iv = words[j].get_int();
+        vdex.push_back(iv);
+    }
+
+    // Check for ++ or -- following the variable.
+    int increment = 0;
+    int ippmm = iw1 + nargs + 1;
+    if (ippmm <= i2 && ippmm <(int)words.size()) {
+        string sppmm = words[ippmm].get_string();
+        if (sppmm == "++") increment = 1;
+        if (sppmm == "--") increment = -1;
+    }
+
+    // Evaluate the variable and replace the words.
+    // Works in any dimensionality.
+    int ln = words[iw1].get_line_number();
+    int file_ln = words[iw1].get_file_line_number();
+    string fname = words[iw1].get_filename();
+    string result = p->second.get_var_value(vdex, varname, ln, file_ln,
+                                            fname, lines, serr, ierr);
+    //int increment = words[iw1].get_increment();
+    if (increment != 0) p->second.bump_var(vdex, increment, ln, file_ln,
+                                           fname, lines, serr, ierr);
+    //words[iw1].set_increment(0);
+    Word w(result, ln, file_ln, fname, lines);
+    replace_words(iw1, iw1+nargs, w);
+    i2 -= nargs;
+
+    // If the variable was followed by a ++ or --, then remove the
+    // ++ or -- since it has been used.
+    if (increment != 0) {
+        delete_words(iw1+1, iw1+1);
+        i2 -= 1;
+    }
+
+    return true;
+}
+
+
+
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Math evaluation.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Math evaluation driver.
+// ===========================================================================
+void Cmd::math_eval(stringstream &serr, int &ierr)
+{
+    // Combine * * into **, i.e. form the exponentiation operator.
+    handle_star_star();
+
+    // Ops like .and., .eq., ... can at this point be part of larger words,
+    // they need to be extracted as individual words.
+    handle_ops();
+
+    //cout << "&&&&&cw Cmd.cc, Enter math_eval" << endl;
+    //for (int i=0; i<(int)words.size(); i++) {
+    //    cout << words[i].get_string() << endl;
+    //}
+
+    int ieq = find_any_char(0, (int)words.size()-1, "=");
+
+    bool ifcmd = false;
+    if (words[0].get_string() == "if") {
+        ifcmd = true;
+        ieq = -1;
+    }
+
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].get_string() == "(" /*&& i>ieq*/) {
+            if (ifcmd && i>1) continue;
+            if (i > (int)words.size()-2) {
+                words[i].fatal_error(serr, ierr);
+                serr << "Expected (...)" << endl;
+                serr << "Found " << words[(int)words.size()-2].get_string() <<
+                    words[(int)words.size()-1].get_string() << endl;
+                ierr = 2;
+                return;
+            }
+
+            // The starting index of the math expression.
+            int istart = i+1;
+
+            // Find the ending index of the math expression.
+            int iclose = find_closing_symbol("(", ")", istart);
+            if (iclose == -1) {
+                words[i+1].fatal_error(serr, ierr);
+                serr << "Did not find a closing parenthesis, ), in"
+                    " math expression" << endl;
+                serr << "Check for unbalanced parentheses in math expression." << endl;
+                ierr = 2;
+                return;
+            }
+            int iend = iclose - 1;
+
+            int iwres = 0;
+            int nargs = 0;
+            for (;;) {
+                if (!handle_innermost_parens(istart, iend, iwres, nargs, true,
+                                             serr, ierr)) break;
+                bool isvar = false;
+                bool doit = true;
+                if (iwres <= 0) doit = false;
+                if (cmd_type == "assignment" && iwres==1) doit = false;
+                if (doit) {
+                    isvar = evaluate_variable(iwres-1, iend, nargs, serr, ierr);
+                }
+                if ((iwres > 0) && (!isvar)) {
+                    evaluate_function(iwres-1, iend, nargs, serr, ierr);
+                }
+            }
+
+            // Now set ihip1,2 to the original set of parens and handle those.
+            // This will do a math eval inside the parens, handle multiple arguments
+            // and possibly remove the parens.
+            // We do not remove the parens if this is a command line or an assignment
+            // line and we are to the left of the equals because a lot of checks
+            // depend on the parens being there.
+            int ihip1 = istart-1;
+            int ihip2 = iend + 1;
+            bool remp = true;
+            if (ieq>ihip2 && ihip1==1) remp = false;
+            handle_innermost_parens(ihip1, ihip2, iwres, nargs, remp,
+                                    serr, ierr);
+
+            // Handle the case of a variable array, i.e. evaluate and replace
+            // the variable array reference. We of course do not do this for
+            // an assignment statement where we are to the left of the equals.
+            //bool isvar = false;
+            bool doit = true;
+            if (iwres <= 0) doit = false;
+            if (cmd_type == "assignment" && iwres==1) doit = false;
+            if (doit) {
+                // We use ihip3 to account for ++ or -- following a
+                // variable array reference.
+                int ihip3 = ihip2 + 1;
+                //isvar = evaluate_variable(iwres-1, ihip3, nargs, serr, ierr);
+                evaluate_variable(iwres-1, ihip3, nargs, serr, ierr);
+            }
+
+            // Do not allow a function outside of parens. We could do this
+            // but for now all math is inside parens.
+            //if ((iwres > 0) && (!isvar)) {
+            //    evaluate_function(iwres-1, iend, nargs, serr, ierr);
+            //}
+
+        }  // if find (
+    } // End of loop through all words on the line.
+
+    //cout << "&&&&&cw Cmd.cc, Exit math_eval" << endl;
+}
+
+
+// ===========================================================================
+// Handle the innermost set of parentheses.
+// The return value is false if parens were not found or if they were
+// unbalanced. If parens were found and handled then true is returned.
+// iwres is an output quantity and is the location of the resultant word.
+// ===========================================================================
+bool Cmd::handle_innermost_parens(int &i1, int &i2, int &iwres, int &nargs,
+                                  bool remp, stringstream &serr, int &ierr)
+{
+    // If no innermost parens are found then iwres is meaningless.
+    iwres = -1;
+
+    // Search for the innermost left parens. It is ok if there is no left
+    // parens, this line just does not have parens.
+    int ip1 = find_last("(", i1, i2);
+    if (ip1 == -1) return false;
+
+    // After evaluation, the resultant word will be at ip1.
+    iwres = ip1;
+
+    int ipstart = ip1 + 1;
+    bool done = false;
+    nargs = 1;
+    for (;;) {
+        int ip2 = find_any_char(ipstart, i2, ",)");
+        if (ip2 == -1) {
+            words[ipstart].fatal_error(serr, ierr);
+            serr << "Did not find a closing parenthesis, ), in"
+                " math expression" << endl;
+            serr << "Check for unbalanced parentheses in math expression." << endl;
+            ierr = 2;
+            return false;
+        }
+
+        if (words[ip2].get_string() == ")") done = true;
+        if (words[ip2].is_comma()) nargs += 1;
+
+        if (remp) {
+            delete_words(ip2, ip2);
+            i2 -= 1;
+        }
+        int ip21a = ip2 - 1;
+        int ip21 = ip2 - 1;
+        seval(ipstart, ip21, serr, ierr);
+        i2 -= ip21a - ip21;
+
+        if (done) break;
+
+        ipstart += 1;
+    }
+
+    // Delete the leading paren.
+    if (remp) {
+        delete_words(ip1, ip1);
+        i2 -= 1;
+    }
+
+    return true;
+}
+
+
+// ===========================================================================
+// Simple evaluation of a series of words i1 to i2 inclusive.
+// ===========================================================================
+void Cmd::seval(int &i1, int &i2, stringstream &serr, int &ierr)
+{
+    Parser_math pmath;
+
+    subvar_w0(i1, i2, serr, ierr);
+    handle_unary_op(i1, i2, "-", serr, ierr);
+    handle_unary_op(i1, i2, "+", serr, ierr);
+
+    //     Level   Operators
+    //     -----   -----------------------
+    //       8     ()
+    //       7     ++ --
+    //       6     **
+    //       5     *  /
+    //       4     +  -
+    //       3     .gt. .ge. .lt. .le. .eq. .ne.
+    //       2     .not.
+    //       1     .and.
+    //       0     .or.
+    for (int level=6; level>=0; level--) {
+        for (int i=i1; i<=i2; i+=1) {
+            if (words[i].is_operator(level)) {
+                int ln = words[i].get_line_number();
+                int file_ln = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                Word w("", ln, file_ln, fname, lines);
+
+                string op_type = words[i].get_op_type();
+                if (op_type == "arithmetic")
+                    pmath.do_op(i-1, i, i+1, words, w, serr, ierr);
+                if (op_type == "relational")
+                    pmath.do_op_relational(i-1, i, i+1, words, w, serr, ierr);
+                if (op_type == "logical" && level == 2)   // .not. is unary
+                    pmath.do_op_not(i, i+1, words, w, serr, ierr);
+                if (op_type == "logical" && level != 2)
+                    pmath.do_op_logical(i-1, i, i+1, words, w, serr, ierr);
+
+                // level 2, .not., is unary and is handled differently.
+                if (level == 2) {
+                    replace_words(i, i+1, w);
+                    i2 -= 1;
+                }
+                else {
+                    replace_words(i-1, i+1, w);
+                    i2 -= 2;
+                    i -= 1;
+                }
+                continue;
+            }
+        }
+    }
+    //cout << "&&&&&cw Leave seval" << endl;
+}
+
+
+// ===========================================================================
+// Handle unary plus and minus.
+// utype is either "+" or "-".
+// ===========================================================================
+void Cmd::handle_unary_op(int i1, int &ipend, string utype,
+                          stringstream &serr, int &ierr)
+{
+    int ipstart = i1;
+    for (;;) {
+        int ip = find(ipstart, ipend, utype);
+
+        // If we do not find any more plus/minus signs then we are done.
+        if (ip == -1) return;
+
+        // Fatal error is the plus/minus sign is the last word on the line.
+        if (ip >= ((int)words.size()-1)) {
+            words[ip].fatal_error(serr, ierr);
+            serr << "Found a " << utype << " sign at the end of a line." << endl;
+            serr << "Expected something to the right of the  " << utype
+                 << " sign to operate on." << endl;
+            ierr = 2;
+            return;
+        }
+
+
+        // If the plus/minus sign is the first word on the line, then it has
+        // to be a unary op. The word after the plus/minus sign must be a
+        // number or variable.
+        // This should never happen because we are always inside (...)
+        // and will never be word 0, still we should be general and take care
+        // of this case.
+        if (ip == 0) {
+            if (!words[ip+1].is_number()) {
+                words[ip+1].fatal_error(serr, ierr);
+                serr << "Expected the object following the unary " << utype
+                     << " to be a number." << endl;
+                serr << "Instead, it was " << words[ip+1].get_string() << endl;
+                ierr = 2;
+                return;
+            }
+
+            // Actually do the negate operation.
+            do_unary_op(ip, utype);
+            ipstart = ip+1;
+            ipend -= 1;
+            continue;
+        }
+         
+        // Check to see if the +/- is a binary op. If so, then nothing needs
+        // to be done with this +/- sign, binary ops are handled elsewhere.
+        if (words[ip-1].is_number() &&
+            (words[ip+1].is_number() || words[ip+1].get_string() == "-" ||
+             words[ip+1].get_string() == "+")
+            ) {
+            ipstart = ip+1;
+            continue;
+        }
+
+        // Check to see if the +/- is a unary op.
+        if (!words[ip-1].is_number() && words[ip+1].is_number()) {
+            do_unary_op(ip, utype);
+            ipstart = ip+1;
+            ipend -= 1;
+            continue;
+        }
+
+        // Check for an error.
+        if (!words[ip-1].is_number() &&
+            !words[ip+1].is_number()) {
+            words[ip-1].fatal_error(serr, ierr);
+            serr << "Expected the object following the unary " << utype << " to"
+                " be a number." << endl;
+            serr << "Instead, it was " << words[ip+1].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+
+        words[ip].fatal_error(serr, ierr);
+        serr << "Unknown error with unary " << utype << endl;
+        serr << "Error with words: " << endl;
+        serr << words[ip].get_string() << words[ip+1].get_string() << endl;
+        ierr = 2;
+        return;
+    }
+}
+
+
+
+// ===========================================================================
+// Do a unary operation.
+// The minus sign is at word ip and the word to be negated is at word ip+1.
+// After negation, both words get replaced by the new negated word.
+// If the unary op is plus then all we need to do is get rid of the + sign.
+// ===========================================================================
+void Cmd::do_unary_op(int ip, string utype)
+{
+    if (utype == "+") {
+        delete_words(ip,ip);
+        return;
+    }
+
+    if (utype == "-") {
+        if (words[ip+1].is_number()) {
+            Word w = words[ip+1];
+            w.negate_value();
+            replace_words(ip, ip+1, w);
+            return;
+        }
+    }
+}
+
+
+
+// ===========================================================================
+// Check to see that all ++ and -- have been handled and removed.
+// ===========================================================================
+void Cmd::check_ppmm(stringstream &serr, int &ierr)
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        string s = words[i].get_string();
+        if (s == "++" || s == "--") {
+            words[i].fatal_error(serr, ierr);
+            serr << "Misplaced " << s << " operator." << endl;
+            serr << "++ and -- operators must follow a variable or " << endl;
+            serr << "an element of an array variable. " << endl;
+            ierr = 2;
+        }
+    }
+}
+
+
+// ===========================================================================
+// Evaluate a function.
+// ===========================================================================
+void Cmd::evaluate_function(int iw1, int &i2, int &nargs,
+                            stringstream &serr, int &ierr)
+{
+    // If there is no map of functions, then we do nothing.
+    if (fmap == NULL) return;
+
+    // If the word at iw1 is not a string then it will not be a function.
+    if (!words[iw1].is_string()) return;
+
+    // Find the function.
+    string s = words[iw1].get_string();
+    map<string, Function>::iterator p;
+    p = fmap->find(s);
+
+    // The function was not found.
+    if (p == fmap->end()) {
+        words[iw1].fatal_error(serr, ierr);
+        serr << "Expected a function" << endl;
+        serr << "Instead found:   " << words[iw1].get_string() << endl;
+        serr << "The list of known functions is:" << endl;
+        for (p=fmap->begin(); p!=fmap->end(); p++) {
+            serr << p->second.get_name() << endl;
+        }
+        ierr = 2;
+        return;
+    }
+
+    // The function was found, do the evaluation and replace the words.
+
+    // Common items needed for all types of functions.
+    int ln = words[iw1].get_line_number();
+    int file_ln = words[iw1].get_file_line_number();
+    string fname = words[iw1].get_filename();
+
+
+    // Is a variable defined or not.
+    if (s == "defined") {
+        string varname = words[iw1+1].get_string();
+        string result = "true";
+        map<string, Variable>::iterator p;
+        p = vmap->find(varname);
+        if (p == vmap->end()) result = "false";
+        Word w(result, ln, file_ln, fname, lines);
+        replace_words(iw1, iw1+nargs, w);
+        i2 -= nargs;
+        return;
+    }
+
+
+    // String functions - string arguments, string results.
+    if (p->second.get_type() == "string") {
+        // Load all the arguments into a vector of strings.
+        vector<string> vs;
+        for (int i=0; i<nargs; i++) {
+            int j = iw1 + 1 + i;
+            string s = words[j].get_string();
+            vs.push_back(s);
+        }
+
+        // Calculate the function and replace the words.
+        string result = p->second.evaluate(vs, serr, ierr, ln, file_ln,
+                                           fname, lines);
+        Word w(result, ln, file_ln, fname, lines);
+        replace_words(iw1, iw1+nargs, w);
+        i2 -= nargs;
+    }
+
+
+    // Real functions - double arguments, double results.
+    if (p->second.get_type() == "real") {
+        // Check to see if all the function arguments have a value.
+        bool has_value = true;
+        for (int i=0; i<nargs; i++) {
+            int j = iw1 + 1 + i;
+            if (!words[j].is_number()) {
+                has_value = false;
+                words[j].fatal_error(serr, ierr);
+                serr << "Expected a number for function argument number " <<
+                    i+1 << endl;
+                serr << "Instead found:   " << words[j].get_string() << endl;
+                ierr = 2;
+            }
+        }
+        if (!has_value) return;
+
+        // All the arguments have values so we can deal with them
+        // as doubles.
+        // Load all the arguments into a vector of doubles.
+        vector<double> vd;
+        for (int i=0; i<nargs; i++) {
+            int j = iw1 + 1 + i;
+            double d = words[j].get_double();
+            vd.push_back(d);
+        }
+
+        // Calculate the function and replace the words.
+        double result = p->second.evaluate(vd, serr, ierr, ln, file_ln,
+                                       fname, lines);
+        Word w(result, ln, file_ln, fname, lines);
+        replace_words(iw1, iw1+nargs, w);
+        i2 -= nargs;
+    }
+}
+
+
+
+// ===========================================================================
+// When two "*" characters are together, assume that is the exponentiation
+// operator, "**", and replace both "*"'s with "**".
+// ===========================================================================
+void Cmd::handle_star_star()
+{
+    for (int i=0; i<(int)words.size()-1; i++) {
+        if (words[i].get_string() == "*" && words[i+1].get_string() == "*") {
+            int lnum = words[i].get_line_number();
+            int file_ln = words[i].get_file_line_number();
+            string fname = words[i].get_filename();
+            string s = "**";
+            Word w(s, lnum, file_ln, fname, lines);
+            replace_words(i, i+1, w);
+        }
+    }
+}
+
+
+// ===========================================================================
+// The parser does not automatically separate operators like .eq., .ne., etc.
+// For example, the phrase a.eq.b will be one word when it should be 3 words.
+// This routine finds those cases and splits the one word into multiple words.
+// ===========================================================================
+void Cmd::handle_ops()
+{
+    vector<string> subs;
+    subs.push_back(".eq.");
+    subs.push_back(".ne.");
+    subs.push_back(".gt.");
+    subs.push_back(".ge.");
+    subs.push_back(".lt.");
+    subs.push_back(".le.");
+    subs.push_back(".hgeq.");
+    subs.push_back(".hgne.");
+    subs.push_back(".hggt.");
+    subs.push_back(".hgge.");
+    subs.push_back(".hglt.");
+    subs.push_back(".hgle.");
+    subs.push_back(".not.");
+    subs.push_back(".and.");
+    subs.push_back(".or.");
+
+    for (int i=0; i<(int)words.size(); i++) {
+        string fstr = words[i].get_string();
+        for (int j=0; j<(int)subs.size(); j++) {
+            vector<string> vs;
+            bool b = separate_str(subs[j], fstr, vs);
+            if (b) {
+                vector<Word> vw;
+                for (int k=0; k<(int)vs.size(); k++) {
+                    int lnum = words[i].get_line_number();
+                    int file_lnum = words[i].get_file_line_number();
+                    string fname = words[i].get_filename();
+                    Word w(vs[k], lnum, file_lnum, fname, lines);
+                    vw.push_back(w);
+                    //cout << vs[k] << endl;
+                }
+                replace_words(i, i, vw);
+                i--;
+                break;
+            }
+        }
+
+
+        //int lnum = words[i].get_line_number();
+        //string s = "**";
+        //Word w(s, lnum, lines);
+        //replace_words(i, i+1, w);
+    }
+}
+
+
+// ===========================================================================
+// After the line has mostly been processed, check for any misplaced math
+// operations. For example, the following line
+//    xcenter = 1.0 + 2.0
+// has a misplaced math op in it, i.e. it should be in parentheses
+//    xcenter = (1.0 + 2.0)
+// ===========================================================================
+void Cmd::check_misplaced_math(stringstream &serr, int &ierr)
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].is_operator()) {
+            words[i].fatal_error(serr, ierr);
+            serr << "Misplaced math operation." << endl;
+            serr << "All math operations must be inside parentheses." << endl;
+            ierr = 2;
+        }
+    }
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Handle if/elseif/else/endif
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Handle if/elseif/else/endif statements.
+// ===========================================================================
+void Cmd::handle_if(bool &skip, deque<bool> &skip_level,
+                    deque<bool> &satisfied, stringstream &serr, int &ierr)
+{
+    // If's can be nested to any level, the number of levels is determined
+    // by the size of skip_level, the size of satisfied would also work here.
+    int nlevels = (int)skip_level.size();
+
+    // The endif statement ends a block if.
+    if (words[0].get_string() == "endif") {
+        if ((int)words.size() > 1) {
+            words[1].fatal_error(serr, ierr);
+            serr << "The endif (or end if) statement should not have "
+                 "anything else on the line." << endl;
+            serr << "Found other words on the line." << endl;
+            ierr = 2;
+        }
+
+        // The if level has ended, just erase it.
+        skip_level.erase(skip_level.begin()+nlevels-1);
+        satisfied.erase(satisfied.begin()+nlevels-1);
+        skip = true;
+        return;
+    }
+
+    // Else statment.
+    if (words[0].get_string() == "else") {
+        if ((int)words.size() > 1) {
+            words[1].fatal_error(serr, ierr);
+            serr << "The else statement should not have "
+                 "anything else on the line." << endl;
+            serr << "Found other words on the line." << endl;
+            ierr = 2;
+        }
+
+        // If the if has been satisfied before this else, then just
+        // skip the else block. Otherwise the if will be satisfied and
+        // we do not skip the else block.
+        if (satisfied[nlevels-1]) {
+            skip_level[nlevels-1] = true;
+        }
+        else {
+            satisfied[nlevels-1] = true;
+            skip_level[nlevels-1] = false;
+        }
+        skip = true;
+        return;
+    }
+
+    // If any level is in skip mode, then we will skip this line.
+    // This is mostly for non if related lines, but the skip flag is
+    // used below.
+    skip = false;
+    for (int n=0; n<nlevels; n++) {
+        if (skip_level[n]) {
+            skip = true;
+        }
+    }
+
+
+    // Process the elseif statement.
+    if (words[0].get_string() == "elseif") {
+        if (satisfied[nlevels-1]) {
+            skip_level[nlevels-1] = true;
+        }
+        else {
+            // If we are in skip mode at a higher level, then we can ignore this
+            // elseif.
+            if (skip && !skip_level[nlevels-1]) return;
+
+            // Do some syntax checking.
+            int wsize = (int)words.size();
+
+            if (wsize > 1) {
+                if (words[1].get_string() != "(") {
+                    words[1].fatal_error(serr, ierr);
+                    serr << "Expected an open parentheses, (, following " <<
+                          words[0].get_string() << endl;
+                    serr << "Instead found: " << words[1].get_string() << endl;
+                    ierr = 2;
+                }
+            }
+
+            int nw = wsize-2;
+            if (nw >= 0) {
+                if (words[nw].get_string() != ")") {
+                    words[nw].fatal_error(serr, ierr);
+                    serr << "Expected a close parentheses, ), as the next to last "
+                        "symbol on the line." << endl;
+                    serr << "Instead found: " << words[nw].get_string() << endl;
+                    ierr = 2;
+                }
+            }
+
+            nw = wsize-1;
+            if (nw >= 0) {
+                if (words[nw].get_string() != "then") {
+                    words[nw].fatal_error(serr, ierr);
+                    serr << "Expected then as the last word on the line." << endl;
+                    serr << "Instead found: " << words[nw].get_string() << endl;
+                    ierr = 2;
+                }
+            }
+
+            // Evaluate the conditional.
+            math_eval(serr, ierr);
+
+            if (words[1].get_bool(serr, ierr)) {
+                satisfied[nlevels-1] = true;
+                skip_level[nlevels-1] = false;
+            }
+            else {
+                skip_level[nlevels-1] = true;
+            }
+
+        }
+
+        // Set skip to skip the elseif statement.
+        skip = true;
+        return;
+    }
+
+
+
+
+    if (words[0].get_string() == "if") {
+        //cout << "&&&&&cw Cmd.cc, if statment encountered" << endl;
+
+        // If we are in skip mode at a higher level, then we can ignore this
+        // if.
+        if (skip) {
+            skip_level.push_back(true);
+            satisfied.push_back(true);
+            return;
+        }
+
+        // Do some syntax checking.
+        int wsize = (int)words.size();
+
+        if (wsize > 1) {
+            if (words[1].get_string() != "(") {
+                words[1].fatal_error(serr, ierr);
+                serr << "Expected an open parentheses, (, following " <<
+                    words[0].get_string() << endl;
+                serr << "Instead found: " << words[1].get_string() << endl;
+                ierr = 2;
+            }
+        }
+
+        // Evaluate the conditional.
+        math_eval(serr, ierr);
+
+        //for (int i=0; i<(int)words.size(); i++) {
+        //    cout << words[i].get_string() << endl;
+        //}
+
+        // Single line if
+        if (words[2].get_string() != "then") {
+            if (words[1].get_bool(serr, ierr)) {
+                delete_words(0,1);
+                reset_name_type();
+                skip = false;
+            }
+            else {
+                skip = true;
+            }
+            return;
+        }
+
+        // Multi-block if
+        if (words[2].get_string() == "then") {
+            if (words[1].get_bool(serr, ierr)) {
+                skip_level.push_back(false);
+                satisfied.push_back(true);
+                skip = true;
+            }
+            else {
+                skip_level.push_back(true);
+                satisfied.push_back(false);
+                skip = true;
+            }
+            return;
+        }
+    }
+
+
+    //for (int i=0; i<(int)words.size(); i++) {
+    //    if (words[i].get_string() == "*" && words[i+1].get_string() == "*") {
+    //    }
+    //}
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Handle do loops
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Handle do loops.
+// ===========================================================================
+void Cmd::handle_do(bool &skip, deque<int> &do_start, int &cdex,
+                    bool &end_do_loop, stringstream &serr, int &ierr)
+{
+    // Do's can be nested to any level, the number of levels is determined
+    // by the size of do_start.
+    int nlevels = (int)do_start.size();
+
+    // End of do loop, go back to do line.
+    if (words[0].get_string() == "enddo") {
+        //cout << "&&&&&cw Cmd, handle_do, start of enddo, cdex=" << cdex << endl;
+        if ((int)words.size() > 1) {
+            words[1].fatal_error(serr, ierr);
+            serr << "The enddo (or end do) statement should not have "
+                 "anything else on the line." << endl;
+            serr << "Found other words on the line." << endl;
+            ierr = 2;
+        }
+
+        cdex = do_start[nlevels-1] - 1;
+        skip = true;
+        return;
+    }
+
+
+    // Cycle command encountered.
+    if (words[0].get_string() == "cycle") {
+        if ((int)words.size() > 1) {
+            words[1].fatal_error(serr, ierr);
+            serr << "The cycle statement should not have "
+                 "anything else on the line." << endl;
+            serr << "Found other words on the line." << endl;
+            ierr = 2;
+        }
+
+        cdex = do_start[nlevels-1] - 1;
+        skip = true;
+        return;
+    }
+
+    // Break out of the do loop.
+    if (words[0].get_string() == "exit") {
+        if ((int)words.size() > 1) {
+            words[1].fatal_error(serr, ierr);
+            serr << "The exit statement should not have "
+                 "anything else on the line." << endl;
+            serr << "Found other words on the line." << endl;
+            ierr = 2;
+        }
+
+        end_do_loop = true;
+        return;
+    }
+
+    if (words[0].get_string() == "do") {
+
+        //for (int i=0; i<(int)words.size(); i++) {
+        //  cout << words[i].get_string() << endl;
+        //}
+
+        // Evaluate any math expressions on the do line.
+        math_eval(serr, ierr);
+
+        // Replace any simple variables on the line with their values.
+        // Of course, do not replace the loop variable.
+        int ieq = -1;
+        for (int i=0; i<(int)words.size(); i++) {
+            if (words[i].get_string() == "=") {
+                ieq = i;
+                break;
+            }
+        }
+        if (ieq >= 0) {
+            int nw1 = (int)words.size()-1;
+            subvar_w0(ieq+1, nw1, serr, ierr);
+        }
+
+        // Handle unary minus
+        handle_cmd_unary_minus(serr, ierr);
+
+        // Number of words on the line after math evaluation.
+        int nwords = (int)words.size();
+
+        // Get the loop variable name.
+        string do_varname = "$i";
+        bool isvar = true;
+        if (nwords>1) {
+            do_varname = words[1].get_string();
+            if (!words[1].is_variable()) isvar = false;
+        }
+
+        // Expecting 6 or 8 words, i.e. "do $i = 1 , 10" 
+        if (nwords < 6) {
+            words[0].fatal_error(serr, ierr);
+            serr << "Expected at least 6 words on this line after any math evaluations."
+                 << endl;
+            serr << "For example, " << endl
+                 << "    do " << do_varname << " = 1 , 10" << endl;
+            serr << "Instead found " << nwords << " words on the line." << endl;
+            serr << "The line (after any math evaluations have been done) is:" << endl;
+            serr << "    ";
+            for (int iw=0; iw<nwords; iw++) {
+                serr << words[iw].get_string() << " ";
+            }
+            serr << endl;
+            ierr = 2;
+            return;
+        }
+
+        // Variables must begin with a $
+        if (!isvar) {
+            words[0].fatal_error(serr, ierr);
+            serr << "Loop variable names must begin with a $ sign." << endl;
+            serr << "Note that putting quotes around a variable name makes it" << endl;
+            serr << "a string, not a variable." << endl;
+            serr << "Instead found: " << do_varname << endl;
+            ierr = 2;
+            return;
+        }
+
+        // Word 3 must be an = sign.
+        if (words[2].get_string() != "=") {
+            words[2].fatal_error(serr, ierr);
+            serr << "The third word must be an = sign." << endl;
+            serr << "Instead found: " << words[2].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+
+        // Word 5 must be a comma.
+        if (!words[4].is_comma()) {
+            words[4].fatal_error(serr, ierr);
+            serr << "The fifth word must be a comma." << endl;
+            serr << "Instead found: " << words[4].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+
+        // The get_int functions generate an error if the values are
+        // not integer.
+        int i1 = words[3].get_int(serr, ierr);
+        int i2 = words[5].get_int(serr, ierr);
+
+        // Get the step (increment) if specified.
+        int istep = 1;
+        if (nwords > 7) istep = words[7].get_int(serr, ierr);
+
+        string s1 = words[3].get_string();
+        string s2 = words[5].get_string();
+
+        bool do_continue = false;
+        if (nlevels > 0) {
+            if (do_start[nlevels-1] == cdex) do_continue = true;
+        }
+
+        if (do_continue) {  // This do has already been encountered.
+            //cout << "&&&&&cw Cmd, handle_do, do:continue" << endl;
+
+            // Find the variable in the list of variables, increment it, test for
+            // ending the loop, and store the incremented value.
+            map<string, Variable>::iterator p;
+            p = vmap->find(do_varname);
+            if (p != vmap->end()) {
+                string do_var_value = p->second.get_var_value();
+                int lnum = words[0].get_line_number();
+                int file_lnum = words[0].get_file_line_number();
+                string fname = words[0].get_filename();
+                Word w(do_var_value, lnum, file_lnum, filename, lines);
+                int ival = w.get_int(serr, ierr);
+                ival += istep;
+                //cout << "&&&&&cw Cmd, handle_do, do:continue, do_var_value=" << ival << endl;
+                if (istep >= 0 && ival > i2) {
+                    end_do_loop = true;
+                    return;
+                }
+                if (istep < 0 && ival < i2) {
+                    end_do_loop = true;
+                    return;
+                }
+                stringstream ss;
+                ss << ival;
+                string sval = ss.str();
+                vector<string> valvec;
+                valvec.push_back(sval);
+                vector<int> istart(0,0);
+                p->second.set_var_value(istart, valvec, lnum, file_lnum, fname,
+                                        lines, serr, ierr);
+            }
+            else {
+                words[1].fatal_error(serr, ierr);
+                serr << "The loop variable, " << do_varname <<
+                    " was not found in the variable list." << endl;
+                serr << "This should not happen, possible code bug?" << endl;
+                ierr = 2;
+                return;
+            }
+        }
+        else {  // A new do loop has been encountered.
+            do_start.push_back(cdex);
+
+            // It is possible that we don't execute the do loop at all.
+            if (istep >= 0 && i1 > i2) {
+                end_do_loop = true;
+                return;
+            }
+            if (istep < 0 && i1 < i2) {
+                end_do_loop = true;
+                return;
+            }
+
+            //cout << "&&&&&cw Cmd, handle_do, do:start, cdex=" << cdex << endl;
+            //cout << "&&&&&cw Cmd, handle_do, do:start, s1=" << s1 << endl;
+            //cout << "&&&&&cw Cmd, handle_do, do:start, s2=" << s2 << endl;
+
+            // Store the loop variable, create it if necessary.
+            vector<int> istart(0,0);
+            int lnum = words[0].get_line_number();
+            int file_lnum = words[0].get_file_line_number();
+            string fname = words[0].get_filename();
+            vector<string> valvec;
+            valvec.push_back(s1);
+            map<string, Variable>::iterator p;
+            p = vmap->find(do_varname);
+            if (p != vmap->end()) {
+                p->second.set_var_value(istart, valvec, lnum, file_lnum, fname,
+                                        lines, serr, ierr);
+            }
+            else {
+                Variable v(do_varname, istart, valvec, lnum, file_lnum, fname,
+                           lines, serr, ierr);
+                vmap->insert(pair<string, Variable>(v.get_varname(), v));
+            }
+        }
+        skip = true;
+        return;
+    }
+}
+
+
+
+// ===========================================================================
+// Starting at a do statement, find the matching enddo.
+// ===========================================================================
+bool Cmd::find_matching_enddo(int &dlev, bool &stop_checking)
+{
+    if (words[0].get_string() == "enddo") {
+        if (dlev == 1) return true;
+        dlev -= 1;
+        return false;
+    }
+    if (words[0].get_string() == "do") {
+        dlev += 1;
+        return false;
+    }
+
+    // If we are in main and hit a subroutine statement then that is the
+    // end of main and we need to stop checking.
+    if (words[0].get_string() == "subroutine") {
+        stop_checking = true;
+        return false;
+    }
+
+    // If we are in a subroutine and hit an endsubroutine statement then
+    // we need to stop checking.
+    if (words[0].get_string() == "endsubroutine") {
+        stop_checking = true;
+        return false;
+    }
+
+    return false;
+}
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Subroutines
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Handle subroutines.
+// ===========================================================================
+void Cmd::handle_subroutines(bool &skip, bool &go_to_sub, string &sub_name,
+                             bool &go_to_call, stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(skip == skip);
+    //assert(serr == serr);
+    assert(ierr == ierr);
+
+    // 
+    if (words[0].get_string() == "call") {
+        sub_name = words[1].get_string();
+        go_to_sub = true;
+        return;
+    }
+
+    if (words[0].get_string() == "endsubroutine" ||
+        words[0].get_string() == "return") {
+        go_to_call = true;
+        return;
+    }
+
+}
+
+
+// ===========================================================================
+// Searching for subroutine sub_name.
+// ===========================================================================
+bool Cmd::find_subroutine(string &sub_name)
+{
+    if ((int)words.size() < 2) return false;
+    if (words[0].get_string() == "subroutine" &&
+        words[1].get_string() == sub_name) return true;
+    return false;
+}
+
+
+// ===========================================================================
+// A call statement has been encountered, get the arguments, if any.
+// The call is expected to be
+//      call subname ( arg1, arg2, ...)
+// ===========================================================================
+void Cmd::get_call_args(vector<string> &sargs, vector<bool> &sargs_isvar,
+                        stringstream &serr, int &ierr)
+{
+    //debug_print_words("Cmd, enter get_call_args");
+
+    // We do not want to modify the words on this line, but we have to
+    // temporarily to get the math eval to work right. Therefore store the
+    // words on the line and restore them later.
+    deque <Word> words_store;
+    for (int i=0; i<(int)words.size(); i++) {
+        words_store.push_back(words[i]);
+    }
+
+    // Erase the call and the subroutine name.
+    erase_word(0);
+    erase_word(0);
+
+    // Erase the opening and closing parens.
+    if ((int)words.size() > 0) {
+        if (words[0].get_string() == "(") erase_word(0);
+    }
+    if ((int)words.size() > 0) {
+        if (words[(int)words.size()-1].get_string() == ")") erase_last_word();
+    }
+    //debug_print_words("Cmd, get_call_args, after erase");
+
+    // Do a math eval to get one word arguments. If the arguments are
+    // variables they will not be evaluated, so we will end up with a mix
+    // of variables and numbers.
+    if ((int)words.size() > 0) {
+        math_eval(serr, ierr);
+        int wlen = (int)words.size() - 1;
+        handle_unary_op(0, wlen, "-", serr, ierr);
+        wlen = (int)words.size() - 1;
+        handle_unary_op(0, wlen, "+", serr, ierr);
+    }
+
+    //debug_print_words("Cmd, get_call_args, after math eval");
+
+    // Store the arguments in the vector of strings, sargs, to be returned
+    // to the calling code and also store in the class, call_args.
+    call_args.clear();
+    call_args_isvar.clear();
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].is_comma()) continue;
+        sargs.push_back(words[i].get_string());
+        sargs_isvar.push_back(words[i].is_variable());
+        call_args.push_back(words[i].get_string());
+        call_args_isvar.push_back(words[i].is_variable());
+    }
+
+    // Restore the words before leaving this function.
+    words.clear();
+    for (int i=0; i<(int)words_store.size(); i++) {
+        words.push_back(words_store[i]);
+    }
+    //debug_print_words("Cmd, get_call_args, after restoring words");
+}
+
+
+// ===========================================================================
+// A subroutine statement has been encountered, get the arguments, if any.
+// The subroutine statement is expected to be
+//      subroutine subname ( arg1, arg2, ...)
+// ===========================================================================
+void Cmd::get_sub_args(vector<string> &sargs, vector<bool> &sargs_isvar)
+{
+    sub_args.clear();
+    sub_args_isvar.clear();
+    for (int i=3; i<(int)words.size(); i+=2) {
+        sargs.push_back(words[i].get_string());
+        sargs_isvar.push_back(words[i].is_variable());
+        sub_args.push_back(words[i].get_string());
+        sub_args_isvar.push_back(words[i].is_variable());
+    }
+}
+
+
+// ===========================================================================
+// Accessor functions for the calling and subroutine arguments.
+// ===========================================================================
+void Cmd::copy_call_args(vector<string> &sargs, vector<bool> &sargs_isvar)
+{
+    for (int i=0; i<(int)call_args.size(); i++) {
+        sargs.push_back(call_args[i]);
+        sargs_isvar.push_back(call_args_isvar[i]);
+    }
+}
+
+void Cmd::copy_sub_args(vector<string> &sargs, vector<bool> &sargs_isvar)
+{
+    for (int i=0; i<(int)sub_args.size(); i++) {
+        sargs.push_back(sub_args[i]);
+        sargs_isvar.push_back(sub_args_isvar[i]);
+    }
+}
+
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Handle comments.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Process single line comments.
+// ===========================================================================
+void Cmd::single_line_comments()
+{
+    for (int i=0; i<(int)words.size()-1; i++) {
+        if ((words[i].get_string() == "!") ||
+            (words[i].get_string() == "#") ||
+            (words[i].get_string() == "/" && words[i+1].get_string() == "/")
+            ) {
+            words.erase(words.begin()+i, words.begin()+(int)words.size());
+            break;
+        }
+    }
+
+    // Handle the case where the last word might be an ! or a #
+    int ilast = (int)words.size()-1; 
+    if (ilast < 0) return;
+    if ((words[ilast].get_string() == "!") || (words[ilast].get_string() == "#"))
+        words.erase(words.begin()+ilast);
+}
+
+
+// ===========================================================================
+// Process multi-line comments.
+// ===========================================================================
+void Cmd::multi_line_comments(int &level)
+{
+    /*
+    cout << "*** Enter multi_line_comments, level=" << level << endl;
+    cout << "**** original string: " << original_str << endl;
+    stringstream ss;
+    print_using_words(ss);
+    cout << "     print words before:" << endl;
+    cout << "         " << ss.str() << endl;
+    */
+
+    int istart = -1;
+    if (level > 0) istart = 0;
+
+    for (int i=0; i<(int)words.size()-1; i++) {
+        //cout << "Top of i loop, i=" << i << endl;
+        if (words[i].get_string() == "/" && words[i+1].get_string() == "*") {
+            if (level == 0) istart = i;
+            level += 1;
+            //cout << "found /*, i=" << i << endl;
+            i += 1;
+            continue;
+        }
+
+        if (words[i].get_string() == "*" && words[i+1].get_string() == "/") {
+            if (level == 0) {
+                cout << "Error in line " << line_number << " umatched */" << endl;
+            }
+            //cout << "found */, istart=" << istart << "  words[istart]=" <<
+            //    words[istart].get_string() << endl;
+            //cout << "found */, i=" << i << "  words[i]=" <<
+            //    words[i].get_string() << endl;
+            //cout << "found */, i+1=" << i+1 << "  words[i+1]=" <<
+            //    words[i+1].get_string() << endl;
+            words.erase(words.begin()+istart, words.begin()+i+2);
+            level -= 1;
+            int ndel = i+1-istart+1;
+            //cout << "ndel=" << ndel << "  i=" << i << endl;
+            i = i+1-ndel+1;
+            //cout << "after changing i, i=" << i << "  words[i]=" <<
+            //    words[i].get_string() << endl;
+            if (level > 0) istart = i;
+            continue;
+        }
+
+    }
+
+    if (level > 0) {
+        words.erase(words.begin()+istart, words.begin()+(int)words.size());
+    }
+
+    /*
+    stringstream ss1;
+    print_using_words(ss1);
+    cout << "     print words after:" << endl;
+    cout << "         " << ss1.str() << endl;
+
+    cout << endl << "**********" << endl;
+    */
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Miscellaneous
+// ***************************************************************************
+// ***************************************************************************
+
+
+// ===========================================================================
+// Go through every word on the line, check for matching quotes, then remove
+// them.
+// ===========================================================================
+void Cmd::handle_quotes(stringstream &serr, int &ierr)
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        words[i].handle_quotes(serr, ierr);
+    }
+}
+
+
+
+// ===========================================================================
+// The execution line arguments are expected to be of the form
+//     -v r1=5 -v somevar = 14
+// The -v is a keyword indicating that a variable setting follows. There is
+// no $ because the shell does not allow that.
+// At this point the execution line arguments have been parsed into words.
+// This function extracts the variable definitions, inserts the $, and turns
+// them into separate lines, and returns that in string sout. Then the
+// parser can simply add that to the top of the user input file.
+// ===========================================================================
+void Cmd::handle_exe_args(string &sout)
+{
+  // We use a stringstream here instead of modifying sout directly so that
+  // we can use endl instead of \n since endl is portable and \n is not.
+  stringstream ss;
+  bool line;
+  for (int i=0; i<(int)words.size()-1; i++) {
+    // if you hit a -<letter>
+    if (words[i].get_string() == "-" &&
+        ( words[i+1].get_string() == "v" ||
+          words[i+1].get_string() == "l" ) ) {
+      // get type of argument
+      line = true;
+      if( words[i+1].get_string() == "v" ){
+        line = false;
+      }
+      // move in after the -<letter> and stuff line until next -<letter>
+      int istart = i+2;
+      for (int j=istart; j<(int)words.size(); j++) {
+        // stop at next -<letter>
+        if (j < (int)words.size()-1) {
+          if (words[j].get_string() == "-" &&
+              ( words[j+1].get_string() == "v" ||
+                words[j+1].get_string() == "l" ) ) {
+            break;
+          }
+        }
+        string sj = words[j].get_string();
+        if (j == istart && !line) {
+          sj.insert(sj.begin(), '$');
+        }
+        ss << sj << " ";
+      }
+      ss << endl;
+    }
+  }
+  sout = ss.str();
+}
+
+
+// ===========================================================================
+// Consider the following input
+//     2.0, 3.0 e15, -7.0
+// The issue is with the middle two words, "3.0 e15", the old parser ignored
+// the space and treated this as one word, 3.0e15. The new parser treats is
+// as two words.
+//
+// This should have been treated as an input error by the old parser but was
+// not, so now we have to deal with it.
+//
+// This routine detects this situation and allows the calling code to deal
+// with it according to the action input, allowed action values are:
+//
+//    ignore      Treat it as two words and silently continue.
+//    fix         Merge the two words into one word, as the old parser did.
+//    error       Generate a fatal error, force the user to fix it.
+//
+// ===========================================================================
+void Cmd::deprecated_input01(string action, stringstream &serr, int &ierr)
+{
+    //if (cmd_name != "depcmd01") return;
+
+    if (cmd_type != "command") return;
+
+    for (int i=0; i<(int)words.size()-2; i++) {
+        // A comma must be found first.
+        if (!words[i].is_comma()) continue;
+
+        // There could be a unary plus or minus on the next number, if so
+        // then skip it. At this point, the unary plus and minus have not
+        // been merged with their number.
+        int in1 = i+1;
+        string spm = words[i+1].get_string();
+        string s1;
+        if (spm == "+" || spm == "-") {
+            s1 = spm;
+            in1 += 1;
+        }
+        s1 += words[in1].get_string();
+
+        // in1 is where the first number is, it needs to be a number.
+        if (!words[in1].is_number()) continue;
+
+        // in2 is where the second number is, it needs to be a number.
+        int in2 = in1 + 1;
+        if (in2 > (int)words.size() - 1) break;
+        if (!words[in2].is_number()) continue;
+        string s2 = words[in2].get_string();
+        s2.erase(s2.begin());
+
+        // The first character of the second number should be an e or E.
+        // But at this point we have already detected this and prepended
+        // a 1 on to the word. So the first character should be 1 and the
+        // second character should be e or E
+        char c30 = words[in2].get_string()[0];
+        if (c30 != '1') continue;
+
+        char c31 = words[in2].get_string()[1];
+        if (c31 != 'e' && c31 != 'E') continue;
+
+        // The next word, if present should be a comma.
+        int ic2 = in2 + 1;
+        if (ic2 <= (int)words.size()-1) {
+            if (!words[ic2].is_comma()) continue;
+        }
+
+        // A deprecated input has been found, ignore it, fix it, or
+        // generate a fatal error.
+        if (action == "ignore") continue;
+        if (action == "fix") {
+            words[in2].erase_char(0);
+            merge_words(in1, in2);
+            continue;
+        }
+        if (action == "error") {
+            words[in1].fatal_error(serr, ierr);
+            serr << "Possible error, detected the following" << endl;
+            serr << "   comma digits space exponent comma" << endl;
+            serr << "The digits and exponent are separated by one or more spaces,"
+                 << endl;
+            serr << "this is not allowed for a single number." << endl;
+            serr << "The digits are: " << s1 << "  and the exponent is: "
+                 << s2 << endl;
+            serr << "If this is one number, then remove the space." << endl;
+            serr << "If this is two numbers, then put a comma between the"
+                 << " digits and exponent."<< endl;
+            serr << "This error (and the same error in subsequent lines) can"
+                 << endl;
+            serr << "be controlled with the following input file command"
+                 << endl;
+            serr << "and arguments (put before the lines with errors)" << endl;
+            serr << "      depcmd_dse argument" << endl;
+            serr << "where argument has one of the following values:" << endl;
+            serr << "      fix     Silently remove the space, merge into one number" << endl;
+            serr << "      ignore  Silently treat as two numbers" << endl;
+            serr << "      error   Generate fatal error (default)" << endl;
+            serr << "While the default is to generate an error, if the" << endl;
+            serr << "command name is matdef, then the default is fix." << endl;
+            ierr = 2;
+            continue;
+        }
+    }
+}
+
+
+
+// ===========================================================================
+// Fatal error
+// This is mainly meant to be called from some other class that does not
+// know about words.
+// ===========================================================================
+void Cmd::fatal_error(int iw, stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(ierr == ierr);
+
+    int lnum = words[iw].get_line_number();
+    int file_lnum = words[iw].get_file_line_number();
+    string fname = words[iw].get_filename();
+    serr << endl;
+    serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+    serr << "    " << (*lines)[lnum-1] << endl;
+    serr << "in file: " << fname << endl;
+}
+
+// ===========================================================================
+// This is meant to be called from within this class.
+// ===========================================================================
+void Cmd::fatal_error2(stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(ierr == ierr);
+
+    serr << endl;
+    serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+    serr << "    " << (*lines)[line_number-1] << endl;
+    serr << "in file: " << filename << endl;
+}
+
+
+// ===========================================================================
+// Warning
+// ===========================================================================
+void Cmd::warning(int iw, stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(ierr == ierr);
+
+    int lnum = words[iw].get_line_number();
+    int file_lnum = words[iw].get_file_line_number();
+    string fname = words[iw].get_filename();
+    serr << endl;
+    serr << "*** WARNING in line " << file_lnum << ":" << endl;
+    serr << "    " << (*lines)[lnum-1] << endl;
+    serr << "in file: " << fname << endl;
+}
+
+
+// ===========================================================================
+// This is used when printing duplicate lines warnings.
+// ===========================================================================
+void Cmd::print_duplicate_line(int iw, stringstream &ss, int fn_width,
+                               int lnum_width, string after_lnum)
+{
+    int lnum = words[iw].get_line_number();
+    int file_lnum = words[iw].get_file_line_number();
+    string fname = words[iw].get_filename();
+    ss << setw(fn_width) << fname;
+    ss << setw(lnum_width) << file_lnum << after_lnum;
+    ss << (*lines)[lnum-1];
+    //print_using_words_fm(ss);
+}
+
+
+// ===========================================================================
+// Get the filename size and line number size for formatting purposes
+// when printing duplicate lines warnings.
+// ===========================================================================
+void Cmd::get_duplicate_sizes(int iw, int &fn_width, int &lnum_width)
+{
+    int file_lnum = words[iw].get_file_line_number();
+    string fname = words[iw].get_filename();
+    fn_width = (int)fname.size();
+    lnum_width = 1;
+    if (file_lnum >= 10)       lnum_width = 2;
+    if (file_lnum >= 100)      lnum_width = 3;
+    if (file_lnum >= 1000)     lnum_width = 4;
+    if (file_lnum >= 10000)    lnum_width = 5;
+    if (file_lnum >= 100000)   lnum_width = 6;
+    if (file_lnum >= 1000000)  lnum_width = 7;
+}
+
+
+// ===========================================================================
+// Look at the places where this function is called to understand the
+// following indices.
+//     wdex = i    Index into the words array.
+//     cdex = k    C index in the output array.
+// ===========================================================================
+void Cmd::error_dup_line(string &cname, int wdex, int cdex,
+                         vector<int> &dup_wdex1, vector<Cmd *> &dup_cmd1,
+                         vector<int> &dup_vals, const vector<int> &size,
+                         int dup_fatal, stringstream &serr, int &ierr)
+{
+    if (dup_vals[cdex] == 0) {
+        dup_cmd1[cdex] = this;
+        dup_wdex1[cdex] = wdex;
+    }
+    dup_vals[cdex] += 1;
+    if (dup_fatal == 0) return;
+    if (dup_vals[cdex] > 1) {
+        int wdex1 = dup_wdex1[cdex];
+        Cmd *cmd = dup_cmd1[cdex];
+
+        // Get the dimension of the array, 0,1,2,3,...
+        int dim = (int)size.size();
+
+        if (dup_fatal == 2) words[wdex].fatal_error(serr, ierr);
+        if (dup_fatal == 1) words[wdex].warning(serr, ierr);
+        int tot_size = 1;
+        for (int ts=0; ts<dim; ts++) {
+            tot_size *= size[ts];
+        }
+        vector<int> irdices(dim, 0);
+        Parser_utils putils(index_base);
+        putils.reverse_dex(cdex, tot_size, irdices, size);
+        serr << "A duplicate value has been specified for: " << cname << "(";
+        for (int irdex=0; irdex<dim; irdex++) {
+            serr << irdices[irdex];
+            if (irdex < dim-1) serr << ",";
+        }
+        serr << ") = " <<
+            words[wdex].get_string() << endl;
+
+        serr << "This array element was first specified in line " <<
+            cmd->get_file_line_number(wdex1) << endl;
+        string fname = cmd->get_filename(wdex1);
+        serr << "    " << (*lines)[cmd->get_line_number(wdex1)-1] <<
+            endl;
+        serr << "in file: " << fname << endl;
+
+        if (dup_fatal == 2) {
+            serr << "This fatal error can be turned into a warning with the command " <<
+                endl << "    duplicate_array_values = warning" << endl;
+        }
+        if (dup_fatal == 1) {
+            serr << "This warning can be turned into a fatal error with the command " <<
+                endl << "    duplicate_array_values = fatal" << endl;
+        }
+        serr << "Duplicate array value checking can be turned off totally with" <<
+            endl << "    duplicate_array_values = none" << endl;
+        serr << "This is not recommended since you will lose the opportunity" <<
+            endl << "to check for legimate errors in your input." << endl;
+
+        ierr = 1;
+        if (dup_fatal == 2) ierr = 3;
+    }
+}
+
+
+// ===========================================================================
+// There are some commands that can be written as two words such as "end if",
+// "else if", and "end do". Find these and combine them into one word.
+// ===========================================================================
+void Cmd::handle_two_words()
+{
+    // Handle + + -> ++
+    for (int i=0; i<(int)words.size()-1; i++) {
+        if (words[i].get_string() == "+" && words[i+1].get_string() == "+") {
+            bool combine = false;
+            if (i == (int)words.size()-2) combine = true;
+            if (i < (int)words.size()-2) {
+                if (!words[i+2].is_numvar()) combine = true;
+            }
+            if (combine) {
+                int lnum = words[i].get_line_number();
+                int file_lnum = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                string s = "++";
+                Word w(s, lnum, file_lnum, fname, lines);
+                replace_words(i, i+1, w);
+            }
+        }
+    }
+
+    // Handle - - -> --
+    for (int i=0; i<(int)words.size()-1; i++) {
+        if (words[i].get_string() == "-" && words[i+1].get_string() == "-") {
+            bool combine = false;
+            if (i == (int)words.size()-2) combine = true;
+            if (i < (int)words.size()-2) {
+                if (!words[i+2].is_numvar()) combine = true;
+            }
+            if (combine) {
+                int lnum = words[i].get_line_number();
+                int file_lnum = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                string s = "--";
+                Word w(s, lnum, file_lnum, fname, lines);
+                replace_words(i, i+1, w);
+            }
+        }
+    }
+
+
+    // The rest of these have at least two words on the line,
+    // like "end subroutine".
+    if ((int)words.size() < 2) return;
+
+    // Common settings.
+    int lnum = words[0].get_line_number();
+    int file_lnum = words[0].get_file_line_number();
+    string fname = words[0].get_filename();
+
+    // Handle the case where enddo is written as two
+    // words, just combine them into one word.
+    if (words[0].get_string() == "end" && words[1].get_string() == "do") {
+        string s = "enddo";
+        Word w(s, lnum, file_lnum, fname, lines);
+        replace_words(0, 1, w);
+    }
+
+    // Handle the case where endsubroutine is written as two
+    // words, just combine them into one word.
+    if (words[0].get_string() == "end" && words[1].get_string() == "subroutine") {
+        string s = "endsubroutine";
+        Word w(s, lnum, file_lnum, fname, lines);
+        replace_words(0, 1, w);
+    }
+
+    // Handle the case where endwhen is written as two
+    // words, just combine them into one word.
+    if (words[0].get_string() == "end" && words[1].get_string() == "when") {
+        string s = "endwhen";
+        Word w(s, lnum, file_lnum, fname, lines);
+        replace_words(0, 1, w);
+    }
+
+    // Handle the case where endif and elseif are written as two
+    // words, just combine them into one word.
+    if (words[0].get_string() == "end" && words[1].get_string() == "if") {
+        string s = "endif";
+        Word w(s, lnum, file_lnum, fname, lines);
+        replace_words(0, 1, w);
+    }
+    if (words[0].get_string() == "else" && words[1].get_string() == "if") {
+        string s = "elseif";
+        Word w(s, lnum, file_lnum, fname, lines);
+        replace_words(0, 1, w);
+    }
+}
+
+
+// ===========================================================================
+// Check for end of input. There are several ways user input ends:
+//    End of file
+//    Encounter a stop command
+//    Encounter a fatal error command.
+// ===========================================================================
+bool Cmd::check_input_end(bool kill_run, stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(kill_run == kill_run);
+
+    if (words[0].get_string() == "fatal_error") {
+        int lnum = words[0].get_line_number();
+        int file_lnum = words[0].get_file_line_number();
+        string fname = words[0].get_filename();
+        serr << endl;
+        serr << "*** User has issued a fatal_error command in line "
+             << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << endl << "The user supplied fatal_error message is: " << endl;
+        serr << "    ";
+        string s = (*lines)[lnum-1];
+        int i1 = s.find("f", 0);
+        for (int i=i1+12; i<(int)s.size(); i++) {
+            serr << s[i];
+        }
+        serr << endl;
+        ierr = 2;
+        return true;
+    }
+
+    if (words[0].get_string() == "stop") return true;
+    return false;
+}
+
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Operations on the deque of words.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Find the first occurrence of string s in part of the line.
+// ===========================================================================
+int Cmd::find(int i1, int i2, string s)
+{
+    for (int i=i1; i<=i2; i++) {
+        if (words[i].get_string() == s) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+
+// ===========================================================================
+// Find the first occurrence of any character in string s in part of
+// the line.
+// ===========================================================================
+int Cmd::find_any_char(int i1, int i2, string s)
+{
+    for (int i=i1; i<=i2; i++) {
+        for (int j=0; j<(int)s.size(); j++) {
+            string ssub = s.substr(j, 1);
+            if (words[i].get_string() == ssub) {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
+
+
+// ===========================================================================
+// Find the last occurrence of string s in the line.
+// ===========================================================================
+int Cmd::find_last(string s, int i1, int i2)
+{
+    int iloc = -1;
+    for (int i=i1; i<=i2; i++) {
+        if (words[i].get_string() == s) {
+            iloc = i;
+        }
+    }
+    return iloc;
+}
+
+
+// ===========================================================================
+// Given an input string, fstr, and a sub string, subs, find the first
+// occurrence of subs in fstr. Return in the string vector, vs, the string
+// to the left of subs, if any, the sub string itself, subs, and the string
+// to the right of subs, if any.
+// ===========================================================================
+bool Cmd::separate_str(string &subs, string &fstr, vector<string> &vs)
+{
+    // Make sure the return vector is empty.
+    vs.clear();
+
+    // Find the sub string, if not found, then nothing more to do.
+    int loc = (int)fstr.find(subs,0);
+    if (loc == (int)string::npos) return false;
+
+    // If fstr only contains subs and nothing more, then there is nothing
+    // to do.
+    if (subs == fstr) return false;
+
+    // Anything to the left of the sub string is the first string returned.
+    if (loc > 0) {
+        string s1 = fstr.substr(0,loc);
+        vs.push_back(s1);
+    }
+
+    // The sub string itself is the second string returned.
+    vs.push_back(subs);
+
+    // Find the number of characters to the right of the sub string.
+    int subs_len = (int)subs.size();
+    int fstr_len = (int)fstr.size();
+    int istart = loc + subs_len;
+    int nchar = fstr_len - istart;
+
+    // Anything to the right of the sub string is the third string returned.
+    if (nchar > 0) {
+        string s2 = fstr.substr(istart,nchar);
+        vs.push_back(s2);
+    }
+
+    return true;
+}
+
+
+// ===========================================================================
+// Find the location of the closing symbol that matches the opening symbol.
+// Symbol examples are (), [], {}
+// We assume that the opening symbol has been found and we are starting the
+// search after the opening symbol location.
+// Nesting is handled, for example, (...(...(...)...)...)
+// ===========================================================================
+int Cmd::find_closing_symbol(string opensym, string closesym, int i1)
+{
+    int level = 0;
+    for (int i=i1; i<(int)words.size(); i++) {
+        string w = words[i].get_string();
+        if (w == opensym) {
+            level += 1;
+            continue;
+        }
+        if (w == closesym) {
+            if (level == 0) return i;
+            level -= 1;
+            continue;
+        }
+    }
+    return -1;
+}
+
+
+// ===========================================================================
+// Delete words i1 through i2 inclusive from the deque.
+// ===========================================================================
+void Cmd::delete_words(int i1, int i2)
+{
+    deque<Word>::iterator p = words.begin();
+    words.erase(p + i1, p + i2 + 1);
+}
+
+
+// ===========================================================================
+// Replace words i1 through i2 inclusive with word w.
+// ===========================================================================
+void Cmd::replace_words(int i1, int i2, Word &w)
+{
+    delete_words(i1, i2);
+    deque<Word>::iterator p = words.begin();
+    words.insert(p + i1, w);
+}
+
+
+// ===========================================================================
+// Replace words i1 through i2 inclusive with all the words in vector vw.
+// ===========================================================================
+void Cmd::replace_words(int i1, int i2, vector<Word> &vw)
+{
+    delete_words(i1, i2);
+    for (int i=(int)vw.size()-1; i>=0; i--) {
+        deque<Word>::iterator p = words.begin();
+        words.insert(p + i1, vw[i]);
+    }
+}
+
+
+// ===========================================================================
+// Merge words i1 through i2 inclusive into one word located at i1, remove
+// words i1+1 through i2 inclusive.
+// ===========================================================================
+void Cmd::merge_words(int i1, int i2)
+{
+    int lnum = words[i1].get_line_number();
+    int file_lnum = words[i1].get_file_line_number();
+    string fname = words[i1].get_filename();
+    string s = words[i1].get_string();
+
+    for (int i=i1+1; i<=i2; i++) {
+        s += words[i].get_string();
+    }
+
+    Word w(s, lnum, file_lnum, fname, lines);
+    replace_words(i1, i2, w);
+}
+
+
+// ===========================================================================
+// Find the equals sign on the line.
+// ===========================================================================
+int Cmd::find_equals()
+{
+    int ieq = -1;
+    for (int i=0; i<(int)words.size(); i++) {
+        if (words[i].get_string() == "=") {
+            ieq = i;
+            break;
+        }
+    }
+    return ieq;
+}
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Handle processed flags.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Set all the processed flags in the line to be false.
+// ===========================================================================
+void Cmd::clear_processed()
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        words[i].set_processed(false);
+    }
+}
+
+void Cmd::set_processed(bool ip)
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        words[i].set_processed(ip);
+    }
+}
+
+
+
+// ===========================================================================
+// Check processed flags for each word.
+// ===========================================================================
+void Cmd::check_processed(bool &good, stringstream &serr, int &ierr)
+{
+    // First we check to see if any of the words on the line have been
+    // processed. If none of the words have been processed, then we print
+    // the entire line as an error. This saves the user from having to
+    // wade through an error print for every word on the line.
+    bool p = false;
+    for (int i=0; i<(int)words.size(); i++) {
+        p = words[i].get_processed();
+        if (p) break;
+    }
+
+    if (!p) {
+        good = false;
+        words[0].fatal_error(serr, ierr);
+        serr << "This line has not been processed." << endl;
+        ierr = 2;
+
+        return;
+    }
+
+
+    // At least one word on the line has been processed.
+    // Check all the words on the line, throw an error for any word not
+    // processed.
+    for (int i=0; i<(int)words.size(); i++) {
+        p = words[i].get_processed();
+
+        if (!p) {
+            good = false;
+            words[i].fatal_error(serr, ierr);
+            serr << "A word on this line has not been processed." << endl;
+            serr << "Not proccessed word = " << words[i].get_string() << endl;
+            ierr = 2;
+
+        }
+    }
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Debug
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Print all the words on the line mainly for debugging.
+// Output is to a stringstream so the calling method can decide what to do
+// with the output - send it to the screen, use it for testing, whatever.
+// ===========================================================================
+void Cmd::print_all_words()
+{
+    stringstream ss;
+    print_all_words(ss);
+    cout << ss.str();
+}
+
+void Cmd::print_all_words(stringstream &ss)
+{
+    ss << "*** Command name = " << cmd_name << endl;
+    for (int i=0; i<(int)words.size(); i++) {
+        stringstream ss2;
+        words[i].print_type(ss2);
+        ss << words[i].get_string() << " " << ss2.str() << endl;
+    }
+    ss << endl;
+}
+
+
+// ===========================================================================
+// Print all the words on the line mainly for debugging.
+// Output is to a stringstream so the calling method can decide what to do
+// with the output - send it to the screen, use it for testing, whatever.
+// ===========================================================================
+void Cmd::print_using_words(stringstream &ss)
+{
+    for (int i=0; i<(int)words.size(); i++) {
+        bool enc_quote = true;
+        if (i == 0) enc_quote = false;
+        ss << words[i].get_print_string(enc_quote) << " ";
+    }
+}
+
+// ===========================================================================
+// Another version of printing all the words on the line.
+// This version is mainly for printing out the final cmds buffer.
+//
+// The output is formatted, commas are put back in, spaces are handled better,
+// if a line is too long (see nctot_max), it is split into more than one line.
+//
+// For example, suppose the words on a line were
+//     a4d ( 1 1 1 2 ) = -3.4 4.7 5.2 4.6e19
+// spaces are used to delimit the words, but it is not very readable. This
+// routine will print the above line as
+//     a4d(1, 1, 1, 2) = -3.4, 4.7, 5.2, 4.6e19
+// This has the added advantage that spaces can be eliminated and a compact
+// form can be achieved.
+//
+// Another example is the line
+//    strinsert_cmd01 = Use The Force
+// The string "Use The Force" is actually one word, even though it appears to
+// be three words. This routine prints this correctly as
+//    strinsert_cmd01 = "Use The Force"
+// ===========================================================================
+void Cmd::print_using_words_fm(stringstream &ss)
+{
+    //debug_print_words("print_using_words_fm");
+    int nctot_max = 75;
+    int istart = 0;
+    int ieq = -1;
+    int ip1 = -1;
+    int ip2 = -1;
+    for (;;) {
+        if (istart > 0) ss << "     ";
+        int nctot = 0;
+        bool done = false;
+        for (int i=istart; i<(int)words.size(); i++) {
+            bool enc_quote = true;
+            if (i == 0) enc_quote = false;
+            string s = words[i].get_print_string(enc_quote);
+            if (s == "=") ieq = i;
+            if (s == "(") ip1 = i;
+            if (s == ")") ip2 = i;
+            string sp = "";
+            if (i<(int)words.size()-1) {
+                sp = words[i+1].get_print_string(enc_quote);
+            }
+            if (sp == ")") ip2 = i+1;
+            int nc = (int)s.size();
+            if ((i>istart) && (nc+1+nctot > nctot_max)) {
+                istart = i;
+                break;
+            }
+            if (i >= (int)words.size()-1) {
+                done = true;
+                ss << s;
+            }
+            else {
+                string endstr = " ";
+                int endinc = 1;
+                if (ieq > -1) {
+                    if (i > ieq) {
+                        endstr = ", ";
+                        endinc = 2;
+                    }
+                }
+                if (ip1 > -1 && (ip2 == -1 || i < ip2)) {
+                    if (i > ip1 && (ip2 == -1 || i < ip2-1)) {
+                        endstr = ", ";
+                        endinc = 2;
+                    }
+                }                    
+                if (endstr == " ") {
+                    if (s == "(") {
+                        endstr = "";
+                        endinc = 0;
+                    }
+                    if (i == ip2-1) {
+                        endstr = "";
+                        endinc = 0;
+                    }
+                    if (i == 0 && sp == "(") {
+                        endstr = "";
+                        endinc = 0;
+                    }
+                }
+                ss << s << endstr;
+                nctot += nc + endinc;
+            }
+        }
+        if (done) break;
+        ss << endl;
+    }
+}
+
+
+// ===========================================================================
+// Print the original command before processing, mainly for debugging.
+// Output is to a stringstream so the calling method can decide what to do
+// with the output - send it to the screen, use it for testing, whatever.
+// ===========================================================================
+void Cmd::print_original_string(stringstream &ss)
+{
+    ss << original_str;
+}
+
+
+// ===========================================================================
+// This is mainly for debugging this class. It prints on all procs.
+// ===========================================================================
+void Cmd::debug_print_words(string s)
+{
+    cout << s << endl;
+    cout << "    ";
+    for (int i=0; i<(int)words.size(); i++) {
+        bool enc_quote = true;
+        if (i == 0) enc_quote = false;
+        cout << words[i].get_print_string(enc_quote) << " ";
+    }
+    cout << endl;
+}
+
+
+
+
+
+
+} // End of the PP namespace
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Cmd.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Cmd.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,306 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef CMDHHINCLUDE
+#define CMDHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// Generalized command class.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <deque>
+#include <vector>
+#include <map>
+#include <sstream>
+#include "Variable.hh"
+#include "Function.hh"
+
+namespace PP
+{
+using std::string;
+using std::deque;
+using std::vector;
+using std::map;
+using std::stringstream;
+
+//class Variable;
+//class Function;
+
+class Cmd
+{
+public:
+    Cmd();
+    Cmd(string s, map<string, Variable> *v, map<string, Function> *f,
+        deque<string> *lstr, int lnum, int file_lnum, string fname,
+        stringstream &serr, int &ierr);
+
+    void set_index_base(int base);
+    void set_case_sensitive(bool case_sensitive_in);
+
+    void add_word(string str, int lnum, int file_lnum, string fname);
+    void erase_word(int iw);
+    void erase_last_word();
+    void reset_name_type();
+    void delete_words(int i1, int i2);
+    void check_ppmm(stringstream &serr, int &ierr);
+    void remove_commas();
+    void handle_two_words();
+    bool check_input_end(bool kill_run, stringstream &serr, int &ierr);
+    void print_duplicate_line(int iw, stringstream &ss, int fn_width,
+                              int lnum_width, string after_lnum);
+    void get_duplicate_sizes(int iw, int &fn_width, int &lnum_width);
+
+    string get_cmd_filename(stringstream &ssfiles);
+    void handle_quotes(stringstream &serr, int &ierr);
+    void handle_exe_args(string &sout);
+    void deprecated_input01(string action, stringstream &serr, int &ierr);
+    void fatal_error(int iw, stringstream &serr, int &ierr);
+    void warning(int iw, stringstream &serr, int &ierr);
+
+    void get_bool_int(string &cname, int *array_vals, const vector<int> &size,
+                      vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                      int dup_fatal, vector<int> &dup_vals,
+                      bool skip, stringstream &serr, int &ierr);
+
+    void get_bool(string &cname, bool *array_vals, const vector<int> &size,
+                  vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                  int dup_fatal, vector<int> &dup_vals,
+                  bool skip, stringstream &serr, int &ierr);
+
+    void get_int(string &cname, int *array_vals, const vector<int> &size,
+                 vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                 int dup_fatal, vector<int> &dup_vals,
+                 bool skip, stringstream &serr, int &ierr);
+
+    void get_int(string &cname, int64_t *array_vals, const vector<int> &size,
+                 vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                 int dup_fatal, vector<int> &dup_vals,
+                 bool skip, stringstream &serr, int &ierr);
+
+    void get_real(string &cname, double *array_vals, const vector<int> &size,
+                  vector<Cmd *> &dup_cmd1, vector<int> &dup_wdex1,
+                  int dup_fatal, vector<int> &dup_vals,
+                  bool skip, stringstream &serr, int &ierr);
+
+    void get_char(string &cname, vector<string> &vstr, const vector<int> &size,
+                  bool single_char, vector<Cmd *> &dup_cmd1,
+                  vector<int> &dup_wdex1, int dup_fatal,
+                  vector<int> &dup_vals, bool skip,
+                  stringstream &serr, int &ierr);
+
+    void get_size(vector<int> &size, stringstream &serr, int &ierr);
+    void get_sizeb(vector<int> &size, stringstream &serr, int &ierr);
+
+    // Handle unary minus and plus in command lines.
+    void handle_cmd_unary_minus(stringstream &serr, int &ierr);
+    void handle_cmd_unary_plus(stringstream &serr, int &ierr);
+
+    // Handle multiplicity in command lines, i.e. a(1)=15*3.0
+    void handle_cmd_multiplicity(stringstream &serr, int &ierr);
+
+    // Handle variables.
+    bool check_for_dimension(stringstream &serr, int &ierr);
+    bool check_for_var_description(stringstream &serr, int &ierr);
+    void substitute_variables(stringstream &serr, int &ierr);
+    void set_variables(stringstream &serr, int &ierr);
+
+    // Math evaluation.
+    void math_eval(stringstream &serr, int &ierr);
+    void check_misplaced_math(stringstream &serr, int &ierr);
+
+    // Handle comments.
+    void single_line_comments();
+    void multi_line_comments(int &level);
+
+    // Handle processed flags.
+    void clear_processed();
+    void set_processed(bool ip);
+    void check_processed(bool &good, stringstream &serr, int &ierr);
+
+    // If statements.
+    void handle_if(bool &skip, deque<bool> &skip_level,
+                   deque<bool> &satisfied, 
+                   stringstream &serr, int &ierr);
+
+    // Do loops.
+    void handle_do(bool &skip, deque<int> &do_start, int &cdex,
+                   bool &end_do_loop, stringstream &serr, int &ierr);
+    bool find_matching_enddo(int &dlev, bool &stop_checking);
+
+    // Subroutines
+    void handle_subroutines(bool &skip,
+                            bool &go_to_sub, string &sub_name,
+                            bool &go_to_call,
+                            stringstream &serr, int &ierr);
+    bool find_subroutine(string &sub_name);
+    void get_call_args(vector<string> &sargs, vector<bool> &sargs_isvar,
+                       stringstream &serr, int &ierr);
+    void get_sub_args(vector<string> &sargs, vector<bool> &sargs_isvar);
+    void copy_call_args(vector<string> &sargs, vector<bool> &sargs_isvar);
+    void copy_sub_args(vector<string> &sargs, vector<bool> &sargs_isvar);
+
+    // Accessor functions.
+    string get_cmd_name() { return cmd_name; }
+    string get_cmd_type() { return cmd_type; }
+    int get_nwords() { return words.size(); }
+    string get_string(int iw) {
+        if ((int)words.size() <= iw) return "";
+        return words[iw].get_string();
+    }
+    string get_original_str() { return original_str; }
+
+    int get_line_number(int iw) { return words[iw].get_line_number(); }
+    int get_file_line_number(int iw) { return words[iw].get_file_line_number(); }
+    string get_filename(int iw) { return words[iw].get_filename(); }
+    string get_filename() { return filename; }
+    deque<string> *get_lines() { return lines; }
+
+    void set_filename(string fn) {
+        filename = fn;
+        for (int iw=0; iw<(int)words.size(); iw++) {
+            words[iw].set_filename(fn);
+        }
+    }
+
+    bool is_include() { if(words[0].get_string() == "include") return true;
+                        return false; }
+
+    // Debug
+    void print_all_words();
+    void print_all_words(stringstream &ss);
+    void print_using_words(stringstream &ss);
+    void print_using_words_fm(stringstream &ss);
+    void print_original_string(stringstream &ss);
+
+
+private:
+    // Initialization method for this class.
+    void init();
+
+    void process_string(string in_str, stringstream &serr, int &ierr);
+    bool extract_next_word(int &istart, string &str, string &word,
+                           stringstream &serr, int &ierr);
+    int find_closing_symbol(string opensym, string closesym, int i1);
+    bool handle_innermost_parens(int &i1, int &i2, int &iwres, int &nargs,
+                                 bool remp, stringstream &serr, int &ierr);
+    void evaluate_function(int iw1, int &i2, int &nargs,
+                           stringstream &serr, int &ierr);
+    void seval(int &i1, int &i2, stringstream &serr, int &ierr);
+    void handle_unary_op(int i1, int &i2, string utype,
+                         stringstream &serr, int &ierr);
+    void do_unary_op(int ip, string utype);
+    void handle_star_star();  // ** exponentiation
+    void handle_ops();
+
+    void subvar_w0(int i1, int &i2, stringstream &serr, int &ierr);
+    void subvar0(int vardex, string &varname, int increment,
+                 stringstream &serr, int &ierr);
+    bool evaluate_variable(int iw1, int &i2, int &nargs,
+                           stringstream &serr, int &ierr);
+
+    int find(int i1, int i2, string s);
+    int find_last(string s, int i1, int i2);
+    int find_any_char(int i1, int i2, string s);
+    void replace_words(int i1, int i2, Word &w);
+    void replace_words(int i1, int i2, vector<Word> &vw);
+    void merge_words(int i1, int i2);
+    bool separate_str(string &subs, string &fstr, vector<string> &vs);
+    int find_equals();
+
+    bool check_syntax(vector<int> &istart, stringstream &serr, int &ierr);
+    bool get_nvals(vector<int> &istart, const vector<int> &size,
+                   int &nvals, stringstream &serr, int &ierr);
+    void debug_print_words(string s);
+
+    void fatal_error2(stringstream &serr, int &ierr);
+    void error_dup_line(string &cname, int wdex, int cdex,
+                        vector<int> &dup_wdex1, vector<Cmd *> &dup_cmd1,
+                        vector<int> &dup_vals, const vector<int> &size,
+                        int dup_fatal, stringstream &serr, int &ierr);
+
+
+    // This is needed for telling the user what line in the input
+    // file or include file the error occurred on.
+    //
+    // line_number  The line_number corresponding to this command, this is
+    //              an index into lines and starts from 1, not 0.
+    // lines        Pointer to the deque of original lines. This contains all
+    //              the lines from the input file and any include files.
+    // file_line_number  The line number in the input file or include file.
+    // filename          The name of the input file or include file.
+    //
+    // file_line_number and filename are needed to that the user can open
+    // the file and go to the line in error.
+    int line_number, file_line_number;
+    string filename;
+    deque<string> *lines;
+    
+    // index base, generally 1 for Fortran style and 0 for C/C++, default 1
+    // int index_base; -- using static variable instead
+
+    // The original string before processing.
+    string original_str;
+
+    // Pointer to the map of variables.
+    map<string, Variable> *vmap;
+
+    // Pointer to the map of functions.
+    map<string, Function> *fmap;
+
+    // Definitions of white space, delimiters, etc.
+    string white_space;
+    string delims;
+
+    // Storage for all the words on the line.
+    deque <Word> words;
+
+    // The name and type of the command.
+    string cmd_name;
+    string cmd_type;
+
+    // Used for subroutines.
+    vector<string> call_args, sub_args;
+    vector<bool> call_args_isvar, sub_args_isvar;
+};
+
+
+} // end of PP namespace
+
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Comm.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,117 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#include <cstdlib>
+#include <assert.h>
+#include "Comm.hh"
+
+namespace PP {
+
+
+// ===========================================================================
+// Constructor
+// ===========================================================================
+Comm::Comm()
+{
+    npes = 1;
+    mype = 0;
+    iope = 0;
+
+#ifdef HAVE_MPI
+    int argc = 1;
+    char **argv = NULL;
+
+    int init_check;
+    MPI_Initialized(&init_check);
+    //printf("DEBUG -- mpi initialized %d\n",init_check);
+
+    init_flag = 0;
+    if (! init_check) {
+       // Only way for init_flag to be true is here; must be false otherwise
+       init_flag = 1;
+       MPI_Init(&argc, &argv);
+    }
+    //printf("DEBUG -- comm constructor -- init_flag %d\n",init_flag);
+
+    MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
+    MPI_Comm_size(MPI_COMM_WORLD, &npes );
+    MPI_Comm_rank(MPI_COMM_WORLD, &mype );
+#endif
+}
+
+// ===========================================================================
+// Destructor
+// ===========================================================================
+Comm::~Comm()
+{
+   //printf("DEBUG -- comm destructor -- init_flag %d\n",init_flag);
+#ifdef HAVE_MPI
+   if (init_flag) {
+      init_flag = 0;
+      MPI_Finalize();
+   }
+#endif
+}
+
+// ===========================================================================
+// Broadcast
+// ===========================================================================
+void Comm::broadcast(char *buffer, int count)
+{
+   // To suppress compiler warnings of unused parameters
+   assert(buffer == buffer);
+   assert(count == count);
+
+   if (npes == 1) return;
+#ifdef HAVE_MPI
+   MPI_Bcast(buffer, count, MPI_CHAR, 0, MPI_COMM_WORLD);
+#endif
+}
+
+// ===========================================================================
+// Error handling
+// ===========================================================================
+void Comm::global_abort_parser()
+{
+#ifdef HAVE_MPI
+   MPI_Abort(MPI_COMM_WORLD, 1);
+#endif
+   exit(1);
+}
+// ===========================================================================
+} // End of PP namespace
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Comm.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Comm.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,93 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef COMMHHINCLUDE
+#define COMMHHINCLUDE
+
+#ifdef __MPI__
+#define HAVE_MPI
+#endif
+
+#ifdef HAVE_MPI
+#define MPI_NO_CPPBIND
+#include "mpi.h"
+#endif
+
+namespace PP {
+
+class Comm
+{
+ public:
+
+    Comm();
+    ~Comm();
+
+    void broadcast(char *buffer, int count);
+    void global_abort_parser();
+
+    int getProcRank(void) const {
+        return(mype);
+    }
+
+    int getNumProcs(void) const {
+        return(npes);
+    }
+
+    int getIORank(void) const {
+        return(iope);
+    }
+
+    bool isIOProc(void) const {
+        if (mype == iope) return true;
+        return false;
+    }
+
+
+ private:
+    int init_flag;
+
+    int npes, mype, iope;
+
+    //Comm(const Comm&);
+    //Comm& operator=(const Comm&);
+};
+
+
+} // End of PP namespace
+
+#endif
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Function.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,324 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds information about a function. It is mostly for use with
+// the parser.
+// ***************************************************************************
+// ***************************************************************************
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+#include <cctype>
+#include <cmath>
+
+#include "stdio.h"
+#include "stdlib.h"
+
+#include "Function.hh"
+
+namespace PP
+{
+using std:: string;
+using std::cout;
+using std::endl;
+using std::deque;
+using std::stringstream;
+using std::setprecision;
+using std::vector;
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Function::Function()
+{
+   name = "__NO_NAME_GIVEN__";
+   external = true;
+   nargs = 1;
+   description = " ";
+   type = "real";
+}
+
+
+// ===========================================================================
+// Most used constructor for functions.
+// ===========================================================================
+Function::Function(string nme, bool ext, int na, string ftype, string fdes)
+{
+   name = nme;
+   external = ext;
+   nargs = na;
+   description = fdes;
+   type = ftype;
+}
+
+
+// ===========================================================================
+// Evaluate the function. This is for the case that the arguments all have
+// values (double type values) and the function can be evaluated to a double.
+// ===========================================================================
+double Function::evaluate(vector<double> &vd, stringstream &serr, int &ierr,
+                          int line_number, int file_line_number,
+                          string filename, deque<string> *lines)
+{
+    // Verify that the number of args needed is equal to the number of args
+    // supplied.
+    int nvd = (int)vd.size();
+    if (nvd != nargs) {
+        args_mismatch_err(nvd, nargs, serr, ierr, line_number,
+                          file_line_number, filename, lines);
+        return 0.;
+    }
+
+    // Functions with one argument.
+    if (nargs == 1) {
+        double d = vd[0];
+        if (name == "acos") {
+            if (d < -1. || d > 1.) {
+                serr << endl;
+                serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+                serr << "    " << (*lines)[line_number-1] << endl;
+                serr << "in file: " << filename << endl;
+                serr << "Argument to acos is out of bounds." << endl;
+                serr << "Argument = " << d << endl;
+                serr << "This must be between -1. and 1." << endl;
+                ierr = 2;
+                return 0.;
+            }
+            return acos(d);
+        }
+
+        if (name == "asin") {
+            if (d < -1. || d > 1.) {
+                serr << endl;
+                serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+                serr << "    " << (*lines)[line_number-1] << endl;
+                serr << "in file: " << filename << endl;
+                serr << "Argument to asin is out of bounds." << endl;
+                serr << "Argument = " << d << endl;
+                serr << "This must be between -1. and 1." << endl;
+                ierr = 2;
+                return 0.;
+            }
+            return asin(d);
+        }
+
+        if (name == "atan")  return atan(d);
+        if (name == "ceil")  return ceil(d);
+        if (name == "cos")   return cos(d);
+        if (name == "cosh")  return cosh(d);
+        if (name == "exp")   return exp(d);
+        if (name == "fabs")  return fabs(d);
+        if (name == "floor") return floor(d);
+        if (name == "log")   return log(d);
+        if (name == "log10") return log10(d);
+        if (name == "sin")   return sin(d);
+        if (name == "sinh")  return sinh(d);
+        if (name == "sqrt")  return sqrt(d);
+        if (name == "tan")   return tan(d);
+        if (name == "tanh")  return tanh(d);
+    }
+
+    // Functions with two arguments.
+    if (nargs == 2) {
+        double d1 = vd[0];
+        double d2 = vd[1];
+
+        if (name == "atan2") return atan2(d1, d2);
+        if (name == "fmod") return fmod(d1, d2);
+
+        if (name == "max") {
+            double result = d2;
+            if (d1 > d2) result = d1;
+            return result;
+        }
+
+        if (name == "min") {
+            double result = d2;
+            if (d1 < d2) result = d1;
+            return result;
+        }
+
+        if (name == "pow") {
+            if (d1 <= 0.) {
+                serr << endl;
+                serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+                serr << "    " << (*lines)[line_number-1] << endl;
+                serr << "in file: " << filename << endl;
+                serr << "First argument (base) to pow is out of bounds." << endl;
+                serr << "Argument = " << d1 << endl;
+                serr << "This must be greater than 0." << endl;
+                ierr = 2;
+                return 0.;
+            }
+            return pow(d1, d2);
+        }
+    }
+
+
+    // If we get down to this point, then the name supplied at
+    // construction was not recognized as a function name.
+    // This should never happen because we check for a valid function
+    // name before entering this function.
+    name_err(serr, ierr, line_number, file_line_number, filename, lines);
+    return 0.;
+}
+
+
+// ===========================================================================
+// Evaluate the function. This is for string functions.
+// ===========================================================================
+string Function::evaluate(vector<string> &vs, stringstream &serr, int &ierr,
+                          int line_number, int file_line_number,
+                          string filename, deque<string> *lines)
+{
+    // Verify that the number of args needed is equal to the number of args
+    // supplied.
+    int nvs = (int)vs.size();
+    if (nvs != nargs) {
+        args_mismatch_err(nvs, nargs, serr, ierr, line_number,
+                          file_line_number, filename, lines);
+        return "";
+    }
+
+    // Functions with one argument.
+    if (nargs == 1) {
+        string s1 = vs[0];
+        if (name == "strlen") {
+            int len = (int)s1.size();
+            stringstream ss;
+            ss << len;
+            return ss.str();
+        }
+
+        if (name == "strtrim") {
+            int len = (int)s1.size();
+            if (len == 0) return s1;
+            string whitespace = " \t";
+            int iend = s1.find_last_not_of(whitespace, len - 1);
+            int NPOS = (int)string::npos;
+            if (iend == NPOS) return s1;
+            s1.erase(iend+1, (len-1) -(iend+1) + 1);
+            return s1;
+        }
+    }
+
+    // Functions with two arguments.
+    if (nargs == 2) {
+        string s1 = vs[0];
+        string s2 = vs[1];
+        if (name == "strcat") {
+            return s1+s2;
+        }
+    }
+
+    // Functions with three arguments.
+    if (nargs == 3) {
+        string s1 = vs[0];
+        string s2 = vs[1];
+        string s3 = vs[2];
+        if (name == "strerase") {
+            int i1 = atoi(s2.c_str()) - 1;   // minus 1 to get c index
+            int i2 = atoi(s3.c_str()) - 1;
+            s1.erase(i1, i2-i1+1);
+            return s1;
+        }
+
+        if (name == "strinsert") {
+            int i1 = atoi(s2.c_str()) - 1;   // minus 1 to get c index
+            s1.insert(i1, s3);
+            return s1;
+        }
+
+        if (name == "strsubstr") {
+            int i1 = atoi(s2.c_str()) - 1;     // minus 1 to get c index
+            int nchar = atoi(s3.c_str()); 
+            string sret = s1.substr(i1, nchar);
+            return sret;
+        }
+    }
+
+    // If we get down to this point, then the name supplied at
+    // construction was not recognized as a function name.
+    // This should never happen because we check for a valid function
+    // name before entering this function.
+    name_err(serr, ierr, line_number, file_line_number, filename, lines);
+    return "";
+}
+
+
+// ===========================================================================
+// Name not recognized error.
+// ===========================================================================
+void Function::name_err(stringstream &serr, int &ierr,
+                        int line_number, int file_line_number,
+                        string filename, deque<string> *lines)
+{
+    serr << endl;
+    serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+    serr << "    " << (*lines)[line_number-1] << endl;
+    serr << "in file: " << filename << endl;
+    serr << "** Math function fatal error **" << endl;
+    serr << "Name not recognized as a function." << endl;
+    serr << "Name = " << name << endl;
+    ierr = 2;
+}
+
+
+// ===========================================================================
+// Number of args mismatch error.
+// ===========================================================================
+void Function::args_mismatch_err(int nargs_found, int nargs_expected,
+                                 stringstream &serr, int &ierr,
+                                 int line_number, int file_line_number,
+                                 string filename, deque<string> *lines)
+{
+    serr << endl;
+    serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+    serr << "    " << (*lines)[line_number-1] << endl;
+    serr << "in file: " << filename << endl;
+    serr << "For function " << name << endl;
+    serr << "Number of args expected = " << nargs_expected << endl;
+    serr << "Number of args found = " << nargs_found << endl;
+    ierr = 2;
+}
+
+} // End of the PP namespace

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Function.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Function.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,120 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef FUNCTIONHHINCLUDE
+#define FUNCTIONHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds information about a function. It is mostly for use with
+// the parser.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+
+namespace PP
+{
+using std::string;
+using std::deque;
+using std::stringstream;
+using std::vector;
+
+enum FuncType {FUNC_};
+
+//class ErrorState;
+
+class Function
+{
+
+public:
+    Function();
+    Function(string nme, bool ext, int na, string ftype,  string fdes);
+
+    // Evaluate the function.
+    double evaluate(vector<double> &vd, stringstream &serr, int &ierr,
+                    int line_number, int file_line_number,
+                    string filename, deque<string> *lines);
+
+    string evaluate(vector<string> &vs, stringstream &serr, int &ierr,
+                    int line_number, int file_line_number,
+                    string filename, deque<string> *lines);
+
+    // Accessor methods.
+    string get_name()        { return name; }
+    int    get_num_args()    { return nargs; }
+    string get_description() { return description; }
+    string get_type()        { return type; }
+
+private:
+
+    void name_err(stringstream &serr, int &ierr,
+                  int line_number, int file_line_number,
+                  string filename, deque<string> *lines);
+
+    void args_mismatch_err(int nargs_found, int nargs_expected,
+                           stringstream &serr, int &ierr,
+                           int line_number, int file_line_number,
+                           string filename, deque<string> *lines);
+
+    // The name of the function.
+    string name;
+
+    // Whether the function is external or internal. External functions
+    // are C++ functions like sin(), log(), ... Internal functions
+    // are defined within the input to the parser (this feature is not
+    // implemented yet).
+    bool external;
+
+    // The number of arguments for the function.
+    int nargs;
+
+    // A text description of the function.
+    string description;
+
+    // The type of function. Allowed types are:
+    //     real    double arguments, double result (cos, sin, log, ...)
+    //     string  string arguments, string results (strlen, strcat, ...)
+    string type;
+};
+
+
+} // End of the PP namespace
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Globals.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Globals.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Globals.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Globals.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ *           Other LANL authors
+ * 
+ */
+#ifndef _Globals_
+#define _Globals_
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+   
+//#define NDEBUG 1
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define ENTITY_COINCIDENCE_TOLERANCE      ((double)1.0E-5)
+
+#define KDTREE_ELEMENT_BLOCKING_SIZE      ((long)1024)
+
+#define POSITIVE_INFINITY (+1.0E+64)
+#define NEGATIVE_INFINITY (-1.0E+64)
+
+#define XAXIS ((unsigned long)0)
+#define YAXIS ((unsigned long)1)
+
+typedef struct {
+   double x, y;
+} TVector;
+
+//#ifndef _BOOL
+//typedef unsigned char boolean;
+//#define true  ((boolean)1)
+//#define false ((boolean)0)
+//#endif
+
+#ifndef SWAP
+#define SWAP(a,b,t) {t h; h = a; a = b; b = h; }
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+   
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/KDTree.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,712 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ *           Other LANL authors
+ * 
+ */
+#include <math.h>
+#include "KDTree.h"
+
+#define MALLOC(n,t) ((t*)(malloc(n * sizeof(t))))
+#define REALLOC(p,n,t) ((t*)(realloc((void*)p, n * sizeof(t))))
+#define FREE(p) { if (p) free(p); }
+
+static void median_sort(TKDTree* t,
+                        unsigned int cut_direction, int k, int num, int* idx)
+{
+   int left, mid, right, a, i, j;
+   
+   for (left = 0, right = num - 1; (right - left) > 1;) {
+      mid = (left + right) / 2;
+      SWAP(idx[mid], idx[left + 1], int);
+      if(Bounds_CenterAxis(&(t->elements[idx[left + 1]]), cut_direction) >
+         Bounds_CenterAxis(&(t->elements[idx[right]]), cut_direction))
+         SWAP(idx[left + 1], idx[right], int);
+      if(Bounds_CenterAxis(&(t->elements[idx[left]]), cut_direction) >
+         Bounds_CenterAxis(&(t->elements[idx[right]]), cut_direction))
+         SWAP(idx[left], idx[right], int);
+      if(Bounds_CenterAxis(&(t->elements[idx[left + 1]]), cut_direction) >
+         Bounds_CenterAxis(&(t->elements[idx[left]]), cut_direction))
+         SWAP(idx[left + 1], idx[left], int);
+      a = idx[left];
+      i = left + 1;
+      j = right;
+      while (1) {
+         for (i++;
+              Bounds_CenterAxis(&(t->elements[idx[i]]), cut_direction) <
+                Bounds_CenterAxis(&(t->elements[a]), cut_direction);
+              i++);
+         for (j--;
+              Bounds_CenterAxis(&(t->elements[idx[j]]), cut_direction) >
+              Bounds_CenterAxis(&(t->elements[a]), cut_direction);
+              j--);
+         if(j < i)
+            break;
+         SWAP(idx[i], idx[j], int);
+      }
+      idx[left] = idx[j];
+      idx[j] = a;
+      if(j >= k)
+         right = j - 1;
+      if(j <= k)
+         left = i;
+   }
+   if(((right - left) ==1) &&
+      (Bounds_CenterAxis(&(t->elements[idx[right]]), cut_direction) <
+       Bounds_CenterAxis(&(t->elements[idx[left]]), cut_direction)))
+      SWAP(idx[right], idx[left], int);
+}
+
+void KDTree_Initialize(TKDTree* t)
+{
+   assert(t);
+   /* Flush the overall tree extent */
+   Bounds_Infinite(&(t->extent));
+   /* Allocate the initial memory for tree elements */
+   t->elements_num = 0;
+   t->elements_allocated = KDTREE_ELEMENT_BLOCKING_SIZE;
+   t->elements = MALLOC(t->elements_allocated, TBounds);
+   assert(t->elements);
+   /* Start without a built tree */
+   t->tree_built = false;
+   t->tree_size = 0;
+   t->tree_safety_boxes = NULL;
+   t->tree_link = NULL;
+}
+
+void KDTree_Finalize(TKDTree* t)
+{
+   free(t->elements);
+}
+
+void KDTree_Destroy(TKDTree* t)
+{
+   assert(t);
+   /* Flush the overall tree extent */
+   Bounds_Infinite(&(t->extent));
+   /* Destroy the element list */
+   t->elements_num = 0;
+   t->elements_allocated = 0;
+   FREE(t->elements);
+   t->elements = NULL;
+   /* Destroy the actual tree */
+   t->tree_built = false;
+   t->tree_size = 0;
+   FREE(t->tree_safety_boxes);
+   t->tree_safety_boxes = NULL;
+   FREE(t->tree_link);
+   t->tree_link = NULL;
+}
+
+
+
+void KDTree_AddElement(TKDTree* t, TBounds* add)
+{
+   assert(t && add);
+   /* Destroy the current tree if it is built */
+   if(t->tree_built) {
+      t->tree_built = false;
+      t->tree_size = 0;
+      FREE(t->tree_safety_boxes);
+      t->tree_safety_boxes = NULL;
+      FREE(t->tree_link);
+      t->tree_link = NULL;
+   }
+   /* Expand the element array if necessary */
+   if(t->elements_num == t->elements_allocated) {
+      t->elements_allocated += KDTREE_ELEMENT_BLOCKING_SIZE;
+      t->elements = REALLOC(t->elements, t->elements_allocated, TBounds);
+      assert(t->elements);
+   }
+   /* Add the new element to the overall extent and the element list */
+   Bounds_AddBounds(&(t->extent), add);
+   Bounds_Copy(add, &(t->elements[t->elements_num]));
+   t->elements_num++;
+}
+
+void KDTree_CreateTree(TKDTree* t)
+{
+   unsigned int i;
+   int next_node, stack_ptr, min, mid, max, parent, cut_direction;
+   double width, max_width;
+   int* stack;
+   int* idx;
+   
+   assert(t);
+   /* If the tree is already built, we don't have to do anything */
+   if(t->tree_built)
+      return;
+   /* If there are no elements in the tree, we don't have to do anything */
+   if(t->elements_num > 0) {
+      /* Allocate the k-D tree memory */
+      t->tree_size = 2 * t->elements_num;
+      t->tree_safety_boxes = MALLOC(t->tree_size, TBounds);
+      t->tree_link = MALLOC(t->tree_size, int);
+      /* Create and initialize temporary arrays */
+      next_node = 0;
+      stack_ptr = 0;
+      stack = MALLOC(3 * t->tree_size, int);
+      idx = MALLOC(t->elements_num, int);
+      for (i = 0; (int)i <  t->elements_num; i++) {
+         idx[i] = i;
+      }
+      /* Setup the root node of the tree and put it on the stack */
+      stack[stack_ptr++] = 0;                   /* Node Number in the Tree */
+      stack[stack_ptr++] = 0;                   /* Element Span Minumum */
+      stack[stack_ptr++] = t->elements_num - 1; /* Element Span Maximum */
+      Bounds_Copy(&(t->extent), &(t->tree_safety_boxes[0]));
+      next_node++;
+      /* Construct k-D tree by setting up each pair of child nodes */
+      while (stack_ptr) {
+         /* Pop the top entry off the stack */
+         max = stack[--stack_ptr];
+         min = stack[--stack_ptr];
+         parent = stack[--stack_ptr];
+         /* If the current node should be a leaf node, make it one */
+         if ((max - min) == 0) {
+            Bounds_Copy(&(t->elements[idx[min]]), &(t->tree_safety_boxes[parent]));
+            t->tree_link[parent] = - idx[min];
+            continue;
+         }
+         /* Select optimum cutting direction for the parent node's safety box */
+         cut_direction = -1;
+         max_width = NEGATIVE_INFINITY;
+         for (i = 0; i < 2; i++) {
+            width = Bounds_WidthAxis(&(t->tree_safety_boxes[parent]), i);
+            if(width > max_width) {
+               max_width = width;
+               cut_direction = i;
+            }
+         }
+         assert(cut_direction >= 0);
+         /* Do a median sort of the elements under the parent node. The sort key
+            is the center point of the element bounding boxes along the selected
+            cutting direction. */
+         mid = (min + max) /2;
+         median_sort(t, (unsigned int)cut_direction, mid - min, max - min + 1, &(idx[min]));
+         /* Give the parent a reference to its two children */
+         t->tree_link[parent] = next_node;
+         /* Add the "left" child to the tree and the stack */
+         stack[stack_ptr++] = next_node;  /* Node Number in the Tree */
+         stack[stack_ptr++] = min;        /* Element Span Minimum */
+         stack[stack_ptr++] = mid;        /* Element Span Maximum */
+         Bounds_Infinite(&(t->tree_safety_boxes[next_node]));
+         for (i = min; (int)i <= mid; i++) {
+            Bounds_AddBounds(&(t->tree_safety_boxes[next_node]),
+                             &(t->elements[idx[i]]));
+         }
+         next_node++;
+         /* Add the "right" child to the tree and the stack */
+         stack[stack_ptr++] = next_node;  /* Node Number in the Tree */
+         stack[stack_ptr++] = mid + 1;    /* Element Span Minimum */
+         stack[stack_ptr++] = max;        /* Element Span Maximum */
+         Bounds_Infinite(&(t->tree_safety_boxes[next_node]));
+         for (i = min + 1; (int)i <= max; i++) {
+            Bounds_AddBounds(&(t->tree_safety_boxes[next_node]),
+                             &(t->elements[idx[i]]));
+         }
+         next_node++;
+      }
+      /* Destroy the temporary arrays */
+      FREE(stack);
+      FREE(idx);
+   }
+   /* Mark the tree "built" */
+   t->tree_built = true;
+}
+
+void KDTree_QueryBoxIntersect(TKDTree* t,
+                              int* result_num, int* result_indicies,
+                              TBounds* box)
+{
+   int stack_ptr, node;
+   TBounds sb;
+   int* stack;
+   
+   assert(t && result_num && result_indicies && box);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   /* Allocate the results array */
+   *result_num = 0;
+   /* Create the temporary stack array */
+   stack_ptr = 0;
+   stack = MALLOC(t->tree_size, int);
+   
+   /* Put the root node of the tree onto the stack */
+   stack[stack_ptr++] = 0;
+   /* Search the k-D tree until the stack is empty */
+   
+   while (stack_ptr) {
+      /* Pop the top entry off the stack */
+      node = stack[--stack_ptr];
+      /* Check if the query box intersects an epsilon-expanded safety box for
+         the current node. */
+      Bounds_Copy(&(t->tree_safety_boxes[node]), &sb);
+      //Bounds_AddEpsilon(&sb, ENTITY_COINCIDENCE_TOLERANCE);
+      /* If the query box doesn't intersect this node's safety box, we are done
+         visiting the node and should continue with the next node */
+      if(!Bounds_IsOverlappingBounds(&sb, box))
+         continue;
+      /* If the current node is a leaf node, add it to the collision list. If
+         the current node is an interior node, add its children to the stack. */
+      if(t->tree_link[node] <= 0) {
+         result_indicies[*result_num] = - t->tree_link[node];
+         (*result_num)++;
+      }
+      else {
+         stack[stack_ptr++] = t->tree_link[node];
+         stack[stack_ptr++] = t->tree_link[node] + 1;
+      }
+   }
+   /* Destroy the temporary stack array */
+   FREE(stack);
+}
+
+void KDTree_QueryCircleIntersect_Double(TKDTree* t,
+                                 int* result_num, int* result_indicies,
+                                 double circ_radius, int ncells, 
+                                 double *x, double *dx, double *y, double *dy)
+{
+   assert(t && result_num && result_indicies && circ_radius);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   
+   int nez;
+   int *ind=(int *)malloc(ncells*sizeof(int));
+   
+   TBounds box;
+   box.min.x = -circ_radius;
+   box.max.x =  circ_radius;
+   box.min.y = -circ_radius;
+   box.max.y =  circ_radius;
+   KDTree_QueryBoxIntersect(t, &nez, ind, &box);
+   
+   //for (int ic=0; ic<nez; ic++) {
+   //   printf("box is ind[%d]=%d\n",ic,ind[ic]);
+   //}
+   
+   /* Allocate the results array */
+   *result_num = 0;
+
+   double rad1, rad2, rad3, rad4;
+   int ii;
+   for (int i=0; i<nez; ++i){
+      ii = ind[i];
+      rad1 = sqrt( pow(x[ii],       2.0) + pow(y[ii],       2.0) );
+      rad2 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii],       2.0) );
+      rad3 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii]+dy[ii],2.0) );
+      rad4 = sqrt( pow(x[ii]       ,2.0) + pow(y[ii]+dy[ii],2.0) );
+      
+      if ((circ_radius < rad1 && circ_radius > rad2 ) ||
+          (circ_radius > rad1 && circ_radius < rad2 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      } else if ((circ_radius < rad2 && circ_radius > rad3 ) ||
+          (circ_radius > rad2 && circ_radius < rad3 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      } else if ((circ_radius < rad3 && circ_radius > rad4 ) ||
+          (circ_radius > rad3 && circ_radius < rad4 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      } else if ((circ_radius < rad4 && circ_radius > rad1 ) ||
+          (circ_radius > rad4 && circ_radius < rad1 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      }
+   } // for  
+   free(ind);
+}
+
+void KDTree_QueryCircleIntersect_Float(TKDTree* t,
+                                 int* result_num, int* result_indicies,
+                                 double circ_radius, int ncells, 
+                                 float *x, float *dx, float *y, float *dy)
+{
+   assert(t && result_num && result_indicies && circ_radius);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   
+   int nez;
+   int *ind=(int *)malloc(ncells*sizeof(int));
+   
+   TBounds box;
+   box.min.x = -circ_radius;
+   box.max.x =  circ_radius;
+   box.min.y = -circ_radius;
+   box.max.y =  circ_radius;
+   KDTree_QueryBoxIntersect(t, &nez, ind, &box);
+   
+   //for (int ic=0; ic<nez; ic++) {
+   //   printf("box is ind[%d]=%d\n",ic,ind[ic]);
+   //}
+   
+   /* Allocate the results array */
+   *result_num = 0;
+
+   double rad1, rad2, rad3, rad4;
+   int ii;
+   for (int i=0; i<nez; ++i){
+      ii = ind[i];
+      rad1 = sqrt( pow(x[ii],       2.0) + pow(y[ii],       2.0) );
+      rad2 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii],       2.0) );
+      rad3 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii]+dy[ii],2.0) );
+      rad4 = sqrt( pow(x[ii]       ,2.0) + pow(y[ii]+dy[ii],2.0) );
+      
+      if ((circ_radius < rad1 && circ_radius > rad2 ) ||
+          (circ_radius > rad1 && circ_radius < rad2 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      } else if ((circ_radius < rad2 && circ_radius > rad3 ) ||
+          (circ_radius > rad2 && circ_radius < rad3 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      } else if ((circ_radius < rad3 && circ_radius > rad4 ) ||
+          (circ_radius > rad3 && circ_radius < rad4 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      } else if ((circ_radius < rad4 && circ_radius > rad1 ) ||
+          (circ_radius > rad4 && circ_radius < rad1 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      }
+   } // for  
+   free(ind);
+}
+
+void KDTree_QueryCircleIntersectWeighted_Double(TKDTree* t,
+                                 int* result_num, int* result_indicies, double *weight,
+                                 double circ_radius, int ncells, 
+                                 double *x, double *dx, double *y, double *dy)
+{
+   assert(t && result_num && result_indicies && circ_radius);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   
+   int nez;
+   int *ind=(int *)malloc(ncells*sizeof(int));
+   
+   TBounds box;
+   box.min.x = -circ_radius;
+   box.max.x =  circ_radius;
+   box.min.y = -circ_radius;
+   box.max.y =  circ_radius;
+   KDTree_QueryBoxIntersect(t, &nez, ind, &box);
+   
+   //for (int ic=0; ic<nez; ic++) {
+   //   printf("box is ind[%d]=%d\n",ic,ind[ic]);
+   //}
+   
+   /* Allocate the results array */
+   *result_num = 0;
+   
+   double rad1, rad2, rad3, rad4;
+   int cuts_bottom, cuts_top, cuts_left, cuts_right;
+   int vertical_half, horizontal_half;
+   int ii;
+   for (int i=0; i<nez; ++i){
+      ii = ind[i];
+      rad1 = sqrt( pow(x[ii],       2.0) + pow(y[ii],       2.0) );
+      rad2 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii],       2.0) );
+      rad3 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii]+dy[ii],2.0) );
+      rad4 = sqrt( pow(x[ii]       ,2.0) + pow(y[ii]+dy[ii],2.0) );
+      
+      cuts_bottom=0;
+      cuts_top=0;
+      cuts_left=0;
+      cuts_right=0;
+      if ((circ_radius < rad1 && circ_radius > rad2 ) ||
+          (circ_radius > rad1 && circ_radius < rad2 ) ) {
+         cuts_bottom=1;
+      }
+      if ((circ_radius < rad2 && circ_radius > rad3 ) ||
+          (circ_radius > rad2 && circ_radius < rad3 ) ) {
+         cuts_right=1;
+      }
+      if ((circ_radius < rad3 && circ_radius > rad4 ) ||
+          (circ_radius > rad3 && circ_radius < rad4 ) ) {
+         cuts_top=1;
+      }
+      if ((circ_radius < rad4 && circ_radius > rad1 ) ||
+          (circ_radius > rad4 && circ_radius < rad1 ) ) {
+         cuts_left=1;
+      }
+      
+      horizontal_half=0;
+      vertical_half=0;
+      if (x[ii]+0.5*dx[ii] > 0.0) horizontal_half = RIGHT_HALF;
+      if (y[ii]+0.5*dy[ii] > 0.0) vertical_half   = TOP_HALF;
+      
+      
+      if        (horizontal_half == RIGHT_HALF && vertical_half == TOP_HALF) { /* quadrant 1 */
+         weight[*result_num] = (circ_radius - rad1)/(rad3-rad1);
+      } else if (horizontal_half == LEFT_HALF  && vertical_half == TOP_HALF) { /* quadrant 2 */
+         weight[*result_num] = (circ_radius - rad2)/(rad4-rad2);
+      } else if (horizontal_half == LEFT_HALF  && vertical_half == BOTTOM_HALF) { /* quadrant 3 */
+         weight[*result_num] = (circ_radius - rad3)/(rad1-rad3);
+      } else if (horizontal_half == RIGHT_HALF && vertical_half == BOTTOM_HALF) { /* quadrant 4 */
+         weight[*result_num] = (circ_radius - rad4)/(rad2-rad4);
+      } else {
+         weight[*result_num] = 0.5;
+      }
+      if (cuts_bottom || cuts_top || cuts_left || cuts_right) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      }
+
+   } // for  
+   free(ind);
+}
+
+void KDTree_QueryCircleIntersectWeighted_Float(TKDTree* t,
+                                 int* result_num, int* result_indicies, double *weight,
+                                 double circ_radius, int ncells, 
+                                 float *x, float *dx, float *y, float *dy)
+{
+   assert(t && result_num && result_indicies && circ_radius);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   
+   int nez;
+   int *ind=(int *)malloc(ncells*sizeof(int));
+   
+   TBounds box;
+   box.min.x = -circ_radius;
+   box.max.x =  circ_radius;
+   box.min.y = -circ_radius;
+   box.max.y =  circ_radius;
+   KDTree_QueryBoxIntersect(t, &nez, ind, &box);
+   
+   //for (int ic=0; ic<nez; ic++) {
+   //   printf("box is ind[%d]=%d\n",ic,ind[ic]);
+   //}
+   
+   /* Allocate the results array */
+   *result_num = 0;
+   
+   double rad1, rad2, rad3, rad4;
+   int cuts_bottom, cuts_top, cuts_left, cuts_right;
+   int vertical_half, horizontal_half;
+   int ii;
+   for (int i=0; i<nez; ++i){
+      ii = ind[i];
+      rad1 = sqrt( pow(x[ii],       2.0) + pow(y[ii],       2.0) );
+      rad2 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii],       2.0) );
+      rad3 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii]+dy[ii],2.0) );
+      rad4 = sqrt( pow(x[ii]       ,2.0) + pow(y[ii]+dy[ii],2.0) );
+      
+      cuts_bottom=0;
+      cuts_top=0;
+      cuts_left=0;
+      cuts_right=0;
+      if ((circ_radius < rad1 && circ_radius > rad2 ) ||
+          (circ_radius > rad1 && circ_radius < rad2 ) ) {
+         cuts_bottom=1;
+      }
+      if ((circ_radius < rad2 && circ_radius > rad3 ) ||
+          (circ_radius > rad2 && circ_radius < rad3 ) ) {
+         cuts_right=1;
+      }
+      if ((circ_radius < rad3 && circ_radius > rad4 ) ||
+          (circ_radius > rad3 && circ_radius < rad4 ) ) {
+         cuts_top=1;
+      }
+      if ((circ_radius < rad4 && circ_radius > rad1 ) ||
+          (circ_radius > rad4 && circ_radius < rad1 ) ) {
+         cuts_left=1;
+      }
+      
+      horizontal_half=0;
+      vertical_half=0;
+      if (x[ii]+0.5*dx[ii] > 0.0) horizontal_half = RIGHT_HALF;
+      if (y[ii]+0.5*dy[ii] > 0.0) vertical_half   = TOP_HALF;
+      
+      
+      if        (horizontal_half == RIGHT_HALF && vertical_half == TOP_HALF) { /* quadrant 1 */
+         weight[*result_num] = (circ_radius - rad1)/(rad3-rad1);
+      } else if (horizontal_half == LEFT_HALF  && vertical_half == TOP_HALF) { /* quadrant 2 */
+         weight[*result_num] = (circ_radius - rad2)/(rad4-rad2);
+      } else if (horizontal_half == LEFT_HALF  && vertical_half == BOTTOM_HALF) { /* quadrant 3 */
+         weight[*result_num] = (circ_radius - rad3)/(rad1-rad3);
+      } else if (horizontal_half == RIGHT_HALF && vertical_half == BOTTOM_HALF) { /* quadrant 4 */
+         weight[*result_num] = (circ_radius - rad4)/(rad2-rad4);
+      } else {
+         weight[*result_num] = 0.5;
+      }
+      if (cuts_bottom || cuts_top || cuts_left || cuts_right) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      }
+
+   } // for  
+   free(ind);
+}
+
+void KDTree_QueryCircleInterior_Double(TKDTree* t,
+                            int* result_num, int* result_indicies,
+                            double circ_radius, int ncells, 
+                            double *x, double *dx, double *y, double *dy)
+{
+   assert(t && result_num && result_indicies && circ_radius);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   
+   int nez;
+   int *ind=(int *)malloc(ncells*sizeof(int));
+   
+   TBounds box;
+   box.min.x = -circ_radius;
+   box.max.x =  circ_radius;
+   box.min.y = -circ_radius;
+   box.max.y =  circ_radius;
+   KDTree_QueryBoxIntersect(t, &nez, ind, &box);
+   
+   //for (int ic=0; ic<nez; ic++) {
+   //   printf("box is ind[%d]=%d\n",ic,ind[ic]);
+   //}
+   
+   /* Allocate the results array */
+   *result_num = 0;
+   
+   double rad1, rad2, rad3, rad4;
+   int ii;
+   for (int i=0; i<nez; ++i){
+      ii = ind[i];
+      rad1 = sqrt( pow(x[ii],       2.0) + pow(y[ii],       2.0) );
+      rad2 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii],       2.0) );
+      rad3 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii]+dy[ii],2.0) );
+      rad4 = sqrt( pow(x[ii]       ,2.0) + pow(y[ii]+dy[ii],2.0) );
+      
+      if ((circ_radius > rad1 || circ_radius > rad2 ) ||
+          (circ_radius > rad3 || circ_radius > rad4 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      }
+   } // for  
+   free(ind);
+}
+
+void KDTree_QueryCircleInterior_Float(TKDTree* t,
+                            int* result_num, int* result_indicies,
+                            double circ_radius, int ncells, 
+                            float *x, float *dx, float *y, float *dy)
+{
+   assert(t && result_num && result_indicies && circ_radius);
+   /* Build the k-D tree if necessary */
+   if(!t->tree_built){
+      //printf("BUILDING TREE... \n");
+      //fflush(stdout);
+      KDTree_CreateTree(t);
+   }
+   
+   int nez;
+   int *ind=(int *)malloc(ncells*sizeof(int));
+   
+   TBounds box;
+   box.min.x = -circ_radius;
+   box.max.x =  circ_radius;
+   box.min.y = -circ_radius;
+   box.max.y =  circ_radius;
+   KDTree_QueryBoxIntersect(t, &nez, ind, &box);
+   
+   //for (int ic=0; ic<nez; ic++) {
+   //   printf("box is ind[%d]=%d\n",ic,ind[ic]);
+   //}
+   
+   /* Allocate the results array */
+   *result_num = 0;
+   
+   double rad1, rad2, rad3, rad4;
+   int ii;
+   for (int i=0; i<nez; ++i){
+      ii = ind[i];
+      rad1 = sqrt( pow(x[ii],       2.0) + pow(y[ii],       2.0) );
+      rad2 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii],       2.0) );
+      rad3 = sqrt( pow(x[ii]+dx[ii],2.0) + pow(y[ii]+dy[ii],2.0) );
+      rad4 = sqrt( pow(x[ii]       ,2.0) + pow(y[ii]+dy[ii],2.0) );
+      
+      if ((circ_radius > rad1 || circ_radius > rad2 ) ||
+          (circ_radius > rad3 || circ_radius > rad4 ) ) {
+         result_indicies[*result_num] = ind[i];
+         (*result_num)++;
+      }
+   } // for  
+   free(ind);
+}
+
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/KDTree.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/KDTree.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ *           Other LANL authors
+ * 
+ * 
+ *  Implements a 2-dimensional k-D tree. One begins to use the k-D tree by
+ *  adding the bounding box of geometric "elements" to the tree structure
+ *  through a call to "KDTreeAddElement". Every element should be of the same
+ *  type, but could be a single point, a line segment, triangles, etc. Once
+ *  all the element bounding boxes have been added, the user of the structure
+ *  may make queries against the tree. The actual tree is constructed lazily
+ *  when an actual query occurs on the structure.
+ *
+ *  This version only has one query -- intersection of a box with the elements
+ *  and a set of "candidate" elements are returned. The candidates are identified
+ *  by an index number (0, ...) signifying the order in which the element was
+ *  added to the tree. It is up to the calling code to do additional processing
+ *  based on the type of element being used to determine "real" intersections.
+ *
+ *  The process of actually building the tree takes "n log n" time. Queries 
+ *  take "log n" time.
+ *
+ */
+
+#ifndef _KDTree_
+#define _KDTree_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+  
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "Globals.h"
+#include "Bounds.h"
+   
+#define LEFT_HALF   0
+#define RIGHT_HALF  1
+#define BOTTOM_HALF 0
+#define TOP_HALF    1   
+
+typedef struct {
+   TBounds extent;
+   int elements_num, elements_allocated;
+   TBounds* elements;
+   bool tree_built;
+   int tree_size;
+   TBounds* tree_safety_boxes;
+   int * tree_link;
+} TKDTree;
+
+extern void KDTree_Initialize(TKDTree *t);
+extern void KDTree_Finalize(TKDTree *t);
+extern void KDTree_Destroy(TKDTree* t);
+extern void KDTree_AddElement(TKDTree* t, TBounds* add);
+extern void KDTree_CreateTree(TKDTree* t);
+extern void KDTree_QueryBoxIntersect(TKDTree* t,
+                                     int* result_num, int* result_indicies,
+                                     TBounds* box);
+
+void KDTree_QueryCircleIntersect_Double(TKDTree* t,
+                                 int* result_num, int* result_indicies,
+                                 double radius, int ncells, 
+                                 double *x, double *dx, double *y, double *dy);
+void KDTree_QueryCircleIntersect_Float(TKDTree* t,
+                                 int* result_num, int* result_indicies,
+                                 double radius, int ncells, 
+                                 float *x, float *dx, float *y, float *dy);
+
+void KDTree_QueryCircleIntersectWeighted_Double(TKDTree* t,
+                                 int* result_num, int* result_indicies, double *weight,
+                                 double circ_radius, int ncells, 
+                                 double *x, double *dx, double *y, double *dy);
+void KDTree_QueryCircleIntersectWeighted_Float(TKDTree* t,
+                                 int* result_num, int* result_indicies, double *weight,
+                                 double circ_radius, int ncells, 
+                                 float *x, float *dx, float *y, float *dy);
+
+void KDTree_QueryCircleInterior_Double(TKDTree* t,
+                                 int* result_num, int* result_indicies,
+                                 double circ_radius, int ncells, 
+                                 double *x, double *dx, double *y, double *dy);
+void KDTree_QueryCircleInterior_Float(TKDTree* t,
+                                 int* result_num, int* result_indicies,
+                                 double circ_radius, int ncells, 
+                                 float *x, float *dx, float *y, float *dy);
+   
+#ifdef __cplusplus
+}
+#endif
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/LICENSE
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/LICENSE?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/LICENSE (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/LICENSE Mon Sep  4 07:25:36 2017
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  CLAMR -- LA-CC-11-094
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ */

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Makefile
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Makefile?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Makefile (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Makefile Mon Sep  4 07:25:36 2017
@@ -0,0 +1,5 @@
+LEVEL = ../../../..
+
+PROG = CLAMR
+RUN_OPTIONS = -n 64 -t 1000
+include $(LEVEL)/MultiSource/Makefile.multisrc

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/MallocPlus.cpp?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.cpp Mon Sep  4 07:25:36 2017
@@ -0,0 +1,1227 @@
+/*
+ *  Copyright (c) 2011-2014, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+
+// SKG TODO op realloc (similar to managed)
+
+#undef HAVE_OPENCL
+
+#include "MallocPlus.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <algorithm>
+#include <queue>
+#include <string.h>
+#ifdef HAVE_OPENCL
+#include "ezcl/ezcl.h"
+#endif
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+#define WARNING_SUPPRESSION 0
+
+#ifdef HAVE_CL_DOUBLE
+#ifdef HAVE_OPENCL
+typedef cl_double2  cl_real2;
+#endif
+#else
+#ifdef HAVE_OPENCL
+typedef cl_float2   cl_real2;
+#endif
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef SWAP_PTR
+#define SWAP_PTR(xnew,xold,xtmp) (xtmp=xnew, xnew=xold, xold=xtmp)
+#endif
+
+typedef unsigned int uint;
+map<void *,malloc_plus_memory_entry*>::iterator it_save, it_end;
+map<string, malloc_plus_memory_entry*, cmp_str>::iterator it_save_by_name, it_end_by_name;
+
+#if defined(HAVE_MPI)
+void
+MallocPlus::pinit(MPI_Comm smComm, std::size_t memPoolSize)
+{
+#if defined(HAVE_J7)
+    try {
+        j7 = new J7(smComm, memPoolSize);
+    }
+    catch(...) {
+        std::cerr << "*** pinit failure ***" << std::endl;
+        throw;
+    }
+#else
+    // Just to suppress compiler warnings
+    if (WARNING_SUPPRESSION) printf("DEBUG memPoolSize = %lu smComm = %p\n",memPoolSize,smComm);
+#endif
+}
+
+void
+MallocPlus::pfini(void)
+{
+#if defined(HAVE_J7)
+    try {
+        delete j7;
+        j7 = NULL;
+    }
+    catch(...) {
+        std::cerr << "*** pfini failure ***" << std::endl;
+        throw;
+    }
+#endif
+}
+#endif // if defined(HAVE_MPI)
+
+void *MallocPlus::memory_malloc(size_t nelem, size_t elsize, const char *name, int flags){
+   malloc_plus_memory_entry *memory_item = (malloc_plus_memory_entry *)malloc(sizeof(malloc_plus_memory_entry));
+
+   memory_item->mem_nelem    = (size_t *)malloc(1*sizeof(size_t));
+   memory_item->mem_nelem[0] = nelem;
+   memory_item->mem_ndims    = 1;
+   memory_item->mem_elsize   = elsize;
+   memory_item->mem_flags    = flags;
+
+   // allocate memory on the accelerator if flag is set
+   if ((flags & DEVICE_REGULAR_MEMORY) != 0){
+#ifdef HAVE_OPENCL
+      cl_context context = ezcl_get_context();
+      memory_item->mem_capacity = nelem;
+      memory_item->mem_ptr      = ezcl_device_memory_malloc(context, NULL, name, nelem, elsize, CL_MEM_READ_WRITE, 0);
+#endif
+   }
+   // Managed memory allocates extra space and expands as necessary to reduce allocations
+   else if ((flags & HOST_MANAGED_MEMORY) != 0){
+      memory_item->mem_capacity = 2 * nelem;
+      memory_item->mem_ptr      = malloc(2* nelem*elsize);
+   }
+#ifdef HAVE_J7
+   // experimental shared memory allocation
+   else if (flags & LOAD_BALANCE_MEMORY) {
+      memory_item->mem_capacity = nelem;
+      memory_item->mem_ptr      = j7->memAlloc(nelem * elsize);
+   }
+#endif
+   // Just regular memory allocation
+   else {
+      memory_item->mem_capacity = nelem;
+      memory_item->mem_ptr      = malloc(nelem*elsize);
+   }
+
+   memory_item->mem_name = strdup(name); // Mallocs memory for copy
+
+   //printf("MALLOC_PLUS_MEMORY_MALLOC: DEBUG -- malloc plus memory pointer for :%s: is %p nelements %ld elsize is %ld flags %d\n",memory_item->mem_name,memory_item->mem_ptr,memory_item->mem_nelem[0],memory_item->mem_elsize,memory_item->mem_flags);
+
+   // Insert entry into dictionary -- two versions, one by name and another by pointer address
+   memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(name, memory_item) );
+   memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(memory_item->mem_ptr, memory_item) );
+
+   if (DEBUG) printf("MALLOC_PLUS_MEMORY_MALLOC: DEBUG -- malloc plus memory pointer for :%s: is %p nelements %ld elsize is %ld\n",memory_item->mem_name,memory_item->mem_ptr,memory_item->mem_nelem[0],memory_item->mem_elsize);
+
+   // return the pointer for use by the calling routine
+   return(memory_item->mem_ptr);
+}
+
+void *MallocPlus::memory_realloc(size_t nelem, void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+   void *mem_ptr=NULL;
+
+   if (it != memory_ptr_dict.end() ){
+      // "second" will be the pointer to the memory entry data structure -- the value
+      // associated with the key
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REALLOC: DEBUG -- reallocated memory pointer %p\n",memory_item->mem_ptr);
+
+      // memory pointer will probably change, so delete the dictionary entry
+      // named dictionary entry does not need to change; the pointer in the data structure
+      //    will just be updated, but the pointer to the memory entry data structure
+      //    will be the same
+      memory_ptr_dict.erase(it);
+
+      if (memory_item->mem_flags & HOST_MANAGED_MEMORY){
+         // Check to see if memory needs to be expanded
+         if (nelem > memory_item->mem_capacity) {
+            // Need to realloc memory. Allocate extra for growth of array.
+            mem_ptr=realloc(memory_item->mem_ptr, 2*nelem*memory_item->mem_elsize);
+            memory_item->mem_capacity = 2*nelem;
+            memory_item->mem_nelem[0] = nelem;
+            memory_item->mem_ptr      = mem_ptr;
+         } else {
+            // Just move size to use more of memory buffer
+            memory_item->mem_nelem[0] = nelem;
+         }
+      }
+#ifdef HAVE_J7
+      else if (memory_item->mem_flags & LOAD_BALANCE_MEMORY) {
+         mem_ptr = j7->memRealloc(memory_item->mem_ptr, nelem * memory_item->mem_elsize);
+         memory_item->mem_capacity = nelem;
+         memory_item->mem_nelem[0] = nelem;
+         memory_item->mem_ptr      = mem_ptr;
+      }
+#endif
+      else {
+         mem_ptr=realloc(memory_item->mem_ptr, nelem*memory_item->mem_elsize);
+         memory_item->mem_capacity = nelem;
+         memory_item->mem_nelem[0] = nelem;
+         memory_item->mem_ptr      = mem_ptr;
+      }
+
+      // Put the pointer entry back into the dictionary
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(memory_item->mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(mem_ptr);
+}
+
+void *MallocPlus::memory_realloc(size_t nelem, const char *name){
+   map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(name);
+   void *mem_ptr=NULL;
+
+   if (it != memory_name_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REALLOC: DEBUG -- "
+                           "reallocated memory pointer %p\n",memory_item->mem_ptr);
+
+      // Need to get the iterator for the pointer entry; the one above is for the name entry
+      map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(memory_item->mem_ptr);
+      memory_ptr_dict.erase(it);
+
+      if (memory_item->mem_flags & HOST_MANAGED_MEMORY) {
+         // Check to see if memory needs to be expanded
+         if (nelem > memory_item->mem_capacity) {
+            // Need to realloc memory. Allocate extra for growth of array.
+            mem_ptr=realloc(memory_item->mem_ptr, 2*nelem*memory_item->mem_elsize);
+            memory_item->mem_capacity = 2*nelem;
+            memory_item->mem_nelem[0] = nelem;
+            memory_item->mem_ptr      = mem_ptr;
+         } else {
+            // Just move size to use more of memory buffer
+            memory_item->mem_nelem[0] = nelem;
+         }
+      }
+#ifdef HAVE_J7
+      else if (memory_item->mem_flags & LOAD_BALANCE_MEMORY) {
+         mem_ptr = j7->memRealloc(memory_item->mem_ptr, nelem * memory_item->mem_elsize);
+         memory_item->mem_capacity = nelem;
+         memory_item->mem_nelem[0] = nelem;
+         memory_item->mem_ptr      = mem_ptr;
+      }
+#endif
+      else {
+         //memory_name_dict.erase(it);
+         mem_ptr=realloc(memory_item->mem_ptr, nelem*memory_item->mem_elsize);
+         memory_item->mem_capacity = nelem;
+         memory_item->mem_nelem[0] = nelem;
+         memory_item->mem_ptr      = mem_ptr;
+         //memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(name, memory_item) );
+      }
+
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(memory_item->mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory named %s not found\n",name);
+   }
+
+   return(mem_ptr);
+}
+
+void *MallocPlus::memory_request(size_t new_capacity, void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+   void *mem_ptr=NULL;
+
+   if (it != memory_ptr_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REQUEST: DEBUG -- reallocated memory pointer %p\n",memory_item->mem_ptr);
+      memory_ptr_dict.erase(it);
+      mem_ptr=realloc(memory_item->mem_ptr, new_capacity*memory_item->mem_elsize);
+      memory_item->mem_capacity = new_capacity;
+      memory_item->mem_ptr      = mem_ptr;
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(mem_ptr);
+}
+
+// Increases the capacity of the allocated memory, primarily for the managed memory functionality
+void *MallocPlus::memory_request(size_t new_capacity, const char *name){
+   map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(name);
+   void *mem_ptr=NULL;
+
+   if (it != memory_name_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REQUEST: DEBUG -- reallocated memory pointer %p\n",memory_item->mem_ptr);
+      map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(memory_item->mem_ptr);
+      memory_ptr_dict.erase(it);
+      mem_ptr=realloc(memory_item->mem_ptr, new_capacity*memory_item->mem_elsize);
+      memory_item->mem_capacity = new_capacity;
+      memory_item->mem_ptr      = mem_ptr;
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory named %s not found\n",name);
+   }
+
+   return(mem_ptr);
+}
+
+void MallocPlus::memory_realloc_all(size_t nelem){
+   // Need a copy of the dictionary since we will be modifying while being used
+   map <void *, malloc_plus_memory_entry*> memory_ptr_dict_old = memory_ptr_dict;
+
+   // Need iterators to both new and old; new will be modified during the loop
+   map<void *, malloc_plus_memory_entry*>::iterator it_old;
+   map<void *, malloc_plus_memory_entry*>::iterator it_new;
+   void *mem_ptr=NULL;
+
+   for ( it_old=memory_ptr_dict_old.begin(); it_old != memory_ptr_dict_old.end(); it_old++){
+      // Get the memory entry for the old dictionary
+      malloc_plus_memory_entry *memory_item = it_old->second;
+
+      // Get the iterator to the new dictionary by memory pointer and delete it
+      //   since it will probably change
+      // The dictionary by name does not need to be updated
+      it_new = memory_ptr_dict.find(memory_item->mem_ptr);
+      memory_ptr_dict.erase(it_new);
+
+      if (memory_item->mem_flags & HOST_MANAGED_MEMORY) {
+         if (nelem > memory_item->mem_capacity) {
+            mem_ptr=realloc(memory_item->mem_ptr, nelem*memory_item->mem_elsize);
+            if (DEBUG) printf("MALLOC_PLUS_MEMORY_REALLOC_ALL: DEBUG -- reallocated memory pointer %p new pointer %p\n",memory_item->mem_ptr,mem_ptr);
+            memory_item->mem_capacity = nelem;
+            memory_item->mem_nelem[0] = nelem;
+            memory_item->mem_ptr      = mem_ptr;
+         } else {
+            memory_item->mem_nelem[0] = nelem;
+         }
+      }
+#ifdef HAVE_J7
+      else if (it->mem_flags & LOAD_BALANCE_MEMORY) {
+         mem_ptr = j7->memRealloc(memory_item->mem_ptr, nelem * memory_item->mem_elsize);
+         memory_item->mem_capacity = nelem;
+         memory_item->mem_nelem[0] = nelem;
+         memory_item->mem_ptr      = mem_ptr;
+      }
+#endif
+      else {
+         mem_ptr=realloc(memory_item->mem_ptr, nelem*memory_item->mem_elsize);
+         if (DEBUG) printf("MALLOC_PLUS_MEMORY_REALLOC_ALL: DEBUG -- reallocated memory pointer %p new pointer %p\n",memory_item->mem_ptr,mem_ptr);
+         memory_item->mem_capacity = nelem;
+         memory_item->mem_nelem[0] = nelem;
+         memory_item->mem_ptr      = mem_ptr;
+      }
+
+      //Insert the entry back into the dictionary
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(mem_ptr, memory_item) );
+   }
+}
+
+void MallocPlus::memory_request_all(size_t new_capacity){
+   map <void *, malloc_plus_memory_entry*> memory_ptr_dict_old = memory_ptr_dict;
+
+   map<void *, malloc_plus_memory_entry*>::iterator it_old;
+   map<void *, malloc_plus_memory_entry*>::iterator it_new;
+
+   for ( it_old=memory_ptr_dict_old.begin(); it_old != memory_ptr_dict_old.end(); it_old++){
+      malloc_plus_memory_entry *memory_item = it_old->second;
+
+      it_new = memory_ptr_dict.find(memory_item->mem_ptr);
+      memory_ptr_dict.erase(it_new);
+
+      void *mem_ptr=realloc(memory_item->mem_ptr, new_capacity*memory_item->mem_elsize);
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REQUEST_ALL: DEBUG -- reallocated memory pointer %p new pointer %p\n",memory_item->mem_ptr,mem_ptr);
+      memory_item->mem_capacity = new_capacity;
+      memory_item->mem_ptr      = mem_ptr;
+
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(mem_ptr, memory_item) );
+   }
+}
+
+// This routine is for memory allocated by the host program and added to the database
+void *MallocPlus::memory_add(void *malloc_mem_ptr, size_t nelem, size_t elsize, const char *name, int flags){
+   malloc_plus_memory_entry *memory_item = (malloc_plus_memory_entry *)malloc(sizeof(malloc_plus_memory_entry));
+
+   memory_item->mem_nelem    = (size_t *)malloc(1*sizeof(size_t));
+   memory_item->mem_nelem[0] = nelem;
+   memory_item->mem_ndims    = 1;
+   memory_item->mem_capacity = nelem;
+   memory_item->mem_elsize   = elsize;
+   memory_item->mem_flags    = flags;
+   memory_item->mem_ptr      = malloc_mem_ptr;
+   memory_item->mem_name = strdup(name); // mallocs memory
+   memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+   memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(name, memory_item) );
+   if (DEBUG) printf("MALLOC_PLUS_MEMORY_ADD: DEBUG -- added memory pointer for %s is %p\n",name,malloc_mem_ptr);
+
+   return(malloc_mem_ptr);
+}
+
+// This routine is for memory allocated by the host program and added to the database
+void *MallocPlus::memory_add(void *malloc_mem_ptr, int ndim, size_t *nelem, size_t elsize, const char *name, int flags){
+   malloc_plus_memory_entry *memory_item = (malloc_plus_memory_entry *)malloc(sizeof(malloc_plus_memory_entry));
+
+   memory_item->mem_nelem    = (size_t *)malloc(ndim*sizeof(size_t));
+   for (int i=0; i<ndim; i++){
+     memory_item->mem_nelem[i] = nelem[i];
+   }
+   memory_item->mem_ndims    = ndim;
+   memory_item->mem_capacity = 0;
+   memory_item->mem_elsize   = elsize;
+   memory_item->mem_flags    = flags;
+   memory_item->mem_ptr      = malloc_mem_ptr;
+   memory_item->mem_name = strdup(name); // mallocs memory
+   memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+   memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(name, memory_item) );
+   if (DEBUG) printf("MALLOC_PLUS_MEMORY_ADD: DEBUG -- added memory pointer for %s is %p\n",name,malloc_mem_ptr);
+
+   return(malloc_mem_ptr);
+}
+
+double *MallocPlus::memory_reorder(double *malloc_mem_ptr, int *iorder){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+      double *ptr;
+
+      memory_ptr_dict.erase(it);
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      double *tmp = (double *)malloc(memory_item->mem_nelem[0]*memory_item->mem_elsize);
+#ifdef _OPENMP
+#pragma omp parallel for
+#endif
+      for (uint ic = 0; ic < memory_item->mem_nelem[0]; ic++){
+         tmp[ic] = malloc_mem_ptr[iorder[ic]];
+      }
+      SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+      free(tmp);
+      memory_item->mem_ptr = malloc_mem_ptr;
+
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(malloc_mem_ptr);
+}
+
+float *MallocPlus::memory_reorder(float *malloc_mem_ptr, int *iorder){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+      float *ptr;
+
+      memory_ptr_dict.erase(it);
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      float *tmp = (float *)malloc(memory_item->mem_nelem[0]*memory_item->mem_elsize);
+#ifdef _OPENMP
+#pragma omp parallel for
+#endif
+      for (uint ic = 0; ic < memory_item->mem_nelem[0]; ic++){
+         tmp[ic] = malloc_mem_ptr[iorder[ic]];
+      }
+      SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+      free(tmp);
+      memory_item->mem_ptr = malloc_mem_ptr;
+
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(malloc_mem_ptr);
+}
+
+int *MallocPlus::memory_reorder(int *malloc_mem_ptr, int *iorder){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+      int *ptr;
+
+      memory_ptr_dict.erase(it);
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      int *tmp = (int *)malloc(memory_item->mem_nelem[0]*memory_item->mem_elsize);
+#ifdef _OPENMP
+#pragma omp parallel for
+#endif
+      for (uint ic = 0; ic < memory_item->mem_nelem[0]; ic++){
+         tmp[ic] = malloc_mem_ptr[iorder[ic]];
+      }
+      SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+      free(tmp);
+      memory_item->mem_ptr = malloc_mem_ptr;
+
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(malloc_mem_ptr);
+}
+
+int *MallocPlus::memory_reorder_indexarray(int *malloc_mem_ptr, int *iorder, int *inv_iorder){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end() ){
+      malloc_plus_memory_entry *memory_item = it->second;
+      int *ptr;
+
+      if (DEBUG) printf("Found memory_item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      memory_ptr_dict.erase(it);
+      int *tmp = (int *)malloc(memory_item->mem_nelem[0]*memory_item->mem_elsize);
+      for (uint ic = 0; ic < memory_item->mem_nelem[0]; ic++){
+         tmp[ic] = inv_iorder[malloc_mem_ptr[iorder[ic]]];
+      }
+      SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+      free(tmp);
+      memory_item->mem_ptr = malloc_mem_ptr;
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(malloc_mem_ptr);
+}
+
+void MallocPlus::memory_reorder_all(int *iorder){
+   map <void *, malloc_plus_memory_entry*> memory_ptr_dict_old = memory_ptr_dict;
+   map <void *, malloc_plus_memory_entry*>::iterator it_old;
+   vector<int> inv_iorder;
+
+   for ( it_old=memory_ptr_dict_old.begin(); it_old != memory_ptr_dict_old.end(); it_old++){
+      malloc_plus_memory_entry *memory_item_old = it_old->second;
+
+      map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(memory_item_old->mem_ptr);
+      malloc_plus_memory_entry *memory_item = it_old->second;
+      memory_ptr_dict.erase(it);
+
+      if (memory_item_old->mem_flags & 0x100) {
+         if (inv_iorder.size() < memory_item_old->mem_nelem[0]) {
+            inv_iorder.resize(memory_item_old->mem_nelem[0]);
+            for (int ic = 0; ic < (int)memory_item_old->mem_nelem[0]; ic++){
+               inv_iorder[iorder[ic]] = ic;
+            }
+         }
+         int *ptr;
+         int *malloc_mem_ptr = (int *)memory_item_old->mem_ptr;
+         int *tmp = (int *)malloc(memory_item_old->mem_nelem[0]*memory_item_old->mem_elsize);
+         for (uint ic = 0; ic < memory_item_old->mem_nelem[0]; ic++){
+            tmp[ic] = inv_iorder[malloc_mem_ptr[iorder[ic]]];
+         }
+         memory_replace(malloc_mem_ptr, tmp);
+         SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+         free(tmp);
+         memory_item->mem_ptr = malloc_mem_ptr;
+         memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+      } else if (memory_item_old->mem_elsize == 8){
+         double *ptr;
+         double *malloc_mem_ptr = (double *)memory_item_old->mem_ptr;
+         double *tmp = (double *)malloc(memory_item_old->mem_nelem[0]*memory_item_old->mem_elsize);
+
+         for (uint ic = 0; ic < memory_item_old->mem_nelem[0]; ic++){
+            tmp[ic] = malloc_mem_ptr[iorder[ic]];
+         }
+
+         SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+         free(tmp);
+         memory_item->mem_ptr = malloc_mem_ptr;
+         memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+      } else {
+         float *ptr;
+         float *malloc_mem_ptr = (float *)memory_item_old->mem_ptr;
+         float *tmp = (float *)malloc(memory_item_old->mem_nelem[0]*memory_item_old->mem_elsize);
+         for (uint ic = 0; ic < memory_item_old->mem_nelem[0]; ic++){
+            tmp[ic] = malloc_mem_ptr[iorder[ic]];
+         }
+         memory_replace(malloc_mem_ptr, tmp);
+         SWAP_PTR(malloc_mem_ptr, tmp, ptr);
+         free(tmp);
+         memory_item->mem_ptr = malloc_mem_ptr;
+         memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr, memory_item) );
+      }
+
+   }
+
+   inv_iorder.clear();
+}
+
+void MallocPlus::memory_report(void){
+   map<void *, malloc_plus_memory_entry*>::iterator it_ptr;
+
+   for ( it_ptr=memory_ptr_dict.begin(); it_ptr != memory_ptr_dict.end(); it_ptr++){
+      malloc_plus_memory_entry *memory_item = it_ptr->second;
+
+      printf("MallocPlus ptr  %p: name %10s ptr %p dims %lu nelem (",
+            it_ptr->first,memory_item->mem_name,memory_item->mem_ptr,memory_item->mem_ndims);
+
+      char nelemstring[80];
+      char *str_ptr = nelemstring;
+      str_ptr += sprintf(str_ptr,"%lu", memory_item->mem_nelem[0]);
+      for (uint i = 1; i < memory_item->mem_ndims; i++){
+         str_ptr += sprintf(str_ptr,", %lu", memory_item->mem_nelem[i]);
+      }
+      printf("%12s",nelemstring);
+
+      printf(") elsize %lu flags %d capacity %lu\n",
+            memory_item->mem_elsize,memory_item->mem_flags,memory_item->mem_capacity);
+   }
+
+   map<string, malloc_plus_memory_entry*>::iterator it_name;
+
+   for ( it_name=memory_name_dict.begin(); it_name != memory_name_dict.end(); it_name++){
+      malloc_plus_memory_entry *memory_item = it_name->second;
+
+      printf("MallocPlus name %14s: name %10s ptr %p dims %lu nelem (",
+            it_name->first.c_str(),memory_item->mem_name,memory_item->mem_ptr,memory_item->mem_ndims);
+
+      char nelemstring[80];
+      char *str_ptr = nelemstring;
+      str_ptr += sprintf(str_ptr,"%lu", memory_item->mem_nelem[0]);
+      for (uint i = 1; i < memory_item->mem_ndims; i++){
+         str_ptr += sprintf(str_ptr,", %lu", memory_item->mem_nelem[i]);
+      }
+      printf("%12s",nelemstring);
+
+      printf(") elsize %lu flags %d capacity %lu\n",
+            memory_item->mem_elsize,memory_item->mem_flags,memory_item->mem_capacity);
+   }
+}
+
+void *MallocPlus::memory_delete(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REMOVE: DEBUG -- removed memory pointer %p\n",memory_item->mem_ptr);
+
+      if ((memory_item->mem_flags & DEVICE_REGULAR_MEMORY) != 0){
+#ifdef HAVE_OPENCL
+         //printf("MALLOC_PLUS_MEMORY_REMOVE: DEBUG -- removed memory pointer %p\n",memory_item->mem_ptr);
+         ezcl_device_memory_delete(memory_item->mem_ptr);
+#endif
+      }
+#ifdef HAVE_J7
+      else if (memory_item->mem_flags & LOAD_BALANCE_MEMORY) {
+         j7->memFree(memory_item->mem_ptr);
+      }
+#endif
+      else {
+         free(memory_item->mem_ptr);
+      }
+
+      memory_ptr_dict.erase(it);
+      // Need to delete the entry in the name dictionary. This is done in a separate scope
+      // so the iterator "it" is isolated for this use
+      {
+         map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(memory_item->mem_name);
+         memory_name_dict.erase(it);
+      }
+
+      free(memory_item->mem_nelem);
+      free(memory_item->mem_name);
+      free(memory_item);
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+
+   return(NULL);
+}
+
+void *MallocPlus::memory_delete(const char *name){
+   map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(name);
+
+   if (it != memory_name_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REMOVE: DEBUG -- removed memory pointer %p\n",memory_item->mem_ptr);
+      if ((memory_item->mem_flags & DEVICE_REGULAR_MEMORY) != 0){
+#ifdef HAVE_OPENCL
+         ezcl_device_memory_delete(memory_item->mem_ptr);
+#endif
+      }
+#ifdef HAVE_J7
+      else if (memory_item->mem_flags & LOAD_BALANCE_MEMORY) {
+         j7->memFree(memory_item->mem_ptr);
+      }
+#endif
+      else {
+         free(memory_item->mem_ptr);
+      }
+
+      memory_name_dict.erase(it);
+      {
+         map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(memory_item->mem_ptr);
+         memory_ptr_dict.erase(it);
+      }
+
+      free(memory_item->mem_nelem);
+      free(memory_item->mem_name);
+      free(memory_item);
+   } else {
+      if (DEBUG) printf("Warning -- memory named %s not found\n",name);
+   }
+
+   return(NULL);
+}
+
+void MallocPlus::memory_delete_all(void){
+   map <void *, malloc_plus_memory_entry*> memory_ptr_dict_old = memory_ptr_dict;
+   map <void *, malloc_plus_memory_entry*>::iterator it;
+
+   for ( it=memory_ptr_dict_old.begin(); it != memory_ptr_dict_old.end(); it++){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REMOVE: DEBUG -- removed memory pointer %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+
+      if ((memory_item->mem_flags & DEVICE_REGULAR_MEMORY) != 0){
+#ifdef HAVE_OPENCL
+         ezcl_device_memory_delete(memory_item->mem_ptr);
+#endif
+      } else {
+         free(memory_item->mem_ptr);
+      }
+
+      free(memory_item->mem_nelem);
+      free(memory_item->mem_name);
+      free(memory_item);
+   }
+
+   memory_ptr_dict.clear();
+   memory_name_dict.clear();
+}
+
+// For memory that was allocated by the host and added to the database with the
+// memory_add function. This is the corresponding routine to delete the dictionary entry.
+// The memory itself is not freed.
+void MallocPlus::memory_remove(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REMOVE: DEBUG -- removed memory pointer %p\n",memory_item->mem_ptr);
+      memory_ptr_dict.erase(it);
+      {
+         map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(memory_item->mem_name);
+         memory_name_dict.erase(it);
+      }
+      free(memory_item->mem_nelem);
+      free(memory_item->mem_name);
+      free(memory_item);
+   } else {
+      if (DEBUG) printf("Warning -- memory pointer %p not found\n",malloc_mem_ptr);
+   }
+}
+
+void MallocPlus::memory_remove(const char *name){
+   map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(name);
+
+   if (it != memory_name_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("MALLOC_PLUS_MEMORY_REMOVE: DEBUG -- removed memory pointer %p\n",memory_item->mem_ptr);
+      memory_name_dict.erase(it);
+      {
+         map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(memory_item->mem_ptr);
+         memory_ptr_dict.erase(it);
+      }
+      free(memory_item->mem_nelem);
+      free(memory_item->mem_name);
+      free(memory_item);
+   } else {
+      if (DEBUG) printf("Warning -- memory named %s not found\n",name);
+   }
+}
+
+void *MallocPlus::memory_begin(void){
+   it_save = memory_ptr_dict.begin();
+   malloc_plus_memory_entry *memory_item = it_save->second;
+   return(memory_item->mem_ptr);
+}
+
+void *MallocPlus::memory_next(void){
+   map <void *, malloc_plus_memory_entry*>::iterator it;
+
+   it_save++;
+   it = it_save;
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_ptr);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+      return(NULL);
+   }
+}
+
+void *MallocPlus::memory_by_name_begin(void){
+   it_save_by_name = memory_name_dict.begin();
+   malloc_plus_memory_entry *memory_item = it_save->second;
+   return(memory_item->mem_ptr);
+}
+
+void *MallocPlus::memory_by_name_next(void){
+   map<string, malloc_plus_memory_entry*, cmp_str>::iterator it_by_name;
+
+   it_save_by_name++;
+   it_by_name = it_save_by_name;
+
+   if (it_by_name != memory_name_dict.end()){
+      malloc_plus_memory_entry *memory_item = it_by_name->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_ptr);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+      return(NULL);
+   }
+}
+
+malloc_plus_memory_entry* MallocPlus::memory_entry_begin(void){
+   it_save = memory_ptr_dict.begin();
+   malloc_plus_memory_entry *memory_item = it_save->second;
+   return(memory_item);
+}
+
+malloc_plus_memory_entry* MallocPlus::memory_entry_next(void){
+   it_save++;
+   if (it_save == memory_ptr_dict.end()) return(NULL);
+   malloc_plus_memory_entry *memory_item = it_save->second;
+   if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+   return(memory_item);
+}
+
+malloc_plus_memory_entry* MallocPlus::memory_entry_end(void){
+   return(NULL);
+}
+
+malloc_plus_memory_entry* MallocPlus::memory_entry_by_name_begin(void){
+   it_save_by_name = memory_name_dict.begin();
+   malloc_plus_memory_entry *memory_item = it_save_by_name->second;
+   return(memory_item);
+}
+
+malloc_plus_memory_entry* MallocPlus::memory_entry_by_name_next(void){
+   it_save_by_name++;
+   if (it_save_by_name == memory_name_dict.end()) return(NULL);
+   malloc_plus_memory_entry *memory_item = it_save_by_name->second;
+   if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+   return(memory_item);
+}
+
+malloc_plus_memory_entry* MallocPlus::memory_entry_by_name_end(void){
+   return(NULL);
+}
+
+size_t MallocPlus::get_memory_size(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_nelem[0]);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(0);
+}
+
+int MallocPlus::get_memory_elemsize(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_elsize);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(0);
+}
+
+int MallocPlus::get_memory_flags(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s attribute %d\n",memory_item->mem_ptr,memory_item->mem_name,memory_item->mem_flags);
+      return(memory_item->mem_flags);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(0);
+}
+
+size_t MallocPlus::get_memory_capacity(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_capacity);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(0);
+}
+
+const char * MallocPlus::get_memory_name(void *malloc_mem_ptr){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_name);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(NULL);
+}
+
+void *MallocPlus::memory_replace(void *malloc_mem_ptr_old, void * const malloc_mem_ptr_new){
+   map <void *, malloc_plus_memory_entry*>::iterator it_old = memory_ptr_dict.find(malloc_mem_ptr_old);
+   map <void *, malloc_plus_memory_entry*>::iterator it_new = memory_ptr_dict.find(malloc_mem_ptr_new);
+
+   if (it_old != memory_ptr_dict.end() && it_new != memory_ptr_dict.end() ){
+      malloc_plus_memory_entry *memory_item_old = it_old->second;
+      malloc_plus_memory_entry *memory_item_new = it_new->second;
+
+      // erase the entries in the pointer dictionary
+      memory_ptr_dict.erase(it_new);
+      memory_ptr_dict.erase(it_old);
+      // get the iterators for the named dictionary
+      map <string, malloc_plus_memory_entry*>::iterator it_old = memory_name_dict.find(memory_item_old->mem_name);
+      map <string, malloc_plus_memory_entry*>::iterator it_new = memory_name_dict.find(memory_item_new->mem_name);
+      memory_name_dict.erase(it_new);
+      memory_name_dict.erase(it_old);
+
+      if (DEBUG) printf("Found memory item ptr_old %p name %s ptr_new %p name %s\n",memory_item_old->mem_ptr,memory_item_old->mem_name,memory_item_new->mem_ptr,memory_item_new->mem_name);
+
+      if ((memory_item_old->mem_flags & DEVICE_REGULAR_MEMORY) != 0){
+#ifdef HAVE_OPENCL
+         if (DEBUG) printf("Deleting device memory name %s pointer %p\n",memory_item_old->mem_name,memory_item_old->mem_ptr);
+         ezcl_device_memory_replace(&memory_item_old->mem_ptr, &memory_item_new->mem_ptr);
+#endif
+      }
+#ifdef HAVE_J7
+      else if (memory_item->mem_flags & LOAD_BALANCE_MEMORY) {
+         j7->memFree(memory_item_old->mem_ptr);
+         memory_item_old->mem_ptr      = memory_item_new->mem_ptr;
+      }
+#endif
+      else {
+         free(memory_item_old->mem_ptr);
+         memory_item_old->mem_ptr      = memory_item_new->mem_ptr;
+      }
+
+      memory_item_old->mem_nelem[0] = memory_item_new->mem_nelem[0];
+      memory_item_old->mem_capacity = memory_item_new->mem_capacity;
+      memory_item_old->mem_elsize   = memory_item_new->mem_elsize;
+      memory_item_old->mem_flags    = memory_item_new->mem_flags;
+      malloc_mem_ptr_old = (void *)malloc_mem_ptr_new;
+      free(memory_item_new->mem_nelem);
+      free(memory_item_new->mem_name);
+      free(memory_item_new);
+      
+      memory_ptr_dict.insert(std::pair<void*, malloc_plus_memory_entry*>(malloc_mem_ptr_old, memory_item_old) );
+      memory_name_dict.insert(std::pair<const char*, malloc_plus_memory_entry*>(memory_item_old->mem_name, memory_item_old) );
+
+      return(memory_item_old->mem_ptr);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(NULL);
+}
+
+void MallocPlus::memory_swap(int **malloc_mem_ptr_old, int **malloc_mem_ptr_new){
+   map <void *, malloc_plus_memory_entry*>::iterator it_old = memory_ptr_dict.find(*malloc_mem_ptr_old);
+   map <void *, malloc_plus_memory_entry*>::iterator it_new = memory_ptr_dict.find(*malloc_mem_ptr_new);
+
+   if (it_old != memory_ptr_dict.end() && it_new != memory_ptr_dict.end() ){
+      // Swap the memory entries during the retrieval
+      malloc_plus_memory_entry *memory_item_new = it_old->second;
+      malloc_plus_memory_entry *memory_item_old = it_new->second;
+
+      if (DEBUG) printf("Found memory item ptr_old %p name %s ptr_new %p name %s\n",memory_item_old->mem_ptr,memory_item_old->mem_name,memory_item_new->mem_ptr,memory_item_new->mem_name);
+
+      const char *mem_name_tmp;
+                  mem_name_tmp  = memory_item_old->mem_name;
+      memory_item_old->mem_name = memory_item_new->mem_name;
+      memory_item_new->mem_name = (char *)mem_name_tmp;
+
+      // Delete the ptr entries
+      memory_ptr_dict.erase(it_old);
+      memory_ptr_dict.erase(it_new);
+
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(memory_item_old->mem_ptr, memory_item_old) );
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(memory_item_new->mem_ptr, memory_item_new) );
+
+      // Delete the named entries
+      map <string, malloc_plus_memory_entry*>::iterator it_name_old = memory_name_dict.find(memory_item_old->mem_name);
+      map <string, malloc_plus_memory_entry*>::iterator it_name_new = memory_name_dict.find(memory_item_new->mem_name);
+      memory_name_dict.erase(it_name_old);
+      memory_name_dict.erase(it_name_new);
+
+      memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(memory_item_old->mem_name, memory_item_old) );
+      memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(memory_item_new->mem_name, memory_item_new) );
+
+      // memory items have been swapped, so return the new pointers
+      *malloc_mem_ptr_old = (int *)memory_item_old->mem_ptr;
+      *malloc_mem_ptr_new = (int *)memory_item_new->mem_ptr;
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+}
+
+void MallocPlus::memory_swap(float **malloc_mem_ptr_old, float **malloc_mem_ptr_new){
+   map <void *, malloc_plus_memory_entry*>::iterator it_old = memory_ptr_dict.find(*malloc_mem_ptr_old);
+   map <void *, malloc_plus_memory_entry*>::iterator it_new = memory_ptr_dict.find(*malloc_mem_ptr_new);
+
+   if (it_old != memory_ptr_dict.end() && it_new != memory_ptr_dict.end() ){
+      // Swap the memory entries during the retrieval
+      malloc_plus_memory_entry *memory_item_new = it_old->second;
+      malloc_plus_memory_entry *memory_item_old = it_new->second;
+
+      if (DEBUG) printf("Found memory item ptr_old %p name %s ptr_new %p name %s\n",memory_item_old->mem_ptr,memory_item_old->mem_name,memory_item_new->mem_ptr,memory_item_new->mem_name);
+
+      const char *mem_name_tmp;
+                  mem_name_tmp  = memory_item_old->mem_name;
+      memory_item_old->mem_name = memory_item_new->mem_name;
+      memory_item_new->mem_name = (char *)mem_name_tmp;
+
+      // Delete the ptr entries
+      memory_ptr_dict.erase(it_old);
+      memory_ptr_dict.erase(it_new);
+
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(memory_item_old->mem_ptr, memory_item_old) );
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(memory_item_new->mem_ptr, memory_item_new) );
+
+      // Delete the named entries
+      map <string, malloc_plus_memory_entry*>::iterator it_old = memory_name_dict.find(memory_item_old->mem_name);
+      map <string, malloc_plus_memory_entry*>::iterator it_new = memory_name_dict.find(memory_item_new->mem_name);
+      memory_name_dict.erase(it_old);
+      memory_name_dict.erase(it_new);
+
+      memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(memory_item_old->mem_name, memory_item_old) );
+      memory_name_dict.insert(std::pair<string, malloc_plus_memory_entry*>(memory_item_new->mem_name, memory_item_new) );
+
+      // memory items have been swapped, so return the new pointers
+      *malloc_mem_ptr_old = (float *)memory_item_old->mem_ptr;
+      *malloc_mem_ptr_new = (float *)memory_item_new->mem_ptr;
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+}
+
+void MallocPlus::memory_swap(double **malloc_mem_ptr_old, double **malloc_mem_ptr_new){
+   map <void *, malloc_plus_memory_entry*>::iterator it_old = memory_ptr_dict.find(*malloc_mem_ptr_old);
+   map <void *, malloc_plus_memory_entry*>::iterator it_new = memory_ptr_dict.find(*malloc_mem_ptr_new);
+
+   if (it_old != memory_ptr_dict.end() && it_new != memory_ptr_dict.end() ){
+      // Swap the memory entries during the retrieval
+      malloc_plus_memory_entry *memory_item_new = it_old->second;
+      malloc_plus_memory_entry *memory_item_old = it_new->second;
+
+      if (DEBUG) printf("Found memory item ptr_old %p name %s ptr_new %p name %s\n",memory_item_old->mem_ptr,memory_item_old->mem_name,memory_item_new->mem_ptr,memory_item_new->mem_name);
+
+      const char *mem_name_tmp;
+                  mem_name_tmp  = memory_item_old->mem_name;
+      memory_item_old->mem_name = memory_item_new->mem_name;
+      memory_item_new->mem_name = (char *)mem_name_tmp;
+
+      // Delete the ptr entries
+      memory_ptr_dict.erase(it_old);
+      memory_ptr_dict.erase(it_new);
+
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(memory_item_old->mem_ptr, memory_item_old) );
+      memory_ptr_dict.insert(std::pair<void *, malloc_plus_memory_entry*>(memory_item_new->mem_ptr, memory_item_new) );
+
+      // Delete the named entries
+      map <string, malloc_plus_memory_entry*>::iterator it_old = memory_name_dict.find(memory_item_old->mem_name);
+      map <string, malloc_plus_memory_entry*>::iterator it_new = memory_name_dict.find(memory_item_new->mem_name);
+      memory_name_dict.erase(it_old);
+      memory_name_dict.erase(it_new);
+
+      memory_name_dict.insert(std::pair<char const *, malloc_plus_memory_entry*>(memory_item_old->mem_name, memory_item_old) );
+      memory_name_dict.insert(std::pair<char const *, malloc_plus_memory_entry*>(memory_item_new->mem_name, memory_item_new) );
+
+      // memory items have been swapped, so return the new pointers
+      *malloc_mem_ptr_old = (double *)memory_item_old->mem_ptr;
+      *malloc_mem_ptr_new = (double *)memory_item_new->mem_ptr;
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+}
+
+// This duplicates memory for a variable and makes a new dictionary entry for the new variable
+void *MallocPlus::memory_duplicate(void *malloc_mem_ptr, const char *addname){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+   void *mem_ptr_dup;
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      // The memory_malloc will add the database entry
+      mem_ptr_dup = memory_malloc(memory_item->mem_nelem[0], memory_item->mem_elsize, addname, memory_item->mem_flags);
+      return(mem_ptr_dup);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(NULL);
+}
+
+void *MallocPlus::get_memory_ptr(const char *name){
+   map <string, malloc_plus_memory_entry*>::iterator it = memory_name_dict.find(name);
+
+   if (it != memory_name_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s\n",memory_item->mem_ptr,memory_item->mem_name);
+      return(memory_item->mem_ptr);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+   return(NULL);
+}
+
+bool MallocPlus::check_memory_attribute(void *malloc_mem_ptr, int attribute){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s attribute %d\n",memory_item->mem_ptr,memory_item->mem_name,memory_item->mem_flags);
+      bool bvalue = false;
+      if (memory_item->mem_flags & attribute) bvalue = true;
+
+      return bvalue;
+   } else {
+      printf("Error -- memory not found\n");
+      exit(1);
+   }
+}
+
+void MallocPlus::set_memory_attribute(void *malloc_mem_ptr, int attribute){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s attribute %d\n",memory_item->mem_ptr,memory_item->mem_name,memory_item->mem_flags);
+      memory_item->mem_flags |= attribute;
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+}
+
+void MallocPlus::clear_memory_attribute(void *malloc_mem_ptr, int attribute){
+   map <void *, malloc_plus_memory_entry*>::iterator it = memory_ptr_dict.find(malloc_mem_ptr);
+
+   if (it != memory_ptr_dict.end()){
+      malloc_plus_memory_entry *memory_item = it->second;
+
+      if (DEBUG) printf("Found memory item ptr %p name %s attribute %d\n",memory_item->mem_ptr,memory_item->mem_name,memory_item->mem_flags);
+      memory_item->mem_flags &= ~attribute;
+      if (DEBUG) printf("Found memory item ptr %p name %s attribute %d\n",memory_item->mem_ptr,memory_item->mem_name,memory_item->mem_flags);
+   } else {
+      if (DEBUG) printf("Warning -- memory not found\n");
+   }
+}
+
+extern "C" {
+   MallocPlus *MallocPlus_new(){
+     return new MallocPlus;
+   }
+
+   void MallocPlus_memory_report(MallocPlus *mem_object) {
+      mem_object->memory_report();
+   }
+
+   void MallocPlus_memory_add(MallocPlus *mem_object, void *dbleptr, size_t nelem,
+       size_t elsize, char *name, unsigned long long flags){
+//   printf("DEBUG -- nelem %lu elsize %lu\n", nelem, elsize);
+     mem_object->memory_add(dbleptr, nelem, elsize, name,
+       (unsigned long long)flags);
+   }
+   void MallocPlus_memory_add_nD(MallocPlus *mem_object, void *dbleptr, int ndim, size_t *nelem,
+       size_t elsize, char *name, unsigned long long flags){
+//   printf("DEBUG -- ndim %d nelem[0] %lu elsize %lu\n",ndim, nelem[0], elsize);
+     mem_object->memory_add(dbleptr, ndim, nelem, elsize, name,
+       (unsigned long long)flags);
+   }
+}

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/MallocPlus.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/MallocPlus.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,812 @@
+/*
+ *  Copyright (c) 2011-2013, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ * 
+ */
+#ifndef MALLOCPLUS_H_
+#define MALLOCPLUS_H_
+
+#include <map>
+#include <string>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define HOST_REGULAR_MEMORY     0x00000
+#define HOST_MANAGED_MEMORY     0x00001
+#define DEVICE_REGULAR_MEMORY   0x00002
+#define INDEX_ARRAY_MEMORY      0x00004
+#define LOAD_BALANCE_MEMORY     0x00008
+#define RESTART_DATA            0x00010
+#define REPLICATED_DATA         0x00020
+#define DISTRIBUTED_INT_DATA    0x00040
+#define DISTRIBUTED_DOUBLE_DATA 0x00080
+
+#if defined(HAVE_MPI)
+#include "mpi.h"
+#if defined(HAVE_J7)
+#include "j7/j7.h"
+#endif
+#endif
+
+using namespace std;
+
+/****************************************************************//**
+ * \brief
+ * Memory entry with fields for each entry in database
+ *******************************************************************/
+struct malloc_plus_memory_entry {
+   void   *mem_ptr;       //!< memory pointer for entry
+   size_t  mem_capacity;  //!< allocated capacity for memory buffer
+                          //!< this may be larger than the number of
+                          //!< elements and is used to internally handle
+                          //!< memory resizing
+   size_t *mem_nelem;     //!< number of elements
+   size_t  mem_ndims;     //!< number of dimensions
+   size_t  mem_elsize;    //!< element size for type of data
+   int     mem_flags;     //!< flags for special handling
+   char   *mem_name;      //!< name of memory entry
+};
+
+struct cmp_str
+{
+   bool operator()(char const *a, char const *b)
+   {
+      return strcmp(a, b) < 0;
+   }
+};
+
+/****************************************************************//**
+ * MallocPlus class
+ *    Provide an enhanced memory allocation package with database
+ *    of allocations, sizes and contiguous memory allocations for
+ *    multi-dimensional arrays
+ *******************************************************************/
+class MallocPlus {
+//protected:
+public:
+   map<string, malloc_plus_memory_entry*> memory_name_dict; //!< Dictionary entries by name
+   map<void*, malloc_plus_memory_entry*> memory_ptr_dict; //!< Dictionary entries by pointer
+
+#if defined(HAVE_MPI) && defined(HAVE_J7)
+private:
+   J7 *j7;
+#endif
+   
+public:
+   // if we have MPI support enable these routines. they only really do anything
+   // if we also have j7 support, but that's okay; we don't want ifdefs all
+   // over.
+#if defined(HAVE_MPI)
+   // parallel initialization routine
+   void pinit(MPI_Comm smComm, std::size_t memPoolSize);
+   // parallel finalization routine
+   void pfini(void);
+#endif
+
+/****************************************************************//**
+ * \brief
+ * Allocates memory for a 1D array and put entry in database
+ *
+ * **Parameters**
+ * * size_t nelem -- number of elements in array
+ * * size_t elsize -- element size in bytes
+ * * const char *name -- name of array
+ * * int flags -- flags for special handling, default is 0
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_malloc(ncells, sizeof(double),
+ *                       "Density");
+ *******************************************************************/
+   void *memory_malloc(size_t nelem, size_t elsize, const char *name, int flags=0);
+
+/****************************************************************//**
+ * \brief
+ * Duplicate memory and add new entry into database
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer to duplicate
+ * * const char *addname -- new name for variable
+ *
+ * Typical Usage
+ *
+ *     double *new_density = my_mem->memory_duplicate(density, "Density_new");
+ *******************************************************************/
+   void *memory_duplicate(void *malloc_mem_ptr, const char *addname);
+
+/****************************************************************//**
+ * \brief
+ * Reallocates memory for memory pointer in database
+ *
+ * **Parameters**
+ * * size_t nelem -- number of elements for new allocation
+ * * void *malloc_mem_ptr -- memory pointer to duplicate
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_realloc(new_ncells, density);
+ *******************************************************************/
+   void *memory_realloc(size_t nelem, void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Reallocates memory for named entry in database
+ *
+ * **Parameters**
+ * * size_t nelem -- number of elements for new allocation
+ * * const char *name -- named entry to duplicate
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_realloc(new_ncells, "Density");
+ *******************************************************************/
+   void *memory_realloc(size_t nelem, const char *name);
+
+/****************************************************************//**
+ * \brief
+ * Request memory buffer capacity reallocation for memory pointer in database.
+ * This only changes the capacity for managed memory and does not change
+ * the current number of elements registered for the array.
+ *
+ * **Parameters**
+ * * size_t capacity -- capacity in number of elements for reallocation
+ * * void *malloc_mem_ptr -- memory pointer to reallocate more capacity
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_request(new_capacity, density);
+ *******************************************************************/
+   void *memory_request(size_t new_capacity, void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Request memory buffer capacity reallocation for named entry in database.
+ * This only changes the capacity for managed memory and does not change
+ * the current number of elements registered for the array.
+ *
+ * **Parameters**
+ * * size_t capacity -- capacity in number of elements for reallocation
+ * * const char *name -- named entry in database
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_request(new_capacity, "Density");
+ *******************************************************************/
+   void *memory_request(size_t new_capacity, const char *name);
+
+/****************************************************************//**
+ * \brief
+ * Reallocates memory for all arrays in the database. Element size stays
+ * the same.
+ *
+ * **Parameters**
+ * * size_t nelem -- number of elements for new allocation
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_realloc_all(new_ncells);
+ *******************************************************************/
+   void memory_realloc_all(size_t nelem);
+
+/****************************************************************//**
+ * \brief
+ * Requests capacity reallocation for all arrays in the database. Element
+ * size and number of elements stays the same. The maximum memory
+ * capacity is increased.
+ *
+ * **Parameters**
+ * * size_t capacity -- number of elements for new allocation
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_realloc_all(new_capacity);
+ *******************************************************************/
+   void memory_request_all(size_t new_capacity);
+
+/****************************************************************//**
+ * \brief
+ * Replaces a database entry with another database entry, effectively
+ * renaming the entry and deallocating the memory for the old entry
+ * and removing the other database entry. Both the return and the 
+ * first argument old memory pointer gets reset to the new memory
+ * location.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr_old -- memory pointer to entry to replace
+ * * void * const malloc_mem_ptr_new -- memory pointer to entry to
+ *       put in place of old memory
+ *
+ * Typical Usage
+ *
+ *     double *density_new = (double *)my_mem->memory_malloc(new_ncells,
+ *                           sizeof(double), "Density_new");
+ *       ... lots of calculations of density_new from density (old) ...
+ *     density = (double *)my_mem->memory_replace(density, density_new);
+ *******************************************************************/
+   void *memory_replace(void *malloc_mem_ptr_old, void * const malloc_mem_ptr_new);
+
+/****************************************************************//**
+ * \brief
+ * Swaps a database entry with another database entry, effectively
+ * renaming both entries. The new pointers are returned in the
+ * two arguments.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr_old -- memory pointer to swap
+ * * void *malloc_mem_ptr_new -- memory pointer to swap
+ *
+ * Typical Usage
+ *
+ *     int *level_old = (int *)my_mem->memory_malloc(new_ncells,
+ *                           sizeof(int), "level_old");
+ *     level = (int *)my_mem->memory_swap(&level, &level_old);
+ *       ... lots of calculations of level from level_new ...
+ *     my_mem->memory_delete(level_old);
+ *******************************************************************/
+   void memory_swap(int **malloc_mem_ptr_old, int **malloc_mem_ptr_new);
+
+/****************************************************************//**
+ * \brief
+ * Swaps a database entry with another database entry, effectively
+ * renaming both entries. The new pointers are returned in the
+ * two arguments.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr_old -- memory pointer to swap
+ * * void *malloc_mem_ptr_new -- memory pointer to swap
+ *
+ * Typical Usage
+ *
+ *     float *density_old = (float *)my_mem->memory_malloc(new_ncells,
+ *                           sizeof(float), "Density_old");
+ *     density = (float *)my_mem->memory_swap(&density, &density_old);
+ *       ... lots of calculations of density from density_new ...
+ *     my_mem->memory_delete(density_old);
+ *******************************************************************/
+   void memory_swap(float **malloc_mem_ptr_old, float **malloc_mem_ptr_new);
+
+/****************************************************************//**
+ * \brief
+ * Swaps a database entry with another database entry, effectively
+ * renaming both entries. The new pointers are returned in the
+ * two arguments.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr_old -- memory pointer to swap
+ * * void *malloc_mem_ptr_new -- memory pointer to swap
+ *
+ * Typical Usage
+ *
+ *     double *density_old = (double *)my_mem->memory_malloc(new_ncells,
+ *                           sizeof(double), "Density_old");
+ *     density = (double *)my_mem->memory_swap(&density, &density_old);
+ *       ... lots of calculations of density from density_new ...
+ *     my_mem->memory_delete(density_old);
+ *******************************************************************/
+   void memory_swap(double **malloc_mem_ptr_old, double **malloc_mem_ptr_new);
+
+/****************************************************************//**
+ * \brief
+ * Adds an entry for an already allocated array into the database
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer to add
+ * * size_t nelem -- number of elements in array
+ * * size_t elsize -- element size in bytes
+ * * const char *name -- name of array
+ * * int flags -- flags for special handling, default is 0
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_add(density, ncells, sizeof(double),
+ *                       "Density");
+ *******************************************************************/
+   void *memory_add(void *malloc_mem_ptr, size_t nelem, size_t elsize,
+      const char *name, int flags=0);
+
+   void *memory_add(void *malloc_mem_ptr, int ndim, size_t *nelem, size_t elsize,
+      const char *name, int flags=0);
+
+/****************************************************************//**
+ * \brief
+ * Reorders all of the arrays in the database by the indices in the
+ * iorder array. The reorder does the following:
+ *     tmp[ic] = density[iorder[ic]];
+ *     SWAP_PTR(tmp, density);
+ * Note that the pointer value will change during the operation and
+ * will be returned in the return value.
+ *
+ * **Parameters**
+ * * double *malloc_mem_ptr -- memory pointer to entry to reorder
+ * * int *iorder -- index array for reordering
+ *
+ * Typical Usage
+ *
+ *     double *density = my_mem->memory_reorder_all(density, iorder);
+ *******************************************************************/
+   double *memory_reorder(double *malloc_mem_ptr, int *iorder);
+
+/****************************************************************//**
+ * \brief
+ * Reorders all of the arrays in the database by the indices in the
+ * iorder array. The reorder does the following:
+ *     tmp[ic] = density[iorder[ic]];
+ *     SWAP_PTR(tmp, density);
+ * Note that the pointer value will change during the operation and
+ * will be returned in the return value.
+ *
+ * **Parameters**
+ * * float *malloc_mem_ptr -- memory pointer to entry to reorder
+ * * int *iorder -- index array for reordering
+ *
+ * Typical Usage
+ *
+ *     float *density = my_mem->memory_reorder_all(density, iorder);
+ *******************************************************************/
+   float *memory_reorder(float *malloc_mem_ptr, int *iorder);
+
+/****************************************************************//**
+ * \brief
+ * Reorders all of the arrays in the database by the indices in the
+ * iorder array. The reorder does the following:
+ *     tmp[ic] = level[iorder[ic]];
+ *     SWAP_PTR(tmp, level);
+ * Note that the pointer value will change during the operation and
+ * will be returned in the return value.
+ *
+ * **Parameters**
+ * * int *malloc_mem_ptr -- memory pointer to entry to reorder
+ * * int *iorder -- index array for reordering
+ *
+ * Typical Usage
+ *
+ *     int *level = my_mem->memory_reorder_all(level, iorder);
+ *******************************************************************/
+   int *memory_reorder(int *malloc_mem_ptr, int *iorder);
+
+/****************************************************************//**
+ * \brief
+ * Reorders an index array in the database by the indices in the
+ * iorder array and reindexes the array by the inverse order given
+ * by inv_iorder. The reorder does the following:
+ *     tmp[ic] = inv_iorder[level[iorder[ic]]];
+ *     SWAP_PTR(tmp, level);
+ * Note that the pointer value will change during the operation and
+ * will be returned in the return value.
+ *
+ * **Parameters**
+ * * int *malloc_mem_ptr -- memory pointer to entry to reorder
+ * * int *iorder -- index array for reordering
+ * * int *inv_order -- inverse index array for reordering
+ *
+ * Typical Usage
+ *
+ *     int *level = my_mem->memory_reorder_all(level, iorder, inv_iorder);
+ *******************************************************************/
+   int *memory_reorder_indexarray(int *malloc_mem_ptr, int *iorder, int *inv_iorder);
+
+/****************************************************************//**
+ * \brief
+ * Reorders all of the arrays in the database by the indices in the
+ * iorder array. The reorder does the following:
+ *     tmp[ic] = density[iorder[ic]];
+ *     SWAP_PTR(tmp, density);
+ * Note that the pointer value will change during the operation and
+ * must be retrieved from the database.
+ *
+ * **Parameters**
+ * * int *iorder -- index array for reordering
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_reorder_all(iorder);
+ *******************************************************************/
+   void memory_reorder_all(int *iorder);
+
+/****************************************************************//**
+ * \brief
+ * Prints out a report of all the arrays in the database.
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_report();
+ *******************************************************************/
+   void memory_report(void);
+
+/****************************************************************//**
+ * \brief
+ * Deallocates memory for a memory pointer in the database and removes the
+ * entry from the database.
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_delete(density);
+ *******************************************************************/
+   void *memory_delete(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Deallocates memory for a named entry in the database and removes the
+ * entry from the database.
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_delete("Density");
+ *******************************************************************/
+   void *memory_delete(const char *name);
+
+/****************************************************************//**
+ * \brief
+ * Deallocates memory for all arrays in the database.
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_delete_all();
+ *******************************************************************/
+   void memory_delete_all(void);
+
+/****************************************************************//**
+ * \brief
+ * Removes the entry for a memory pointer from the database. (This does
+ * not delete the memory).
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_delete(density);
+ *******************************************************************/
+   void memory_remove(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Removes the entry for a named entry from the database. (This does
+ * not delete the memory).
+ *
+ * Typical Usage
+ *
+ *     my_mem->memory_delete("Density");
+ *******************************************************************/
+   void memory_remove(const char *name);
+
+/****************************************************************//**
+ * \brief
+ * Gets initial memory pointer from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     for (void *mem_ptr = my_mem.memory_begin(); mem_ptr!=NULL;
+ *          mem_ptr = my_mem.memory_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   void *memory_begin(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets next memory pointer from database for iterating over the
+ * entries and processing each. Note that their is an implied caching
+ * of the current memory pointer in MallocPlus.
+ *
+ * Typical Usage
+ *
+ *     for (void *mem_ptr = my_mem.memory_begin(); mem_ptr!=NULL;
+ *          mem_ptr = my_mem.memory_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   void *memory_next(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets initial memory pointer from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     for (void *mem_ptr = my_mem.memory_by_name_begin(); mem_ptr!=NULL;
+ *          mem_ptr = my_mem.memory_by_name_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   void *memory_by_name_begin(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets next memory pointer from database for iterating over the
+ * entries and processing each. Note that their is an implied caching
+ * of the current memory pointer in MallocPlus.
+ *
+ * Typical Usage
+ *
+ *     for (void *mem_ptr = my_mem.memory_by_name_begin(); mem_ptr!=NULL;
+ *          mem_ptr = my_mem.memory_by_name_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   void *memory_by_name_next(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets initial memory entry from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     malloc_plus_memory_entry memory_item;
+ *     for (memory_item = my_mem.memory_entry_begin(); 
+ *          memory_item != my_mem.memory_entry_end();
+ *          memory_item = my_mem.memory_entry_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   malloc_plus_memory_entry *memory_entry_begin(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets next memory entry from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     malloc_plus_memory_entry memory_item;
+ *     for (memory_item = my_mem.memory_entry_begin(); 
+ *          memory_item != my_mem.memory_entry_end();
+ *          memory_item = my_mem.memory_entry_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   malloc_plus_memory_entry *memory_entry_next(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets initial memory iterator from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     malloc_plus_memory_entry *memory_item;
+ *     for (memory_item = my_mem.memory_entry_begin(); 
+ *          memory_item != my_mem.memory_entry_end();
+ *          memory_item = my_mem.memory_entry_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   malloc_plus_memory_entry *memory_entry_end(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets initial memory entry from name database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     malloc_plus_memory_entry memory_item;
+ *     for (memory_item = my_mem.memory_entry_by_name_begin(); 
+ *          memory_item != my_mem.memory_entry_by_name_end();
+ *          memory_item = my_mem.memory_entry_by_name_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   malloc_plus_memory_entry *memory_entry_by_name_begin(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets next memory entry from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     malloc_plus_memory_entry memory_item;
+ *     for (memory_item = my_mem.memory_entry_by_name_begin(); 
+ *          memory_item != my_mem.memory_entry_by_name_end();
+ *          memory_item = my_mem.memory_entry_by_name_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   malloc_plus_memory_entry *memory_entry_by_name_next(void);
+
+/****************************************************************//**
+ * \brief
+ * Gets initial memory iterator from database for iterating over the
+ * entries and processing each.
+ *
+ * Typical Usage
+ *
+ *     malloc_plus_memory_entry *memory_item;
+ *     for (memory_item = my_mem.memory_entry_by_name_begin(); 
+ *          memory_item != my_mem.memory_entry_by_name_end();
+ *          memory_item = my_mem.memory_entry_by_name_next() ){
+ *        ... process entries ...
+ *     }
+ *******************************************************************/
+   malloc_plus_memory_entry *memory_entry_by_name_end(void);
+
+/****************************************************************//**
+ * \brief
+ * Get number of elements for a memory pointer in the database.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer for entry in the database
+ * 
+ * Typical Usage
+ *
+ *     size_t nsize = my_mem->get_memory_size(density);
+ *******************************************************************/
+   size_t get_memory_size(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Get the memory capacity in number of elements for a memory pointer
+ * in the database. Memory capacity is the overallocated size of the
+ * array in schemes where memory is managed internally to reduce
+ * the number of reallocations.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer for entry in the database
+ * 
+ * Typical Usage
+ *
+ *     size_t var_capacity = my_mem->get_memory_capacity(density);
+ *******************************************************************/
+   size_t get_memory_capacity(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Get the element size for a memory pointer in the database.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer for entry in the database
+ * 
+ * Typical Usage
+ *
+ *     int elsize = my_mem->get_memory_elemsize(density);
+ *******************************************************************/
+   int get_memory_elemsize(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Get name for a memory pointer in the database.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer for entry in the database
+ * 
+ * Typical Usage
+ *
+ *     const char *var_name = my_mem->get_memory_name(density);
+ *******************************************************************/
+   const char *get_memory_name(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Get memory pointer for a named entry from the database.
+ *
+ * **Parameters**
+ * * const char *name -- name of entry in the database
+ * 
+ * Typical Usage
+ *
+ *     density = my_mem->get_memory_ptr("Density");
+ *******************************************************************/
+   void *get_memory_ptr(const char *name);
+
+/****************************************************************//**
+ * \brief
+ * Set a memory attribute for a memory pointer in the database.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer of entry in the database
+ * * int attribute -- flag to set for entry
+ *
+ * Typical Usage
+ *
+ *     my_mem->set_memory_attribute(density, HOST_MANAGED_MEMORY);
+ *******************************************************************/
+   void set_memory_attribute(void *malloc_mem_ptr, int attribute);
+
+/****************************************************************//**
+ * \brief
+ * Clear memory attribute for a memory pointer in the database.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer of entry in the database
+ * * int attribute -- flag to clear for entry
+ *
+ * Typical Usage
+ *
+ *     my_mem->clear_memory_attribute(density, HOST_MANAGED_MEMORY);
+ *******************************************************************/
+   void clear_memory_attribute(void *malloc_mem_ptr, int attribute);
+
+/****************************************************************//**
+ * \brief
+ * Get memory attributes for a memory pointer in the database. Returns
+ * the flag field.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer of entry in the database
+ *
+ * Typical Usage
+ *
+ *     int flag = my_mem->get_memory_attribute(density);
+ *******************************************************************/
+   int  get_memory_flags(void *malloc_mem_ptr);
+
+/****************************************************************//**
+ * \brief
+ * Checks the setting for a memory attribute for a memory pointer in
+ * the database. Returns true for set and false for unset.
+ *
+ * **Parameters**
+ * * void *malloc_mem_ptr -- memory pointer of entry in the database
+ * * int attribute -- flag to check setting for entry
+ *
+ * Typical Usage
+ *
+ *     bool flag = my_mem->check_memory_attribute(density, HOST_MANAGED_MEMORY);
+ *******************************************************************/
+   bool  check_memory_attribute(void *malloc_mem_ptr, int attribute);
+};
+
+extern "C" {
+  MallocPlus *MallocPlus_new();
+           
+  void MallocPlus_memory_report(MallocPlus *mem_object);
+
+  void MallocPlus_memory_add(MallocPlus *mem_object, void *dbleptr,
+    size_t nelem, size_t elsize, char *name, unsigned long long flags);
+  void MallocPlus_memory_add_nD(MallocPlus *mem_object, void *dbleptr,
+    int ndim, size_t *nelem, size_t elsize, char *name, unsigned long long flags);
+}
+
+#endif // ifndef MALLOCPLUS_H_
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Parser_math.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,326 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// This class collects various parser math functions.
+//
+// There are two reasons to have this class:
+//     1. To keep the command processing class from getting too big.
+//     2. Some of these functions are used in more than one class.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+#include <math.h>
+
+#include "Word.hh"
+#include "Parser_math.hh"
+
+namespace PP
+{
+using std:: string;
+using std::cout;
+using std::endl;
+using std::stringstream;
+using std::setprecision;
+using std::vector;
+using std::deque;
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Parser_math::Parser_math()
+{
+}
+
+
+// ===========================================================================
+// Do a single arithmetic binary operation involving 3 words. i1, on the left,
+// is supposed to be a number, i2 is the operator, and i3, on the right, is
+// supposed to be a number.
+// The result is put in word wres.
+// ===========================================================================
+void Parser_math::do_op(int i1, int i2, int i3,deque <Word> &wq, Word &wres,
+                        stringstream &serr, int &ierr)
+{
+    // The words to the left and right of the operator have to be a number.
+    if ((!wq[i1].is_number()) || (!wq[i3].is_number())) {
+        wq[i2].fatal_error(serr, ierr);
+        serr << "Expected some number " << wq[i2].get_string() <<
+            " some number" << endl;
+        serr << "But did not find a number, instead found" << endl;
+        serr << wq[i1].get_string() << wq[i2].get_string() <<
+            wq[i3].get_string() << endl;
+        ierr = 2;
+        wres.set_value(0.);
+        return;
+    }
+
+
+    double d1 = wq[i1].get_double();
+    string op = wq[i2].get_string();
+    double d2 = wq[i3].get_double();
+
+    double result = 0.;
+
+    if (op == "+") result = d1 + d2;
+    if (op == "-") result = d1 - d2;
+    if (op == "*") result = d1 * d2;
+
+    if (op == "**") {
+        if (d1 == 0. && d2 >= 0.) {
+            wres.set_value(0.);
+            return;
+        }
+
+        if (d1 == 0. && d2 < 0.) {
+            wq[i2].fatal_error(serr, ierr);
+            serr << "Trying to exponentiate 0 to a negative power." << endl;
+            serr << "Base = " << d1 << "  Exponent = " << d2 << endl;
+            ierr = 2;
+            wres.set_value(0.);
+            return;
+        }
+
+        if (d1 < 0. && !wq[i3].is_integer()) {
+            wq[i2].fatal_error(serr, ierr);
+            serr << "Trying to exponentiate a negative number to a non-integer power." << endl;
+            serr << "Base = " << d1 << "  Exponent = " << d2 << endl;
+            ierr = 2;
+            wres.set_value(0.);
+            return;
+        }
+
+        result = pow(d1,d2);
+    }
+
+    if (op == "/") {
+        if (d2 == 0.) {
+            if (d1 == 0.) result = 0.;
+            else          result = 1.e30;
+            wq[i2].fatal_error(serr, ierr);
+            serr << "Divide by 0." << endl;
+            serr << "Numerator = " << d1 << "  Denominator = " << d2 << endl;
+            ierr = 2;
+            wres.set_value(result);
+            return;
+        }
+        result = d1 / d2;
+    }
+
+    // Do not implement the % operator, it is too much like the fortran %
+    // operator which is for referencing components of a fortran structure.
+    /*
+    if (op == "%") {
+        if (d2 == 0.) {
+            result = 0.;
+            wq[i2].fatal_error(serr, ierr);
+            serr << "Modulus (%) second argument is 0." << endl;
+            serr << "First arg = " << d1 << "  second arg = " << d2 << endl;
+            ierr = 2;
+            wres.set_value(result);
+            return;
+        }
+        result = ((int)d1) % ((int)d2);
+    }
+    */
+
+    wres.set_value(result);
+}
+
+
+// ===========================================================================
+// Do a single relational binary operation involving 3 words.
+// Relational operators include .eq., .ne., .le., ...
+// The result is either true or false and is put in word wres.
+// ===========================================================================
+void Parser_math::do_op_relational(int i1, int i2, int i3, deque <Word> &wq,
+                                   Word &wres, stringstream &serr, int &ierr)
+{
+    string s1 = wq[i1].get_string();
+    string op = wq[i2].get_string();
+    string s3 = wq[i3].get_string();
+    bool result = false;
+
+    //cout << "&&&&&cw op = " << s1 << op << s3 << endl;
+
+    if ((wq[i1].is_bool()) && (wq[i3].is_bool())) {
+        if (op == ".gt." || op == ".ge." || op == ".lt." || op == ".le.") {
+            wq[i2].fatal_error(serr, ierr);
+            serr << "Does not make sense to compare logical values" << endl;
+            serr << " with greater than or less than" << endl;
+            serr << "    " << s1 << " " << op << " " << s3 << endl;
+            ierr = 2;
+            wres.set_value(false);
+            return;
+        }
+    }
+
+    if ( ((wq[i1].is_bool()) && (!wq[i3].is_bool())) ||
+         ((!wq[i1].is_bool()) && (wq[i3].is_bool()))
+         ) {
+        wq[i2].fatal_error(serr, ierr);
+        serr << "Does not make sense to compare logical and" << endl;
+        serr << " non-logical values" << endl;
+        serr << "    " << s1 << " " << op << " " << s3 << endl;
+        ierr = 2;
+        wres.set_value(false);
+        return;
+    }
+
+    if ( ((wq[i1].is_number()) && (!wq[i3].is_number())) ||
+         ((!wq[i1].is_number()) && (wq[i3].is_number()))
+         ) {
+        wq[i2].fatal_error(serr, ierr);
+        serr << "Does not make sense to compare numerical and" << endl;
+        serr << " non-numerical values" << endl;
+        serr << "    " << s1 << " " << op << " " << s3 << endl;
+        ierr = 2;
+        wres.set_value(false);
+        return;
+    }
+
+    // Compare two numbers.
+    if ( (wq[i1].is_number()) && (wq[i3].is_number()) ) {
+        double d1 = wq[i1].get_double();
+        double d3 = wq[i3].get_double();
+        if (op == ".gt.") result = d1 >  d3;
+        if (op == ".ge.") result = d1 >= d3;
+        if (op == ".lt.") result = d1 <  d3;
+        if (op == ".le.") result = d1 <= d3;
+        if (op == ".eq.") result = d1 == d3;
+        if (op == ".ne.") result = d1 != d3;
+        //cout << "&&&&&cw relational result = " << result << endl;
+        wres.set_value(result);
+        return;
+    }
+
+    if ( (wq[i1].is_bool()) && (wq[i3].is_bool()) ) {
+        bool b1 = wq[i1].get_bool(serr, ierr);
+        bool b3 = wq[i3].get_bool(serr, ierr);
+        if (op == ".eq.") result = b1 == b3;
+        if (op == ".ne.") result = b1 != b3;
+        //cout << "&&&&&cw relational result = " << result << endl;
+        wres.set_value(result);
+        return;
+    }
+
+    // Compare two strings.
+    if (op == ".gt.") result = s1 >  s3;
+    if (op == ".ge.") result = s1 >= s3;
+    if (op == ".lt.") result = s1 <  s3;
+    if (op == ".le.") result = s1 <= s3;
+    if (op == ".eq.") result = s1 == s3;
+    if (op == ".ne.") result = s1 != s3;
+    wres.set_value(result);
+    return;
+}
+
+// ===========================================================================
+// Do the .not. operation, this is different from all the others in that
+// .not. is a unary operator, the others are binary ops.
+// The result is either true or false and is put in word wres.
+// ===========================================================================
+void Parser_math::do_op_not(int i2, int i3, deque <Word> &wq,
+                            Word &wres, stringstream &serr, int &ierr)
+{
+    string op = wq[i2].get_string();
+    string s3 = wq[i3].get_string();
+    bool result = false;
+
+    if (!wq[i3].is_bool()) {
+        wq[i2].fatal_error(serr, ierr);
+        serr << "The word following the .not. operator must be"
+             " true or false." << endl;
+        serr << "Instead the word following .not. is " << s3 << endl;
+        ierr = 2;
+        wres.set_value(false);
+        return;
+    }
+
+    result = true;
+    if (wq[i3].get_bool(serr, ierr) == true) result = false;
+    wres.set_value(result);
+    return;
+}
+
+
+// ===========================================================================
+// Do a single logical binary operation involving 3 words.
+// The binary logical operators are .and. and .or.
+// The result is either true or false and is put in word wres.
+// ===========================================================================
+void Parser_math::do_op_logical(int i1, int i2, int i3, deque <Word> &wq,
+                                Word &wres, stringstream &serr, int &ierr)
+{
+    string s1 = wq[i1].get_string();
+    string op = wq[i2].get_string();
+    string s3 = wq[i3].get_string();
+    bool result = false;
+
+    //cout << "&&&&&cw logical = " << s1 << op << s3 << endl;
+
+    // For .and. and .or., both operands must be boolean.
+    if ((!wq[i1].is_bool()) || (!wq[i3].is_bool())) {
+        wq[i2].fatal_error(serr, ierr);
+        serr << "The operator is " << op << endl;
+        serr << "The two operands (on the left and right of the operator)" << endl;
+        serr << "must be logical values (true or false)." << endl;
+        serr << "    " << s1 << " " << op << " " << s3 << endl;
+        ierr = 2;
+        wres.set_value(false);
+        return;
+    }
+
+    bool b1 = wq[i1].get_bool(serr, ierr);
+    bool b3 = wq[i3].get_bool(serr, ierr);
+    if (op == ".and.") result = b1 && b3;
+    if (op == ".or.")  result = b1 || b3;
+    //cout << "&&&&&cw logical result = " << result << endl;
+    wres.set_value(result);
+    return;
+}
+
+
+
+} // End of the PP namespace

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Parser_math.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_math.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,85 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef PARSERMATHHHINCLUDE
+#define PARSERMATHHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// This class collects various parser math functions.
+// There are two reasons to have this class:
+// 1. To keep the command processing class from getting too big.
+// 2. Some of these functions are used in more than one class.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+
+namespace PP
+{
+using std::string;
+using std::stringstream;
+using std::vector;
+using std::deque;
+
+
+class Parser_math
+{
+
+public:
+    Parser_math();
+
+    void do_op(int i1, int i2, int i3, deque <Word> &wq, Word &wres,
+               stringstream &serr, int &ierr);
+    void do_op_relational(int i1, int i2, int i3, deque <Word> &wq,
+                          Word &wres, stringstream &serr, int &ierr);
+    void do_op_logical(int i1, int i2, int i3, deque <Word> &wq,
+                       Word &wres, stringstream &serr, int &ierr);
+    void do_op_not(int i2, int i3, deque <Word> &wq,
+                   Word &wres, stringstream &serr, int &ierr);
+
+
+private:
+
+};
+
+
+} // End of the PP namespace
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Parser_utils.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,329 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// This class collects various low level utilities for the parser.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+
+#include "Parser_utils.hh"
+
+namespace PP
+{
+using std:: string;
+using std::cout;
+using std::endl;
+using std::stringstream;
+using std::setprecision;
+using std::vector;
+using std::deque;
+using std::setw;
+
+static int index_base = 1; // For Fortran, 0 for C/C++style
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Parser_utils::Parser_utils(int base)
+{
+   index_base = base;
+}
+
+
+// ===========================================================================
+// Given an array command like
+//     cmd(5,3) = 1.0, 3.0, -5.0
+// find the starting position in a 1d array.
+//
+// The indices in cmd are referenced from 1 (i.e. fortran) while the 1d array
+// is referenced from 0 (C++).
+//
+// This function works for any dimension array, 0,1,2,3,...
+//
+// Example 1: Consider a 1d command
+//     cmd(5) = 1.0, 3.4
+// We start filling the 1d fortran array at position 5 and put in two values.
+// Subtract 1 to reference from 0, so this function returns 4.
+//
+// Example 2: Consider the 2d command above:
+//     cmd(5,3) = 1.0, 3.0, -5.0
+// We also need to know that the max size of the first dimension is say 7.
+// Since in fortran, the first index varies fastest, the fortran 1d index
+// would be
+//     5 + (3-1)*7 = 19
+// Subtract 1 to reference from 0, thus the return value is 18.
+//
+// The istart vector contains the indices, for example 2 this would be 5 and
+// 3. The size vector contains the max size of each dimension, for example 2
+// this would be 7 and whatever for the second dimension.
+// ===========================================================================
+int Parser_utils::start_dex(vector<int> &istart, const vector<int> &size)
+{
+    // Get the array dimension, 0,1,2,3,...
+    int dim = (int)istart.size();
+
+    // 0d is a special case.
+    if (dim == 0) return 0;
+
+    // Find the index.
+    // Adjustment for base 1
+    int ix = istart[0]-index_base;
+    for (int i=1; i<dim; i++) {
+        int t = istart[i]-index_base;
+        for (int j=0; j<i; j++) {
+            t *= size[j];
+        }
+        ix += t;
+    }
+
+    return ix;
+}
+    
+
+// ===========================================================================
+// This is the reverse of the start_dex function above.
+// Given the 1d index, icdex (from 0 to nvals-1), find the corresponding
+// multi dimensional fortran indices (each starting from 1).
+//
+// Example 1: Consider a 1d array
+//     var1d(1) = 1 3 5 9 -4 -5 6
+// Suppose the user inputs icdex=3, corresponding to array value 9.
+// This 1d case is very simple, all we do is add 1 to icdex to get a reference
+// from 1, thus returning 4.
+//
+// Example 1: Consider a 2d array
+//     $var2d(1,1) = 11. 21. 31.   12. 22. 32.   13. 23. 33.
+// Where the max of the first dimension is 3. Suppose the user specifies
+// icdex = 5, this corresponds to array value 32. The two indices returned
+// would be 3,2 (referenced from 1).
+//
+// The istart vector contains the output indices, for example 2 this would be 3
+// and 2. The size vector contains the max size of each dimension, for example
+// 2 this would be 3 and whatever for the second dimension. The number of
+// elements in size is normally dim-1, but it does not hurt if it has dim
+// elements (in which case the last element is not referenced or used).
+// ===========================================================================
+void Parser_utils::reverse_dex(int icdex,
+                               int nvals,
+                               vector<int> &istart,
+                               const vector<int> &size)
+{
+    // Get the dimension.
+    int dim = (int)istart.size();
+
+    // Nothing to do for scalars.
+    if (dim == 0) return;
+
+    // Start at 1,1,1,1,1,1,...
+    for (int i=0; i<dim; i++) {
+        istart[i] = index_base;
+    }
+
+    // Get the first 1d index (referenced from 0)
+    int i1 = start_dex(istart, size);
+    if (i1 == icdex) return;
+
+    // Go through all indices until the desired one is found.
+    // Yes, this is inefficient, but dim is a small integer, like 2,3,4, so
+    // the efficiency does not really matter.
+    // Perhaps somebody can devise a better algorithm someday.
+    for (int i1dex=0; i1dex<nvals; i1dex++) {
+        for (int i=0; i<dim; i++) {
+            if (i < dim-1) {
+                if (istart[i] == size[i]) {
+                    istart[i] = index_base;
+                }
+                else {
+                    istart[i] += 1;
+                    break;
+                }
+            }
+            else {
+                istart[i] += 1;
+                break;
+            }
+        }
+
+        i1 = start_dex(istart, size);
+        if (i1 == icdex) return;
+    }
+}
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// Utilities for printing to the screen (or to a file).
+// ***************************************************************************
+// ***************************************************************************
+
+
+
+// ===========================================================================
+
+
+//                    Line                                                        
+//      Filename     Number                         Command                       
+//    ------------   ------   ------------------------------------------------
+//         test.in        4   some_logical_cmd = false
+//         test.in       28   some_logical_cmd = false
+//         test.in      170   some_logical_cmd = false
+//         test.in      175   some_logical_cmd = true     //No space betwe ...
+//    test_inc1.in        2   some_logical_cmd = true
+//    test_inc3.in        2   some_logical_cmd = true
+//                             
+//         test.in      442   strinsert_cmd01 = "test duplicates commands"
+//         test.in      456   strinsert_cmd01 = "test duplicates commands"
+
+
+
+// Given a header row of strings and several data rows of string where each
+// row consists of the same number of columns, list all the rows with the
+// columns lined up and the headers centered on the columns.
+// ===========================================================================
+void Parser_utils::print_strings(vector< vector<string> > rows, int n_header_rows,
+                                 int offset, int col_spacing, int line_len_max,
+                                 stringstream &ss)
+{
+    // Get the number of columns.
+    int ncol = (int)rows[0].size();
+
+    // Find the max number of characters in each column for all the rows.
+    vector<int> maxc(ncol, 0);
+    for (int row=0; row<(int)rows.size(); row++) {
+        for (int c=0; c<ncol; c++) {
+            string s = rows[row][c];
+            if ((int)s.size() > maxc[c]) maxc[c] = (int)s.size();
+        }
+    }
+
+    // Find the column widths.
+    vector<int> col_width(ncol,0);
+    for (int c=0; c<ncol; c++) {
+        if (maxc[c] > col_width[c]) col_width[c] = maxc[c];
+    }
+
+    // Spacing between columns.
+    vector<int> cspace(ncol, col_spacing);
+    cspace[0] = offset;
+
+    // Limit the lines to a max length.
+    if (line_len_max > 0) {
+        int line_len = 0;
+        for (int c=0; c<ncol; c++) {
+            line_len += cspace[c] + col_width[c];
+        }
+        int excess_c = line_len - line_len_max;
+
+        if (excess_c > 0) {
+            col_width[ncol-1] -= excess_c;
+            for (int row=0; row<(int)rows.size(); row++) {
+                int len = 0;
+                for (int c=0; c<ncol; c++) {
+                    string s = rows[row][c];
+                    if (c < ncol-1) len += cspace[c] + col_width[c];
+                    if (c == ncol-1) len += cspace[c] + (int)s.size();
+                }
+                if (len <= line_len_max) continue;
+
+                int c = ncol -1;
+                string s = rows[row][c];
+                int ec = len - line_len_max;
+                int start = (int)s.size() - ec - 4;
+                if (start < 0) start = 0;
+                int nc = ec+4;
+                if (nc > (int)s.size()) nc = (int)s.size();
+                s.erase(start, nc);
+                rows[row][c] = s + " ...";
+            }
+        }
+    }
+
+
+    // Write the rows.
+    for (int row=0; row<(int)rows.size(); row++) {
+
+        // Insert the line of dashes after the header rows.
+        if (row == n_header_rows) {
+            for (int c=0; c<ncol; c++) {
+                for (int i=0; i<cspace[c]; i++) ss << " ";
+                for (int i=0; i<col_width[c]; i++) ss << "-";
+            }
+            ss << endl;
+        }
+
+        for (int c=0; c<ncol; c++) {
+            // Use nc to center the headers, but not center the data.
+            int nc = maxc[c];
+            if (row < n_header_rows) nc = (int)rows[row][c].size();
+
+            int nsp_left = 0;
+            int nsp_right = 0;
+            int dsp = col_width[c] - nc;
+            if (dsp > 0) {
+                nsp_left = dsp/2;
+                nsp_right = col_width[c] - nsp_left - nc;
+            }
+            for (int i=0; i<cspace[c]; i++) ss << " ";
+            for (int i=0; i<nsp_left; i++) ss << " ";
+
+
+            if (row >= n_header_rows) {
+                if (c < ncol-1)  ss << setw(maxc[c]) << rows[row][c];
+                if (c == ncol-1) ss << rows[row][c];
+            }
+            else {
+                ss << rows[row][c];
+            }
+
+            for (int i=0; i<nsp_right; i++) ss << " ";
+        }
+        ss << endl;
+    }
+}
+
+
+
+} // End of the PP namespace

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Parser_utils.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Parser_utils.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,80 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef PARSERUTILSHHINCLUDE
+#define PARSERUTILSHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// This class collects various low level utilities for the parser.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+
+namespace PP
+{
+using std::string;
+using std::stringstream;
+using std::vector;
+using std::deque;
+
+
+class Parser_utils
+{
+
+public:
+    Parser_utils(int base);
+
+    int start_dex(vector<int> &istart, const vector<int> &size);
+    void reverse_dex(int icdex, int nvals, vector<int> &istart,
+                     const vector<int> &size);
+
+    void print_strings(vector< vector<string> > rows, int n_header_rows,
+                       int offset, int col_spacing, int line_len_max,
+                       stringstream &ss);
+
+private:
+
+};
+
+
+} // End of the PP namespace
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/PowerParser.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,3269 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// Provide a class that parses text files into lines and words.
+// ***************************************************************************
+// ***************************************************************************
+
+#include "PowerParser.hh"
+#include "Parser_utils.hh"
+#include "Variable.hh"
+#include "Function.hh"
+#include <cctype>
+#include <cstdio>
+#include <unistd.h>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <algorithm>
+#include <stdint.h>
+#include <string.h>
+#include <cstdlib>
+#include <assert.h>
+
+namespace PP
+{
+using std::cout;
+using std::endl;
+using std::string;
+using std::ifstream;
+using std::ios;
+using std::deque;
+using std::map;
+using std::pair;
+using std::vector;
+using std::stringstream;
+using std::setw;
+using std::setprecision;
+using std::numeric_limits;
+
+static int index_base = 1;
+static bool case_sensitive = false;
+
+// ===========================================================================
+// Various constructors.
+// ===========================================================================
+PowerParser::PowerParser()
+{
+    comm = new Comm();
+
+    init();                     // Init vars, setup functions, ...
+    nrb_on_dump = 0;
+    coutbuf = NULL;
+}
+
+PowerParser::PowerParser(string filename)
+{
+    comm = new Comm();
+
+    init();                     // Init vars, setup functions, ...
+    nrb_on_dump = 0;
+    parse_file(filename);       // Parse the file.
+    coutbuf = NULL;
+}
+
+PowerParser::PowerParser(const char *filename)
+{
+    comm = new Comm();
+
+    string fstring(filename);
+
+    init();                     // Init vars, setup functions, ...
+    nrb_on_dump = 0;
+    parse_file(fstring);        // Parse the file.
+    coutbuf = NULL;
+}
+
+// ===========================================================================
+// Destructor
+// ===========================================================================
+PowerParser::~PowerParser()
+{
+    fileout.close();
+    if (coutbuf != NULL) cout.rdbuf(coutbuf); // restore cout's original streambuf
+    delete comm;
+
+    cmd_strings.clear();
+    vmap.clear();
+    fmap.clear();
+    cmds.clear();
+    cmdsf.clear();
+    whenthens.clear();
+    restartblocks.clear();
+    pre_defined_varss.str("");
+}
+
+// ===========================================================================
+// Parse a file. The basic strategy is to read the file into a string on the
+// io processor, broadcast the string to all the other processors, then parse
+// the string.
+// ===========================================================================
+void PowerParser::parse_file(string filename)
+{
+    // Read the file into a string. This simply copies every character in
+    // the file to the string including end of line characters.
+    // Note that only the io processor reads the file into the string.
+    string s_in = "";
+    read_into_string(filename, s_in);
+
+    // Broadcast the buffer string to all the other processors. After this
+    // braodcast, all the processors should have the same buffer string.
+    broadcast_buffer(s_in);
+
+    // Parse the string. After this is done, the parser is ready to be used
+    // by the application code.
+    parse_string(filename, s_in);
+}
+
+void PowerParser::parse_file(const char *filename)
+{
+    string fstring(filename);
+    parse_file(fstring);
+}
+
+int PowerParser::NumIncludeFiles()
+{
+    return IncludeFiles.size();
+}
+
+string PowerParser::GetIncludeFile(int i)
+{
+    if (0 <= i && i < IncludeFiles.size()) return IncludeFiles[i];
+    return string("");
+}
+
+void PowerParser::ListIncludeFiles()
+{
+    int i, num_include;
+    num_include = NumIncludeFiles();
+    std::cerr << "Number of include files = " << num_include << "\n";
+    for (i = 0; i < num_include; ++i)
+    {
+        std::cerr << "Include file << "<< i << " = " << GetIncludeFile(i) << "\n";
+    }
+}
+
+// ===========================================================================
+// Given a multi-line string on every processor, parse it into cmds and words.
+// After calling this function, the parser is ready for use.
+// ===========================================================================
+void PowerParser::parse_string(string filename, string buffer)
+{
+    // Get command lines from the buffer and store them as strings.
+    int current_pos = 0;
+    string sline1 = "";
+    string sline = "";
+    int file_line_number = 0;
+    bool exe_args_inserted = false;
+    for (;;) {
+        // Get the next line from the buffer. No processing is done, just
+        // get each line. This does, however, remove the end of line
+        // characters (either \r\n or only \n) from the string.
+        if (!get_line_from_string(buffer, sline1, current_pos)) break;
+        line_number += 1;
+        file_line_number += 1;
+
+        // Store the line without any processing. This is done so that a
+        // fortran routine can get each original line and echo it to an
+        // output file.
+        cmd_strings.push_back(sline1);
+
+        // The line, sline1, may be composed of sub-lines separated by
+        // semicolons. Loop through the line extracting each semicolon
+        // separated sub-line and process it.
+        int current_sc_pos = 0;
+        for (;;) {
+            if (!get_sc_line_from_string(sline1, sline, current_sc_pos)) break;
+
+            // Flag for making the command or not.
+            bool make_cmd = true;
+
+            // Get rid of leading and trailing blanks and tabs.
+            eliminate_white_space(sline);
+
+            // If after removing white space, the resulting line string is empty,
+            // then do not turn it into a command.
+            if ((int)sline.size() == 0) make_cmd = false;
+
+            // Turn the line into a command. This creates the words. Empty lines
+            // can be skipped.
+            if (make_cmd) {
+                stringstream serr;
+                int ierr = 0;
+                Cmd cmd(sline, &vmap, &fmap, &cmd_strings,
+                        line_number, file_line_number, filename, serr, ierr);
+                process_error(serr, ierr);
+                if (cmd.get_string(0) == "set_index_base_zero") {
+                   // C/C++ index convention
+                   cmd.set_index_base(0);
+                   Variable v(0);
+                   index_base = 0;
+                }
+                if (cmd.get_string(0) == "set_index_base_one") {
+                   // Fortran index convention
+                   cmd.set_index_base(1);
+                   Variable v(1);
+                   index_base = 1;
+                }
+                if (cmd.get_string(0) == "set_case_sensitive") {
+                   cmd.set_case_sensitive(true);
+                   case_sensitive = true;
+                }
+                if (cmd.get_string(0) == "set_case_insensitive") {
+                   cmd.set_case_sensitive(false);
+                   case_sensitive = false;
+                }
+                if (cmd.get_string(0) == "put_exe_args_here") {
+                    if (exe_args_str != "") {
+                        parse_string("execution line arguments", exe_args_str);
+                        exe_args_inserted = true;
+                    }
+                }
+                else if (cmd.is_include()) {
+                    string fname = "";
+                    stringstream ssfiles;
+                    if(comm->isIOProc()) {
+                        fname = cmd.get_cmd_filename(ssfiles);
+                    }
+                    broadcast_buffer(fname);
+		    map<int,string>::iterator ifp;
+		    int isize = IncludeFiles.size();
+		    IncludeFiles[isize] = fname;
+                    if (fname == "") {
+                        stringstream serr;
+                        serr << endl;
+                        serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+                        serr << "    " << cmd_strings[line_number-1] << endl;
+                        serr << "in file: " << filename << endl;
+                        serr << "Could not open include file." << endl;
+                        serr << "The name of the file and any alternates are:" << endl;
+                        serr << ssfiles.str() << endl;
+                        int ierr = 2;
+                        process_error(serr, ierr);
+                        return;
+                    }
+                    parse_file(fname);
+                }
+                else {
+                    cmds.push_back(cmd);                
+                }
+            }
+        }
+    }
+    // process inserted command line args if not parsing just the args
+    if (filename != "execution line arguments" && 
+        filename != "exe_args_tmp" &&
+        exe_args_str != "") {
+      // if inserting manually, remove the tmp insertion at the beginning
+      if (exe_args_inserted) {
+        for (int i=0; i<(int)cmds.size(); i++) {
+          if (cmds[i].get_filename() == "exe_args_tmp") {
+            cmds.erase(cmds.begin()+i);
+            i -= 1;
+          }
+        }
+      }
+      // change the file name to the real name for args
+      else {
+        for (int i=0; i<(int)cmds.size(); i++) {
+          if (cmds[i].get_filename() == "exe_args_tmp") {
+            cmds[i].set_filename("execution line arguments");
+          }
+        }
+      }
+    }
+}
+
+
+// ===========================================================================
+// Handle the execution line arguments.
+// ===========================================================================
+void PowerParser::handle_exe_args(string other_args)
+{
+    if ((int)other_args.size() == 0) return;
+
+    stringstream serr;
+    int ierr = 0;
+    Cmd cmd(other_args, &vmap, &fmap, &cmd_strings,
+            1, 1, "", serr, ierr);
+    process_error(serr, ierr);
+    //print_line(cmd);
+    exe_args_str = "";
+    cmd.handle_exe_args(exe_args_str);
+    if (cmd.get_nwords() == 0) {
+        exe_args_str = "";
+        return;
+    }
+    parse_string("exe_args_tmp", exe_args_str);
+}
+
+
+// ===========================================================================
+// Clear out the parser and re-init.
+// ===========================================================================
+void PowerParser::clear_and_init()
+{
+    // comm does not need to be reset
+    cmd_strings.clear();
+    vmap.clear();
+    fmap.clear();
+    cmds.clear();
+    cmdsf.clear();
+    whenthens.clear();
+    restartblocks.clear();
+    pre_defined_varss.str("");
+
+    // Do not clear out the restart block info from the dump since the whole
+    // point of doing this function is to be able to reset the parser with
+    // the restart block info from the dump.
+
+    //for (int i=0; i<(int)bnames_on_dump.size(); i++) {
+    //    cout << "&&&&&cw PowerParser.cc, clear_and_init, bnames_on_dump = " <<
+    //        bnames_on_dump[i] << endl;
+    //    cout << "&&&&&cw PowerParser.cc, clear_and_init, baflags_on_dump = " <<
+    //        baflags_on_dump[i] << endl;
+    //}
+
+    // Do the initialization again.
+    init();
+}
+
+// ===========================================================================
+// Echo user input to a stringstream.
+// ===========================================================================
+void PowerParser::echo_input_start()
+{
+    ssfout.str("");
+    echo_input_ss(ssfout);
+    ssfout_current_pos = 0;
+}
+void PowerParser::echo_input_ss(stringstream &ssinp)
+{
+    if (!comm->isIOProc()) return;
+    for (int i=0; i<(int)cmd_strings.size(); i++) {
+        ssinp << cmd_strings[i] << endl;
+    }
+}
+
+
+// ===========================================================================
+// The input file(s) has been read and put into commands. Now do the
+// compilation phase.
+// ===========================================================================
+void PowerParser::compile_buffer(int &return_value)
+{
+    // At this point, the list of variables only contains the pre-defined
+    // parser variables, thus if we list the variables at this point we will
+    // have a list of only the pre-defined variables. This is stored in a
+    // stringstream to be printed later.
+    string lv1 = "********** List of pre-defined parser variables";
+    string lv2 = "********** End list of pre-defined parser variables";
+    list_vars_ss(lv1, lv2, "", pre_defined_varss);
+
+    int return_local;
+
+    return_local =-1;
+    return_value = 0;
+
+    // Handle single line (! and //) comments and multi line
+    // comments (/* ... */)
+    // The level variable is used for nested multi line comments.
+    int level = 0;
+    for (int i=0; i<(int)cmds.size(); i++) {
+        cmds[i].single_line_comments();
+        cmds[i].multi_line_comments(level);
+    }
+
+    // Check for matching quotes and remove them.
+    int ierr = 0;
+    stringstream serr;
+    for (int i=0; i<(int)cmds.size(); i++) {
+        cmds[i].handle_quotes(serr, ierr);
+    }
+    return_local = process_error_return_int(serr, ierr);
+    return_value = return_local;
+
+    if (return_local > 0) {
+       cout << "handle quotes gave error " << ierr << endl;
+       if (return_local > 1) return;
+    }
+
+    // Remove empty lines.
+    for (int i=0; i<(int)cmds.size(); i++) {
+        if (cmds[i].get_nwords() == 0) {
+            cmds.erase(cmds.begin()+i);
+            i -= 1;
+            continue;
+        }
+    }
+
+    // Handle continuation lines (ending in & or ,).
+    // Continuation lines are merged into one long (possibly very long)
+    // line.
+    for (int i=(int)cmds.size()-1; i>=0; i--) {
+        int nw1 = cmds[i].get_nwords();
+        if (cmds[i].get_string(nw1-1) == "&" ||
+            cmds[i].get_string(nw1-1) == ",") {
+            if (cmds[i].get_string(nw1-1) == "&")
+                cmds[i].erase_word(nw1-1);
+            int nw2 = cmds[i+1].get_nwords();
+            for (int j=0; j<nw2; j++) {
+                cmds[i].add_word(cmds[i+1].get_string(j),
+                                 cmds[i+1].get_line_number(j),
+                                 cmds[i+1].get_file_line_number(j),
+                                 cmds[i+1].get_filename(j)
+                                 );
+            }
+            cmds.erase(cmds.begin()+i+1);
+            continue;
+        }
+    }
+
+
+    // Reset the command name and type. Consider the following command:
+    //      * lasdkj */ cmd = 5.0
+    // The original command name is "*", but after the multi-line comment is
+    // removed, the command name should be "cmd".
+    for (int i=0; i<(int)cmds.size(); i++) {
+        cmds[i].reset_name_type();
+    }
+
+
+    // Debug: print each command.
+    //for (int i=0; i<(int)cmds.size(); i++) {
+        //stringstream ss3;
+        //cmds[i].print_all_words(ss3);
+        //cmds[i].print_using_words(ss3);
+        //cmds[i].print_original_string(ss3);
+        //cout << ss3.str() << endl;
+
+        //cout << "Command name = " << cmds[i].get_cmd_name() << endl;
+        //cout << "Command type = " << cmds[i].get_cmd_type() << endl;
+    //}
+    //cout << endl;
+
+    // Handle all the variable dimension statements.
+    ierr = 0;
+    serr.str("");
+    for (int i=0; i<(int)cmds.size(); i++) {
+        if (cmds[i].check_for_dimension(serr, ierr)) {
+            cmds.erase(cmds.begin()+i);
+            i--;
+            continue;
+        }            
+    }
+    return_local = process_error_return_int(serr, ierr);
+
+    if (return_local > 0) {
+       cout << "handle variable dimension statement has error " << ierr << endl;
+       if (return_local > 1) return;
+    }
+
+    // Combine things like "end if" into one word, i.e. "endif".
+    for (int i=0; i<(int)cmds.size(); i++) {
+        cmds[i].handle_two_words();
+    }
+
+    // Handle the case of a space between digits and the e for reals.
+    // For example, in the following,
+    //     1.0, 2.3 e14, -5.6
+    // there is a space between 2.3 and e14 which should most likely
+    // be treated as a single number, 2.3e14.
+    ierr = 0;
+    serr.str("");
+    string action = "error";
+    bool action_set = false;
+    for (int i=0; i<(int)cmds.size(); i++) {
+        if (cmds[i].get_cmd_name() == "depcmd_dse") {
+            action = cmds[i].get_string(1);
+            action_set = true;
+            cmds.erase(cmds.begin()+i);
+            i--;
+            continue;
+        }
+        if (cmds[i].get_cmd_name() == "matdef") {
+            if (!action_set) action = "fix";
+        }
+        cmds[i].deprecated_input01(action, serr, ierr);
+    }
+
+    return_local = process_error_return_int(serr, ierr);
+    return_value = return_local;
+    if (return_local > 0) {
+       cout << "handle space between digits has error " << ierr << endl;
+       if (return_local > 1) return;
+    }
+
+
+    // This is the main loop where most everything is done.
+    bool print_final_buffer = false;
+    deque<bool> skip_level;
+    deque<bool> satisfied;
+    deque<int> do_start;
+    string sub_name = "";
+    deque<int> icall, isub;
+    bool skip_sub = false;
+    int nwhen = 0;
+    int when_level = 0;
+    bool single_line_when = false;
+    int nrb = 0;                       // Number of restart blocks
+    bool single_line_rb = false;       // Flag for single line restart blocks
+    bool skiprb = false;               // Flag for skipping cmds in restart block
+    for (int i=0; i<(int)cmds.size(); i++) {
+        // Work with cmdi, so that cmds will be available for do loops.
+        Cmd cmdi = cmds[i];
+        //print_line(cmdi);
+
+        if (cmdi.get_cmd_name() == "parser_redirect_to_file") {
+            string fname;
+            int nw = cmdi.get_nwords();
+            if (nw > 1) {
+               fname = cmdi.get_string(1);
+            } else {
+               fname = "parser.out";
+            }
+            if (comm->isIOProc()) {
+               //cout << "DEBUG fname is " << fname << endl;
+               //cout << "Redirecting output to file" << endl;
+               cout.flush();
+               coutbuf = cout.rdbuf();
+               fileout.open(fname.c_str());
+               cout.rdbuf(fileout.rdbuf());
+               //cout << "Start of output to file" << endl;
+            }
+
+            continue;
+        }
+
+        // Handle restart_block commands.
+        if (cmdi.get_string(0) == "restart_block") {
+            Restartblock rb(nrb, cmdi, skiprb, single_line_rb, 
+                            bnames_on_dump, baflags_on_dump,
+                            rbsatprb_on_dump, rbsat_on_dump,
+                            serr, ierr);
+            restartblocks.push_back(rb);
+
+            for (int rbi=0; rbi<(int)restartblocks.size(); rbi++) {
+                string rbi_name = restartblocks[rbi].get_name();
+                for (int rbj=rbi+1; rbj<(int)restartblocks.size(); rbj++) {
+                    if (rbi_name == restartblocks[rbj].get_name()) {
+                        cmdi.fatal_error(0, serr, ierr);
+                        serr << "Restart block names must be unique." << endl;
+                        serr << "Non unique name = " << rbi_name << endl;
+                        ierr = 2;
+                    }
+                }
+            }
+
+            if (single_line_rb && skiprb) {
+                skiprb = false;
+                continue;
+            }
+            bool cflag = true;
+            if (single_line_rb && !skiprb) cflag = false;
+            if (cflag) continue;
+        }
+        if (cmdi.get_string(0) == "end_restart_block") {
+            skiprb = false;
+            continue;
+        }
+        if (skiprb) continue;
+
+
+        if (skip_sub) {
+            if (cmdi.get_string(0) == "endsubroutine") {
+                skip_sub = false;
+                //cout << "endsubroutine found, turning skip_sub to false" << endl;
+            }
+            continue;
+        }
+
+        return_local = ierr;
+        return_value = return_local;
+        if (return_local > 0) {
+           if (return_local > 1) return;
+        }
+     
+
+
+        // List variables, functions, etc.
+        if (cmdi.get_cmd_name() == "parser_list_variables") {
+            string lv1 = "********** Debugging: list variable names and values "
+                "available in input file.";
+            string lv2 = "********** Debugging END: list variable names and values";
+            string var_to_list = "";
+            int nw = cmdi.get_nwords();
+            if (nw > 1) var_to_list = cmdi.get_string(1);
+            if (comm->isIOProc()) cout << endl;
+            list_vars(lv1, lv2, var_to_list);
+            if (comm->isIOProc()) cout << endl;
+            continue;
+        }
+        if (cmdi.get_cmd_name() == "parser_list_functions") {
+            string lf1 = "********** Debugging: list function names available in input file.";
+            string lf2 = "********** Debugging END: list function names.";
+            if (comm->isIOProc()) cout << endl;
+            list_funcs(lf1, lf2);
+            if (comm->isIOProc()) cout << endl;
+            continue;
+        }
+        if (cmdi.get_cmd_name() == "parser_print_fbuffer") {
+            print_final_buffer = true;
+            continue;
+        }
+
+        // Handle when ... then commands.
+        string wtcmd = cmdi.get_string(0);
+        if (wtcmd == "when" || wtcmd == "whenever") {
+            bool skipwhen = true;
+            bool ever_flag = false;
+            if (wtcmd == "whenever") ever_flag = true;
+            Whenthen wt(nwhen, cmdi, skipwhen, single_line_when, ever_flag, serr, ierr);
+            when_level += 1;
+            whenthens.push_back(wt);
+            if (skipwhen) continue;
+        }
+        if (cmdi.get_string(0) == "endwhen") {
+            when_level -= 1;
+            if (when_level < 0) {
+                cmdi.fatal_error(0, serr, ierr);
+                serr << "Extra endwhen (or end when) found with no matching "
+                        "when command." << endl;
+                serr << "Make sure every when command has one and only one"
+                     << endl << "matching endwhen command." << endl;
+                ierr = 2;
+            }
+            return_local = ierr;
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "handle endwhen " << ierr << endl;
+                 return;
+             }
+             continue;
+        }
+
+
+        // Handle if/elseif/else/endif statements.
+        bool skip = false;
+        cmdi.handle_if(skip, skip_level, satisfied, serr, ierr);
+        if (skip) continue;
+
+        // Handle do loops. Note that we terminate if there is an error to
+        // avoid the possibility of an infinite loop.
+        int cdex = i;
+        bool end_do = false;
+        int ierr2 = 0;
+        cmdi.handle_do(skip, do_start, cdex, end_do, serr, ierr2);
+        if (ierr2 == 2) {
+            ierr = 2;
+            return_local = ierr;
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "handle endwhen " << ierr << endl;
+             }
+            break;
+        }
+        if (end_do) {
+            if (!end_do_loop(i, do_start, serr, ierr)) break;
+            continue;
+        }
+        i = cdex;
+        if (skip) continue;
+
+        // Handle call/subroutines.
+        bool go_to_sub = false;
+        bool go_to_call = false;
+        cmdi.handle_subroutines(skip, go_to_sub, sub_name, go_to_call,
+                                serr, ierr);
+        if (go_to_call) {
+            end_do_ret(i, do_start, serr, ierr);
+            return_local = jump_to_call(i, icall, isub, serr, ierr);
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "jump_to_call error " << ierr << endl;
+             }
+            continue;
+        }
+
+        if (go_to_sub) {
+            icall.push_back(i);
+            return_local = jump_to_sub(i, sub_name, serr, ierr);
+            isub.push_back(i);
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "jump_to_sub error " << ierr << endl;
+             }
+            continue;
+        }
+
+        if (cmdi.get_string(0) == "subroutine") {
+            //cout << "subroutine found!!!, turning skip_sub to true" << endl;
+            skip_sub = true;
+            continue;
+        }
+
+        // Check for a variable description command. If found we set the description,
+        // then go to the next line.
+        if (cmdi.check_for_var_description(serr, ierr)) continue;
+
+        // Stop if we hit a stop command or a fatal_error command
+        bool kill_run = false;
+        if (cmdi.check_input_end(kill_run, serr, ierr)) {
+            // Killing the calculation will be done, for example, if the user
+            // issues a fatal_error command.
+            if (kill_run) {
+                return_local = process_error_return_int(serr, ierr);
+               if (return_local > return_value) {
+                   return_value = return_local;
+               }
+               if (return_local > 0) {
+                    cout << "handle endwhen " << ierr << endl;
+                    if (return_local > 1) return;
+                }
+            }
+            
+            // Clear out all do's so we don't get an error about unmatched
+            // do/enddo.
+            do_start.clear();
+            break;
+        }
+
+        cmdi.math_eval(serr, ierr);
+        cmdi.substitute_variables(serr, ierr);   // Sub vars not in math expressions.
+        cmdi.check_ppmm(serr, ierr);             // All ++, -- should be gone.
+        cmdi.remove_commas();
+        cmdi.handle_cmd_unary_minus(serr, ierr);
+        cmdi.handle_cmd_unary_plus(serr, ierr);
+        cmdi.handle_cmd_multiplicity(serr, ierr);
+        cmdi.check_misplaced_math(serr, ierr);
+        cmdi.set_variables(serr, ierr);
+
+        // Copy the command to the final commands deque.
+        if (cmdi.get_cmd_type() == "command") {
+            if (when_level > 0) {
+                whenthens[nwhen-1].add_cmdf(cmdi);
+                if (single_line_when) {
+                    when_level -= 1;
+                    single_line_when = false;
+                }
+            }
+            else {
+                cmdsf.push_back(cmdi);
+            }
+        }
+    }
+    // Print error messages and terminate if fatal.
+    return_local = process_error_return_int(serr, ierr);
+    if (return_local > return_value) {
+        return_value = return_local;
+    }
+    if (return_local > 0) {
+        return_value = return_local;
+        if (return_local > 1) return;
+    }
+
+    // Check that an enddo was found for every do.
+    check_enddo(do_start, serr, ierr);
+
+    // Print error messages and terminate if fatal.
+    return_local = process_error_return_int(serr, ierr);
+    if (return_local > return_value) {
+        return_value = return_local;
+    }
+    if (return_local > 0) {
+        return_value = return_local;
+        if (comm->isIOProc()) {
+           cout << "handle enddo is wrong with err " << ierr << endl;
+        }
+        if (return_local > 1) return;
+    }
+
+    // Set the processed flag in every word in every command to be false.
+    // At the end of parsing, if any word has not been processed in some way,
+    // then that is a fatal error.
+    for (int i=0; i<(int)cmdsf.size(); i++) {
+        cmdsf[i].clear_processed();
+    }
+
+    // If this is a recreate of the parser, then there might be some commands 
+    // that have already been processed, set these.
+    cmd_set_reprocessed(true);
+
+    // Check and print duplicate scalar commands.
+    // Remove duplicate scalar commands.
+    // Process the duplicate_array_values command.
+    return_local = process_dav_cmd();
+    if (return_local > return_value) {
+        return_value = return_local;
+    }
+    if (return_local > 0) {
+        if (comm->isIOProc()) {
+           cout << "Checked for  duplicate arrays and error is " << return_local << endl;
+        }
+    }
+    //check_duplicates();
+
+    // Debug: print each of the final commands to the screen.
+    if (print_final_buffer) {
+        if (comm->isIOProc()) {
+            cout << "********************************************************************************\n"
+                 << "********** Echo final parser buffer, this is what the code uses to set internal \n" 
+                 << "********** code variables." << endl;
+            list_cmdsf("", "");
+            cout << "********** End of echo final parser buffer.\n" 
+                 << "********************************************************************************\n\n" 
+                 << endl;
+
+            cout << "********************************************************************************\n"
+                 << "********** Echo final when...then parser buffers, this is what the code uses to \n"
+                 << "********** set internal code variables when processing when...then commands." << endl;
+            list_wt_cmdsf();
+            cout << "********** End of echo final when...then parser buffers.\n"
+                 << "********************************************************************************\n\n" 
+                 << endl;
+
+            cout << "********************************************************************************\n"
+                 << "********** Echo restart block information." << endl;
+            list_rb();
+            cout << "********** End of echo restart block information.\n"
+                 << "********************************************************************************\n\n"
+                 << endl;
+        }
+    }
+
+    // Return the to the calling program
+
+    return;
+}
+
+
+// ===========================================================================
+// A "endsubroutine" or "return" command has been found. Jump back to the call
+// statement. This sets the loop index i so that we end up on the line after
+// the call.
+// ===========================================================================
+int PowerParser::jump_to_call(int &i, deque<int> &icall, deque<int> &isub,
+                         stringstream &serr, int &ierr)
+{
+    int return_value;
+    int return_local;
+    return_value = 0;
+    return_local = 0;
+
+    int icsize = (int)icall.size();
+    if (icsize == 0) {
+        cmds[i].fatal_error(0, serr, ierr);
+        serr << "icall size = 0, this should never happen." << endl;
+        ierr = 2;
+        return_value = process_error_return_int(serr, ierr);
+        if (return_local > return_value) {
+           return_value = return_local;
+        }
+        if (return_local > 0) {
+             cout << "jump_to_call icall  error " << ierr << endl;
+             if (return_local > 1) return return_value;
+        }
+    }
+    i = icall[icsize-1];
+    icall.erase(icall.begin()+icsize-1);
+
+    vector<string> call_args;
+    vector<bool> call_args_isvar;
+    cmds[i].copy_call_args(call_args, call_args_isvar);
+    int idex_sub = isub[(int)isub.size()-1];
+    vector<string> sub_args;
+    vector<bool> sub_args_isvar;
+    cmds[idex_sub].copy_sub_args(sub_args, sub_args_isvar);
+    //cout << "jump_to_call, sub args, then call args" << endl;
+    //for (int j=0; j<(int)sub_args.size(); j++) {
+    //    cout << sub_args[j] << endl;
+    //}
+    //for (int j=0; j<(int)call_args.size(); j++) {
+    //    cout << call_args[j] << endl;
+    //}
+    //cout << "--------------------------------" << endl;
+
+    for (int j=0; j<(int)sub_args.size(); j++) {
+        string sub_var = sub_args[j];
+        string call_var = call_args[j];
+
+        map<string, Variable>::iterator psub;
+        psub = vmap.find(sub_var);
+        string sub_value = "";
+        if (psub != vmap.end()) {
+            sub_value = psub->second.get_var_value();
+        }
+        else {
+            cmds[i].fatal_error(0, serr, ierr);
+            serr << "Subroutine argument not found." << endl;
+            serr << "This should not happen." << endl;
+            ierr = 2;
+            return_value = process_error_return_int(serr, ierr);
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "jump_to_call Subroutine argument not found " << endl;
+                 if (return_local > 1) return return_value;
+            }
+        }
+
+        if (!call_args_isvar[j]) {
+            if (sub_value != call_var) {
+                cmds[i].fatal_error(0, serr, ierr);
+                cmds[isub[(int)isub.size()-1]].fatal_error(0, serr, ierr);
+                serr << "The calling argument, argument number " << j+1
+                     << ", (after any math eval) is " << call_var << endl;
+                serr << "The corrseponding subroutine dummy argument, "
+                     << sub_var << ", has"
+                     << " the value of " << sub_value << endl;
+                serr << "These are different and should not be." << endl;
+                serr << "The calling argument is not a variable and thus" 
+                     " is fixed and cannot be changed." << endl;
+                serr << "The dummy argument was changed in the subroutine," << endl;
+                serr << "thus you are trying to change a fixed quantity which" 
+                     " is not allowed." << endl;
+                ierr = 2;
+                return_value = process_error_return_int(serr, ierr);
+                if (return_local > return_value) {
+                   return_value = return_local;
+                }
+                if (return_local > 0) {
+                     cout << "jump_to_call subroutine arguments errors " << endl;
+                     if (return_local > 1) return return_value;
+            }
+            }
+        }
+        else {
+            map<string, Variable>::iterator pcall;
+            pcall = vmap.find(call_var);
+            if (pcall != vmap.end()) {
+                pcall->second = psub->second;
+                pcall->second.set_temporary(false);
+                pcall->second.set_varname(call_var);
+            }
+            else {
+                cmds[i].fatal_error(0, serr, ierr);
+                serr << "Calling argument not found." << endl;
+                serr << "This should not happen." << endl;
+                ierr = 2;
+                return_value = process_error_return_int(serr, ierr);
+                if (return_local > return_value) {
+                   return_value = return_local;
+                }
+                if (return_local > 0) {
+                     cout << "jump_to_call calling argument not found " << endl;
+                     if (return_local > 1) return return_value;
+                }
+            }
+        }
+
+    }
+
+    // Erase temporary variables.
+    // There should be a better way to do this.
+    map<string, Variable>::iterator p;
+    for (;;) {
+        bool erase_done = false;
+        for(p = vmap.begin(); p != vmap.end(); p++) {
+            if (p->second.is_temporary()) {
+                vmap.erase(p);
+                erase_done = true;
+                break;
+            }
+        }
+        if (!erase_done) break;
+    }
+
+    // Remove the index to the subroutine line.
+    isub.erase(isub.begin()+(int)isub.size()-1);
+
+    return return_value;
+
+}  // End of jump_to_call
+
+
+// ===========================================================================
+// A "call" command has been found. Find the subroutine it is trying to call
+// and set the loop index, i, to the subroutine line so we will end up on the
+// line after the subroutine.
+// ===========================================================================
+int PowerParser::jump_to_sub(int &i, string &sub_name,
+                        stringstream &serr, int &ierr)
+{
+    int return_value;
+    int return_local;
+    return_value = 0;
+    return_local = 0;
+
+    // At this point, i is the index for the call line.
+    //cout << "&&&&&cw PowerParser loop, jump_to_sub, i=" << i << endl;
+
+    // Find the line index, cdex, for the subroutine.
+    int cdex = -1;
+    for (int j=0; j<(int)cmds.size(); j++) {
+        if (cmds[j].find_subroutine(sub_name)) {
+            cdex = j;
+            break;
+        }
+    }
+
+    if (cdex == -1) {
+        cmds[i].fatal_error(0, serr, ierr);
+        serr << "Subroutine " << sub_name << " not found." << endl;
+        ierr = 2;
+        return_value = process_error_return_int(serr, ierr);
+        if (return_local > return_value) {
+           return_value = return_local;
+        }
+        if (return_local > 0) {
+             cout << "Subroutine name not found " << ierr << endl;
+             if (return_local > 1) return return_value;
+        }
+    }
+
+    // Get the calling arguments. This will potentially be a mix
+    // of variable names and numbers. This does not modify the words
+    // in cmds[i], but it does store the call arguments in cmds[i].
+    vector<string> call_args;
+    vector<bool> call_args_isvar;
+    cmds[i].get_call_args(call_args, call_args_isvar, serr, ierr);
+    //for (int j=0; j<(int)call_args.size(); j++) {
+    //    cout << call_args[j] << endl;
+    //}
+
+    // Get the subroutine arguments.
+    // This does not modify the words in cmds[cdex], but it does store
+    // the subroutine arguments in cmds[cdex]
+    //print_line(cdex);
+    vector<string> sub_args;
+    vector<bool> sub_args_isvar;
+    cmds[cdex].get_sub_args(sub_args, sub_args_isvar);
+    //for (int j=0; j<(int)sub_args.size(); j++) {
+    //    cout << sub_args[j] << endl;
+    //}
+
+    // Error checking.
+    int ncall_args = (int)call_args.size();
+    int nsub_args = (int)sub_args.size();
+    if (ncall_args != nsub_args) {
+        cmds[i].fatal_error(0, serr, ierr);
+        cmds[cdex].fatal_error(0, serr, ierr);
+        serr << "Number of calling arguments = " << ncall_args << endl;
+        serr << "Number of subroutine arguments = " << nsub_args << endl;
+        serr << "These must be the same." << endl;
+        ierr = 2;
+        return_local = process_error_return_int(serr, ierr);
+        if (return_local > return_value) {
+           return_value = return_local;
+        }
+        if (return_local > 0) {
+             cout << "Arguments in subroutine and in calling are different " << ierr << endl;
+             if (return_local > 1) return return_value;
+        }
+    }
+
+    for (int j=0; j<(int)sub_args.size(); j++) {
+        if (!sub_args_isvar[j]) {
+            cmds[cdex].fatal_error(0, serr, ierr);
+            serr << "Subroutine dummy arguments must always be variables." << endl;
+            serr << "Argument " << j+1 << ", " << sub_args[j] << ", "
+                 << "is not a variable." << endl;
+            serr << "Remember that variables always begin with a" 
+                " dollar sign, $" << endl;
+            serr << "Note that putting quotes around a variable name makes it" << endl;
+            serr << "a string, not a variable." << endl;
+            ierr = 2;
+            return_local = process_error_return_int(serr, ierr);
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "Dummy arguments must be variables " << ierr << endl;
+                 if (return_local > 1) return return_value;
+            }
+        }
+    }
+
+
+    // Define new, temporary variables for the subroutine dummy arguments.
+    // Set their values to the call values.
+    for (int j=0; j<(int)sub_args.size(); j++) {
+        string sub_vname = sub_args[j];
+        string call_vname = call_args[j];
+
+        // Find the subroutine variable name in the variable map.
+        map<string, Variable>::iterator psub;
+        psub = vmap.find(sub_vname);
+
+        if (psub != vmap.end()) {
+            cmds[cdex].fatal_error(0, serr, ierr);
+            serr << "Argument " << j+1 << ", " << sub_args[j] << ", "
+                 << "is both a global variable and a dummy subroutine argument." << endl;
+            serr << "This is not allowed, dummy subroutine arguments "
+                "cannot also be" << endl;
+            serr << "global variables." << endl;
+            ierr = 2;
+            return_local = process_error_return_int(serr, ierr);
+            if (return_local > return_value) {
+               return_value = return_local;
+            }
+            if (return_local > 0) {
+                 cout << "Dummy argument cannot be global variable " << ierr << endl;
+                 if (return_local > 1) return return_value;
+            }
+        }
+        else {
+            // If the calling argument is a variable, then we set the
+            // temporary variable equal to the calling variable. This passes
+            // in the correct value, but it also passes in arrays, and
+            // whatever characteristics the calling variable has.
+            //
+            // If the calling argument is not a variable, then we just
+            // create the new, temporary variable and give it the calling
+            // argument as its value.
+            if (call_args_isvar[j]) {
+                map<string, Variable>::iterator pcall;
+                pcall = vmap.find(call_vname);
+                if (pcall != vmap.end()) {
+                    Variable v = pcall->second;
+                    v.set_varname(sub_vname);
+                    v.set_temporary(true);
+                    vmap.insert(pair<string, Variable>(v.get_varname(), v));
+                }
+                else {
+                    // FATAL ERROR
+                    // calling argument variable not defined.
+                }
+            }
+            else {
+                vector<int> istart(0,0);
+                vector<string> valvec;
+                valvec.push_back(call_vname);
+                int lnum = cmds[cdex].get_line_number(0);
+                int file_lnum = cmds[cdex].get_file_line_number(0);
+                string fname = cmds[cdex].get_filename(0);
+                Variable v(sub_vname, istart, valvec, lnum, file_lnum,
+                           fname, &cmd_strings, serr, ierr);
+                v.set_temporary(true);
+                vmap.insert(pair<string, Variable>(v.get_varname(), v));
+            }
+
+        }
+    }
+
+    // Set the loop index to the index of the subroutine so we
+    // will end up at the line after the subroutine line.
+    i = cdex;
+    return return_value;
+}  // End of jump_to_sub
+
+
+
+
+// ===========================================================================
+// End a do loop. This happens when a do loop has gone through all its
+// iterations or when an exit statment is encountered.
+// Basically, find the matching enddo  and continue after that statement.
+// ===========================================================================
+bool PowerParser::end_do_loop(int &i, deque<int> &do_start,
+                        stringstream &serr, int &ierr)
+{
+    int rtvl = 0;
+    // Find the matching enddo.
+    // Stop checking will be true if we are in main and hit a subroutine
+    // statement or if we are in a subroutine and hit an endsubroutine
+    // statement.
+    int cdex = -1;
+    int dlev = 1;
+    for (int j=i+1; j<(int)cmds.size(); j++) {
+        bool stop_checking = false;
+        if (cmds[j].find_matching_enddo(dlev, stop_checking)) {
+            cdex = j;
+            break;
+        }
+        if (stop_checking) break;
+    }
+
+    // If the matching enddo was not found then that is a fatal error.
+    int nlevels = (int)do_start.size();
+    if (cdex == -1) {
+        if (nlevels > 0) {
+            int ido = do_start[nlevels-1];
+            cmds[ido].fatal_error(0, serr, ierr);
+        }
+        serr << "No enddo found for do statement." << endl;
+        ierr = 2;
+        rtvl = process_error_return_int(serr, ierr);
+        if (rtvl > 0) cout << "Enddo not found " << endl;
+        return false;
+    }
+
+    // We are done with this do loop, so we can get rid of the reference
+    // to it.
+    if (nlevels > 0) {
+        do_start.erase(do_start.begin()+nlevels-1);
+    }
+
+    // Set the loop index to the enddo statement so that we will start
+    // processing immediately after the enddo.
+    i = cdex;
+    return true;
+} // End end_do_loop
+
+
+// ===========================================================================
+// A return statement in a subroutine has been encountered. We need to handle
+// the do loops before returning to the call statement, otherwise the code
+// will complain about do loops without enddo statements.
+// This routine searches from the return statement to the endsubroutine
+// statement, finds any free enddo's and erases the corresponding references
+// to the do statements.
+// ===========================================================================
+void PowerParser::end_do_ret(int &i, deque<int> &do_start,
+                       stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    //assert(serr == serr);
+    assert(ierr == ierr);
+
+    int istart = i;
+    for (;;) {
+
+        // Find an enddo.
+        // Stop checking will be true if we are in main and hit a subroutine
+        // statement or if we are in a subroutine and hit an endsubroutine
+        // statement.
+        int cdex = -1;
+        int dlev = 1;
+        bool stop_checking = false;
+        for (int j=istart; j<(int)cmds.size(); j++) {
+            if (cmds[j].find_matching_enddo(dlev, stop_checking)) {
+                cdex = j;
+                istart = j+1;
+                break;
+            }
+            if (stop_checking) break;
+        }
+
+        // If we don't find an enddo, then we are done.
+        if (cdex == -1) break;
+        if (stop_checking) break;
+
+        // We are done with this do loop, so we can get rid of the reference
+        // to it.
+        int nlevels = (int)do_start.size();
+        if (nlevels > 0) {
+            do_start.erase(do_start.begin()+nlevels-1);
+        }
+    }
+} // End end_do_ret
+
+
+
+
+// ===========================================================================
+// Check that an enddo was found for every do.
+// ===========================================================================
+void PowerParser::check_enddo(deque<int> &do_start, stringstream &serr, int &ierr)
+{
+    for (int i=0; i<(int)do_start.size(); i++) {
+        int ido = do_start[i];
+        cmds[ido].fatal_error(0, serr, ierr);
+        serr << "No enddo found for do statement." << endl;
+        ierr = 2;
+    }
+}
+
+
+// ===========================================================================
+// Check all processed flags on every command. If any word on any command
+// has not been processed, then that is a fatal error.
+// ===========================================================================
+void PowerParser::check_processed(bool &good)
+{
+    int rtvl = 0;
+    int ierr = 0;
+    stringstream serr;
+
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        (*cmdsfp)[i].check_processed(good, serr, ierr);
+    }
+
+    process_error(serr, ierr);
+}
+
+
+// ===========================================================================
+// Process the duplicate array values command.
+// ===========================================================================
+int PowerParser::process_dav_cmd()
+{
+    int rtvl         = 0;
+    int return_value = 0;
+
+    // Process the duplicate_array_values command.
+    // Note that duplicate array values are processed when the calls are made
+    // from the host code to actually extract information from the final
+    // buffer.
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        string cmdi = (*cmdsfp)[i].get_string(0);
+        if (cmdi != "duplicate_array_values") continue;
+        (*cmdsfp)[i].set_processed(true);
+        string vali = (*cmdsfp)[i].get_string(2);
+        if (vali == "warning") dup_fatal = 1;
+        else if (vali == "fatal") dup_fatal = 2;
+        else if (vali == "none") dup_fatal = 0;
+        else {
+            int ierr = 0;
+            stringstream serr;
+            (*cmdsfp)[i].fatal_error(0, serr, ierr);
+            serr << "The value for the duplicate_array_values command must" << endl <<
+                "be either none, warning, or fatal" << endl;
+            ierr = 2;
+            cout << "The value for the duplicate_array_values command must" << endl;
+            cout << "be either none, warning, or fatal" << endl;
+            rtvl = process_error_return_int(serr, ierr);
+            if (rtvl > return_value) {
+                return_value = rtvl;
+            }
+
+            if (rtvl > 0) {
+                 cout << "Duplicate array values not recognized " << ierr << endl;
+            }
+            return return_value;
+        }
+        if (dup_fatal > 0 ) return dup_fatal;
+    }
+    return 0;
+}
+
+
+// ===========================================================================
+// If commands appear more than once in the input file(s), print a warning
+// to the user.
+// ===========================================================================
+void PowerParser::check_duplicates()
+{
+    // Check for and print and duplicate scalar commands in the input file.
+    //if (comm->isIOProc()) {
+    //    cout << "********************************************************************************" << endl;
+    //}
+    //bool found_any = false;
+    bool fany;
+    check_dup_scalar(-1, fany);
+    //if (fany) found_any = true;
+    for (int wtn=0; wtn<(int)whenthens.size(); wtn++) {
+        check_dup_scalar(wtn, fany);
+        //if (fany) found_any = true;
+    }
+    wt_reset();
+
+    // If duplicate scalar commands are not found, we do not really need to
+    // pollute the output telling the user that.
+    //if (!found_any) {
+    //    if (comm->isIOProc()) {
+    //        cout << "********** No Duplicate Scalar Commands Found in User Input File" << endl;
+    //    }
+    //}
+    //if (comm->isIOProc()) {
+    //    cout << "********************************************************************************" << endl;
+    //    cout << endl << endl;
+    //}
+
+
+    // Remove and duplicate scalar commands from the final buffer.
+    remove_dup_scalar(-1);
+    for (int wtn=0; wtn<(int)whenthens.size(); wtn++) {
+        remove_dup_scalar(wtn);
+    }
+    wt_reset();
+}
+
+// ===========================================================================
+// Check for duplicate scalar commands in the user input file.
+// Print a table of any duplicate scalar commands to stdout.
+// ===========================================================================
+void PowerParser::check_dup_scalar(int wtn, bool &found_any)
+{
+    vector< vector<string> > rows;
+
+    vector<string> row1;
+    row1.push_back(" ");
+    row1.push_back("Line");
+    row1.push_back(" ");
+    rows.push_back(row1);
+
+    vector<string> row2;
+    row2.push_back("Filename");
+    row2.push_back("Number");
+    row2.push_back("Command");
+    rows.push_back(row2);
+
+    int n_header_rows = (int)rows.size();
+
+    if (wtn < 0) cmdsfp = &cmdsf;
+    else         cmdsfp = whenthens[wtn].get_cmdsf_ptr();
+
+    vector<string> cmds_done;
+    found_any = false;
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        bool already_printed_i = false;
+        string cmdi = (*cmdsfp)[i].get_string(0);
+        string w1i = (*cmdsfp)[i].get_string(1);
+        if (w1i == "(") continue;
+
+        bool already_done = false;
+        for (int j=0; j<(int)cmds_done.size(); j++) {
+            if (cmdi == cmds_done[j]) {
+                already_done = true;
+                break;
+            }
+        }
+        if (already_done) continue;
+
+        bool found = false;
+        for (int j=i+1; j<(int)cmdsfp->size(); j++) {
+            string cmdj = (*cmdsfp)[j].get_string(0);
+            if (cmdi == cmdj) {
+                stringstream ss;
+                if (!already_printed_i) {
+                    vector<string> row;
+                    set_dup_row(row, (*cmdsfp)[i], 0);
+                    rows.push_back(row);
+                    already_printed_i = true;
+                }
+                vector<string> row;
+                set_dup_row(row, (*cmdsfp)[j], 0);
+                rows.push_back(row);
+                found = true;
+                found_any = true;
+            }
+        }
+        if (found) {
+            cmds_done.push_back(cmdi);
+            vector<string> row;
+            row.push_back(" ");  row.push_back(" ");  row.push_back(" ");
+            rows.push_back(row);
+        }
+    }
+
+    if (found_any) {
+        if (comm->isIOProc()) {
+            cout << endl;
+            if (wtn < 0) {
+                cout << "********** WARNING: Duplicate Scalar Commands Found in User Input File" << endl;
+                cout << "  The following commands appear more than once in the user input file." << endl;
+            }
+            else {
+                cout << "********** WARNING: Duplicate Scalar Commands Found in when...then" << endl;
+                cout << "  The following commands appear more than once in the when...then." << endl;
+            }
+            cout << "  The last instance of the command will be used." << endl;
+            cout << "  Is this what you want??" << endl << endl;
+            stringstream ssout;
+            Parser_utils putils(index_base);
+            putils.print_strings(rows, n_header_rows, 4, 3, 80, ssout);
+            cout << ssout.str() << endl;
+        }
+    }
+}
+
+
+// ===========================================================================
+// Helper function for check_dup_scalar.
+// The duplicate scalar commands are printed as rows with each row containing
+// the file name the duplicate command was found in, the line number, and the
+// command line itself.
+// Given the duplicate command, this function generates that row of
+// information and adds it to the row vector.
+// ===========================================================================
+void PowerParser::set_dup_row(vector<string> &row, Cmd &cmdi, int iw)
+{
+    int lnum = cmdi.get_line_number(iw);
+    int file_lnum = cmdi.get_file_line_number(iw);
+    string fname = cmdi.get_filename(iw);
+
+    row.push_back(fname);
+    stringstream ss;
+    ss << file_lnum;
+    row.push_back(ss.str());
+    row.push_back(cmd_strings[lnum-1]);
+}
+
+
+
+// ===========================================================================
+// Remove duplicate scalar commands in the user input file.
+// Keep only the last instance of the command.
+// ===========================================================================
+void PowerParser::remove_dup_scalar(int wtn)
+{
+    if (wtn < 0) cmdsfp = &cmdsf;
+    else         cmdsfp = whenthens[wtn].get_cmdsf_ptr();
+
+    for (int i=(int)cmdsfp->size()-1; i>=0; i--) {
+        string cmdi = (*cmdsfp)[i].get_string(0);
+        string w1i = (*cmdsfp)[i].get_string(1);
+        if (w1i == "(") continue;
+
+        for (int j=i-1; j>=0; j--) {
+            string cmdj = (*cmdsfp)[j].get_string(0);
+            if (cmdi == cmdj) {
+                cmdsfp->erase(cmdsfp->begin()+j);
+                i--;
+            }
+        }
+    }
+}
+
+// ===========================================================================
+// Helper function to convert doubles to strings.
+// ===========================================================================
+std::string const to_string( double const x )
+{
+    std::ostringstream tmp;
+    tmp << std::setprecision(16) << x;
+    return tmp.str();
+}
+
+// ===========================================================================
+// Initialize the parser. This will typically be called by the
+// constructors.
+// ===========================================================================
+void PowerParser::init()
+{
+    line_number = 0;
+    cmdsfp = &cmdsf;
+    dup_fatal = 1;
+    ierr_global = 0;
+
+    // make a little smaller (2.0) to avoid floating point excepting on some
+    // compilers
+    double huge_double = numeric_limits<double>::max( )/2.0;
+    Word whuge_double(huge_double, 1, 1, "", NULL);
+    Variable vhuge_double("$huge_double", whuge_double.get_string(), true, "largest double/2.0");
+    vmap.insert(pair<string, Variable>(vhuge_double.get_varname(), vhuge_double));
+
+    float huge_float = numeric_limits<float>::max( );
+    Word whuge_float(huge_float, 1, 1, "", NULL);
+    Variable vhuge_float("$huge_float", whuge_float.get_string(), true, "largest float");
+    vmap.insert(pair<string, Variable>(vhuge_float.get_varname(), vhuge_float));
+
+    int huge_int = numeric_limits<int>::max( );
+    Word whuge_int(huge_int, 1, 1, "", NULL);
+    Variable vhuge_int("$huge_int", whuge_int.get_string(), true, "largest integer");
+    vmap.insert(pair<string, Variable>(vhuge_int.get_varname(), vhuge_int));
+
+    double tiny_double = numeric_limits<double>::min( );
+    Word wtiny_double(tiny_double, 1, 1, "", NULL);
+    Variable vtiny_double("$tiny_double", wtiny_double.get_string(), true, "tiniest double");
+    vmap.insert(pair<string, Variable>(vtiny_double.get_varname(), vtiny_double));
+
+    float tiny_float = numeric_limits<float>::min( );
+    Word wtiny_float(tiny_float, 1, 1, "", NULL);
+    Variable vtiny_float("$tiny_float", wtiny_float.get_string(), true, "tiniest float");
+    vmap.insert(pair<string, Variable>(vtiny_float.get_varname(), vtiny_float));
+
+    int tiny_int = numeric_limits<int>::min( );
+    Word wtiny_int(tiny_int, 1, 1, "", NULL);
+    Variable vtiny_int("$tiny_int", wtiny_int.get_string(), true, "tiniest integer");
+    vmap.insert(pair<string, Variable>(vtiny_int.get_varname(), vtiny_int));
+
+    int ncores_tot = comm->getNumProcs();
+    Word wncores_tot(ncores_tot, 1, 1, "", NULL);
+    Variable vncores_tot("$ncores_tot", wncores_tot.get_string(), true, "total number of cores");
+    vmap.insert(pair<string, Variable>(vncores_tot.get_varname(), vncores_tot));
+
+
+    // ***********************************************************************
+    // Define the default functions.
+    Function facos("acos", true, 1, "real",
+                   "arccosine, radians, arg -1 to 1");
+    fmap.insert(pair<string, Function>(facos.get_name(), facos));
+
+    Function fasin("asin", true, 1, "real",
+                   "arcsine, radians, arg -1 to 1");
+    fmap.insert(pair<string, Function>(fasin.get_name(), fasin));
+
+    Function fatan("atan", true, 1, "real", "arctangent, returns radians");
+    fmap.insert(pair<string, Function>(fatan.get_name(), fatan));
+
+    Function fceil("ceil", true, 1, "real", "round up (smallest int >= arg)");
+    fmap.insert(pair<string, Function>(fceil.get_name(), fceil));
+
+    Function fcos("cos", true, 1, "real", "cosine, arg in radians");
+    fmap.insert(pair<string, Function>(fcos.get_name(), fcos));
+
+    Function fcosh("cosh", true, 1, "real", "hyperbolic cosine");
+    fmap.insert(pair<string, Function>(fcosh.get_name(), fcosh));
+
+    Function fexp("exp", true, 1, "real", "exponential");
+    fmap.insert(pair<string, Function>(fexp.get_name(), fexp));
+
+    Function ffabs("fabs", true, 1, "real", "absolute value of a real");
+    fmap.insert(pair<string, Function>(ffabs.get_name(), ffabs));
+
+    Function ffloor("floor", true, 1, "real",
+                    "round down (largest int <= arg)");
+    fmap.insert(pair<string, Function>(ffloor.get_name(), ffloor));
+
+    Function flog("log", true, 1, "real", "log to base e, arg>0");
+    fmap.insert(pair<string, Function>(flog.get_name(), flog));
+
+    Function flog10("log10", true, 1, "real", "log to base 10, arg>0");
+    fmap.insert(pair<string, Function>(flog10.get_name(), flog10));
+
+    Function fsin("sin", true, 1, "real", "sine, arg in radians");
+    fmap.insert(pair<string, Function>(fsin.get_name(), fsin));
+
+    Function fsinh("sinh", true, 1, "real", "hyperbolic sine");
+    fmap.insert(pair<string, Function>(fsinh.get_name(), fsinh));
+
+    Function fsqrt("sqrt", true, 1, "real", "square root (arg >= 0)");
+    fmap.insert(pair<string, Function>(fsqrt.get_name(), fsqrt));
+
+    Function ftan("tan", true, 1, "real", "tangent, arg in radians");
+    fmap.insert(pair<string, Function>(ftan.get_name(), ftan));
+
+    Function ftanh("tanh", true, 1, "real", "hyperbolic tangent");
+    fmap.insert(pair<string, Function>(ftanh.get_name(), ftanh));
+
+    Function fatan2("atan2", true, 2, "real", "arctangent, 2 args");
+    fmap.insert(pair<string, Function>(fatan2.get_name(), fatan2));
+
+    Function ffmod("fmod", true, 2, "real", "remainder of arg1/arg2");
+    fmap.insert(pair<string, Function>(ffmod.get_name(), ffmod));
+
+    Function fpow("pow", true, 2, "real", "arg1 raised to arg2 power");
+    fmap.insert(pair<string, Function>(fpow.get_name(), fpow));
+
+    Function ffmax("max", true, 2, "real", "return the greater of two args");
+    fmap.insert(pair<string, Function>(ffmax.get_name(), ffmax));
+
+    Function ffmin("min", true, 2, "real", "return the lesser of two args");
+    fmap.insert(pair<string, Function>(ffmin.get_name(), ffmin));
+
+    Function fstrlen("strlen", true, 1, "string", "number of chars in arg");
+    fmap.insert(pair<string, Function>(fstrlen.get_name(), fstrlen));
+
+    Function fstrcat("strcat", true, 2, "string", "concatenate two strings");
+    fmap.insert(pair<string, Function>(fstrcat.get_name(), fstrcat));
+
+    Function fstrerase("strerase", true, 3, "string", "erase chars from string");
+    fmap.insert(pair<string, Function>(fstrerase.get_name(), fstrerase));
+
+    Function fstrinsert("strinsert", true, 3, "string", "insert chars into string");
+    fmap.insert(pair<string, Function>(fstrinsert.get_name(), fstrinsert));
+
+    Function fstrsubstr("strsubstr", true, 3, "string", "get sub string");
+    fmap.insert(pair<string, Function>(fstrsubstr.get_name(), fstrsubstr));
+
+    Function fstrtrim("strtrim", true, 1, "string", "remove trailing whitespace");
+    fmap.insert(pair<string, Function>(fstrtrim.get_name(), fstrtrim));
+
+    Function fdefined("defined", true, 1, "logical", "is a variable defined or not");
+    fmap.insert(pair<string, Function>(fdefined.get_name(), fdefined));
+}
+
+void PowerParser::dictionary_add(char *name, double value, bool pred, char *vdesc)
+{
+   Variable *Var_entry = new Variable(name, to_string(value), pred, vdesc);
+   vmap.insert(pair<string, Variable>(Var_entry->get_varname(), *Var_entry));
+}
+
+void PowerParser::dictionary_env_add(char *name, bool pred)
+{
+   const char *getenv_p;
+   const char *getenv_p_not_defined = "";
+
+   getenv_p = getenv(name);
+   if( getenv_p == NULL ){
+      getenv_p = getenv_p_not_defined;
+   }
+
+   int len_name = strlen(name);
+
+   // One extra character for $ and another for null termination
+   char *varname = (char *)malloc(sizeof(char)*(len_name+2));
+
+   varname[0] = '$';
+   strncpy(varname+1, name, len_name+1);
+
+   Variable *Var_entry = new Variable(varname, getenv_p, pred, name);
+   vmap.insert(pair<string, Variable>(Var_entry->get_varname(), *Var_entry));
+
+   free(varname);
+}
+
+
+// ===========================================================================
+// Read a file into a string.
+// This is only done on the io processor.
+// ===========================================================================
+void PowerParser::read_into_string(string filename, string &s_in)
+{
+    if(comm != NULL) {
+        if(!comm->isIOProc()) return;
+    }
+
+    // Its OK if an input file is not specified.
+    if (filename == " ") {
+        s_in = " ";
+        return;
+    }
+
+    // Open the input data file.
+    ifstream in_stream(filename.c_str(), ios::in);
+    if( !in_stream ) {
+        stringstream serr;
+        serr << endl << "*** FATAL ERROR" << endl;
+        serr << "Could not open input (or include) file." << endl;
+        serr << "The name of the file is " << filename << endl;
+        if (filename == "") {
+            serr << "(The file name is blank.)" << endl;
+        }
+        int ierr = 2;
+        process_error(serr, ierr);
+        return;
+    }
+
+    // Read each character and store in a string. We use a string so we
+    // don't have to fiddle with memory allocation and reallocation.
+    // There are more efficient ways to do this, but whatever way is
+    // used has to handle arbitrarily long files.
+    char c;
+    while (in_stream) {
+        in_stream.get(c);
+        if (!in_stream) break;
+        s_in += c;
+    }
+
+    // Check for a 0 size input file, this might be an indication of a
+    // full file system.
+    if( (int)s_in.size() == 0 ) {
+        stringstream serr;
+        serr << endl << "*** FATAL ERROR" << endl;
+        serr << "The name of the input file is " << filename << endl;
+        serr << "This file exists, but its size is 0 bytes, (empty file)." << endl;
+        serr << "Perhaps the file system is full??" << endl;
+        serr << "Use a unix command like \"df -k .\" to find out how full the"
+             " file system is." << endl;
+        int ierr = 2;
+        process_error(serr, ierr);
+        return;
+    }
+
+    // Now that the file contents are transferred to a string we do not need
+    // the data file anymore and can close it.
+    in_stream.close();
+}
+
+
+//+***************************************************************************
+// ***************************************************************************
+// Driver functions for getting values from the commands.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Driver for getting boolean values as integers.
+// This works for arrays of any dimension, 0,1,2,3,...
+// ===========================================================================
+void PowerParser::get_bool_int(string &cname,
+                         int *cvalue,
+                         const vector<int> &size,
+                         bool skip)
+{
+    // Note that we do not default cvalue. Its value only changes if the
+    // command is found.
+
+    // Used in checking for duplicate array values
+    int dim = (int)size.size();
+    int tot_size = 1;
+    for (int i=0; i<dim; i++) {
+        tot_size *= size[i];
+    }
+    vector<int> dup_vals(tot_size, 0);
+    vector<Cmd *> dup_cmd1(tot_size);
+    vector<int> dup_wdex1(tot_size, -1);
+
+    int ierr = 0;
+    stringstream serr;
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_bool_int(cname, cvalue, size, dup_cmd1, dup_wdex1,
+                                      dup_fatal, dup_vals, skip, serr, ierr);
+            processed_cmd_names.push_back(cname);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+void PowerParser::get_bool_int(const char *cname,
+                         int *cvalue,
+                         const vector<int> &size,
+                         bool skip)
+{
+   string cstring(cname);
+   get_bool_int( cstring, cvalue, size, skip);
+}
+
+void PowerParser::get_bool(string &cname,
+                     bool *cvalue,
+                     const vector<int> &size,
+                     bool skip)
+{
+    // Note that we do not default cvalue. Its value only changes if the
+    // command is found.
+
+    // Used in checking for duplicate array values
+    int dim = (int)size.size();
+    int tot_size = 1;
+    for (int i=0; i<dim; i++) {
+        tot_size *= size[i];
+    }
+    vector<int> dup_vals(tot_size, 0);
+    vector<Cmd *> dup_cmd1(tot_size);
+    vector<int> dup_wdex1(tot_size, -1);
+
+    int ierr = 0;
+    stringstream serr;
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_bool(cname, cvalue, size, dup_cmd1, dup_wdex1,
+                                  dup_fatal, dup_vals, skip, serr, ierr);
+            processed_cmd_names.push_back(cname);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+void PowerParser::get_bool(const char *cname,
+                     bool *cvalue,
+                     const vector<int> &size,
+                     bool skip)
+{
+   string cstring(cname);
+   get_bool( cstring, cvalue, size, skip);
+}
+
+
+// ===========================================================================
+// Driver for getting integer values.
+// This works for arrays of any dimension, 0,1,2,3,...
+// ===========================================================================
+template< typename T >
+void PowerParser::get_int(string &cname, T *cvalue, const vector<int> &size, bool skip)
+{
+    // Note that we do not default cvalue. Its value only changes if the
+    // command is found.
+
+    // Used in checking for duplicate array values
+    int dim = (int)size.size();
+    int tot_size = 1;
+    for (int i=0; i<dim; i++) {
+        tot_size *= size[i];
+    }
+    vector<int> dup_vals(tot_size, 0);
+    vector<Cmd *> dup_cmd1(tot_size);
+    vector<int> dup_wdex1(tot_size, -1);
+
+    int ierr = 0;
+    stringstream serr;
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_int(cname, cvalue, size, dup_cmd1, dup_wdex1,
+                                 dup_fatal, dup_vals, skip, serr, ierr);
+            processed_cmd_names.push_back(cname);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+//! Explicit instantiation of supported template types.  If more types are
+//! needed those explicit versions must be listed here.  We are not using
+//! automatic inclusion (we would need to move the function definition into
+//! the header file for that).  The listed versions below are the only ones
+//! that will be included in the library.
+template void PowerParser::get_int(
+    string &cname, int     *cvalue, const vector<int> &size, bool skip);
+template void PowerParser::get_int(
+    string &cname, int64_t *cvalue, const vector<int> &size, bool skip);
+
+template< typename T >
+void PowerParser::get_int(const char *cname,
+                    T *cvalue,
+                    const vector<int> &size,
+                    bool skip)
+{
+   string cstring(cname);
+   get_int( cstring, cvalue, size, skip);
+}
+
+template void PowerParser::get_int(
+    const char *cname, int     *cvalue, const vector<int> &size, bool skip);
+template void PowerParser::get_int(
+    const char *cname, int64_t *cvalue, const vector<int> &size, bool skip);
+
+// ===========================================================================
+// Driver for getting real values.
+// This works for arrays of any dimension, 0,1,2,3,...
+// ===========================================================================
+void PowerParser::get_real(string &cname,
+                     double *cvalue,
+                     const vector<int> &size,
+                     bool skip)
+{
+    // Note that we do not default cvalue. Its values only change if the
+    // command is found.
+
+    // Used in checking for duplicate array values
+    int dim = (int)size.size();
+    int tot_size = 1;
+    for (int i=0; i<dim; i++) {
+        tot_size *= size[i];
+    }
+    vector<int> dup_vals(tot_size, 0);
+    vector<Cmd *> dup_cmd1(tot_size);
+    vector<int> dup_wdex1(tot_size, -1);
+
+    int ierr = 0;
+    stringstream serr;
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_real(cname, cvalue, size, dup_cmd1, dup_wdex1,
+                                  dup_fatal, dup_vals, skip, serr, ierr);
+            processed_cmd_names.push_back(cname);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+void PowerParser::get_real(const char *cname,
+                     double *cvalue,
+                     const vector<int> &size,
+                     bool skip)
+{
+   string cstring(cname);
+   get_real( cstring, cvalue, size, skip);
+}
+
+// ===========================================================================
+// Driver for getting character strings.
+// This works for arrays of any dimension, 0,1,2,3,...
+// ===========================================================================
+void PowerParser::get_char(string &cname,
+                     vector<string> &vstr,
+                     const vector<int> &size,
+                     bool single_char,
+                     bool skip)
+{
+    // Note that we do not default cvalue. Its value only changes if the
+    // command is found.
+
+    // Used in checking for duplicate array values
+    int dim = (int)size.size();
+    int tot_size = 1;
+    for (int i=0; i<dim; i++) {
+        tot_size *= size[i];
+    }
+    vector<int> dup_vals(tot_size, 0);
+    vector<Cmd *> dup_cmd1(tot_size);
+    vector<int> dup_wdex1(tot_size, -1);
+
+    int ierr = 0;
+    stringstream serr;
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_char(cname, vstr, size, single_char, dup_cmd1,
+                                  dup_wdex1, dup_fatal, dup_vals,
+                                  skip, serr, ierr);
+            processed_cmd_names.push_back(cname);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+void PowerParser::get_char(const char *cname,
+                     vector<string> &vstr,
+                     const vector<int> &size,
+                     bool single_char,
+                     bool skip)
+{
+   string cstring(cname);
+   get_char( cstring, vstr, size, single_char, skip);
+}
+
+// ===========================================================================
+// Driver for getting array sizes.
+// ===========================================================================
+void PowerParser::get_size(string &cname, vector<int> &size)
+{
+    int ierr = 0;
+    stringstream serr;
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_size(size, serr, ierr);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+
+// ===========================================================================
+// Driver for getting array sizes. Version to get all sizes
+// ===========================================================================
+void PowerParser::get_sizeb(string &cname, vector<int> &size)
+{
+    int ierr = 0;
+    stringstream serr;
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].get_sizeb(size, serr, ierr);
+        }
+    }
+
+    // Process errors, global abort if ierr==2
+    process_error(serr, ierr);
+}
+
+
+// ===========================================================================
+// Check if the input command, cname, appears in the final, parsed user input.
+//
+// The two outputs are in_input and in_whenthen,
+//    in_input     command is in (or not) the main part of the input, i.e.
+//                 everything except the when...then statements.
+//    in_whenthen  command is in (or not) at least one when...then statement.
+// ===========================================================================
+void PowerParser::cmd_in_input(string &cname, bool &in_input, bool &in_whenthen)
+{
+    in_input = false;
+    in_whenthen = false;
+
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            in_input = true;
+            break;
+        }
+    }
+
+    for (int wtn=0; wtn<(int)whenthens.size(); wtn++) {
+        cmdsfp = whenthens[wtn].get_cmdsf_ptr();
+        for (int i=0; i<(int)cmdsfp->size(); i++) {
+            if ((*cmdsfp)[i].get_cmd_name() == cname) {
+                in_whenthen = true;
+                break;
+            }
+        }
+        if (in_whenthen) break;
+    }
+
+    wt_reset();
+}
+
+
+// ===========================================================================
+// Set the processed flag for all words for all commands that match cname.
+// The value to set the processed flag to is bval.
+// This sets the processed flag for commands in the final buffer and in the
+// when...then final buffers.
+// ===========================================================================
+void PowerParser::cmd_set_processed(string &cname, bool bval)
+{
+    if (! case_sensitive) {
+       transform(cname.begin(), cname.end(), cname.begin(), tolower);
+    }
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        if ((*cmdsfp)[i].get_cmd_name() == cname) {
+            (*cmdsfp)[i].set_processed(bval);
+        }
+    }
+    for (int wtn=0; wtn<(int)whenthens.size(); wtn++) {
+        cmdsfp = whenthens[wtn].get_cmdsf_ptr();
+        for (int i=0; i<(int)cmdsfp->size(); i++) {
+            if ((*cmdsfp)[i].get_cmd_name() == cname) {
+                (*cmdsfp)[i].set_processed(bval);
+            }
+        }
+    }
+    wt_reset();
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void PowerParser::cmd_set_reprocessed(bool bval)
+{
+    for (int c=0; c<(int)processed_cmd_names.size(); c++) {
+        string cname = processed_cmd_names[c];
+        cmd_set_processed(cname, bval);
+    }
+}
+
+
+// ===========================================================================
+// Process errors.
+// ===========================================================================
+void PowerParser::process_error_global(int &return_value)
+{
+    int return_val_local;
+    int ierr = ierr_global;
+
+    return_val_local = 0;
+    if (ierr == 0) {
+      return_value = 0;
+      return;
+    }
+
+    return_val_local = process_error_return_int(serr_global, ierr);
+    return_value     = return_val_local;
+}
+
+// ===========================================================================
+//
+
+void PowerParser::process_error(stringstream &serr, int &ierr)
+{
+    if (ierr == 0) return;
+
+    if (ierr == 3) {
+        serr_global << serr.str();
+        ierr_global = ierr;
+        return;
+    }
+
+    string err_type = "Warnings";
+    if (ierr == 2) err_type = "Fatal errors";
+
+    if (comm->isIOProc()) {
+        cout << endl;
+        cout << err_type << " have been encountered while parsing the user"
+            " input file." << endl;
+        cout << "Note that often fixing the first error will also fix the"
+            " other errors." << endl;
+        cout << serr.str() << endl;
+        fflush(NULL);
+    }
+    if (ierr == 2) {
+        // Force all processors to quit.
+        // We have the problem that the non-IO procs may kill the calculation
+        // before the IO proc can finish printing the error messages, thus
+        // force the IO proc to do the global abort but still allow the
+        // possibility that the IO proc may not have aborted, some other
+        // proc might have.
+        if (comm->isIOProc()) {
+            comm->global_abort_parser();
+        }
+        else {
+            sleep(2);
+            comm->global_abort_parser();
+        }
+    }
+
+
+    // A possible sleep function if the library sleep function is not portable.
+    // #include <time.h>
+    // void sleep(unsigned int mseconds)
+    // {
+    //    clock_t goal = mseconds + clock();
+    //    while (goal > clock());
+    // }
+
+
+    // A better function is the following since it uses CLOCKS_PER_SEC and
+    // thus does not assume its value.
+    //
+    //#include <time.h>
+    //void wait ( int seconds )
+    //{
+    //  clock_t endwait;
+    //  endwait = clock () + seconds * CLOCKS_PER_SEC ;
+    //  while (clock() < endwait) {}
+    //}
+
+    // We might want to put this in Comm, i.e. modify global_abort.
+}
+
+
+// ===========================================================================
+int PowerParser::process_error_return_int(stringstream &serr, int &ierr)
+{
+    int return_value;
+
+    return_value = ierr;
+
+    if (ierr == 0) return(return_value);
+
+    return_value = ierr;
+
+    if (ierr == 3) {
+      serr_global << serr.str();
+      ierr_global = ierr;
+      cout << "Error encountered in process_error_return_int -- err code is " << ierr << endl; 
+      fflush(NULL);
+    }
+
+    if (comm->isIOProc()) {
+        cout << endl;
+        cout << "Error encountered while parsing the user input file -- err code is "
+             << ierr << endl;
+        cout << "Note that often fixing the first error will also fix the"
+            " other errors." << endl;
+        cout << serr.str() << endl;
+        cout.flush();
+        fflush(NULL);
+    }
+
+    return(return_value);
+
+
+    // A possible sleep function if the library sleep function is not portable.
+    // #include <time.h>
+    // void sleep(unsigned int mseconds)
+    // {
+    //    clock_t goal = mseconds + clock();
+    //    while (goal > clock());
+    // }
+
+
+    // A better function is the following since it uses CLOCKS_PER_SEC and
+    // thus does not assume its value.
+    //
+    //#include <time.h>
+    //void wait ( int seconds )
+    //{
+    //  clock_t endwait;
+    //  endwait = clock () + seconds * CLOCKS_PER_SEC ;
+    //  while (clock() < endwait) {}
+    //}
+
+}
+
+
+//+***************************************************************************
+// ***************************************************************************
+// When...then commands
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Check if a when...then condition is satisfied.
+// ===========================================================================
+void PowerParser::wt_check(int wtn, vector<string> &code_varnames,
+                     vector<string> &code_values, 
+                     vector<int> &vv_active, int *wtci)
+{
+    stringstream serr;
+    int ierr = 0;
+    whenthens[wtn-1].check_wt(code_varnames, code_values, vv_active, wtci,
+                              serr, ierr);
+    process_error(serr, ierr);
+    if ( (*wtci) == 1) {
+        cmdsfp = whenthens[wtn-1].get_cmdsf_ptr();
+    }
+}
+
+
+// ===========================================================================
+// Set the commands final buffer pointer.
+// This is also done in the check routine.
+// ===========================================================================
+void PowerParser::wt_set_cmdsfp(int wtn)
+{
+    cmdsfp = whenthens[wtn-1].get_cmdsf_ptr();
+}
+
+
+// ===========================================================================
+// Reset the commands final buffer pointer.
+// ===========================================================================
+void PowerParser::wt_reset()
+{
+    cmdsfp = &cmdsf;
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void PowerParser::wt_casize(int wtn, int *wt_casize)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(wt_casize == wt_casize);
+
+    whenthens[wtn-1].get_char_array_size(wt_casize);
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void PowerParser::wt_carray(int wtn, char *wt_ca, int wt_casize)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(wt_casize == wt_casize);
+
+    string sc;
+    whenthens[wtn-1].get_char_array(sc);
+    for (int i=0; i<(int)sc.size(); i++) {
+        wt_ca[i] = sc[i];
+    }
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void PowerParser::wt_satsize(int wtn, int *wt_satsize)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(wt_satsize == wt_satsize);
+
+    whenthens[wtn-1].get_satsize(wt_satsize);
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void PowerParser::wt_getsat(int wtn, int *wt_sat, int wt_satsize)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(wt_satsize == wt_satsize);
+
+    whenthens[wtn-1].getsat(wt_sat);
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void PowerParser::wt_setsat(int wtn, int *wt_sat, int wt_satsize)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(wt_satsize == wt_satsize);
+
+    whenthens[wtn-1].setsat(wt_sat);
+}
+
+
+// ===========================================================================
+// Get and Set the processed flag for a whenthen.
+// ===========================================================================
+void PowerParser::wt_getprocessed(int wtn, int *wtp)
+{
+    whenthens[wtn-1].getprocessed(wtp);
+}
+
+void PowerParser::wt_setprocessed(int wtn, int wtp)
+{
+    whenthens[wtn-1].setprocessed(wtp);
+}
+
+
+// ===========================================================================
+// Get and Set the sequence index for a whenthen.
+// ===========================================================================
+void PowerParser::wt_getseq(int wtn, int *wtseq)
+{
+    whenthens[wtn-1].getseq(wtseq);
+}
+
+void PowerParser::wt_setseq(int wtn, int wtseq)
+{
+    whenthens[wtn-1].setseq(wtseq);
+}
+
+
+
+
+//+***************************************************************************
+// ***************************************************************************
+// restart_block commands
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Check if a restart block condition is satisfied.
+// ===========================================================================
+void PowerParser::rb_check(vector<string> &code_varnames,
+                     vector<string> &code_values,
+                     vector<int> &vv_active, int *rbci,
+                     int *rb_ntriggered, int *rb_triggered_indices)
+{
+    stringstream serr;
+    int ierr = 0;
+    *rbci = 0;
+    *rb_ntriggered = 0;
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        int ri = 0;
+        restartblocks[i].check_rb(code_varnames, code_values, vv_active, &ri,
+                                  serr, ierr);
+        if (ri == 1) {
+            *rbci = 1;
+            rb_triggered_indices[*rb_ntriggered] = i;
+            *rb_ntriggered += 1;
+        }
+    }
+    process_error(serr, ierr);
+}
+
+
+// ===========================================================================
+// Get/set the restart block names
+// ===========================================================================
+void PowerParser::get_rb_names(vector<string> &rb_names_vstr)
+{
+    rb_names_vstr.clear();
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        rb_names_vstr.push_back(restartblocks[i].get_name());
+    }
+}
+void PowerParser::set_rb_names(vector<string> &rb_names_vstr)
+{
+    bnames_on_dump.clear();
+    for (int i=0; i<(int)rb_names_vstr.size(); i++) {
+        bnames_on_dump.push_back(rb_names_vstr[i]);
+    }
+}
+
+
+// ===========================================================================
+// Get/set the restart block activity flags.
+// ===========================================================================
+void PowerParser::get_rb_aflags(int *rb_aflags)
+{
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        rb_aflags[i] = restartblocks[i].get_aflag();
+    }
+}
+void PowerParser::set_rb_aflags(int *rb_aflags, int rb_num)
+{
+    baflags_on_dump.clear();
+    for (int j=0; j<rb_num; j++) {
+        baflags_on_dump.push_back(rb_aflags[j]);
+    }
+}
+
+
+// ===========================================================================
+// Get/set the restart block satsize.
+// satsize is defined as the total number of sub-conditions over all restart
+// blocks.
+// ===========================================================================
+void PowerParser::get_rb_satsize(int *rb_satsize)
+{
+    int rb_sum = 0;
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        rb_sum += restartblocks[i].get_satsize();
+    }
+    *rb_satsize = rb_sum;
+}
+
+void PowerParser::set_rb_satsize(int rb_satsize)
+{
+    satsize_on_dump = rb_satsize;
+}
+
+
+// ===========================================================================
+// Get/set the number of sub-conditions per restart block
+// ===========================================================================
+void PowerParser::get_rb_satprb(int *rb_satprb)
+{
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        rb_satprb[i] = restartblocks[i].get_satsize();
+    }
+}
+
+void PowerParser::set_rb_satprb(int *rb_satprb, int rb_num)
+{
+    rbsatprb_on_dump.clear();
+    for (int i=0; i<rb_num; i++) {
+        rbsatprb_on_dump.push_back(rb_satprb[i]);
+    }
+}
+
+
+// ===========================================================================
+// Get/set the satisfied flag for each sub-condition for each restart block
+// ===========================================================================
+void PowerParser::get_rb_sat(int *rb_sat)
+{
+    int k = 0;
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        for (int j=0; j<(int)restartblocks[i].get_satsize(); j++) {
+            rb_sat[k] = restartblocks[i].get_sat(j);
+            k++;
+        }
+    }
+}
+
+
+void PowerParser::set_rb_sat(int *rb_sat, int rb_satsize)
+{
+    rbsat_on_dump.clear();
+    for (int i=0; i<rb_satsize; i++) {
+        bool b = false;
+        if (rb_sat[i] == 1) b = true;
+        rbsat_on_dump.push_back(b);
+    }
+}
+
+
+// ===========================================================================
+// Get a combined list of the restart block variable names. Note that there
+// might be more than one variable name per restart block depending on how
+// complicated the condition is.
+// ===========================================================================
+int PowerParser::get_rb_num_varnames()
+{
+    int numv = 0;
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        numv += restartblocks[i].get_num_varnames();
+    }
+    for (int i=0; i<(int)whenthens.size(); i++) {
+        numv += whenthens[i].get_num_varnames();
+    }
+    return numv;
+}
+void PowerParser::get_rb_varnames(vector<string> &rb_varnames_vstr)
+{
+    rb_varnames_vstr.clear();
+    for (int i=0; i<(int)restartblocks.size(); i++) {
+        int numv = restartblocks[i].get_num_varnames();
+        for (int j=0; j<numv; j++) {
+            rb_varnames_vstr.push_back(restartblocks[i].get_varname(j));
+        }
+    }
+    for (int i=0; i<(int)whenthens.size(); i++) {
+        int numv = whenthens[i].get_num_varnames();
+        for (int j=0; j<numv; j++) {
+            rb_varnames_vstr.push_back(whenthens[i].get_varname(j));
+        }
+    }
+}
+
+
+// ===========================================================================
+// Print info about restart blocks.
+// ===========================================================================
+void PowerParser::list_rb()
+{
+    stringstream ssc;
+    list_rb_ss(ssc);
+    if (comm->isIOProc()) {
+        cout << ssc.str();
+    }
+}
+
+void PowerParser::list_rb_start()
+{
+    ssfout.str("");
+    list_rb_ss(ssfout);
+    ssfout_current_pos = 0;
+}
+
+void PowerParser::list_rb_ss(stringstream &ssc)
+{
+    int rblen = (int)restartblocks.size();
+    if (rblen <= 0) {
+        ssc << endl << "No restart blocks have been specified."
+            << endl << endl;
+        return;
+    }
+
+    for (int rb=0; rb<rblen; rb++) {
+        list_one_rb_ss(ssc, rb);
+    }
+}
+
+void PowerParser::list_rb1_start(int *rb)
+{
+    ssfout.str("");
+    list_rb1_ss(ssfout, rb);
+    ssfout_current_pos = 0;
+}
+
+void PowerParser::list_rb1_ss(stringstream &ssc, int *rbp)
+{
+    int rb = *rbp;
+    int rblen = (int)restartblocks.size();
+    if (rb < 0) {
+        ssc << endl << "List restart block error: rb<0"
+            << endl << endl;
+        return;
+    }
+    if (rb >= rblen) {
+        ssc << endl << "List restart block error: rb>=rblen"
+            << endl << endl;
+        return;
+    }
+
+    list_one_rb_ss(ssc, rb);
+}
+
+
+// ===========================================================================
+// List info for one restart block, index=rb
+// ===========================================================================
+void PowerParser::list_one_rb_ss(stringstream &ssc, int rb)
+{
+    ssc << endl;
+    ssc << "** Echo restart block info, restart block name = "
+        << restartblocks[rb].get_name() << endl;
+    string s = "false";
+    if (restartblocks[rb].get_aflag() == 1) s = "true";
+    ssc << "    Active flag = " << s << endl;
+    ssc << "    Condition for this restart block =" << endl;
+    restartblocks[rb].list_condition("        ", "        ", ssc);
+    ssc << endl;
+    ssc << "    Number of sub-conditions = " <<
+        restartblocks[rb].get_satsize() << endl;
+    for (int i=0; i<restartblocks[rb].get_satsize(); i++) {
+        string t = "false";
+        if (restartblocks[rb].get_sat(i) == 1) t = "true";
+        ssc << "        For sub-condition " << i+1 <<
+            ", satisfied flag = " << t << endl;
+    }
+    ssc << endl;
+}
+
+//+***************************************************************************
+// ***************************************************************************
+// Debugging commands/functions.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Print a cmds line.
+// ===========================================================================
+void PowerParser::print_line(int i)
+{
+    if (!comm->isIOProc()) return;
+    stringstream ss3;
+    cmds[i].print_using_words(ss3);
+    cout << ss3.str() << endl;
+}
+
+void PowerParser::print_line(Cmd &cmd)
+{
+    if (!comm->isIOProc()) return;
+    //cout << cmd.get_cmd_name() << endl;
+    //if (cmd.get_cmd_name() != "acmd5") return;
+    stringstream ss3;
+    cmd.print_using_words(ss3);
+    //cmd.print_all_words(ss3);
+    cout << ss3.str() << endl;
+}
+
+
+// ===========================================================================
+// List variables
+//
+// lv1 and lv2 are header and footer strings to delimit the list.
+//
+// var_to_list is a specific variable to list. If it is blank then all vars
+// will be listed, otherwise only the specific var will be listed.
+// ===========================================================================
+void PowerParser::list_vars(string lv1, string lv2, string var_to_list)
+{
+    stringstream ssv;
+    list_vars_ss(lv1, lv2, var_to_list, ssv);
+    if (comm->isIOProc()) {
+        cout << ssv.str();
+    }
+}
+    
+void PowerParser::list_vars_start()
+{
+    ssfout.str("");
+    ssfout << pre_defined_varss.str() << endl;
+    list_vars_ss("", "", "", ssfout);
+    ssfout_current_pos = 0;
+}
+
+void PowerParser::list_vars_ss(string lv1, string lv2, string var_to_list,
+                         stringstream &ssvars)
+{
+    if (!comm->isIOProc()) return;
+    ssvars << lv1 << endl;
+
+    map<string, Variable>::iterator p;
+
+    // Holds the various header and data rows to be printed.
+    vector< vector<string> > rows;
+
+    // Construct the header row.
+    vector<string> header_row;
+    header_row.push_back("Variable name");
+    header_row.push_back("Value");
+    header_row.push_back("Description");
+    rows.push_back(header_row);
+    int n_header_rows = (int)rows.size();
+
+    // Set the number of columns.
+    int ncol = (int)header_row.size();
+
+    // Construct the data rows.
+    for(p = vmap.begin(); p != vmap.end(); p++) {
+        string vname = p->first;
+        if (var_to_list != "") {
+            if (vname != var_to_list) continue;
+        }
+        int nvalues = p->second.get_nvalues();
+        string description = p->second.get_description();
+
+        int ndim = p->second.get_ndim();
+        vector<int> istart(ndim,0);
+
+        for (int n=0; n<nvalues; n++) {
+            string vnamep = vname;
+            if (nvalues > 1) {
+                p->second.get_indices(n, istart);
+                stringstream ss;
+                ss << vname << "(";
+                for (int d=0; d<ndim; d++) {
+                    if (d < ndim-1) ss << istart[d] << ",";
+                    else            ss << istart[d];
+                }
+                ss << ")";
+                vnamep = ss.str();
+            }
+            string value = p->second.get_var_value(n);
+            vector<string> sv;
+            for (int c=0; c<ncol; c++) {
+                if (c == 0) sv.push_back(vnamep);
+                if (c == 1) sv.push_back(value);
+                if (c == 2) sv.push_back(description);
+            }
+            rows.push_back(sv);
+        }
+    }
+
+    // List the data with the columns lined up.
+    Parser_utils putils(index_base);
+    putils.print_strings(rows, n_header_rows, 3, 3, 85, ssvars);
+
+    ssvars << lv2 << endl;
+}
+
+
+// ===========================================================================
+// List functions.
+// ===========================================================================
+void PowerParser::list_funcs(string lf1, string lf2)
+{
+    stringstream ssf;
+    list_funcs_ss(lf1, lf2, ssf);
+    if (comm->isIOProc()) {
+        cout << ssf.str();
+    }
+
+    // Alternate method. 
+    //list_funcs_start();
+    //for (;;) {
+    //    string sline;
+    //    if (!get_ssfout_line(sline)) break;
+    //    if (comm->isIOProc()) {
+    //        cout << sline << endl;
+    //    }
+    //}
+}
+
+void PowerParser::list_funcs_start()
+{
+    ssfout.str("");
+    list_funcs_ss("", "", ssfout);
+    ssfout_current_pos = 0;
+}
+
+void PowerParser::list_funcs_ss(string lf1, string lf2, stringstream &ssfunc)
+{
+    if (!comm->isIOProc()) return;
+    ssfunc << lf1 << endl;
+
+    map<string, Function>::iterator p;
+
+    // Holds the various header and data rows to be printed.
+    vector< vector<string> > rows;
+
+    // Construct the header row.
+    vector<string> header_row;
+    header_row.push_back("Function name");
+    header_row.push_back("nargs");
+    header_row.push_back("type");
+    header_row.push_back("Description");
+    rows.push_back(header_row);
+    int n_header_rows = (int)rows.size();
+
+    // Set the number of columns.
+    int ncol = (int)header_row.size();
+
+    // Construct the data rows.
+    for(p = fmap.begin(); p != fmap.end(); p++) {
+        string fname = p->first;
+        vector<string> sv;
+        int nargs = p->second.get_num_args();
+        stringstream ss;
+        ss << nargs;
+        string type = p->second.get_type();
+        string fdes = p->second.get_description();
+        for (int c=0; c<ncol; c++) {
+            if (c == 0) sv.push_back(fname);
+            if (c == 1) sv.push_back(ss.str());
+            if (c == 2) sv.push_back(type);
+            if (c == 3) sv.push_back(fdes);
+        }
+        rows.push_back(sv);
+    }
+
+    // List the data with the columns lined up.
+    Parser_utils putils(index_base);
+    putils.print_strings(rows, n_header_rows, 3, 4, 85, ssfunc);
+
+    ssfunc << lf2 << endl;
+}
+
+
+
+// ===========================================================================
+// List final set of commands.
+// ===========================================================================
+void PowerParser::list_cmdsf(string lc1, string lc2)
+{
+    stringstream ssc;
+    list_cmdsf_ss(lc1, lc2, ssc);
+    if (comm->isIOProc()) {
+        cout << ssc.str();
+    }
+}
+
+void PowerParser::list_cmdsf_start()
+{
+    ssfout.str("");
+    list_cmdsf_ss("", "", ssfout);
+    ssfout_current_pos = 0;
+}
+
+void PowerParser::list_cmdsf_ss(string lc1, string lc2,
+                          stringstream &ssc)
+{
+    if (!comm->isIOProc()) return;
+    ssc << lc1;
+
+    for (int i=0; i<(int)cmdsfp->size(); i++) {
+        (*cmdsfp)[i].print_using_words_fm(ssc);
+        //(*cmdsfp)[i].print_all_words(ssc);
+        //(*cmdsfp)[i].print_original_string(ssc);
+        ssc << endl;
+    }
+
+    for (int wt=0; wt<(int)whenthens.size(); wt++) {
+        ssc << "when (";
+        whenthens[wt].list_condition("", "      ", ssc);
+        ssc << ") then " << endl;
+        whenthens[wt].list_cmdsf_ss(ssc);
+        ssc << "endwhen" << endl;
+    }
+
+    ssc << lc2;
+}
+
+
+void PowerParser::list_wt_cmdsf()
+{
+    stringstream ssc;
+    list_wt_cmdsf_ss(ssc);
+    if (comm->isIOProc()) {
+        cout << ssc.str();
+    }
+}
+
+void PowerParser::list_wt_cmdsf_start()
+{
+    ssfout.str("");
+    list_wt_cmdsf_ss(ssfout);
+    ssfout_current_pos = 0;
+}
+
+void PowerParser::list_wt_cmdsf_ss(stringstream &ssc)
+{
+    int wtlen = (int)whenthens.size();
+    if (wtlen <= 0) {
+        ssc << endl << "No when...then commands have been specified."
+            << endl << endl;
+        return;
+    }
+
+    for (int wt=0; wt<wtlen; wt++) {
+        ssc << endl;
+        ssc << "** Echo when...then final buffer, when...then number = "
+               << wt+1 << endl;
+        ssc << "    Condition for this when...then =" << endl;
+        whenthens[wt].list_condition("        ", "        ", ssc);
+        ssc << endl;
+        ssc << "    Commands for this when...then =" << endl;
+        whenthens[wt].list_cmdsf_ss(ssc);
+        ssc << endl;
+    }
+}
+
+
+
+//+***************************************************************************
+// ***************************************************************************
+// Low level functions.
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Get a line from the ssfout stringstream.
+// ===========================================================================
+bool PowerParser::get_ssfout_line(string &sline)
+{
+    string s = ssfout.str();
+    if (!get_line_from_string(s, sline,
+                              ssfout_current_pos)) return false;
+    return true;
+}
+
+
+// ===========================================================================
+// Broadcast the buffer the all the other processors.
+// ===========================================================================
+void PowerParser::broadcast_buffer(string &s_in)
+{
+    // If there is no comm or if there is only one processor, then we don't
+    // have to do anything.
+    if (comm == NULL) return;
+    if (comm->getNumProcs() == 1) return;
+
+    // Get the length of the input string on the io processor.
+    int cbuffer_len = 0;
+    if(comm->isIOProc()) cbuffer_len = (int)s_in.size();
+
+    // Broadcast the length of the input buffer to the other processors.
+    comm->broadcast((char*)&cbuffer_len, sizeof(int));
+
+    // All processors allocate memory for the buffer.
+    vector<char> cbuffer(cbuffer_len, 'a');
+
+    // The io processor fills the buffer from the string.
+    if(comm->isIOProc()) {
+        for (int i=0; i<cbuffer_len; i++) cbuffer[i] = s_in[i];
+    }
+
+    // The io processor broadcasts the buffer to everyone.
+    char *cb = &cbuffer[0];
+    comm->broadcast(cb, cbuffer_len);
+
+    // On all the other processors, copy the buffer into the string.
+    if(!comm->isIOProc()) {
+        s_in.resize(cbuffer_len);
+        for (int i=0; i<cbuffer_len; i++) s_in[i] = cbuffer[i];
+    }
+}
+
+
+
+// ===========================================================================
+// Get the next line from the buffer without any processing.
+// Starting at the current position in the buffer, current_pos, search for
+// the next \n. The output string is from the current position to the \n (but
+// does not include the \n). Also remove any \r in the string.
+// ===========================================================================
+bool PowerParser::get_line_from_string(string &strn, string &sout, int &current_pos)
+{
+    // Default the output.
+    sout = "";
+
+    // If the current position is at or beyond the end of the input string,
+    // then nothing further needs to be done.
+    int strn_len = (int)strn.size();
+    if (current_pos >= strn_len) return false;
+
+    for (int i = current_pos; i<strn_len; i++) {
+        // If we encounter an eol, then we are done.
+        if (strn[i] == '\n') {
+            current_pos = i+1;
+            return true;
+        }
+
+        // Some systems use \r\n instead of \n only. Ignore any \r characters.
+        if (strn[i] == '\r') continue;
+
+        // If we get to this point, then all that remains is to add the
+        // character to the output string.
+        sout += strn[i];
+    }
+
+    // If we reach this point then we have gone through the entire input
+    // string and have found that it does not end in a \n. This is ok and does
+    // happen sometimes. We just set the current position to one past the
+    // end of the buffer and return success.
+    current_pos = strn_len;
+    return true;
+}
+
+
+// ===========================================================================
+// This is similar to the get_line_from_string() but this routine gets
+// lines from the input string that are separated by semicolons.
+// Starting at the current position in the buffer, current_pos, search for
+// the next ;. The output string is from the current position to the ; (but
+// does not include the ;).
+// ===========================================================================
+bool PowerParser::get_sc_line_from_string(string &strn, string &sout, int &current_pos)
+{
+    // Default the output.
+    sout = "";
+
+    // If the current position is at or beyond the end of the input string,
+    // then nothing further needs to be done.
+    int strn_len = (int)strn.size();
+    if (current_pos >= strn_len) return false;
+
+    bool ignore_sc = false;
+    for (int i = current_pos; i<strn_len; i++) {
+        if (strn[i] == '!') ignore_sc = true;
+        if (strn[i] == '#') ignore_sc = true;
+        if (i < strn_len-1) {
+            if (strn[i] == '/' && strn[i+1] == '/') ignore_sc = true;            
+        }
+
+        // If we encounter a semicolon, then we are done.
+        if (!ignore_sc) {
+            if (strn[i] == ';') {
+                current_pos = i+1;
+                return true;
+            }
+        }
+
+        // If we get to this point, then all that remains is to add the
+        // character to the output string.
+        sout += strn[i];
+    }
+
+    // If we reach this point then we have gone through the entire input
+    // string and have found that it does not end in a ;. This is ok and does
+    // happen sometimes. We just set the current position to one past the
+    // end of the buffer and return success.
+    current_pos = strn_len;
+    return true;
+}
+
+
+// ===========================================================================
+// Get rid of leading and trailing blanks and tabs.
+// ===========================================================================
+void PowerParser::eliminate_white_space(string &sline)
+{
+    int NPOS = (int)string::npos;
+
+    // Eliminate leading stuff first.
+    int len = (int)sline.size();
+    if (len == 0) return;
+    string whitespace = " \t";
+    int istart = sline.find_first_not_of(whitespace, 0);
+    if (istart == NPOS) istart = (int)sline.size();
+    sline.erase(0, istart);
+
+    // Now eliminate trailing stuff.
+    len = (int)sline.size();
+    if (len == 0) return;
+    int iend = sline.find_last_not_of(whitespace, len - 1);
+    if (iend == NPOS) return;
+    sline.erase(iend+1, (len-1) -(iend+1) + 1);
+
+    return;
+}
+
+
+// ===========================================================================
+// Convert an array of characters into a vector of C++ strings.
+//
+// chars_1d   The array of characters (input). This is composed of a sequence
+//            of strings, each one nchar long. The number of strings is nv.
+// vstr       Vector of C++ strings (output). There will be nv number of
+//            C++ strings in this vector. The length of each C++ string will
+//            vary depending on how much white space is removed.
+// nv         Number of strings in chars_1d (input).
+// nchar      Number of characters in each string in chars_1d (input).
+//
+// Why would anyone want to do this?
+// When passing strings between Fortran and C++ it is cleaner and easier to
+// pass a packed array of single characters. This routine takes that packed
+// array and converts it to something familiar to C++ developers.
+// ===========================================================================
+void PowerParser::chars_to_vstr(char *chars_1d, vector<string> &vstr,
+                          int nv, int nchar)
+{
+    // Temporary storage for each string in the array of characters.
+    char *cnchar = new char[nchar];
+
+    // Loop through all the strings in the array of characters.
+    for (int i=0; i<nv; i++) {
+
+        // Copy each string in the 1d array into a temporary array of chars.
+        // This will be used to create the C++ string.
+        int istart = i * nchar;
+        for (int c=istart; c<istart+nchar; c++) {
+            cnchar[c-istart] = chars_1d[c];
+        }
+        int cnchar_len = nchar;
+
+        // Remove trailing spaces.
+        for (int c=nchar-1; c >= 0; c--) {
+            if (cnchar[c] != ' ') {
+                cnchar_len = c+1;
+                break;
+            }
+        }
+
+        // Create the C++ string.
+        string s(cnchar,cnchar_len);
+
+        // Remove leading spaces.
+        int i2=0;
+        for (int c=0; c<(int)s.size(); c++) {
+            if (s[c] != ' ') {
+                i2=c;
+                break;
+            }
+        }
+        if (i2 != 0) s.erase(s.begin(), s.begin()+i2);
+
+        // Add the string to the vector of strings.
+        vstr.push_back(s);
+    }
+    delete [] cnchar;
+}
+
+
+// ===========================================================================
+// Convert  a vector of C++ strings into a packed array of characters.
+//
+// chars_1d   The array of characters (output). This is composed of a sequence
+//            of strings, each one nchar long. The number of strings is nv.
+// vstr       Vector of C++ strings (input). There will be nv number of
+//            C++ strings in this vector. The length of each C++ string will
+//            vary, whitespace is added to each C++ string to make its length
+//            nchar.
+// nv         Number of strings in chars_1d (input).
+// nchar      Number of characters in each string in chars_1d (input).
+//
+// Why would anyone want to do this?
+// When passing strings between Fortran and C++ it is cleaner and easier to
+// pass a packed array of single characters. This routine takes the vector
+// of strings and converts that to a packed character array.
+// ===========================================================================
+void PowerParser::vstr_to_chars(char *chars_1d, vector<string> &vstr,
+                          int nv, int nchar)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(nv == nv);
+
+    // Loop through each string in the vector of strings.
+    for (int strdex=0; strdex<(int)vstr.size(); strdex++) {
+
+        // Starting location in the 1d array of characters for each string.
+        int i1d = strdex * nchar;
+
+        // Number of characters in the C++ string. Should be smaller or 
+        // equal to nchar, but we handle the case where it is larger
+        // than nchar.
+        int nc = (int)vstr[strdex].size();
+        if (nc > nchar) nc = nchar;
+
+        // Copy the string into the 1d character array.
+        for (int c=i1d; c<i1d+nc; c++) {
+            chars_1d[c] = vstr[strdex][c-i1d];
+        }
+
+        // Pad with blanks.
+        for (int c=i1d+nc; c<i1d+nchar; c++) {
+            chars_1d[c] = ' ';
+        }
+    }
+}
+
+
+
+
+} // end of PP namespace
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/PowerParser.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/PowerParser.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,717 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// Provide a class that parses text files into lines and words.
+// ***************************************************************************
+// ***************************************************************************
+#ifndef PARSEHHINCLUDE
+#define PARSEHHINCLUDE
+
+// Need to include Cmd.hh because on the PGI compiler, the deque<Cmd>
+// declaration did not work with just doing "class Cmd;", we need to fully
+// include Cmd.hh. 
+#include "Comm.hh"
+#include <sstream>
+#include <fstream>
+#include "Word.hh"
+#include "Cmd.hh"
+#include "Restartblock.hh"
+#include "Whenthen.hh"
+
+/****************************************************************//**
+ * PP is the namespace for PowerParser. Example:
+ *
+ *     using namespace PP;
+ *******************************************************************/
+namespace PP
+{
+using std::ofstream;
+using std::streambuf;
+
+/****************************************************************//**
+ * PowerParser class 
+ *    Provide a class that parses text files into lines and words.
+ *******************************************************************/
+class PowerParser
+{
+
+public:
+
+    ofstream fileout;
+    streambuf *coutbuf;
+
+    // Constructors, destructors and drivers.
+/****************************************************************//**
+ * \brief
+ * Constructor with no arguments
+ *
+ * Typical Usage   
+ *
+ *     PowerParser parse;
+ *           or
+ *     PowerParser *parse = new PowerParser();
+ *******************************************************************/
+    PowerParser(void);
+
+/****************************************************************//**
+ * \brief
+ * Constructor -- with input filename in string format
+ *
+ * **Parameters**
+ * * string filename[in] -- the input file. The file will be
+ *    read in, broadcast, and then parsed
+ *
+ * Typical Usage
+ *
+ *     string fin("simfile.in");
+ *     PowerParser parse(fin);
+ *           or
+ *     string fin("simfile.in");
+ *     PowerParser *parse = new PowerParser(fin);
+ *******************************************************************/
+    PowerParser(string filename);
+
+/****************************************************************//**
+ * \brief
+ *  Constructor -- with input filename in char array format
+ *
+ *  **Parameters**
+ *  * const char *filename[in] -- the input file. The file will be
+ *    read in, broadcast, and then parsed
+ *
+ * Typical Usage
+ *
+ *     PowerParser parse("simfile.in");
+ *           or
+ *     PowerParser *parse = new PowerParser("simfile.in");
+ *******************************************************************/
+    PowerParser(const char *filename);
+
+/****************************************************************//**
+ * \brief
+ *  Destructor with no arguments
+ *
+ * Typical Usage   
+ *
+ *     delete parse;
+ *******************************************************************/
+    ~PowerParser(void);
+
+    void dictionary_add(char *name, double value, bool pred, char *vdesc);
+    void dictionary_env_add(char *name, bool pred);
+
+/****************************************************************//**
+ * \brief
+ * Reads the file in on the IO processor, broadcast the string
+ * to all the other processors, then parse the string.
+ *
+ * **Parameters**
+ * * string filename
+ *
+ * Typical Usage
+ *
+ *     string fin("simfile.in");
+ *     PowerParser parse();
+ *     parse.parse_file(fin);
+ *******************************************************************/
+    void parse_file(string filename);
+
+/****************************************************************//**
+ * \brief
+ * Reads the file in on the IO processor, broadcast the string
+ * to all the other processors, then parse the string.
+ *
+ * **Parameters**
+ * * const char *filename
+ *
+ * Typical Usage
+ *
+ *     PowerParser parse();
+ *     parse.parse_file("simfile.in");
+ *******************************************************************/
+    void parse_file(const char *filename);
+
+/****************************************************************//**
+ * \brief
+ * Given a multi-line string on every processor, parse it into cmds
+ * and words. After calling this function, the parser is ready for use.
+ *******************************************************************/
+    void parse_string(string filename, string s_in);
+
+/****************************************************************//**
+ * \brief
+ * The input file(s) has been read and put into commands. Now do the
+ * compilation phase.
+ *******************************************************************/
+    void compile_buffer(int &return_value);
+
+/****************************************************************//**
+ * \brief
+ * Handle the execution line arguments
+ *******************************************************************/
+    void handle_exe_args(string other_argggs);
+
+/****************************************************************//**
+ * \brief
+ * Clear out the parser and re-init
+ *******************************************************************/
+    void clear_and_init();
+
+/****************************************************************//**
+ *******************************************************************/
+    void store_exe_args(string &oargs, string &fname) {
+        other_args = oargs;
+        file_name = fname;
+    }
+
+/****************************************************************//**
+ *******************************************************************/
+    void get_exe_args(string &oargs, string &fname) {
+        oargs = other_args;
+        fname = file_name;
+    }
+
+/****************************************************************//**
+ * \brief
+ * String version of the driver for getting boolean values as integers.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * string &cname -- key word in input file
+ * * int *cvalue -- variable to set in simulation code
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        string InputName("OutputGraphics");
+ *        int iflag = 0;
+ *        parse.get_bool_int(InputName, &iflag);
+ *     or for arrays
+ *        string InputName("OutputGraphicsTypes");
+ *        vector<int> iflags[2] = {0, 0};
+ *        vector<int> size = {2};
+ *        parse.get_bool_int(InputName, &iflags[0], size);
+ *******************************************************************/
+    void get_bool_int(string &cname,
+                      int *cvalue,
+                      const vector<int> &size = vector<int>(), // optional argument
+                      bool skip = false);                      // optional argument
+
+/****************************************************************//**
+ * \brief
+ * String version of the driver for getting boolean values.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * string &cname -- key word in input file
+ * * bool *cvalue -- variable to set in simulation code
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        string InputName("OutputGraphics");
+ *        bool iflag = 0;
+ *        parse.get_bool(InputName, &iflag);
+ *     or for arrays
+ *        string InputName("OutputGraphicsTypes");
+ *        vector<bool> iflags[2] = {0, 0};
+ *        vector<int> size = {2};
+ *        parse.get_bool(InputName, &iflags[0], size);
+ *******************************************************************/
+    void get_bool(string &cname,
+                  bool *cvalue,
+                  const vector<int> &size = vector<int>(),     // optional argument
+                  bool skip = false);                          // optional argument
+
+/****************************************************************//**
+ * \brief
+ * String version of the driver for getting integer values.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * const char *cname -- key word in input file
+ * * int *cvalue -- variable to set in simulation code. Int can be
+ *      either standard int or long long int
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        int ivalue = 0;
+ *        parse.get_int("Num_Cycles", &ivalue);
+ *     or for arrays
+ *        vector<int> ivalue[2] = {0, 0};
+ *        vector<int> size = {2};
+ *        parse.get_int("Dimensions", &ivalue[0], size);
+ *******************************************************************/
+    template< typename T >
+    void get_int(string &cname,
+                 T *cvalue,
+                 const vector<int> &size = vector<int>(),      // optional argument
+                 bool skip = false);                           // optional argument
+
+/****************************************************************//**
+ * \brief
+ * String version of the driver for getting real values.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * const char *cname -- key word in input file
+ * * double *cvalue -- variable to set in simulation code.
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        double rvalue = 0;
+ *        parse.get_real("TimeStop", &rvalue);
+ *     or for arrays
+ *        vector<double> rvalues[2] = {0.0, 0.0};
+ *        vector<int> size = {2};
+ *        parse.get_real("DumpTimes", &rvalues[0], size);
+ *******************************************************************/
+    void get_real(string &cname,
+                  double *cvalue,
+                  const vector<int> &size = vector<int>(),     // optional argument
+                  bool skip = false);                          // optional argument
+
+/****************************************************************//**
+ *******************************************************************/
+    void get_char(string &cname,
+                  vector<string> &vstr,
+                  const vector<int> &size = vector<int>(),     // optional argument
+                  bool single_char = false,                    // optional argument
+                  bool skip = false);                          // optional argument
+
+    // These are just convenience function to allow char arrays for get variable so
+    // the calls are simpler. They convert the cname to a string and call the 
+    // string versions above
+
+/****************************************************************//**
+ * \brief
+ * Char array version of the driver for getting boolean values as integers.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * const char *cname -- key word in input file
+ * * int *cvalue -- variable to set in simulation code
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        int iflag = 0;
+ *        parse.get_bool_int("OutputGraphics", &iflag);
+ *     or for arrays
+ *        vector<int> iflags[2] = {0, 0};
+ *        vector<int> size = {2};
+ *        parse.get_bool_int("OutputGraphicsTypes", &iflags[0], size);
+ *******************************************************************/
+    void get_bool_int(const char *cname,
+                      int *cvalue,
+                      const vector<int> &size = vector<int>(), // optional argument
+                      bool skip = false);                      // optional argument
+
+/****************************************************************//**
+ * \brief
+ * Char array version of the driver for getting boolean values.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * const char *cname -- key word in input file
+ * * bool *cvalue -- variable to set in simulation code
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        bool iflag = 0;
+ *        parse.get_bool("OutputGraphics", &iflag);
+ *     or for arrays
+ *        vector<bool> iflags[2] = {0, 0};
+ *        vector<int> size = {2};
+ *        parse.get_bool("OutputGraphicsTypes", &iflags[0], size);
+ *******************************************************************/
+    void get_bool(const char *cname,
+                  bool *cvalue,
+                  const vector<int> &size = vector<int>(),     // optional argument
+                  bool skip = false);                          // optional argument
+
+/****************************************************************//**
+ * \brief
+ * Char array version of the driver for getting integer values.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * const char *cname -- key word in input file
+ * * int *cvalue -- variable to set in simulation code. Int can be
+ *      either standard int or long long int
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        int ivalue = 0;
+ *        parse.get_int("Num_Cycles", &ivalue);
+ *     or for arrays
+ *        vector<int> ivalue[2] = {0, 0};
+ *        vector<int> size = {2};
+ *        parse.get_int("Dimensions", &ivalue[0], size);
+ *******************************************************************/
+    template< typename T >
+    void get_int(const char *cname,
+                 T *cvalue,
+                 const vector<int> &size = vector<int>(),      // optional argument
+                 bool skip = false);                           // optional argument
+
+/****************************************************************//**
+ * \brief
+ * Char array version of the driver for getting real values.
+ * This works for arrays of any dimension, 0,1,2,3,...
+ *
+ * **Parameters**
+ * * const char *cname -- key word in input file
+ * * double *cvalue -- variable to set in simulation code.
+ * * const vector<int> &size = vector<int>() -- sizes of array,
+ *      (default is null for a scalar).
+ * * bool skip = false -- skip setting variable, (default is false)
+ *
+ * Typical Usage
+ *
+ *     for scalars
+ *        double rvalue = 0;
+ *        parse.get_real("TimeStop", &rvalue);
+ *     or for arrays
+ *        vector<real> rvalue[2] = {0.0, 0.0};
+ *        vector<int> size = {2};
+ *        parse.get_real("DumpTimes", &rvalue[0], size);
+ *******************************************************************/
+    void get_real(const char *cname,
+                  double *cvalue,
+                  const vector<int> &size = vector<int>(),     // optional argument
+                  bool skip = false);                          // optional argument
+
+/****************************************************************//**
+ *******************************************************************/
+    void get_char(const char *cname,
+                  vector<string> &vstr,
+                  const vector<int> &size = vector<int>(),     // optional argument
+                  bool single_char = false,                    // optional argument
+                  bool skip = false);                          // optional argument
+
+
+/****************************************************************//**
+ * \brief
+ * Driver for getting array sizes.
+ *******************************************************************/
+    void get_size(string &cname, vector<int> &size);
+
+/****************************************************************//**
+ * \brief
+ * Driver for getting array sizes. Version to get all sizes
+ *******************************************************************/
+    void get_sizeb(string &cname, vector<int> &size);
+
+
+/****************************************************************//**
+ * \brief
+ * Check if the input command, cname, appears in the final, parsed user input.
+ *
+ * The two outputs are in_input and in_whenthen,
+ *    in_input     command is in (or not) the main part of the input, i.e.
+ *                 everything except the when...then statements.
+ *    in_whenthen  command is in (or not) at least one when...then statement.
+ *******************************************************************/
+    void cmd_in_input(string &cname, bool &in_input, bool &in_whenthen);
+
+/****************************************************************//**
+ * \brief
+ * Set the processed flag for all words for all commands that match cname.
+ * The value to set the processed flag to is bval.
+ * This sets the processed flag for commands in the final buffer and in the
+ * when...then final buffers.
+ *******************************************************************/
+    void cmd_set_processed(string &cname, bool bval);
+
+/****************************************************************//**
+ * \brief
+ * Check all processed flags on every command. If any word on any command
+ * has not been processed, then that is a fatal error.
+ *******************************************************************/
+    void check_processed(bool &good);
+
+/****************************************************************//**
+ * \brief
+ * If commands appear more than once in the input file(s), print a warning
+ * to the user.
+ *******************************************************************/
+    void check_duplicates();
+
+
+/****************************************************************//**
+ * \brief
+ * Echo user input to a stringstream.
+ *******************************************************************/
+    void echo_input_start();
+
+/****************************************************************//**
+ * \brief
+ * Echo user input to a stringstream.
+ *******************************************************************/
+    void echo_input_ss(stringstream &ssinp);
+
+/****************************************************************//**
+ * Get a line from the ssfout stringstream. (low-level function)
+ *******************************************************************/
+    bool get_ssfout_line(string &sline);
+
+    // Communications object from the infrastructure.
+/****************************************************************//**
+ * \brief
+ *  Holds internal comm class for PowerParser. Comm is initialized
+ *  automatically and will use an already initialized MPI or 
+ *  initialize it itself.  This is meant to be for use internal to
+ *  the package, but developers can get the number of processors
+ *  and rank with
+ *
+ *      int mype = parse->comm->getProcRank();
+ *      int npes = parse->comm->getNumProcs();
+ *******************************************************************/
+    Comm *comm;
+
+/****************************************************************//**
+ *******************************************************************/
+    void list_funcs_start();
+
+/****************************************************************//**
+ *******************************************************************/
+    void list_vars_start();
+
+/****************************************************************//**
+ *******************************************************************/
+    void list_cmdsf_start();
+
+/****************************************************************//**
+ *******************************************************************/
+    void list_wt_cmdsf_start();
+
+    void process_error_global(int &return_value);
+
+
+    void rb_check(vector<string> &code_varnames,
+                  vector<string> &code_values,
+                  vector<int> &vv_active, int *rbci,
+                  int *rb_ntriggered, int *rb_triggered_indices);
+    int  get_rb_num_varnames();
+    void get_rb_varnames(vector<string> &rb_varnames_vstr);
+    void get_num_rb(int *rbnum) { *rbnum = (int)restartblocks.size(); }
+    void set_num_rb(int rbnum)  { nrb_on_dump = rbnum; }
+    void get_rb_names(vector<string> &rb_names_vstr);
+    void set_rb_names(vector<string> &rb_names_vstr);
+    void get_rb_aflags(int *rb_aflags);
+    void set_rb_aflags(int *rb_aflags, int rb_num);
+    void get_rb_satsize(int *rb_satsize);
+    void set_rb_satsize(int rb_satsize);
+    void get_rb_satprb(int *rb_satprb);
+    void set_rb_satprb(int *rb_satprb, int rb_num);
+    void get_rb_sat(int *rb_sat);
+    void set_rb_sat(int *rb_sat, int rb_satsize);
+    void list_rb();
+    void list_rb_start();
+    void list_rb_ss(stringstream &ssc);
+    void list_rb1_start(int *rb);
+    void list_rb1_ss(stringstream &ssc, int *rbp);
+    void list_one_rb_ss(stringstream &ssc, int rb);
+
+
+    void get_num_whenthen(int *wtnum) { *wtnum = (int)whenthens.size(); }
+    void wt_check(int wtn, vector<string> &code_varnames,
+                  vector<string> &code_values,
+                  vector<int> &vv_active, int *wtci);
+    void wt_set_cmdsfp(int wtn);
+    void wt_reset();
+    void wt_casize(int wtn, int *wt_casize);
+    void wt_carray(int wtn, char *wt_ca, int wt_casize);
+
+    void wt_satsize(int wtn, int *wt_satsize);
+    void wt_getsat(int wtn, int *wt_sat, int wt_satsize);
+    void wt_setsat(int wtn, int *wt_sat, int wt_satsize);
+    void wt_getprocessed(int wtn, int *wtp);
+    void wt_setprocessed(int wtn, int wtp);
+    void wt_getseq(int wtn, int *wtseq);
+    void wt_setseq(int wtn, int wtseq);
+
+    void chars_to_vstr(char *chars_1d, vector<string> &vstr,
+                       int nv, int nchar);
+    void vstr_to_chars(char *chars_1d, vector<string> &vstr,
+                       int nv, int nchar);
+
+    void ListIncludeFiles();
+    int NumIncludeFiles();
+    string GetIncludeFile(int);
+
+
+
+private:
+
+    void init();
+    int  process_dav_cmd();
+    void check_dup_scalar(int wtn, bool &found_any);
+    void set_dup_row(vector<string> &row, Cmd &cmdi, int iw);
+    void remove_dup_scalar(int wtn);
+    void read_into_string(string filename, string &s_in);
+    void broadcast_buffer(string &s_in);
+    bool get_line_from_string(string &strn, string &sout, int &current_pos);
+    bool get_sc_line_from_string(string &strn, string &sout, int &current_pos);
+    void store_line_strings(string &s_in);
+    void eliminate_white_space(string &sline);
+    void cmd_set_reprocessed(bool bval);
+    int  process_error_return_int(stringstream &serr, int &ierr);
+    void process_error(stringstream &serr, int &ierr);
+
+    void list_vars(string lv1, string lv2, string var_to_list);
+    void list_vars_ss(string lv1, string lv2, string var_to_list,
+                      stringstream &ssvars);
+
+    void list_funcs(string lf1, string lf2);
+    void list_funcs_ss(string lf1, string lf2, stringstream &ssfunc);
+
+    void list_cmdsf(string lc1, string lc2);
+    void list_cmdsf_ss(string lc1, string lc2,
+                       stringstream &ssc);
+    void list_wt_cmdsf();
+    void list_wt_cmdsf_ss(stringstream &ssc);
+
+    void print_strings(vector< vector<string> > rows, int n_header_rows,
+                       int offset, int col_spacing, int line_len_max,
+                       stringstream &ss);
+    bool end_do_loop(int &i, deque<int> &do_start,
+                     stringstream &serr, int &ierr);
+    void end_do_ret(int &i, deque<int> &do_start,
+                    stringstream &serr, int &ierr);
+    void check_enddo(deque<int> &do_start, stringstream &serr, int &ierr);
+    int  jump_to_call(int &i, deque<int> &icall, deque<int> &isub,
+                      stringstream &serr, int &ierr);
+    int  jump_to_sub(int &i, string &sub_name,
+                     stringstream &serr, int &ierr);
+    void print_line(int i);
+    void print_line(Cmd &cmd);
+
+    // Store exe line arguments.
+    string other_args, file_name;
+
+    // A double ended queue for storing the original lines. This is
+    // before the lines get turned into Cmds. 
+    // line_number is an index into cmd_strings, note that it starts
+    // from 1, not 0.
+    deque<string> cmd_strings;
+    int line_number;
+
+    // Define a map for a set of variables.
+    map<string, Variable> vmap;
+    
+    // Maintain a list of included files
+
+    std::map<int,string> IncludeFiles;
+
+    // Define a map for the functions.
+    map<string, Function> fmap;
+
+    // A double ended queue for storing the commands.
+    deque<Cmd> cmds;
+    deque<Cmd> cmdsf;
+    deque<Cmd> *cmdsfp;
+
+    // Store cmd names that have been processed, used for clearing and
+    // recreating the parser.
+    deque<string> processed_cmd_names;
+
+    // Related to writing output to a fortran file.
+    int ssfout_current_pos;
+    stringstream ssfout;
+
+    // Used for storing the list of pre-defined variables to be printed
+    // out later.
+    stringstream pre_defined_varss;
+
+    // Used for storing multiple errors and processing them later.
+    stringstream serr_global;
+    int ierr_global;
+
+    // The execution line arguments are put in this string.
+    string exe_args_str;
+
+    // The when ... then objects.
+    deque<Whenthen> whenthens;
+
+    // Restart blocks.
+    deque<Restartblock> restartblocks;
+    int nrb_on_dump;
+    deque<string> bnames_on_dump;
+    deque<bool> baflags_on_dump;
+    int satsize_on_dump;
+    deque<bool> rbsat_on_dump;
+    deque<int> rbsatprb_on_dump;
+
+    // Flag for whether duplicate array values will be none, fatal, or
+    // a warning, determined by the duplicate_array_values command.
+    //    dup_fatal = 0     Turn off duplicate array value checking
+    //    dup_fatal = 1     Duplicate array value checking is a warning
+    //    dup_fatal = 2     Duplicate array value checking is a fatal error
+    int dup_fatal;
+};
+
+} // end of PP namespace
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Restartblock.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,598 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// Restart Blocks
+// Run the code until a restart block condition is satisfied. Set the restart
+// block as active, write a restart dump, stop the code, and restart.
+// ***************************************************************************
+// ***************************************************************************
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <deque>
+#include <sstream>
+#include <map>
+#include <math.h>
+
+#include "Variable.hh"
+#include "Function.hh"
+#include "Word.hh"
+#include "Parser_math.hh"
+#include "Cmd.hh"
+#include "Restartblock.hh"
+
+namespace PP
+{
+using std::cout;
+using std::endl;
+using std::string;
+using std::deque;
+using std::vector;
+using std::stringstream;
+using std::pair;
+using std::ifstream;
+using std::ios;
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Restartblock::Restartblock() 
+{
+    active = -1;
+}
+
+// ===========================================================================
+// Usual constructor.
+//    restart_block name (time .eq. 50) then
+// ===========================================================================
+Restartblock::Restartblock(int &nrb, Cmd &cmdi, bool &skiprb,
+                           bool &single_line_rb,
+                           deque<string> &bnames_on_dump,
+                           deque<bool> &baflags_on_dump,
+                           deque<int> &rbsatprb_on_dump,
+                           deque<bool> &rbsat_on_dump,
+                           stringstream &serr, int &ierr)
+{
+    //cout << "&&&&&cw ********** Restartblock.cc, Enter Constructor **********" << endl;
+    active = -1;
+    nrb += 1;
+    skiprb = true;
+    single_line_rb = false;
+    int nwords = cmdi.get_nwords();
+
+    // &&&&&cw
+    //stringstream ssprint;
+    //cmdi.print_using_words(ssprint);
+    //cout << ssprint.str() << endl;
+
+    if (nwords < 8) {
+        cmdi.fatal_error(0, serr, ierr);
+        serr << "A restart block line must have at least 8 words on it (the "
+             << endl
+             << "opening and closing parentheses each count as a word)"
+             << endl;
+        serr << "This restart block command only has " << nwords <<
+            " words on it." << endl;
+        serr << "Expected something like (this has 8 words):" << endl;
+        serr << "    restart_block after5 (time .gt. 5) then" << endl;
+        serr << "Or perhaps a single line restart block like (this has 13 words):"
+             << endl;
+        serr << "    restart_block after5 (time .gt. 5) sizemat(2) = 0.005" << endl;
+        ierr = 2;
+        return;
+    }
+
+    string p2 = cmdi.get_string(2);
+    if (p2 != "(") {
+        cmdi.fatal_error(2, serr, ierr);
+        serr << "Expected an open parentheses following the restart block name.."
+             << endl;
+        serr << "Instead found " << p2 << " following the restart block name."
+             << endl;
+        serr << "The restart block command should be something like:" << endl;
+        serr << "    restart_block t_is_gt_5 (time .gt. 5) then" << endl;
+        serr << "Or perhaps a single line restart block like:" << endl;
+        serr << "    restart_block t_is_gt_5 (time .gt. 5) sizemat(2) = 0.005" << endl;
+        ierr = 2;
+        return;
+    }
+
+
+    for (int i=1; i<nwords-1; i++) {
+        string t1 = cmdi.get_string(i);
+        if (t1 == "then") {
+            cmdi.fatal_error(i, serr, ierr);
+            serr << "Found a then keyword embedded in the restart_block command."
+                 << endl;
+            serr << "If a then keyword is present it must be the last "
+                 "word on the line." << endl;
+            serr << "The restart_block command should be something like:" << endl;
+            serr << "    restart_block t_is_gt_5 (time .gt. 5) then" << endl;
+            serr << "Or perhaps a single line restart block like:" << endl;
+            serr << "    restart_block t_is_gt_5 (time .gt. 5) sizemat(2) = 0.005" << endl;
+            ierr = 2;
+            return;
+        }
+    }
+
+
+    // Find the closing parenthesis
+    int close_paren_dex = -1;
+    for (int i=2; i<nwords; i++) {
+        string pi = cmdi.get_string(i);
+        if (pi == "then") break;
+        if (pi == ")") {
+            close_paren_dex = i;
+            break;
+        }
+    }
+
+    if (close_paren_dex == -1) {
+        cmdi.fatal_error(0, serr, ierr);
+        serr << "Expected a close parentheses following the condition."
+             << endl;
+        serr << "Did not find a close parentheses." << endl;
+        serr << "The restart_block command should be something like:" << endl;
+        serr << "    restart_block t_is_gt_5 (time .gt. 5) then" << endl;
+        serr << "Or perhaps a single line restart block like:" << endl;
+        serr << "    restart_block t_is_gt_5 (time .gt. 5) sizemat(2) = 0.005" << endl;
+        ierr = 2;
+        return;
+    }
+
+
+    int nw = close_paren_dex - 3;
+    if ((nw+1)%4 != 0) {
+        cmdi.fatal_error(0, serr, ierr);
+        serr << "Wrong number of words in the restart_block condition."
+             << endl;
+        serr << "The number of words in this condition is " << nw << endl;
+        serr << "The number of words + 1 should be a multiple of 4." << endl;
+        serr << "The condition should be something like:" << endl;
+        serr << "    time .gt. 5" << endl;
+        serr << "This has 3 words and 3+1 is a multiple of 4." << endl;
+        serr << "Or the following is valid" << endl;
+        serr << "    time .gt. 5 .and. ncycle .ge. 10" << endl;
+        serr << "This has 7 words and 7+1 is a multiple of 4." << endl;
+        ierr = 2;
+        return;
+    }
+
+    
+
+
+    for (int i=3; i<close_paren_dex; i+=4) {
+        add_word(cmdi, i,   varname);
+        add_word(cmdi, i+1, relation);
+        add_word(cmdi, i+2, value);
+
+        if (i+3 < close_paren_dex) add_word(cmdi, i+3, logop);
+        else                       add_word(cmdi, i+3, logop, "none");
+
+        satisfied.push_back("false");
+    }
+
+
+    // Check to make sure that the relation is valid.
+    for (int n=0; n<(int)varname.size(); n++) {
+        bool valid_relation = false;
+        if (relation[n].get_string() == ".hglt.") valid_relation = true;
+        if (relation[n].get_string() == ".hgle.") valid_relation = true;
+        if (relation[n].get_string() == ".hgeq.") valid_relation = true;
+        if (relation[n].get_string() == ".hgne.") valid_relation = true;
+        if (relation[n].get_string() == ".hggt.") valid_relation = true;
+        if (relation[n].get_string() == ".hgge.") valid_relation = true;
+        if (relation[n].get_string() == ".lt.") valid_relation = true;
+        if (relation[n].get_string() == ".le.") valid_relation = true;
+        if (relation[n].get_string() == ".eq.") valid_relation = true;
+        if (relation[n].get_string() == ".ne.") valid_relation = true;
+        if (relation[n].get_string() == ".gt.") valid_relation = true;
+        if (relation[n].get_string() == ".ge.") valid_relation = true;
+
+        if (!valid_relation) {
+            relation[n].fatal_error(serr, ierr);
+            serr << "Invalid restart_block relation." << endl;
+            serr << "Expected  .lt., .le., .eq., .ne., .gt., .ge." << endl;
+            serr << "Also could be .hglt., .hgle., .hgeq., .hgne., .hggt., .hgge." << endl;
+            serr << "Instead found relation:  " << relation[n].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+    }
+
+    // The name of the restart block is the second word on the
+    // restart_block command.
+    name = cmdi.get_string(1);
+    //cout << "&&&&&cw Restartblock.cc, name1 = " << name << endl;
+    //cout << "&&&&&cw Restartblock.cc, satsize = " << satisfied.size() << endl;
+
+    // If this is a restart, then restart block names and active flags
+    // could be stored on the restart dump. If this restart block matches
+    // any stored on the dump, then set the active flag to what is on
+    // the dump.
+    for (int i=0; i<(int)bnames_on_dump.size(); i++) {
+        //cout << "&&&&&cw Restartblock.cc, name = " << name << endl;
+        //cout << "&&&&&cw Restartblock.cc, bnames_on_dump = " << 
+        //    bnames_on_dump[i] << endl;
+        //cout << "&&&&&cw Restartblock.cc, baflags_on_dump = " << 
+        //    baflags_on_dump[i] << endl;
+        if (name == bnames_on_dump[i]) {
+            active = 0;
+            if (baflags_on_dump[i]) active = 1;
+
+            int satdex = 0;
+            for (int j=0; j<i; j++) {
+                satdex += rbsatprb_on_dump[j];
+            }
+            for (int j=satdex; j<satdex+rbsatprb_on_dump[i]; j++) {
+                string s = "false";
+                if (rbsat_on_dump[j]) s = "true";
+                satisfied[j-satdex] = s;
+            }
+
+            break;
+        }
+    }
+    //cout << "&&&&&cw Restartblock.cc, after set restart" << endl;
+
+
+    // If this restart block is active, that means we want to process
+    // the commands in the block, therefore we set the skip flag to false.
+    if (active == 1) skiprb = false;
+
+
+    // Set the has gotten to flags.
+    for (int n=0; n<(int)varname.size(); n++) {
+        bool hg = false;
+
+        if (relation[n].get_string() == ".hglt.") {
+            hg = true;
+            relation[n].set_value(".lt.");
+        }
+        else if (relation[n].get_string() == ".hgle.") {
+            hg = true;
+            relation[n].set_value(".le.");
+        }
+        else if (relation[n].get_string() == ".hgeq.") {
+            hg = true;
+            relation[n].set_value(".eq.");
+        }
+        else if (relation[n].get_string() == ".hgne.") {
+            hg = true;
+            relation[n].set_value(".ne.");
+        }
+        else if (relation[n].get_string() == ".hggt.") {
+            hg = true;
+            relation[n].set_value(".gt.");
+        }
+        else if (relation[n].get_string() == ".hgge.") {
+            hg = true;
+            relation[n].set_value(".ge.");
+        }
+
+
+        has_got.push_back(hg);
+    }
+
+
+    // Handle single line restart_block
+    if (cmdi.get_string(nwords-1) != "then") {
+        single_line_rb = true;
+        cmdi.delete_words(0, 5);
+        cmdi.reset_name_type();
+    }
+    //cout << "&&&&&cw ********** Restartblock.cc, Exit Constructor **********" << endl;
+}
+
+
+// ===========================================================================
+// Add word to the deque wq.
+// ===========================================================================
+void Restartblock::add_word(Cmd &cmdi, int idex, deque<Word> &wq)
+{
+    int ln = cmdi.get_line_number(idex);
+    int file_ln = cmdi.get_file_line_number(idex);
+    string fname = cmdi.get_filename(idex);
+    deque<string> *lines = cmdi.get_lines();
+    Word w(cmdi.get_string(idex), ln, file_ln, fname, lines);
+    wq.push_back(w);
+}
+
+void Restartblock::add_word(Cmd &cmdi, int idex, deque<Word> &wq, string sadd)
+{
+    int ln = cmdi.get_line_number(idex);
+    int file_ln = cmdi.get_file_line_number(idex);
+    string fname = cmdi.get_filename(idex);
+    deque<string> *lines = cmdi.get_lines();
+    Word w(sadd, ln, file_ln, fname, lines);
+    wq.push_back(w);
+}
+
+
+// ===========================================================================
+// This is the check for when the condition is satisfied.
+// ===========================================================================
+void Restartblock::check_rb(vector<string> &code_varnames,
+                            vector<string> &code_values,
+                            vector<int> &vv_active, int *rbci,
+                            stringstream &serr, int &ierr)
+{
+    *rbci = 0;
+    //if (active==1) return;
+
+    Parser_math pmath;
+
+    deque<Word> wordsf;
+
+    bool skip_sat = false;
+    int num_sub_cond = (int)varname.size();
+    for (int n=0; n<num_sub_cond; n++) {
+        deque<Word> words;
+
+        if (satisfied[n] == "true") {
+            int ln = varname[n].get_line_number();
+            int file_ln = varname[n].get_file_line_number();
+            string fname = varname[n].get_filename();
+            deque<string> *lines = varname[n].get_lines();
+            Word w("true", ln, file_ln, fname, lines);
+            words.push_back(w);
+        }
+        else {
+            words.push_back(varname[n]);
+            words.push_back(relation[n]);
+            words.push_back(value[n]);
+
+            process_words(words, code_varnames, code_values, vv_active,
+                          serr, ierr);
+
+            if (has_got[n]) {
+                if (words[0].get_bool(serr, ierr)) {
+                    bool doit = true;
+                    if (n > 0) {
+                        if (logop[n-1].get_string() == ".andthen." && skip_sat) {
+                            doit = false;
+                        }
+                    }
+                    if (doit) satisfied[n] = "true";
+                }
+                else {
+                    skip_sat = true;
+                }
+            }
+        }
+
+        wordsf.push_back(words[0]);
+        if (logop[n].get_string() == "none") break;
+        else wordsf.push_back(logop[n]);
+    }
+
+    process_words(wordsf, code_varnames, code_values, vv_active,
+                  serr, ierr);
+
+    // rbci is an output flag telling the code to write a dump and end
+    // the calculation or not. rbci=0 means do not end the calc,
+    // rbci=1 tells the code to end the calc.
+    // Basically, if the condition changes from its previous value, then
+    // set rbci to 1.
+
+    // This is the current value of the condition that was calculated above.
+    bool b = wordsf[0].get_bool(serr, ierr);
+
+    // *rcbi is the key output result from this function
+    //     *rbci = 0    Calling code does nothing
+    //     *rbci = 1    Calling code stops calculation, normally does restart
+    *rbci = 0;
+
+    // Here we check to see if the condition has changed, i.e. is b different
+    // from the active flag. If so, then we end the calculation.
+    // When the restart block is first created, the active flag is set to -1,
+    // this is for runs from scratch.
+    // If this is a restart, then the active flag will come from the dump and
+    // be either 0 or 1.
+    // So if active is -1 and the condition is true, then we end the calculation
+    // right away (this should not be common, but could happen).
+    //
+    // Changed on 7/2/10 - The original idea for restart blocks was that they
+    // would trigger when the condition changed from false to true. But they
+    // would also trigger when the condition changed back from true to false.
+    // This causes problems for the users when the restart block would
+    // repeatedly trigger because the condition oscillates between true and
+    // false. Therefore, change the restart blocks so they trigger once and
+    // only once (which happens when the condition first becomes true). If
+    // the users ever need a restart block that also triggers when the
+    // condition changes from true to false, then some
+    // sort of option could be put in to allow this.
+    if (b  && active == -1) { *rbci = 1; active = 1; return; }   // Trigger
+    if (b  && active ==  0) { *rbci = 1; active = 1; return; }   // Trigger
+    if (b  && active ==  1) { *rbci = 0;             return; }   // Do nothing
+    if (!b && active == -1) { *rbci = 0; active = 0; return; }   // Do nothing
+    if (!b && active ==  0) { *rbci = 0;             return; }   // Do nothing
+
+    // This is the true to false trigger that causes problems.
+    //if (!b && active ==  1) { *rbci = 1; active = 0; return; }   // Trigger
+}
+
+
+
+// ===========================================================================
+// Given a deque of words, go through them evaluating relational and logical
+// operators. The words should evaluate to one final word.
+// ===========================================================================
+void Restartblock::process_words(deque <Word> &words, vector<string> &code_varnames,
+                                 vector<string> &code_values,
+                                 vector<int> &vv_active,
+                                 stringstream &serr, int &ierr)
+{
+    Parser_math pmath;
+
+    // Replace any code vars with their values.
+    int i2 = (int)words.size();
+    for (int i=0; i<i2; i++) {
+        for (int j=0; j<(int)code_varnames.size(); j++) {
+            if (words[i].get_string() == code_varnames[j]) {
+                int ln = words[i].get_line_number();
+                int file_ln = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                deque<string> *lines = words[i].get_lines();
+                if (vv_active[j] == 0) {
+                    Word wj("false", ln, file_ln, fname, lines);
+                    replace_words(i, i+2, words, wj);
+                    i2 -= 2;
+                    break;
+                }
+                else {
+                    Word wj(code_values[j], ln, file_ln, fname, lines);
+                    words[i] = wj;
+                }
+            }
+        }
+    }
+
+    int i1 = 0;
+    i2 = (int)words.size() - 1;
+    for (int level=6; level>=0; level--) {
+        for (int i=i1; i<=i2; i+=1) {
+            if (words[i].is_operator(level)) {
+                int ln = words[i].get_line_number();
+                int file_ln = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                deque<string> *lines = words[i].get_lines();
+                Word w("", ln, file_ln, fname, lines);
+
+                string op_type = words[i].get_op_type();
+
+                if (op_type == "relational") {
+                    pmath.do_op_relational(i-1, i, i+1, words, w, serr, ierr);
+                }
+
+                if (op_type == "logical" && level == 2)   // .not. is unary
+                    pmath.do_op_not(i, i+1, words, w, serr, ierr);
+
+                if (op_type == "logical" && level != 2)
+                    pmath.do_op_logical(i-1, i, i+1, words, w, serr, ierr);
+
+                // level 2, .not., is unary and is handled differently.
+                if (level == 2) {
+                    replace_words(i, i+1, words, w);
+                    i2 -= 1;
+                }
+                else {
+                    replace_words(i-1, i+1, words, w);
+                    i2 -= 2;
+                    i -= 1;
+                }
+                continue;
+            }
+        }
+    }
+
+    // The condition has to evaluate to a single boolean value.
+    if ((int)words.size() != 1) {
+        words[0].fatal_error(serr, ierr);
+        serr << "restart_block condition did not evaluate to a single boolean value."
+             << endl;
+        serr << "Fix the restart_block condition" << endl;
+        ierr = 2;
+    }
+}
+
+
+// ===========================================================================
+// List the condition for this restart block to a stringstream.
+// This is done to let the user indentify this restart block. It is
+// also useful for debugging.
+// ===========================================================================
+void Restartblock::list_condition(string offset1, string offset2,
+                                  stringstream &ssc)
+{
+    for (int n=0; n<(int)varname.size(); n++) {
+
+        string relstr = relation[n].get_string();
+        string rstr = relstr;
+        if (has_got[n]) {
+            if (relstr == ".lt.") rstr = ".hglt.";
+            if (relstr == ".le.") rstr = ".hgle.";
+            if (relstr == ".eq.") rstr = ".hgeq.";
+            if (relstr == ".ne.") rstr = ".hgne.";
+            if (relstr == ".gt.") rstr = ".hggt.";
+            if (relstr == ".ge.") rstr = ".hgge.";
+        }
+        relstr = rstr;
+
+        string offset = offset1;
+        if (n > 0) offset = offset2;
+
+        ssc << offset << varname[n].get_string() << " "
+            << relstr << " " << value[n].get_string();
+
+        if (logop[n].get_string() == "none") break;
+        ssc << " " << logop[n].get_string();
+        ssc << endl;
+    }
+}
+
+
+// ===========================================================================
+// Delete words i1 through i2 inclusive from the deque.
+// ===========================================================================
+void Restartblock::delete_words(int i1, int i2, deque <Word> &words)
+{
+    deque<Word>::iterator p = words.begin();
+    words.erase(p + i1, p + i2 + 1);
+}
+
+
+// ===========================================================================
+// Replace words i1 through i2 inclusive with word w.
+// ===========================================================================
+void Restartblock::replace_words(int i1, int i2, deque <Word> &words, Word &w)
+{
+    delete_words(i1, i2, words);
+    deque<Word>::iterator p = words.begin();
+    words.insert(p + i1, w);
+}
+
+
+
+} // End of the PP namespace
+
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Restartblock.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Restartblock.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,136 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef RESTARTBLOCKHHINCLUDE
+#define RESTARTBLOCKHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// Restart Blocks
+// Run the code until a restart block condition is satisfied. Set the restart
+// block as active, write a restart dump, stop the code, and restart.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <deque>
+#include <vector>
+#include <map>
+#include <sstream>
+
+#include "Word.hh"
+
+namespace PP
+{
+using std::string;
+using std::deque;
+using std::vector;
+using std::map;
+using std::stringstream;
+
+class Restartblock
+{
+
+public:
+    Restartblock();
+    Restartblock(int &nrb, Cmd &cmdi, bool &skiprb,
+                 bool &single_line_rb,
+                 deque<string> &bnames_on_dump,
+                 deque<bool> &baflags_on_dump,
+                 stringstream &serr, int &ierr);
+
+    Restartblock(int &nrb, Cmd &cmdi, bool &skiprb,
+                 bool &single_line_rb,
+                 deque<string> &bnames_on_dump,
+                 deque<bool> &baflags_on_dump,
+                 deque<int> &rbsatprb_on_dump,
+                 deque<bool> &rbsat_on_dump,
+                 stringstream &serr, int &ierr);
+
+
+    void check_rb(vector<string> &code_varnames,
+                  vector<string> &code_values,
+                  vector<int> &vv_active, int *rbci,
+                  stringstream &serr, int &ierr);
+
+    void list_condition(string offset1, string offset2,
+                        stringstream &ssc);
+
+    string get_name() { return name; }
+    int get_aflag() { return active; }
+    void set_aflag(int af) { active = af; }
+    int get_satsize() { return (int)satisfied.size(); }
+    int get_sat(int j) { if (satisfied[j] == "true") return 1; return 0; }
+    int get_num_varnames() { return (int)varname.size(); }
+    string get_varname(int i) { return varname[i].get_string(); }
+
+
+private:
+
+    void add_word(Cmd &cmdi, int idex, deque<Word> &wq);
+    void add_word(Cmd &cmdi, int idex, deque<Word> &wq, string sadd);
+    void process_words(deque <Word> &words, vector<string> &code_varnames,
+                       vector<string> &code_values, vector<int> &vv_active,
+                       stringstream &serr, int &ierr);
+    void delete_words(int i1, int i2, deque <Word> &words);
+    void replace_words(int i1, int i2, deque <Word> &words, Word &w);
+
+
+    // The condition:   varname relation value  logical  varname relation value etc.
+    // Example:           time     .gt.   3.0    .and.    ncycle   .ge.    50
+    // The condition is thought of as a sequence of subconditions connected by
+    // logical operators. The above example has two subconditions connected by the
+    // .and. logical operator.
+    deque<Word>   varname;    // Host code variable name to be replaced by host code value.
+    deque<Word>   relation;   // Relation between varname and value, like .gt., .hglt., ...
+    deque<Word>   value;      // Value to compare with host code value.
+    deque<Word>   logop;      // Logical operator connecting subconditions.
+    deque<string> satisfied;  // Satisfied flag for each subcondition.
+    deque<bool>   has_got;    // Has got flag for the relation. This is true if
+                              // the relation is .hggt., .hglt., ..., false otherwise.
+
+    // The restart_block commands are processed if active is true (== 1)
+    int active;
+
+    // The name of this restart block.
+    string name;
+};
+
+
+} // end of PP namespace
+
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Variable.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,491 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds information about a variable. It is mostly for use with
+// the parser.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+
+#include "Parser_utils.hh"
+#include "Word.hh"
+#include "Variable.hh"
+
+namespace PP
+{
+using std:: string;
+using std::cout;
+using std::endl;
+using std::stringstream;
+using std::setprecision;
+using std::vector;
+using std::deque;
+
+static int index_base = 1;
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Variable::Variable()
+{
+    name = "__NO_NAME_GIVEN__";
+    value.push_back("__NO_VALUE_GIVEN__");
+    ndim = -1;
+    lnum_ndim = 0;
+    lnum_bounds = 0;
+    pre_defined = false;
+    description = "";
+    temporary = false;
+}
+
+// ===========================================================================
+// Constructor to reset index base
+// ===========================================================================
+Variable::Variable(int base)
+{
+    index_base = base;
+}
+
+// ===========================================================================
+// Constructor given a string as input. This constructs a scalar variable.
+// ===========================================================================
+Variable::Variable(string nme, string v, bool pred, string tdes)
+{
+    name = nme;
+    value.push_back(v);
+    ndim = 0;
+    lnum_ndim = 0;
+    lnum_bounds = 0;
+    pre_defined = pred;
+    description = tdes;
+    temporary = false;
+}
+
+
+// ===========================================================================
+// Constructor for variables with no value.
+// ===========================================================================
+Variable::Variable(string nme)
+{
+    name = nme;
+    value.push_back("__NO_VALUE_GIVEN__");
+    ndim = -1;
+    lnum_ndim = 0;
+    lnum_bounds = 0;
+    pre_defined = false;
+    description = "";
+    temporary = false;
+}
+
+
+// ===========================================================================
+// Constructor given a vector of strings as input.
+// ===========================================================================
+Variable::Variable(string nme, vector<int> &istart, vector<string> &valvec,
+                   int lnum, int file_lnum, string fname, deque<string> *lines,
+                   stringstream &serr, int &ierr)
+{
+    name = nme;
+    ndim = -1;
+    lnum_ndim = 0;
+    lnum_bounds = 0;
+    pre_defined = false;
+    description = "";
+    temporary = false;
+    set_var_value(istart, valvec, lnum, file_lnum, fname, lines, serr, ierr);
+}
+
+
+// ===========================================================================
+// istart gives the starting location in the array for setting values.
+// The istart indices start from 1 (fortran based).
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Variable::set_var_value(vector<int> &istart, vector<string> &valvec,
+                             int lnum, int file_lnum, string fname,
+                             deque<string> *lines, stringstream &serr, int &ierr)
+{
+    // Cannot redefine a pre-defined variable.
+    if (pre_defined) {
+        serr << endl;
+        serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << "Cannot redefine a pre-defined variable." << endl;
+        ierr = 2;
+        return;
+    }
+    
+    // Set the array dimension and make sure the user is not trying to
+    // change it.
+    int ndim_new = (int)istart.size();
+    if (ndim >= 0) {
+        if (ndim != ndim_new) {
+            // Throw an error
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+            serr << "    " << (*lines)[lnum-1] << endl;
+            serr << "in file: " << fname << endl;
+            serr << "Cannot redefine the dimensionality of a variable." << endl;
+            serr << "Original number of dimensions = " << ndim << endl;
+            serr << "New number of dimensions = " << ndim_new << endl;
+            if (lnum_ndim > 0) {
+                serr << "Previously set in line " << lnum_ndim << ":" << endl;
+                serr << "    " << (*lines)[lnum_ndim-1] << endl;
+            }
+            ierr = 2;
+            return;
+        }
+    }
+    else {
+        ndim = ndim_new;
+        lnum_ndim = lnum;
+    }
+
+    int bsize = (int)maxdim.size();
+
+    if (ndim == 0 && bsize > 0) {
+        serr << endl;
+        serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << "Array boundaries not allowed for scalar variable." << endl;
+        if (lnum_bounds > 0) {
+            serr << "Array boundaries were set in line " << lnum_bounds << ":" << endl;
+            serr << "    " << (*lines)[lnum_bounds-1] << endl;
+        }
+        ierr = 2;
+        return;
+    }
+
+    if (ndim > 0) {
+        if (ndim != bsize+1) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+            serr << "    " << (*lines)[lnum-1] << endl;
+            serr << "in file: " << fname << endl;
+            serr << "Number of dimensions = " << ndim << endl;
+            serr << "Number of array boundaries + 1 = " << bsize+1 << endl;
+            serr << "These should match but don't. " << endl;
+            ierr = 2;
+            return;
+        }
+    }
+
+    // Find the 1d starting position given multiple array indices.
+    Parser_utils putils(index_base);
+    int i1 = putils.start_dex(istart, maxdim);
+
+    // nvals    Number of values after the = sign.
+    // Note that multiplicity is already handled, i.e. valvec has already
+    // been expanded to include multiplicites.
+    int nvals = (int)valvec.size();
+
+    // Get memory that we need.
+    if (i1+nvals > (int)value.size()) {
+        value.resize(i1+nvals, "");
+    }
+
+    // Store the array values.
+    for (int i=i1; i<i1+nvals; i++) {
+        value[i] = valvec[i-i1];
+    }
+}
+
+
+// ===========================================================================
+// Increment (or decrement) a variable value by an integer amount.
+// ===========================================================================
+void Variable::bump_var(vector<int> &istart, int increment,
+                        int lnum, int file_lnum, string fname,
+                        deque<string> *lines, stringstream &serr, int &ierr)
+{
+    // Find the 1d starting position given multiple array indices.
+    Parser_utils putils(index_base);
+    int i1 = putils.start_dex(istart, maxdim);
+
+    // We are incrementing an existing variable, so i1 should be valid.
+    if (i1 >= (int)value.size()) {
+        // Fatal Error
+    }
+
+    Word w1(value[i1], lnum, file_lnum, fname, lines);
+    if (!w1.is_number()) {  } // FATAL ERROR 
+
+    stringstream ss;
+    if (w1.is_integer()) {
+        int ia1 = w1.get_int(serr, ierr);
+        int ia  = ia1 + increment;
+        ss << ia;
+    }
+    else {
+        double d1 = w1.get_double(serr, ierr);
+        double d = d1 + increment;
+        ss << setprecision(15) << d;
+    }
+    value[i1] = ss.str();
+}
+
+
+
+// ===========================================================================
+// The problem with multi-dimensional variable arrays is that the user has
+// to tell us the bounds on every dimension except the last one. This info
+// is input in the bounds vector and stored.
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Variable::set_bounds(vector<int> &bounds, int lnum, int file_lnum,
+                          string fname, deque<string> *lines,
+                          stringstream &serr, int &ierr)
+
+{
+    // Cannot redefine a pre-defined variable.
+    if (pre_defined) {
+        serr << endl;
+        serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << "Cannot redefine a pre-defined variable." << endl;
+        ierr = 2;
+        return;
+    }
+    
+    // Set the array dimension and make sure the user is not trying to
+    // change it.
+    int ndim_new = (int)bounds.size() + 1;
+    if (ndim >= 0) {
+        if (ndim != ndim_new) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+            serr << "    " << (*lines)[lnum-1] << endl;
+            serr << "in file: " << fname << endl;
+            serr << "Cannot redefine the dimensionality of a variable "
+                "(set_bounds)." << endl;
+            serr << "Original number of dimensions = " << ndim << endl;
+            serr << "New number of dimensions = " << ndim_new << endl;
+            if (lnum_ndim > 0) {
+                serr << "Previously set in line " << lnum_ndim << ":" << endl;
+                serr << "    " << (*lines)[lnum_ndim-1] << endl;
+            }
+            ierr = 2;
+            return;
+        }
+    }
+    else {
+        ndim = ndim_new;
+        lnum_ndim = lnum; // Store line num for better err messages.
+    }
+
+    // Check to make sure the user is not reseting the bounds.
+    if ((int)maxdim.size() > 0) {
+        serr << endl;
+        serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << "The bounds on this array has already been set," << endl;
+        serr << "cannot reset them." << endl;
+        if (lnum_bounds > 0) {
+            serr << "Previously set in line " << lnum_bounds << ":" << endl;
+            serr << "    " << (*lines)[lnum_bounds-1] << endl;
+        }
+        ierr = 2;
+        return;
+    }
+
+    // Store the line num where bounds were set for better err messages.
+    lnum_bounds = lnum;
+
+    // Store the bounds.
+    maxdim.clear();
+    for (int i=0; i<(int)bounds.size(); i++) {
+        maxdim.push_back(bounds[i]);
+    }
+}
+
+
+// ===========================================================================
+// Given indices, in adex, get the value of the variable.
+// For example, suppose you want the value of
+//    $var2d(3,5)
+// The adex vector contains 2 numbers, 3 and 5, for the fortran indices.
+// The start_dex function is used to get the 1d index into the value array.
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+string Variable::get_var_value(vector<int> &adex, string vname, int lnum,
+                               int file_lnum, string fname, deque<string> *lines,
+                               stringstream &serr, int &ierr)
+{
+    int adex_size = (int)adex.size();
+
+    // Special case for scalar variables.
+    if (ndim == 0 || adex_size == 0) return value[0];
+
+    // The adex indices and bounds indices must match.
+    if (adex_size - 1 != (int)maxdim.size()) {
+        serr << endl;
+        serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << "The dimensionality of variable " << vname << endl;
+        serr << "does not match what was previously set." << endl;
+        if (lnum_bounds > 0) {
+            serr << "Previous dimensionality set in line " << lnum_bounds << ":" << endl;
+            serr << "    " << (*lines)[lnum_bounds-1] << endl;
+        }
+        ierr = 2;
+        return "";
+    }
+    
+    // Indices cannot exceed max allowed.
+    // Remember that adex if referenced from 1 (fortran index).
+    for (int d=0; d<(int)maxdim.size(); d++) {
+        if (adex[d] > maxdim[d]) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+            serr << "    " << (*lines)[lnum-1] << endl;
+            serr << "in file: " << fname << endl;
+            serr << "Variable name = " << vname << endl;
+            serr << "The value for dimension " << d+1 << " = " << adex[d] << endl;
+            serr << "This exceeds the max dimension of " << maxdim[d] << endl;
+            if (lnum_bounds > 0) {
+                serr << "The array bounds were set in line " << lnum_bounds << ":" << endl;
+                serr << "    " << (*lines)[lnum_bounds-1] << endl;
+            }
+            ierr = 2;
+        }
+    }
+
+    if (ierr == 2) return "";
+
+    // Indices cannot be < 1.
+    for (int d=0; d<(int)adex.size(); d++) {
+        if (adex[d] < 1) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+            serr << "    " << (*lines)[lnum-1] << endl;
+            serr << "in file: " << fname << endl;
+            serr << "Variable name = " << vname << endl;
+            serr << "Expected index greater than or equal to 1 " << endl;
+            serr << "Instead, index =  " << adex[d] << endl;
+            ierr = 2;
+        }
+    }
+
+    if (ierr == 2) return "";
+
+
+    // Using the indices in adex and the bounds for multi-d arrays, maxdim,
+    // get the 1d index into the value array.
+    Parser_utils putils(index_base);
+    int i1 = putils.start_dex(adex, maxdim);
+
+    // Check that the value array size has not been exceeded.
+    if (i1 >= (int)value.size()) {
+        serr << endl;
+        serr << "*** FATAL ERROR in line " << file_lnum << ":" << endl;
+        serr << "    " << (*lines)[lnum-1] << endl;
+        serr << "in file: " << fname << endl;
+        serr << "Variable name = " << vname << endl;
+        serr << "Exceeded array bounds. Check to make sure you are not" << endl;
+        serr << "requesting an array element you have not yet set." << endl;
+
+        vector<int> maxdex((int)adex.size(), 0);
+        get_indices((int)value.size()-1, maxdex);
+        for (int d=0; d<(int)adex.size(); d++) {
+            string s = "";
+            if (adex[d] > maxdex[d]) s = "  ERROR, max exceeded";
+            serr << "    Requested index = " << adex[d]
+                 << "  Max index = " << maxdex[d] << s << endl;
+        }
+
+        ierr = 2;
+        return "";
+    }
+
+    // Return the value.
+    return value[i1];
+}
+
+
+
+// ===========================================================================
+// Given the 1d index, icdex (starting from 0), find the corresponding
+// multi dimensional fortran indices (each starting from 1).
+//
+// Example 1: Consider a 1d array
+//     var1d(1) = 1 3 5 9 -4 -5 6
+// Suppose icdex=3, corresponding to array value 9.
+// This 1d case is very simple, all we do is add 1 to icdex to get a reference
+// from 1, thus returning 4.
+//
+// Example 1: Consider a 2d array
+//     $var2d(1,1) = 11. 21. 31.   12. 22. 32.   13. 23. 33.
+// Where the max of the first dimension is 3. Suppose the user specifies
+// icdex = 5, this corresponds to array value 32. The two indices returned
+// would be 3,2 (referenced from 1).
+//
+// The adex vector contains the output indices, for example 2 this would be 3
+// and 2.
+//
+// This function works for any dimension, 0,1,2,3,...
+// ===========================================================================
+void Variable::get_indices(int icdex, vector<int> &adex)
+{
+    // Nothing to do for scalar variables.
+    if (ndim == 0) return;
+
+    // Given icdex, get the indices.
+    int nvalues = (int)value.size();
+    Parser_utils putils(index_base);
+    putils.reverse_dex(icdex, nvalues, adex, maxdim);
+}
+
+
+
+
+} // End of the PP namespace

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Variable.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Variable.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,130 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef VARIABLEHHINCLUDE
+#define VARIABLEHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds information about a variable.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <deque>
+
+namespace PP
+{
+using std::string;
+using std::stringstream;
+using std::vector;
+using std::deque;
+
+
+
+class Variable
+{
+
+public:
+    Variable();
+    Variable(int base);
+    Variable(string nme, string v, bool pred, string tdes);
+    Variable(string nme);
+    Variable(string nme, vector<int> &istart, vector<string> &vvec,
+             int lnum, int file_lnum, string fname, deque<string> *lines,
+             stringstream &serr, int &ierr);
+
+    // Accessor methods.
+    string get_varname() { return name; }
+    void set_varname(string s) { name = s; }
+    int get_ndim() { return ndim; }
+
+    int get_nvalues() { return (int)value.size(); }
+
+    string get_var_value()   { return value[0]; }
+    string get_var_value(int idex)   { return value[idex]; }
+    string get_var_value(vector<int> &adex, string vname, int lnum,
+                         int file_lnum, string fname, deque<string> *lines,
+                         stringstream &serr, int &ierr);
+
+
+    void set_var_value(vector<int> &istart, vector<string> &valvec,
+                       int lnum, int file_lnum, string fname,
+                       deque<string> *lines, stringstream &serr, int &ierr);
+    void bump_var(vector<int> &istart, int increment,
+                  int lnum, int file_lnum, string fname,
+                  deque<string> *lines, stringstream &serr, int &ierr);
+
+
+    void set_bounds(vector<int> &bounds, int lnum, int file_lnum,
+                    string fname, deque<string> *lines,
+                    stringstream &serr, int &ierr);
+
+    void get_indices(int icdex, vector<int> &adex);
+
+    string get_description() { return description; }
+    void set_description(string vardes) { description = vardes; }
+
+    bool is_pre_defined() { return pre_defined; }
+
+    void set_temporary(bool b) { temporary = b; }
+    bool is_temporary() { return temporary; }
+
+private:
+
+    // name         The name of the variable.
+    // value        Vector containing the values of the variable.
+    // ndim         Number of dimensions, for example var(9,3) has ndim=2
+    // maxdim       Max num for each dimension except the last.
+    // lnum_ndim    The line number where ndim was set.
+    // lnum_bounds  The line number where maxdim was set.
+    // pre_defined  Pre-defined vars cannot be redefined.
+    // description  Text description of the variable.
+    // temporary    A temporary variable.
+    string name;
+    vector<string> value;
+    int ndim, lnum_bounds, lnum_ndim;
+    vector<int> maxdim;
+    bool pre_defined, temporary;
+    string description;
+};
+
+
+} // End of the PP namespace
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Whenthen.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,633 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <vector>
+#include <deque>
+#include <sstream>
+#include <map>
+#include <math.h>
+
+#include "Variable.hh"
+#include "Function.hh"
+#include "Word.hh"
+#include "Parser_math.hh"
+#include "Cmd.hh"
+#include "Whenthen.hh"
+
+namespace PP
+{
+using std::cout;
+using std::endl;
+using std::string;
+using std::deque;
+using std::vector;
+using std::stringstream;
+using std::pair;
+using std::ifstream;
+using std::ios;
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Whenthen::Whenthen() 
+{
+    processed = false;
+    seqdex = -1;
+    ever_flag = false;
+}
+
+
+// ===========================================================================
+// Usual constructor.
+// ===========================================================================
+Whenthen::Whenthen(int &nwhen, Cmd &cmdi, bool &skipwhen,
+                   bool &single_line_when, bool eflag,
+                   stringstream &serr, int &ierr)
+{
+    processed = false;
+    seqdex = -1;
+    ever_flag = eflag;
+    nwhen += 1;
+    skipwhen = true;
+    single_line_when = false;
+    int nwords = cmdi.get_nwords();
+
+    // &&&&&cw
+    //stringstream ssprint;
+    //cmdi.print_using_words(ssprint);
+    //cout << ssprint.str() << endl;
+
+    if (nwords < 7) {
+        cmdi.fatal_error(0, serr, ierr);
+        serr << "A when command line must have at least 7 words on it (the "
+             << endl
+             << "opening and closing parenthses each count as a word)"
+             << endl;
+        serr << "This when command only has " << nwords << " words on it." << endl;
+        serr << "Expected something like (this has 7 words):" << endl;
+        serr << "    when (time .gt. 5) then" << endl;
+        serr << "Or perhaps a single line when like (this has 9 words):" << endl;
+        serr << "    when (time .gt. 5) shortmodcyc = 5" << endl;
+        ierr = 2;
+        return;
+    }
+
+    string p1 = cmdi.get_string(1);
+    if (p1 != "(") {
+        cmdi.fatal_error(1, serr, ierr);
+        serr << "Expected an open parentheses following the when keyword."
+             << endl;
+        serr << "Instead found " << p1 << " following the when keyword."
+             << endl;
+        serr << "The when command should be something like:" << endl;
+        serr << "    when (time .gt. 5) then" << endl;
+        serr << "Or perhaps a single line when like:" << endl;
+        serr << "    when (time .gt. 5) shortmodcyc = 5" << endl;
+        ierr = 2;
+        return;
+    }
+
+
+    for (int i=1; i<nwords-1; i++) {
+        string t1 = cmdi.get_string(i);
+        if (t1 == "then") {
+            cmdi.fatal_error(i, serr, ierr);
+            serr << "Found a then keyword embedded in the when command."
+                 << endl;
+            serr << "If a then keyword is present it must be the last "
+                 "word on the line." << endl;
+            serr << "The when command should be something like:" << endl;
+            serr << "    when (time .gt. 5) then" << endl;
+            serr << "Or perhaps a single line when like:" << endl;
+            serr << "    when (time .gt. 5) shortmodcyc = 5" << endl;
+            ierr = 2;
+            return;
+        }
+    }
+
+
+    // Find the closing parenthesis
+    int close_paren_dex = -1;
+    for (int i=2; i<nwords; i++) {
+        string pi = cmdi.get_string(i);
+        if (pi == "then") break;
+        if (pi == ")") {
+            close_paren_dex = i;
+            break;
+        }
+    }
+
+    if (close_paren_dex == -1) {
+        cmdi.fatal_error(0, serr, ierr);
+        serr << "Expected a close parentheses following the condition."
+             << endl;
+        serr << "Did not find a close parentheses." << endl;
+        serr << "The when command should be something like:" << endl;
+        serr << "    when (time .gt. 5) then" << endl;
+        serr << "Or perhaps a single line when like:" << endl;
+        serr << "    when (time .gt. 5) shortmodcyc = 5" << endl;
+        ierr = 2;
+        return;
+    }
+
+
+    int nw = close_paren_dex - 2;
+    if ((nw+1)%4 != 0) {
+        cmdi.fatal_error(0, serr, ierr);
+        serr << "Wrong number of words in the when...then condition."
+             << endl;
+        serr << "The number of words in this condition is " << nw << endl;
+        serr << "The number of words + 1 should be a multiple of 4." << endl;
+        serr << "The condition should be something like:" << endl;
+        serr << "    time .gt. 5" << endl;
+        serr << "This has 3 words and 3+1 is a multiple of 4." << endl;
+        serr << "Or the following is valid" << endl;
+        serr << "    time .gt. 5 .and. ncycle .ge. 10" << endl;
+        serr << "This has 7 words and 7+1 is a multiple of 4." << endl;
+        ierr = 2;
+        return;
+    }
+
+    
+
+
+    for (int i=2; i<close_paren_dex; i+=4) {
+        add_word(cmdi, i,   varname);
+        add_word(cmdi, i+1, relation);
+        add_word(cmdi, i+2, value);
+
+        if (i+3 < close_paren_dex) add_word(cmdi, i+3, logop);
+        else                       add_word(cmdi, i+3, logop, "none");
+
+        satisfied.push_back("false");
+    }
+
+
+    // Check to make sure that the relation is valid.
+    for (int n=0; n<(int)varname.size(); n++) {
+        bool valid_relation = false;
+        if (relation[n].get_string() == ".hglt.") valid_relation = true;
+        if (relation[n].get_string() == ".hgle.") valid_relation = true;
+        if (relation[n].get_string() == ".hgeq.") valid_relation = true;
+        if (relation[n].get_string() == ".hgne.") valid_relation = true;
+        if (relation[n].get_string() == ".hggt.") valid_relation = true;
+        if (relation[n].get_string() == ".hgge.") valid_relation = true;
+        if (relation[n].get_string() == ".lt.") valid_relation = true;
+        if (relation[n].get_string() == ".le.") valid_relation = true;
+        if (relation[n].get_string() == ".eq.") valid_relation = true;
+        if (relation[n].get_string() == ".ne.") valid_relation = true;
+        if (relation[n].get_string() == ".gt.") valid_relation = true;
+        if (relation[n].get_string() == ".ge.") valid_relation = true;
+
+        if (!valid_relation) {
+            relation[n].fatal_error(serr, ierr);
+            serr << "Invalid when...then relation." << endl;
+            serr << "Expected  .lt., .le., .eq., .ne., .gt., .ge." << endl;
+            serr << "Also could be .hglt., .hgle., .hgeq., .hgne., .hggt., .hgge." << endl;
+            serr << "Instead found relation:  " << relation[n].get_string() << endl;
+            ierr = 2;
+            return;
+        }
+    }
+
+
+    // Set the has gotten to flags.
+    for (int n=0; n<(int)varname.size(); n++) {
+        bool hg = false;
+
+        if (relation[n].get_string() == ".hglt.") {
+            hg = true;
+            relation[n].set_value(".lt.");
+        }
+        else if (relation[n].get_string() == ".hgle.") {
+            hg = true;
+            relation[n].set_value(".le.");
+        }
+        else if (relation[n].get_string() == ".hgeq.") {
+            hg = true;
+            relation[n].set_value(".eq.");
+        }
+        else if (relation[n].get_string() == ".hgne.") {
+            hg = true;
+            relation[n].set_value(".ne.");
+        }
+        else if (relation[n].get_string() == ".hggt.") {
+            hg = true;
+            relation[n].set_value(".gt.");
+        }
+        else if (relation[n].get_string() == ".hgge.") {
+            hg = true;
+            relation[n].set_value(".ge.");
+        }
+
+
+        has_got.push_back(hg);
+    }
+
+
+    // Handle single line when...then
+    if (cmdi.get_string(nwords-1) != "then") {
+        single_line_when = true;
+        cmdi.delete_words(0, 5);
+        cmdi.reset_name_type();
+        skipwhen = false;
+    }
+}
+
+
+// ===========================================================================
+// Add word.
+// ===========================================================================
+void Whenthen::add_word(Cmd &cmdi, int idex, deque<Word> &wq)
+{
+    int ln = cmdi.get_line_number(idex);
+    int file_ln = cmdi.get_file_line_number(idex);
+    string fname = cmdi.get_filename(idex);
+    deque<string> *lines = cmdi.get_lines();
+    Word w(cmdi.get_string(idex), ln, file_ln, fname, lines);
+    wq.push_back(w);
+}
+
+void Whenthen::add_word(Cmd &cmdi, int idex, deque<Word> &wq, string sadd)
+{
+    int ln = cmdi.get_line_number(idex);
+    int file_ln = cmdi.get_file_line_number(idex);
+    string fname = cmdi.get_filename(idex);
+    deque<string> *lines = cmdi.get_lines();
+    Word w(sadd, ln, file_ln, fname, lines);
+    wq.push_back(w);
+}
+
+
+
+// ===========================================================================
+// Add a command to the deque of commands for this whenthen.
+// ===========================================================================
+void Whenthen::add_cmdf(Cmd &cmdi)
+{
+    cmdsf.push_back(cmdi);
+}
+
+
+// ===========================================================================
+// This is the check for when the condition is satisfied.
+// ===========================================================================
+void Whenthen::check_wt(vector<string> &code_varnames,
+                        vector<string> &code_values,
+                        vector<int> &vv_active,
+                        int *wtci, stringstream &serr, int &ierr)
+{
+    *wtci = 0;
+    if (processed) return;
+
+    Parser_math pmath;
+
+    deque<Word> wordsf;
+
+    bool skip_sat = false;
+    int num_sub_cond = (int)varname.size();
+    for (int n=0; n<num_sub_cond; n++) {
+        deque<Word> words;
+
+        if (satisfied[n] == "true") {
+            int ln = varname[n].get_line_number();
+            int file_ln = varname[n].get_file_line_number();
+            string fname = varname[n].get_filename();
+            deque<string> *lines = varname[n].get_lines();
+            Word w("true", ln, file_ln, fname, lines);
+            words.push_back(w);
+        }
+        else {
+            words.push_back(varname[n]);
+            words.push_back(relation[n]);
+            words.push_back(value[n]);
+
+            process_words(words, code_varnames, code_values, vv_active,
+                          serr, ierr);
+
+            if (has_got[n]) {
+                if (words[0].get_bool(serr, ierr)) {
+                    bool doit = true;
+                    if (n > 0) {
+                        if (logop[n-1].get_string() == ".andthen." && skip_sat) {
+                            doit = false;
+                        }
+                    }
+                    if (doit) satisfied[n] = "true";
+                }
+                else {
+                    skip_sat = true;
+                }
+            }
+        }
+
+        wordsf.push_back(words[0]);
+        if (logop[n].get_string() == "none") break;
+        else wordsf.push_back(logop[n]);
+    }
+
+    process_words(wordsf, code_varnames, code_values, vv_active,
+                  serr, ierr);
+
+    // The output value, wtci, defaults to false (0). If the condition
+    // is satisfied then the output is true (1). 
+    if (wordsf[0].get_bool(serr, ierr)) {
+        *wtci = 1;
+        if (!ever_flag) processed = true;
+        return;
+    }
+}
+
+
+
+// ===========================================================================
+// Given a deque of words, go through them evaluating relational and logical
+// operators. The words should evaluate to one final word.
+// ===========================================================================
+void Whenthen::process_words(deque <Word> &words, vector<string> &code_varnames,
+                             vector<string> &code_values,
+                             vector<int> &vv_active,
+                             stringstream &serr, int &ierr)
+{
+    Parser_math pmath;
+
+    // Replace any code vars with their values.
+    int i2 = (int)words.size();
+    for (int i=0; i<i2; i++) {
+        for (int j=0; j<(int)code_varnames.size(); j++) {
+            if (words[i].get_string() == code_varnames[j]) {
+                int ln = words[i].get_line_number();
+                int file_ln = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                deque<string> *lines = words[i].get_lines();
+                if (vv_active[j] == 0) {
+                    Word wj("false", ln, file_ln, fname, lines);
+                    replace_words(i, i+2, words, wj);
+                    i2 -= 2;
+                    break;
+                }
+                else {
+                    Word wj(code_values[j], ln, file_ln, fname, lines);
+                    words[i] = wj;
+                }
+            }
+        }
+    }
+
+    int i1 = 0;
+    i2 = (int)words.size() - 1;
+    for (int level=6; level>=0; level--) {
+        for (int i=i1; i<=i2; i+=1) {
+            if (words[i].is_operator(level)) {
+                int ln = words[i].get_line_number();
+                int file_ln = words[i].get_file_line_number();
+                string fname = words[i].get_filename();
+                deque<string> *lines = words[i].get_lines();
+                Word w("", ln, file_ln, fname, lines);
+
+                string op_type = words[i].get_op_type();
+
+                if (op_type == "relational") {
+                    pmath.do_op_relational(i-1, i, i+1, words, w, serr, ierr);
+                }
+
+                if (op_type == "logical" && level == 2)   // .not. is unary
+                    pmath.do_op_not(i, i+1, words, w, serr, ierr);
+
+                if (op_type == "logical" && level != 2)
+                    pmath.do_op_logical(i-1, i, i+1, words, w, serr, ierr);
+
+                // level 2, .not., is unary and is handled differently.
+                if (level == 2) {
+                    replace_words(i, i+1, words, w);
+                    i2 -= 1;
+                }
+                else {
+                    replace_words(i-1, i+1, words, w);
+                    i2 -= 2;
+                    i -= 1;
+                }
+                continue;
+            }
+        }
+    }
+
+    // The condition has to evaluate to a single boolean value.
+    if ((int)words.size() != 1) {
+        words[0].fatal_error(serr, ierr);
+        serr << "When...then condition did not evaluate to a single boolean value."
+             << endl;
+        serr << "Fix the when...then condition" << endl;
+        ierr = 2;
+    }
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void Whenthen::get_char_array_size(int *ca_size)
+{
+    string sc;
+    get_char_array(sc);
+    (*ca_size) = (int)sc.size();
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void Whenthen::get_char_array(string &sc)
+{
+    for (int n=0; n<(int)varname.size(); n++) {
+        sc += varname[n].get_string();
+        sc += relation[n].get_string();
+        sc += value[n].get_string();
+        sc += logop[n].get_string();
+        if (has_got[n]) sc += "hasgot";
+    }
+    for (int n=0; n<(int)cmdsf.size(); n++) {
+        int nw = cmdsf[n].get_nwords();
+        for (int i=0; i<nw; i++) {
+            sc += cmdsf[n].get_string(i);
+        }
+    }
+}
+
+
+// ===========================================================================
+// ===========================================================================
+void Whenthen::get_satsize(int *sat_size)
+{
+    (*sat_size) = (int)satisfied.size();
+}
+
+
+// ===========================================================================
+// Get and Set the satisfied flags.
+// ===========================================================================
+void Whenthen::getsat(int *sat)
+{
+    for (int i=0; i<(int)satisfied.size(); i++) {
+        if (satisfied[i] == "true")  sat[i] = 1;
+        if (satisfied[i] == "false") sat[i] = 0;
+    }
+}
+
+void Whenthen::setsat(int *sat)
+{
+    for (int i=0; i<(int)satisfied.size(); i++) {
+        if (sat[i] == 1) satisfied[i] = "true";
+        if (sat[i] == 0) satisfied[i] = "false";
+    }
+}
+
+
+// ===========================================================================
+// Get and Set the processed flag for a whenthen.
+// ===========================================================================
+void Whenthen::getprocessed(int *wtp)
+{
+    *wtp = 0;
+    if (processed) *wtp = 1;
+}
+
+void Whenthen::setprocessed(int wtp)
+{
+    processed = false;
+    if (wtp == 1) processed = true;
+}
+
+
+// ===========================================================================
+// Get and Set the sequence index.
+// ===========================================================================
+void Whenthen::getseq(int *wtseq)
+{
+    *wtseq = seqdex;
+}
+
+void Whenthen::setseq(int wtseq)
+{
+    seqdex = wtseq;
+}
+
+
+
+
+// ===========================================================================
+// List the final commands deque for this whenthen to a stringstream.
+// This is done to let the user know what the final commands are. It is
+// also useful for debugging.
+// ===========================================================================
+void Whenthen::list_cmdsf_ss(stringstream &ssc)
+{
+    for (int i=0; i<(int)cmdsf.size(); i++) {
+        ssc << "        ";
+        cmdsf[i].print_using_words_fm(ssc);
+        ssc << endl;
+    }
+}
+
+
+// ===========================================================================
+// List the condition for this whenthen to a stringstream.
+// This is done to let the user indentify this whenthen. It is
+// also useful for debugging.
+// ===========================================================================
+void Whenthen::list_condition(string offset1, string offset2,
+                              stringstream &ssc)
+{
+    for (int n=0; n<(int)varname.size(); n++) {
+
+        string relstr = relation[n].get_string();
+        string rstr = relstr;
+        if (has_got[n]) {
+            if (relstr == ".lt.") rstr = ".hglt.";
+            if (relstr == ".le.") rstr = ".hgle.";
+            if (relstr == ".eq.") rstr = ".hgeq.";
+            if (relstr == ".ne.") rstr = ".hgne.";
+            if (relstr == ".gt.") rstr = ".hggt.";
+            if (relstr == ".ge.") rstr = ".hgge.";
+        }
+        relstr = rstr;
+
+        string offset = offset1;
+        if (n > 0) offset = offset2;
+
+        ssc << offset << varname[n].get_string() << " "
+            << relstr << " " << value[n].get_string();
+
+        if (logop[n].get_string() == "none") break;
+        ssc << " " << logop[n].get_string();
+        ssc << endl;
+    }
+}
+
+
+// ===========================================================================
+// Delete words i1 through i2 inclusive from the deque.
+// ===========================================================================
+void Whenthen::delete_words(int i1, int i2, deque <Word> &words)
+{
+    deque<Word>::iterator p = words.begin();
+    words.erase(p + i1, p + i2 + 1);
+}
+
+
+// ===========================================================================
+// Replace words i1 through i2 inclusive with word w.
+// ===========================================================================
+void Whenthen::replace_words(int i1, int i2, deque <Word> &words, Word &w)
+{
+    delete_words(i1, i2, words);
+    deque<Word>::iterator p = words.begin();
+    words.insert(p + i1, w);
+}
+
+
+
+
+
+} // End of the PP namespace
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Whenthen.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Whenthen.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,139 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef WHENTHENHHINCLUDE
+#define WHENTHENHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <deque>
+#include <vector>
+#include <map>
+#include <sstream>
+
+#include "Word.hh"
+
+namespace PP
+{
+using std::string;
+using std::deque;
+using std::vector;
+using std::map;
+using std::stringstream;
+
+class Whenthen
+{
+
+public:
+    Whenthen();
+    Whenthen(int &nwhen, Cmd &cmdi, bool &skipwhen, bool &single_line_when,
+             bool eflag, stringstream &serr, int &ierr);
+    void add_cmdf(Cmd &cmdi);
+    void list_condition(string offset1, string offset2,
+                        stringstream &ssc);
+    void list_cmdsf_ss(stringstream &ssc);
+
+    void check_wt(vector<string> &code_varnames,
+                  vector<string> &code_values,
+                  vector<int> &vv_active,
+                  int *wtci, stringstream &serr, int &ierr);
+
+    deque<Cmd> *get_cmdsf_ptr() { return &cmdsf; }
+
+    void get_char_array_size(int *ca_size);
+    void get_char_array(string &sc);
+
+    void get_satsize(int *sat_size);
+    void getsat(int *sat);
+    void setsat(int *sat);
+    void getprocessed(int *wtp);
+    void setprocessed(int wtp);
+    void getseq(int *wtseq);
+    void setseq(int wtseq);
+    int get_num_varnames() { return (int)varname.size(); }
+    string get_varname(int i) { return varname[i].get_string(); }
+
+
+private:
+
+    void add_word(Cmd &cmdi, int idex, deque<Word> &wq);
+    void add_word(Cmd &cmdi, int idex, deque<Word> &wq, string sadd);
+    void process_words(deque <Word> &words, vector<string> &code_varnames,
+                       vector<string> &code_values,
+                       vector<int> &vv_active,
+                       stringstream &serr, int &ierr);
+    void delete_words(int i1, int i2, deque <Word> &words);
+    void replace_words(int i1, int i2, deque <Word> &words, Word &w);
+
+    // The condition:   varname relation value  logical  varname relation value etc.
+    // Example:           time     .gt.   3.0    .and.    ncycle   .ge.    50
+    // The condition is thought of as a sequence of subconditions connected by
+    // logical operators. The above example has two subconditions connected by the
+    // .and. logical operator.
+    deque<Word>   varname;    // Host code variable name to be replaced by host code value.
+    deque<Word>   relation;   // Relation between varname and value, like .gt., .hglt., ...
+    deque<Word>   value;      // Value to compare with host code value.
+    deque<Word>   logop;      // Logical operator connecting subconditions.
+    deque<string> satisfied;  // Satisfied flag for each subcondition.
+    deque<bool>   has_got;    // Has got flag for the relation. This is true if
+                              // the relation is .hggt., .hglt., ..., false otherwise.
+
+    // Commands to be done when the condition is satisfied.
+    deque<Cmd> cmdsf;
+
+    // The whenthen is only done once when the condition is satisfied.
+    // This flag keeps it from being done again.
+    bool processed;
+
+    // This flag is used to distinguish between the when command and the
+    // whenever command.
+    bool ever_flag;
+
+    // This is a sequence index to keep track of what order the whenthen's
+    // have been processed in.
+    int seqdex;
+};
+
+
+} // end of PP namespace
+
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.cc
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Word.cc?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.cc (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.cc Mon Sep  4 07:25:36 2017
@@ -0,0 +1,1193 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds each word from the line.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <deque>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef SGI
+#else
+#include <cctype>
+#endif
+
+#include "Word.hh"
+
+namespace PP
+{
+using std::string;
+using std::cout;
+using std::endl;
+//using std::isdigit;
+using std::stringstream;
+using std::setprecision;
+using std::vector;
+using std::map;
+using std::deque;
+using std::pair;
+
+
+// ===========================================================================
+// Default constructor.
+// ===========================================================================
+Word::Word() 
+{
+    wstr = "";
+    init();
+}
+
+
+// ===========================================================================
+// Construct given a string.
+// ===========================================================================
+Word::Word(string s)
+{
+    wstr = s;
+    init();
+    set_type();
+}
+
+
+// ===========================================================================
+// Construct given a string. Also set the map of variables.
+// ===========================================================================
+Word::Word(string s, int lnum, int file_lnum, string fname,
+           deque<string> *lstr)
+{
+    wstr = s;
+    init();
+    line_number = lnum;
+    file_line_number = file_lnum;
+    filename = fname;
+    lines = lstr;
+    set_type();
+}
+
+
+// ===========================================================================
+// Construct given a double
+// ===========================================================================
+Word::Word(double d, int lnum, int file_lnum, string fname,
+           deque<string> *lstr)
+{
+    stringstream ss;
+    ss << setprecision(15) << d;
+    wstr = ss.str();
+    init();
+    type = DOUBLE;
+    line_number = lnum;
+    file_line_number = file_lnum;
+    filename = fname;
+    lines = lstr;
+}
+
+
+// ===========================================================================
+// Construct given an integer.
+// ===========================================================================
+Word::Word(int ia, int lnum, int file_lnum, string fname,
+           deque<string> *lstr)
+{
+    stringstream ss;
+    ss << ia;
+    wstr = ss.str();
+    init();
+    type = DOUBLE;
+    line_number = lnum;
+    file_line_number = file_lnum;
+    filename = fname;
+    lines = lstr;
+}
+
+
+// ===========================================================================
+/*! = operator. */
+// ===========================================================================
+Word Word::operator=(const Word &ws) 
+{
+   if (&ws == this) return *this;
+   wstr = ws.wstr;
+   processed = ws.processed;
+   type = ws.type;
+   negate = ws.negate;
+   line_number = ws.line_number;
+   file_line_number = ws.file_line_number;
+   filename = ws.filename;
+   lines = ws.lines;
+   multiplicity = ws.multiplicity;
+   op_level = ws.op_level;
+   op_type = ws.op_type;
+   return *this;
+}
+
+
+// ===========================================================================
+/*! Copy constructor. */
+// ===========================================================================
+Word::Word(const Word &ws) 
+{
+   wstr = ws.wstr;
+   processed= ws.processed;
+   type = ws.type;
+   negate = ws.negate;
+   line_number = ws.line_number;
+   file_line_number = ws.file_line_number;
+   filename = ws.filename;
+   lines = ws.lines;
+   multiplicity = ws.multiplicity;
+   op_level = ws.op_level;
+   op_type = ws.op_type;
+}
+
+
+// ===========================================================================
+// Common initialization routine called from constructors.
+// ===========================================================================
+void Word::init()
+{
+    processed = false;
+    type = WUNKNOWN;
+    negate = false;
+    lines = NULL;
+    line_number = 0;
+    file_line_number = 0;
+    filename = "";
+    multiplicity = 1;
+    op_level = -1;
+    op_type = "";
+}
+
+
+
+// ===========================================================================
+/*! Destructor */
+// ===========================================================================
+Word::~Word()
+{
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+// Change the value of a word.
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Set the word to a double.
+// ===========================================================================
+void Word::set_value(double d)
+{
+    stringstream ss;
+    ss << setprecision(15) << d;
+    wstr = ss.str();
+    set_type();
+}
+
+
+// ===========================================================================
+// Set the word to a string.
+// ===========================================================================
+void Word::set_value(string s)
+{
+    wstr = s;
+    set_type();
+}
+
+
+// ===========================================================================
+// Set the word to a string.
+// Use this when you want to do set_value("lasjdf"), otherwise c++ cannot
+// get which set_type to use (and it does not tell you it is having trouble).
+// ===========================================================================
+void Word::set_value(const char *s)
+{
+    wstr = s;
+    set_type();
+}
+
+
+// ===========================================================================
+// Set the word to a boolean.
+// ===========================================================================
+void Word::set_value(bool b)
+{
+    if (!b) wstr = "false";
+    if (b)  wstr = "true";
+    set_type();
+}
+
+
+
+
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+// This section handles the type of the word, whether it is an operator,
+// a function, a string, etc.
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+
+
+// ===========================================================================
+/*! Set the type of word. */
+// ===========================================================================
+void Word::set_type()
+{
+   // Make sure the type is initialized. If the word is not anything else,
+   // then it is a string.
+   type = WSTRING;
+
+   // Just for convenience.
+   int len = (int)wstr.size();
+
+   // First determine if the word starts and ends with quotes. If it does,
+   // then it is a string. We do not strip off the quote symbols at this
+   // point because we might be in a comment region where the quotes donot
+   // matter. Later after the comments are stripped out, we check for
+   // matching quotes and remove them.
+   if ((wstr[0] == '\"') || (wstr[0] == '\'') ||
+       (wstr[len-1] == '\"') || (wstr[len-1] == '\'')) {
+      type = WSTRING;
+      //wstr.erase(wstr.end() - 1);
+      //wstr.erase(wstr.begin());
+      return;
+   }
+
+   // Check for a delimiter.
+   if (wstr == "(") { type = OPEN_PARENS; return; }
+   if (wstr == ")") { type = CLOSED_PARENS; return; }
+   if (wstr == "[") { type = OPEN_SQUARE_BRACKET; return; }
+   if (wstr == "]") { type = CLOSED_SQUARE_BRACKET; return; }
+   if (wstr == "{") { type = OPEN_BRACE; return; }
+   if (wstr == "}") { type = CLOSED_BRACE; return; }
+
+   // Comma is used for a couple of things.
+   if (wstr == ",") { type = COMMA; return; }
+
+   // Variables always begin with $. Of course, if the word is in quotes it is
+   // not a variable even if it does begin with $.
+   if (wstr[0] == '$') { type = VARIABLE; return; }
+
+   // Check for an operator.
+   if (wstr == "++")    { type=OPERATOR; op_level=7; op_type="arithmetic"; return; }
+   if (wstr == "--")    { type=OPERATOR; op_level=7; op_type="arithmetic"; return; }
+
+   if (wstr == "**")    { type=OPERATOR; op_level=6; op_type="arithmetic"; return; }
+
+   // Do not implement the % operator, it is too much like the fortran %
+   // operator which is for referencing components of a fortran structure.
+   //if (wstr == "%")     { type=OPERATOR; op_level=5; op_type="arithmetic"; return; }
+   if (wstr == "*")     { type=OPERATOR; op_level=5; op_type="arithmetic"; return; }
+   if (wstr == "/")     { type=OPERATOR; op_level=5; op_type="arithmetic"; return; }
+
+   if (wstr == "+")     { type=OPERATOR; op_level=4; op_type="arithmetic"; return; }
+   if (wstr == "-")     { type=OPERATOR; op_level=4; op_type="arithmetic"; return; }
+
+   if (wstr == ".gt.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".ge.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".lt.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".le.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".eq.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".ne.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+
+   if (wstr == ".hggt.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".hgge.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".hglt.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".hgle.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".hgeq.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+   if (wstr == ".hgne.")  { type=OPERATOR; op_level=3; op_type="relational"; return; }
+
+   if (wstr == ".not.") { type=OPERATOR; op_level=2; op_type="logical";    return; }
+
+   if (wstr == ".and.") { type=OPERATOR; op_level=1; op_type="logical";    return; }
+
+   if (wstr == ".or.")  { type=OPERATOR; op_level=0; op_type="logical";    return; }
+
+   // Equals sign.
+   if (wstr == "=")  { type = EQUALS; return; }
+
+   // At this point the word is either a string or a number.
+
+   // If the word begins with a + or - sign, then it is numeric.
+   bool start_with_pm = false;
+   if (wstr[0] == '+') start_with_pm = true;
+   if (wstr[0] == '-') start_with_pm = true;
+
+   // If the word does not begin with a + or - sign or a digit, or a
+   // ., or an e or a d then it is a string.
+   if (!start_with_pm) {
+       if(!isdigit(wstr[0])) {
+           if (wstr[0] != '.') {
+               if (wstr[0] != 'e') {
+                   if (wstr[0] != 'E') {
+                       if (wstr[0] != 'd') {
+                           if (wstr[0] != 'D') {
+                               type = WSTRING; return;
+                           }
+                       }
+                   }
+               }
+           }
+       }
+   }
+
+   // Check for all digits, i.e. an integer.
+   bool is_number = true;
+   int istart = 0;
+   if (start_with_pm) istart = 1;
+   for (int i=istart; i<(int)wstr.size(); i++) {
+      if (!isdigit(wstr[i])) {
+         is_number = false;
+         break;
+      }
+   }
+   if (is_number) { type = INTEGER; return; }
+
+   // Check for floating point.
+   // If there is anything in the string that is not a component of a
+   // floating point number, then that makes it a string.
+   is_number = true;
+   for (int i=0; i<(int)wstr.size(); i++) {
+      if (!isdigit(wstr[i]) && wstr[i]!='.' && wstr[i]!='e' && wstr[i]!='E' &&
+          wstr[i]!='d' && wstr[i]!='D' && wstr[i]!='+' && wstr[i]!='-') {
+         is_number = false;
+         break;
+      }
+   }
+   //if (is_number) { type = DOUBLE; return; }
+   if (!is_number) { type = WSTRING; return; }
+
+   // We suspect a floating point number.
+   // At this point, everything in the string is a component of a floating
+   // point number, i.e.  "+ - digit e E d D ."
+   type = DOUBLE;
+
+   // Check that strings that start with "e E d D" really are numbers.
+   // And for numbers like e+01, e-05, etc, the atof or strtod functions do not
+   // interpret those as numbers, therefore we insert a 1 in front of the e
+   // so that atof and strtod will call it a number.
+   if (wstr[0] == 'e' || wstr[0] == 'E' || wstr[0] == 'd' || wstr[0] == 'D') {
+
+       // Check for proper syntax after the "e E d D".
+       if (!check_after_e(wstr, 1, (int)wstr.size()-1)) {
+           type = WSTRING;
+           return;
+       }
+
+       // This appears to be a number, insert the digit.
+       wstr.insert(0, "1");
+       return;
+   }
+
+   // The string appears to be a floating point number (fpn), check syntax.
+   // First, find the location of the "e E d D". Check that there can be
+   // only one "e E d D" in the string.
+   int ie = -1;
+   for (int i=0; i<(int)wstr.size(); i++) {
+       if (wstr[i] == 'e' || wstr[i] == 'E' || wstr[i] == 'd' ||
+           wstr[i] == 'D') {
+           ie = i;
+           break;
+       }
+   }
+   if (ie > -1) {
+       for (int i=ie+1; i<(int)wstr.size(); i++) {
+           if (wstr[i] == 'e' || wstr[i] == 'E' || wstr[i] == 'd' ||
+               wstr[i] == 'D') {
+               type = WSTRING;
+               return;
+           }
+       }
+   }
+
+   // Check that the characters before the "e E d D" are valid. If no
+   // "e E d D" was found then check the entire string as if it preceeded
+   // an "e E d D".
+   int ic1 = 0;
+   int ic2 = (int)wstr.size() - 1;
+   if (ie > -1) {
+       ic2 = ie - 1;
+   }
+   if (!check_before_e(wstr, ic1, ic2)) {
+       type = WSTRING;
+       return;
+   }
+
+   // All other cases handled, this must be a fpn (type DOUBLE).
+   return;
+}
+
+
+// ===========================================================================
+// The input string, s, could be a floating point number (fpn). It has been
+// determined that s contains an "e E d D" located at position i2+1. Check
+// everything before the "e E d D", postions i1 through i2 inclusive to
+// verify that this is a fpn.
+//
+// It is also possible that an "e E d D" was not found in which case the
+// entire string is checked as if it preceeded an "e E d D".
+//
+// Return false if this is a string
+//        true  if this could be a fpn
+// ===========================================================================
+bool Word::check_before_e(string s, int i1, int i2)
+{
+    // If there is nothing before the "e E d D" then this still could be a fpn.
+    int size = i2 - i1 + 1;
+    if (size < 1) return true;
+           
+    // The first character could be "+ -", but the remaining characters
+    // cannot be "+ -".
+    int ie1 = i1;
+    if (s[i1] == '+' || s[i1] == '-') ie1 = i1+1;
+    for (int i=ie1; i<=i2; i++) {
+        if (s[i] == '+' || s[i] == '-') return false;
+    }
+
+    // Locate the optional "." character. There can only be one ".".
+    int pointdex = -1;
+    for (int i=ie1; i<=i2; i++) {
+        if (s[i] == '.') {
+            pointdex = i;
+            break;
+        }
+    }
+    if (pointdex > -1) {
+        for (int i=pointdex+1; i<=i2; i++) {
+            if (s[i] == '.') return false;
+        }
+    }
+
+
+    // Everything before and after the point must be a digit (except
+    // that the very first character could be "+ -").
+    if (pointdex > -1) {
+        for (int i=ie1; i<pointdex; i++) {
+            if (!isdigit(s[i])) return false;
+        }
+        for (int i=pointdex+1; i<=i2; i++) {
+            if (!isdigit(s[i])) return false;
+        }
+    }
+
+    // If there is no point then everything must be digits (except
+    // that the very first character could be "+ -").
+    if (pointdex == -1) {
+        for (int i=ie1; i<=i2; i++) {
+            if (!isdigit(s[i])) return false;
+        }
+    }
+
+    // All other cases handled, this could be a fpn.
+    return true;
+}
+    
+
+// ===========================================================================
+// The input string, s, could be a floating point number (fpn). It has been
+// determined that s contains an "e E d D" located at position i1-1. Check
+// everything after the "e E d D", postions i1 through i2 inclusive to
+// verify that this is a fpn.
+//
+// Return false if this is a string
+//        true  if this could be a fpn
+// ===========================================================================
+bool Word::check_after_e(string s, int i1, int i2)
+{
+    // If there is nothing after the "e E d D" then that is not a number.
+    int size = i2 - i1 + 1;
+    if (size < 1) return false;
+           
+    // The character following the "e E d D" must be "+ - digit"
+    if (s[i1] != '+' && s[i1] != '-' && (!isdigit(s[i1])))
+        return false;
+
+    // Everything after the e or e+ or e- must be a digit.
+    int ie1 = i1;
+    if (s[i1] == '+' || s[i1] == '-') ie1 = i1+1;
+    for (int i=ie1; i<=i2; i++) {
+        if (!isdigit(s[i])) return false;
+    }
+
+    // All other cases handled, this could be a fpn.
+    return true;
+}
+    
+
+
+// ===========================================================================
+/*! Print the type of word. */
+// ===========================================================================
+void Word::print_type(stringstream &ss)
+{
+   if (type == WUNKNOWN) ss << "unknown";
+   if (type == WSTRING) ss << "string";
+   if (type == INTEGER) ss << "integer";
+   if (type == DOUBLE) ss << "double";
+   if (type == EQUALS) ss << "=";
+   if (type == OPERATOR) ss << "operator";
+   if (type == OPEN_PARENS) ss << "(";
+   if (type == CLOSED_PARENS) ss << ")";
+   if (type == OPEN_SQUARE_BRACKET) ss << "[";
+   if (type == CLOSED_SQUARE_BRACKET) ss << "]";
+   if (type == OPEN_BRACE) ss << "{";
+   if (type == CLOSED_BRACE) ss << "}";
+   if (type == COMMA) ss << ",";
+   if (type == VARIABLE) ss << "variable";
+}
+
+
+// ===========================================================================
+// Check to see if the word is boolean (true or false)
+// ===========================================================================
+bool Word::is_bool()
+{
+    bool retValue = false;
+
+    // We don't want to test all possible combinations of spellings for
+    // "True" vs "true" vs "tRue" etc.  So we create a temporary string that
+    // is all lower case and compare against the temporary.
+
+    // Create a copy of the string that can be modified locally.
+    string str( wstr );
+
+    // Force the string to all lower case.
+    string_to_lower( str );
+    
+    // The comparison is a character-by-character over the length of the
+    // first string.  To avoid uninitialized memory reads we convert char
+    // array literals to strings.
+    if( str == string("true") || str == string(".true.") ) 
+        retValue = true;
+    if ( str == string("false") || str == string(".false.") )
+        retValue = true;
+
+   return retValue;
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+// This section provides the methods for returning the word as double,
+// int, bool, etc.
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+
+// ===========================================================================
+// Get the word as a boolean
+// ===========================================================================
+bool Word::get_bool(stringstream &serr, int &ierr)
+{
+    // Mark this word as having been processed.
+    processed = true;
+
+    bool retValue = false;
+
+    // We don't want to test all possible combinations of spellings for
+    // "True" vs "true" vs "tRue" etc.  So we create a temporary string that
+    // is all lower case and compare against the temporary.
+    string str( wstr );
+
+    // Force the string to all lower case.
+    string_to_lower( str );
+    
+    // The comparison is a character-by-character over the length of the
+    // first string.  To avoid uninitialized memory reads we convert char
+    // array literals to strings.
+    if( str == string("true") || str == string(".true.") ) 
+        retValue = true;
+    else if ( str == string("false") || str == string(".false.") )
+        retValue = false;
+    else { // We default any other bool value to false but also warn the user. 
+        if (lines != NULL) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+            serr << "    " << (*lines)[line_number-1] << endl;
+            serr << "in file: " << filename << endl;
+        }
+        serr << "Values on this line should be true or false "
+            "(or .true. or .false.)" << endl;
+        serr << "    (any case is fine, for example true, True, TrUe "
+            "are all ok)" << endl;
+        serr << "Instead found value: " << wstr << endl << endl;
+        ierr = 2;
+        retValue = false;
+    }
+
+    // Apply the negate flag if it is turned on.
+    if (negate) {
+        bool b = false;
+        if (retValue == false) b = true;
+        retValue = b;
+    }
+
+    return retValue;
+}        
+
+
+// ===========================================================================
+// Get the word as as int, error processing version.
+// ===========================================================================
+int Word::get_int(stringstream &serr, int &ierr)
+{
+    // Mark this word as having been processed.
+    processed = true;
+
+    // The word must at least be a number.
+    if ((type != DOUBLE) && (type != INTEGER)) {
+        if (lines != NULL) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+            serr << "    " << (*lines)[line_number-1] << endl;
+            serr << "in file: " << filename << endl;
+        }
+        serr << "Expected a numerical, integer value." << endl;
+        serr << "Instead got: " << wstr << endl << endl;
+        ierr = 2;
+        return 0;
+    }
+
+    // The word might begin with a + or - sign.
+    bool start_with_pm = false;
+    if (wstr[0] == '+') start_with_pm = true;
+    if (wstr[0] == '-') start_with_pm = true;
+
+    // We allow 2. or 2.0 for example as an integer, but not 2.3.
+    bool dot_found = false;
+    bool is_int = true;
+    int istart = 0;
+    if (start_with_pm) istart = 1;
+    for (int i=istart; i<(int)wstr.size(); i++) {
+        if (!isdigit(wstr[i]) && wstr[i]!='.' ) {
+            is_int = false;
+            break;
+        }
+        if (wstr[i]=='.' ) {
+            dot_found = true;
+            continue;
+        }
+        if (dot_found && wstr[i]!='0' ) {
+            is_int = false;
+            break;
+        }
+    }
+    if (!is_int) {
+        if (lines != NULL) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+            serr << "    " << (*lines)[line_number-1] << endl;
+            serr << "in file: " << filename << endl;
+        }
+        serr << "Expected an integer." << endl;
+        serr << "For example, 2 or 3, even 2. or 2.0 is ok." << endl;
+        serr << "Instead got: " << wstr << endl << endl;
+        ierr = 2;
+        return 0;
+    }
+
+    
+    // Apply the negate flag if it is turned on.
+    int iret = atoi(wstr.c_str() ); 
+    if (negate) iret *= -1;
+    return iret;
+}
+
+int64_t Word::get_int64_t(stringstream &serr, int &ierr)
+{
+    // Mark this word as having been processed.
+    processed = true;
+
+    // The word must at least be a number.
+    if ((type != DOUBLE) && (type != INTEGER)) {
+        if (lines != NULL) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+            serr << "    " << (*lines)[line_number-1] << endl;
+            serr << "in file: " << filename << endl;
+        }
+        serr << "Expected a numerical, integer value." << endl;
+        serr << "Instead got: " << wstr << endl << endl;
+        ierr = 2;
+        return 0;
+    }
+
+    // The word might begin with a + or - sign.
+    bool start_with_pm = false;
+    if (wstr[0] == '+') start_with_pm = true;
+    if (wstr[0] == '-') start_with_pm = true;
+
+    // We allow 2. or 2.0 for example as an integer, but not 2.3.
+    bool dot_found = false;
+    bool is_int = true;
+    int istart = 0;
+    if (start_with_pm) istart = 1;
+    for (int i=istart; i<(int)wstr.size(); i++) {
+        if (!isdigit(wstr[i]) && wstr[i]!='.' ) {
+            is_int = false;
+            break;
+        }
+        if (wstr[i]=='.' ) {
+            dot_found = true;
+            continue;
+        }
+        if (dot_found && wstr[i]!='0' ) {
+            is_int = false;
+            break;
+        }
+    }
+    if (!is_int) {
+        if (lines != NULL) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+            serr << "    " << (*lines)[line_number-1] << endl;
+            serr << "in file: " << filename << endl;
+        }
+        serr << "Expected an integer." << endl;
+        serr << "For example, 2 or 3, even 2. or 2.0 is ok." << endl;
+        serr << "Instead got: " << wstr << endl << endl;
+        ierr = 2;
+        return 0;
+    }
+
+    std::stringstream sstr(wstr);
+    int64_t iret;
+    sstr >> iret;
+    // Apply the negate flag if it is turned on.
+    if (negate) iret *= -1;
+    return iret;
+}        
+
+// ===========================================================================
+// Get the word as a double, error processing version.
+// ===========================================================================
+double Word::get_double(stringstream &serr, int &ierr)
+{
+    // Mark this word as having been processed.
+    processed = true;
+
+    // The word must at least be a number.
+    if ((type != DOUBLE) && (type != INTEGER)) {
+        if (lines != NULL) {
+            serr << endl;
+            serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+            serr << "    " << (*lines)[line_number-1] << endl;
+            serr << "in file: " << filename << endl;
+        }
+        serr << "Expected a numerical value." << endl;
+        serr << "Instead got: " << wstr << endl << endl;
+        ierr = 2;
+        return 0;
+    }
+
+    // Use a temporary string that might be modified.
+    string s = wstr;
+
+    // We allow exponents using d and D in addition to e and E, for example
+    // 1.d14 or -1.38D-18. The problem with this is that atof and strtod
+    // do not allow d or D, therefore we have to replace d or D with e
+    // before sending it to atof or strtod.
+    if (type == DOUBLE) {
+        for (int i=0; i<(int)s.size(); i++) {
+            if (s[i] == 'd') s[i] = 'e';
+            if (s[i] == 'D') s[i] = 'e';
+        }
+    }
+
+    // Convert the string to a double.
+    double d = atof(s.c_str()); 
+
+    // Apply the negate flag if it is turned on.
+    if (negate) d *= -1.0;
+    return d;
+}        
+
+
+// ===========================================================================
+// Get the word as a single character, error processing version.
+// ===========================================================================
+char Word::get_single_char(stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    //assert(serr == serr);
+    assert(ierr == ierr);
+
+    // Mark this word as having been processed.
+    processed = true;
+
+    return wstr[0];
+}
+
+
+// ===========================================================================
+// Get the word as an int, no error processing version.
+// ===========================================================================
+int Word::get_int()
+{
+   int dummy;
+   return get_val( dummy );
+}
+
+// support uint64_t
+int64_t Word::get_int64_t()
+{
+   int64_t dummy;
+   return get_val( dummy );
+}
+
+// ===========================================================================
+// Get the word as a float
+// ===========================================================================
+float Word::get_float()
+{
+   float dummy;
+   return get_val( dummy );
+}        
+
+// ===========================================================================
+// Get the word as a double
+// ===========================================================================
+double Word::get_double()
+{
+   double dummy;
+   return get_val( dummy );
+}        
+
+
+// ===========================================================================
+// Get the word as a Type T. 
+// ===========================================================================
+template< class T >
+T Word::get_val( T &dummyValue )
+{
+   // To suppress compiler warnings of unused parameters
+   assert(dummyValue == dummyValue);
+
+   T retValue;
+
+   // Mark this word as having been processed.
+   processed = true;
+
+   // Convert the word to the requested data type.
+   retValue = convertFromString( retValue, wstr );
+
+   return retValue;
+}        
+
+//! Explicit instantiation of supported template types.  If more types are
+//! needed those explicit versions must be listed here.  We are not using
+//! automatic inclusion (we would need to move the function definition into
+//! the header file for that).  The listed versions below are the only ones
+//! that will be included in the library.
+template int     Word::get_val( int&     );
+template int64_t Word::get_val( int64_t& );
+template float   Word::get_val( float&   );
+template double  Word::get_val( double&  );
+//template bool  Word::get_val( bool&    );
+template string  Word::get_val( string&  );
+
+// ===========================================================================
+// Convert from string to return type explicitly.
+// ===========================================================================
+
+//! rtti is only used for type identification (each overloaded function must
+//! have a unique signature.  The return value is not part of the signature).
+
+// Convert string to integer.
+int    Word::convertFromString( const int &rtti, const string &s ) const 
+{ 
+   // To suppress compiler warnings of unused parameters
+   assert(rtti == rtti);
+
+   int iret = atoi( s.c_str() ); 
+   if (negate) iret *= -1;
+   return iret;
+}
+
+// Convert string to int64_t.
+int64_t Word::convertFromString( const int64_t &rtti, const string &s ) const 
+{
+   // To suppress compiler warnings of unused parameters
+   assert(rtti == rtti);
+
+   int64_t iret;
+   std::stringstream( s ) >> iret;
+   if (negate) iret *= -1;
+   return iret;
+}
+
+// Convert string to string (do nothing).
+string Word::convertFromString( const string &rtti, const string &s ) const 
+{ 
+   // To suppress compiler warnings of unused parameters
+   assert(rtti == rtti);
+
+    return s; 
+}
+
+// Convert string to float.
+float Word::convertFromString( const float &rtti, const string &s ) const 
+{ 
+   // To suppress compiler warnings of unused parameters
+   assert(rtti == rtti);
+
+    // Use a temporary string that might be modified.
+    string sm = s;
+
+    // We allow exponents using d and D in addition to e and E, for example
+    // 1.d14 or -1.38D-18. The problem with this is that atof and strtod
+    // do not allow d or D, therefore we have to replace d or D with e
+    // before sending it to atof or strtod.
+    for (int i=0; i<(int)sm.size(); i++) {
+        if (sm[i] == 'd') sm[i] = 'e';
+        if (sm[i] == 'D') sm[i] = 'e';
+    }
+
+    float f = (float)atof( sm.c_str() );  
+    if (negate) f *= -1.;
+    return f;
+}
+
+// Convert string to double.
+double Word::convertFromString( const double &rtti, const string &s ) const 
+{ 
+    // To suppress compiler warnings of unused parameters
+    assert(rtti == rtti);
+
+    // Use a temporary string that might be modified.
+    string sm = s;
+
+    // We allow exponents using d and D in addition to e and E, for example
+    // 1.d14 or -1.38D-18. The problem with this is that atof and strtod
+    // do not allow d or D, therefore we have to replace d or D with e
+    // before sending it to atof or strtod.
+    for (int i=0; i<(int)sm.size(); i++) {
+        if (sm[i] == 'd') sm[i] = 'e';
+        if (sm[i] == 'D') sm[i] = 'e';
+    }
+
+    double d = atof( sm.c_str() );  
+    if (negate) d *= -1.;
+    return d;
+}
+
+
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+// Utility functions.
+// ***************************************************************************
+// ***************************************************************************
+// ***************************************************************************
+
+
+// ===========================================================================
+// Return the word as a string for printing. This is usually just the word
+// but if it has multiplicity, then include that in the return string.
+// ===========================================================================
+string Word::get_print_string(bool enc_quotes)
+{
+    bool equotes = true;
+    if (!enc_quotes) equotes = false;
+    if (wstr == "true") equotes = false;
+    if (wstr == "false") equotes = false;
+
+
+    string sq = "";
+
+    if (equotes) {
+        if (type == WSTRING) sq = "\"";
+        sq += wstr;
+        if (type == WSTRING) sq += "\"";
+    }
+    else {
+        sq = wstr;
+    }
+
+    if (multiplicity <= 1) return sq;
+
+    stringstream ss;
+    ss << multiplicity;
+    string s = "";
+    s = ss.str() + "*" + sq;
+    return s;
+}
+
+
+// ===========================================================================
+// If a word starts or ends with quotes, make sure the quotes match, if not
+// generate a fatal error, and then strip off the quotes.
+// ===========================================================================
+void Word::handle_quotes(stringstream &serr, int &ierr)
+{
+    // Just for convenience.
+    int len = (int)wstr.size();
+
+    // Check for matching quotes, generate a fatal error if they do not match.
+    bool ferr = false;
+    if ((wstr[0] == '\"') && (wstr[len-1] != '\"')) ferr = true;
+    if ((wstr[0] == '\'') && (wstr[len-1] != '\'')) ferr = true;
+    if ((wstr[len-1] == '\"') && (wstr[0] != '\"')) ferr = true;
+    if ((wstr[len-1] == '\'') && (wstr[0] != '\'')) ferr = true;
+
+    if (ferr) {
+        fatal_error(serr, ierr);
+        serr << "Quotes mismatch found." << endl;
+        serr << "A starting quotes must have a closing quotes." << endl;
+        serr << "Double quotes, \", must be matched with double quotes."
+             << endl;
+        serr << "Single quotes, \', must be matched with single quotes."
+             << endl;
+        ierr = 2;
+    }
+
+    // Determine if the word starts and ends with quotes. If it does,
+    // then we strip off the quote symbols.
+    if (((wstr[0] == '\"') || (wstr[0] == '\'')) &&
+        ((wstr[len-1] == '\"') || (wstr[len-1] == '\''))) {
+        wstr.erase(wstr.end() - 1);
+        wstr.erase(wstr.begin());
+        return;
+    }
+}
+
+
+// ===========================================================================
+// Erase a single character from the word, ic is the index of the character
+// to be erased (starting from 0).
+// ===========================================================================
+void Word::erase_char(int ic)
+{
+    if (ic >= (int)wstr.size()) return;
+    wstr.erase(wstr.begin() + ic);
+}
+
+
+
+// ===========================================================================
+// Fatal error
+// ===========================================================================
+void Word::fatal_error(stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(ierr == ierr);
+
+    serr << endl;
+    serr << "*** FATAL ERROR in line " << file_line_number << ":" << endl;
+    serr << "    " << (*lines)[line_number-1] << endl;
+    serr << "in file: " << filename << endl;
+}
+
+void Word::warning(stringstream &serr, int &ierr)
+{
+    // To suppress compiler warnings of unused parameters
+    assert(ierr == ierr);
+
+    serr << endl;
+    serr << "*** WARNING in line " << file_line_number << ":" << endl;
+    serr << "    " << (*lines)[line_number-1] << endl;
+    serr << "in file: " << filename << endl;
+}
+
+
+// ===========================================================================
+// Negate a word.
+// ===========================================================================
+void Word::negate_value()
+{
+   int len = (int)wstr.size();
+
+   if (type == INTEGER || type == DOUBLE) {
+      negate = false;
+
+      // If the string starts with a - sign, then delete it.
+      for (int i=0; i<len; i++) {
+         if (wstr[i] == ' ' || wstr[i] == '\t') continue;
+         if (wstr[i] == '-') {
+            wstr[i] = ' ';
+            return;
+         }
+         break;
+      }
+
+      // The string did not start with a minus sign so insert one.
+      // Using insert causes link problems with SGI CC
+      string s = "-" + wstr;
+      wstr = s;
+      //wstr.insert(0, s);
+      return;
+   }
+}
+
+
+
+// ===========================================================================
+// Convert the input string to lower case.
+// ===========================================================================
+void Word::string_to_lower( string &s ) const 
+{
+   int i, c, d;
+   int len = (int)s.size();
+   for (i=0; i<len; i++) {
+      c = (int)s[i];
+      d = c;
+      if (isalpha(c)) d = tolower(c);
+      s[i] = (char)d;
+   }
+}
+
+
+
+} // End of the PP namespace
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.hh
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/Word.hh?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.hh (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/Word.hh Mon Sep  4 07:25:36 2017
@@ -0,0 +1,244 @@
+/* Copyright 2015.  Los Alamos National Security, LLC. This material was produced
+ * under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ * Laboratory (LANL), which is operated by Los Alamos National Security, LLC
+ * for the U.S. Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS
+ * ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
+ * ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ * to produce derivative works, such modified software should be clearly marked,
+ * so as not to confuse it with the version available from LANL.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy
+ * of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * Under this license, it is required to include a reference to this work. We
+ * request that each derivative work contain a reference to LANL Copyright
+ * Disclosure C15076/LA-CC-15-054 so that this work's impact can be roughly
+ * measured.
+ *
+ * This is LANL Copyright Disclosure C15076/LA-CC-15-054
+ */
+
+/*
+ *  PowerParser is a general purpose input file parser for software applications.
+ *
+ *  Authors: Chuck Wingate   XCP-2   caw at lanl.gov
+ *           Robert Robey    XCP-2   brobey at lanl.gov
+ */
+
+#ifndef WORDHHINCLUDE
+#define WORDHHINCLUDE
+
+// ***************************************************************************
+// ***************************************************************************
+// This class holds each word from the line.
+// ***************************************************************************
+// ***************************************************************************
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <map>
+#include <deque>
+#include <stdint.h>
+
+namespace PP
+{
+using std::string;
+using std::stringstream;
+using std::vector;
+using std::map;
+using std::deque;
+
+enum WordType {WUNKNOWN, WSTRING, INTEGER, DOUBLE, EQUALS, OPERATOR,
+               OPEN_PARENS, CLOSED_PARENS,
+               OPEN_SQUARE_BRACKET, CLOSED_SQUARE_BRACKET,
+               OPEN_BRACE, CLOSED_BRACE,
+               COMMA, VARIABLE};
+
+class Word
+{
+
+public:
+    Word();
+    Word(string s);
+    Word(string s, int lnum, int file_lnum, string fname,
+         deque<string> *lstr);
+    Word(double d, int lnum, int file_lnum, string fname,
+         deque<string> *lstr);
+    Word(int ia, int lnum, int file_lnum, string fname,
+         deque<string> *lstr);
+    Word operator=(const Word &);
+    Word(const Word &);
+    ~Word();
+
+    // Given a word, change its value.
+    void set_value(double d);
+    void set_value(string s);
+    void set_value(const char *s);
+    void set_value(bool b);
+
+    // Print the type of word to a stringstream.
+    void print_type(stringstream &ss);
+
+    // Set the type of word.
+    void set_type();
+
+    // Get the operator type, arithmetic, relational, ...
+    string get_op_type() {return op_type;}
+
+    bool is_operator() { if (type == OPERATOR) return true; return false; }
+
+    bool is_operator(int level) {
+        if (type != OPERATOR) return false;
+        if (level == op_level) return true;
+        return false;
+    }
+
+    bool is_bool();
+
+    bool is_string()   { if (type == WSTRING)  return true; return false; }
+
+    bool is_integer()  { if (type == INTEGER) return true; return false; }
+
+    bool is_number()   { if (type == INTEGER || type == DOUBLE) return true;
+                         return false; }
+
+    bool is_numvar()   { if (type == INTEGER || type == DOUBLE ||
+                             type == VARIABLE) return true;
+                         return false; }
+
+    bool has_value()   { if (type == INTEGER || type == DOUBLE) return true;
+                         return false; }
+
+    bool is_variable() { if (type == VARIABLE) return true; return false; }
+
+    bool is_comma()    { if (type == COMMA) return true; return false; }
+
+    /*! \brief Get the word as a string. */
+    string get_string()    { return wstr; }
+    string get_print_string(bool enc_quotes);
+    string get_stringp()   { processed=true; return wstr; }
+    char get_single_char(stringstream &serr, int &ierr);
+
+    /*! \brief Get the word as a float. */
+    float get_float();
+
+    /*! \brief Get the word as a double. */
+    double get_double();
+    double get_double(stringstream &serr, int &ierr);
+
+    // Get the word as an int, without and with error processing.
+    int get_int();
+    int get_int(stringstream &serr, int &ierr);
+
+    int64_t get_int64_t();
+    int64_t get_int64_t(stringstream &serr, int &ierr);
+
+    /*! \brief Get the word as a boolean. */
+    bool get_bool(stringstream &serr, int &ierr);
+
+    /*! \brief Templated get method for get_double, get_int, etc. */
+    template< class T >
+    T get_val( T &dummy );
+
+    /*!
+     * \brief Convert string s to the type of the first argument.  Function
+     * returns the converted value as a reference and as the function
+     * result. 
+     *
+     * These overloaded functions are the base for the templated accessor
+     * functions "get_val()".
+     *
+     * \param rtti - Convert the string s into the type of rtti and return it.
+     */
+    int     convertFromString ( const int     &rtti, const string &s ) const; 
+    int64_t convertFromString ( const int64_t &rtti, const string &s ) const; 
+    string  convertFromString ( const string  &rtti, const string &s ) const;
+    float   convertFromString ( const float   &rtti, const string &s ) const;
+    double  convertFromString ( const double  &rtti, const string &s ) const;
+    //bool    convertFromString ( const bool   &rtti, const string &s ) const;
+
+    /*! \brief Negate the word or set a flag to negate it later. */
+    void negate_value();
+
+    // Handle errors.
+    void fatal_error(stringstream &serr, int &ierr);
+    void warning(stringstream &serr, int &ierr);
+
+    // Miscellaneous functions.
+    void handle_quotes(stringstream &serr, int &ierr);
+    void erase_char(int ic);
+
+    // Accessor methods.
+    void   set_word(string str)    { wstr = str; }
+    void   set_processed(bool p)   { processed = p; }
+    bool   get_processed()         { return processed; }
+    int    get_line_number()       { return line_number; }
+    int    get_file_line_number()  { return file_line_number; }
+    string get_filename()          { return filename; }
+    deque<string> *get_lines()     { return lines; }
+    void   set_filename(string fn) { filename = fn; }
+    int    get_multiplicity()      { return multiplicity; }
+    void   set_multiplicity(int m) { multiplicity = m; }
+
+private:
+    void init();
+    bool check_before_e(string s, int i1, int i2);
+    bool check_after_e(string s, int i1, int i2);
+
+    // This is the basic storage for the word.
+    string wstr;
+
+    // The type of word, like operator, string, variable, etc.
+    WordType type;
+
+    // Flag for testing whether this word was processed or not.
+    bool processed;
+
+    // Flag to negate a variable.
+    bool negate;
+
+    // This word is repeated multiplicity times.
+    int multiplicity;
+
+    // If the word is an operator, then this is its level, i.e. "**" has
+    // the highest level, then "*","/", etc.
+    int op_level;
+
+    // The operator type, arithmetic, relational, ...
+    string op_type;
+
+    // Convert the input string to lower case.
+    void string_to_lower( string &s ) const;
+
+    // This is needed for telling the user what line in the input
+    // file or include file the error occurred on.
+    //
+    // line_number  The line_number corresponding to this command, this is
+    //              an index into lines and starts from 1, not 0.
+    // lines        Pointer to the deque of original lines. This contains all
+    //              the lines from the input file and any include files.
+    // file_line_number  The line number in the input file or include file.
+    // filename          The name of the input file or include file.
+    //
+    // file_line_number and filename are needed to that the user can open
+    // the file and go to the line in error.
+    int line_number, file_line_number;
+    string filename;
+    deque<string> *lines;
+    
+};
+
+
+} // end of PP namespace
+
+#endif

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/clamr_cpuonly.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/clamr_cpuonly.cpp?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/clamr_cpuonly.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/clamr_cpuonly.cpp Mon Sep  4 07:25:36 2017
@@ -0,0 +1,832 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+
+#include <algorithm>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <vector>
+//#include "graphics/display.h"
+#include "graphics.h"
+#include "input.h"
+#include "mesh.h"
+#include "partition.h"
+#include "state.h"
+#include "timer.h"
+#include "memstats.h"
+#include "crux.h"
+#include "PowerParser.hh"
+#include "MallocPlus.h"
+#ifdef HAVE_ITTNOTIFY
+#include <ittnotify.h>
+#endif
+
+using namespace PP;
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+#undef DEBUG_RESTORE_VALS
+
+#define MIN3(x,y,z) ( min( min(x,y), z) )
+
+static int do_cpu_calc = 1;
+static int do_gpu_calc = 0;
+
+typedef unsigned int uint;
+
+static bool do_display_graphics = false;
+
+#ifdef HAVE_GRAPHICS
+static double circle_radius=-1.0;
+#ifdef FULL_PRECISION
+   void (*set_display_cell_coordinates)(double *, double *, double *, double *) = &set_display_cell_coordinates_double;
+   void (*set_display_cell_data)(double *) = &set_display_cell_data_double;
+#else
+   void (*set_display_cell_coordinates)(float *, float *, float *, float *) = &set_display_cell_coordinates_float;
+   void (*set_display_cell_data)(float *) = &set_display_cell_data_float;
+#endif
+#endif
+
+static int view_mode = 0;
+
+#ifdef FULL_PRECISION
+#define  SUM_ERROR 2.0e-16
+   void (*set_graphics_cell_coordinates)(double *, double *, double *, double *) = &set_graphics_cell_coordinates_double;
+   void (*set_graphics_cell_data)(double *) = &set_graphics_cell_data_double;
+#else
+#define  SUM_ERROR 1.0e-8
+   void (*set_graphics_cell_coordinates)(float *, float *, float *, float *) = &set_graphics_cell_coordinates_float;
+   void (*set_graphics_cell_data)(float *) = &set_graphics_cell_data_float;
+#endif
+
+void store_crux_data(Crux *crux, int ncycle);
+void restore_crux_data_bootstrap(Crux *crux, char *restart_file, int rollback_counter);
+void restore_crux_data(Crux *crux);
+
+bool        restart,        //  Flag to start from a back up file; init in input.cpp::parseInput().
+            verbose,        //  Flag for verbose command-line output; init in input.cpp::parseInput().
+            localStencil,   //  Flag for use of local stencil; init in input.cpp::parseInput().
+            face_based,     //  Flag for face-based finite difference;
+            outline;        //  Flag for drawing outlines of cells; init in input.cpp::parseInput().
+int         outputInterval, //  Periodicity of output; init in input.cpp::parseInput().
+            crux_type,      //  Type of checkpoint/restart -- CRUX_NONE, CRUX_IN_MEMORY, CRUX_DISK;
+                            //  init in input.cpp::parseInput().
+            enhanced_precision_sum,//  Flag for enhanced precision sum (default true); init in input.cpp::parseInput().
+            lttrace_on,     //  Flag to turn on logical time trace package;
+            do_quo_setup,   //  Flag to turn on quo dynamic scheduling policies package;
+            levmx,          //  Maximum number of refinement levels; init in input.cpp::parseInput().
+            nx,             //  x-resolution of coarse grid; init in input.cpp::parseInput().
+            ny,             //  y-resolution of coarse grid; init in input.cpp::parseInput().
+            niter,          //  Maximum iterations; init in input.cpp::parseInput().
+            graphic_outputInterval, // Periodicity of graphic output that is saved; init in input.cpp::parseInput()
+            checkpoint_outputInterval, // Periodicity of checkpoint output that is saved; init in input.cpp::parseInput()
+            num_of_rollback_states,// Maximum number of rollback states to maintain; init in input.cpp::parseInput()
+            backup_file_num,//  Backup file number to restart simulation from; init in input.cpp::parseInput()
+            numpe,          //  
+            ndim    = 2;    //  Dimensionality of problem (2 or 3).
+double      upper_mass_diff_percentage; //  Flag for the allowed pecentage difference to the total
+                                        //  mass per output intervals; init in input.cpp::parseInput().
+
+char *restart_file;
+
+static int it = 0;
+
+enum partition_method initial_order,  //  Initial order of mesh.
+                      cycle_reorder;  //  Order of mesh every cycle.
+static Mesh        *mesh;           //  Object containing mesh information
+static State       *state;          //  Object containing state information corresponding to mesh
+static Crux        *crux;           //  Object containing checkpoint/restart information
+static PowerParser *parse;          //  Object containing input file parsing
+
+static real_t circ_radius = 0.0;
+static int next_cp_cycle = 0;
+static int next_graphics_cycle = 0;
+
+//  Set up timing information.
+static struct timeval tstart, tstart_cpu, tstart_partmeas;
+
+static double H_sum_initial = 0.0;
+static double cpu_time_graphics = 0.0;
+static double cpu_time_calcs    = 0.0;
+static double cpu_time_partmeas = 0.0;
+
+static int     ncycle  = 0;
+static double  simTime = 0.0;
+static double  deltaT = 0.0;
+char total_sim_time_log[] = {"total_execution_time.log"};
+struct timeval total_exec;
+
+static int mype=0;
+int main(int argc, char **argv) {
+
+   // Needed for code to compile correctly on the Mac
+   int numpe=-1;
+
+   //  Process command-line arguments, if any.
+   parseInput(argc, argv);
+
+#ifdef _OPENMP
+   int nt = 0;
+   int tid = 0;
+
+   nt = omp_get_max_threads();
+   tid = omp_get_thread_num();
+   if (0 == tid && mype == 0) {
+        printf("--- max num openmp threads: %d\n", nt);
+   }
+#pragma omp parallel firstprivate(nt, tid)
+   {
+      nt = omp_get_num_threads();
+      tid = omp_get_thread_num();
+
+#pragma omp master
+      if (mype == 0) {
+         printf("--- num openmp threads in parallel region: %d\n", nt);
+      }
+   }
+#endif
+
+   parse = new PowerParser();
+
+   struct timeval tstart_setup;
+   cpu_timer_start(&tstart_setup);
+
+   crux = new Crux(crux_type, num_of_rollback_states, restart);
+
+   circ_radius = 6.0;
+   //  Scale the circle appropriately for the mesh size.
+   circ_radius = circ_radius * (real_t) nx / 128.0;
+   int boundary = 1;
+   int parallel_in = 0;
+   double deltax_in = 1.0;
+   double deltay_in = 1.0;
+
+   if (restart){
+      restore_crux_data_bootstrap(crux, restart_file, 0);
+      mesh  = new Mesh(nx, ny, levmx, ndim, deltax_in, deltay_in, boundary, parallel_in, do_gpu_calc);
+      mesh->init(nx, ny, circ_radius, initial_order, do_gpu_calc);
+
+      state = new State(mesh);
+      restore_crux_data(crux);
+      mesh->proc.resize(mesh->ncells);
+      mesh->calc_distribution(numpe);
+   } else {
+      mesh = new Mesh(nx, ny, levmx, ndim, deltax_in, deltay_in, boundary, parallel_in, do_gpu_calc);
+      if (DEBUG) {
+         //if (mype == 0) mesh->print();
+
+         char filename[10];
+         sprintf(filename,"out%1d",mype);
+         mesh->fp=fopen(filename,"w");
+
+         //mesh->print_local();
+      }
+
+      mesh->init(nx, ny, circ_radius, initial_order, do_gpu_calc);
+      state = new State(mesh);
+      state->init(do_gpu_calc);
+      mesh->proc.resize(mesh->ncells);
+      mesh->calc_distribution(numpe);
+      state->fill_circle(circ_radius, 100.0, 7.0);
+   }
+
+   size_t &ncells = mesh->ncells;
+
+   if (graphic_outputInterval > niter) next_graphics_cycle = graphic_outputInterval;
+   if (checkpoint_outputInterval > niter) next_cp_cycle = checkpoint_outputInterval;
+
+
+   //  Kahan-type enhanced precision sum implementation.
+   double H_sum = state->mass_sum(enhanced_precision_sum);
+   if (mype == 0) printf ("Mass of initialized cells equal to %14.12lg\n", H_sum);
+   H_sum_initial = H_sum;
+
+   if(upper_mass_diff_percentage < 0){
+      upper_mass_diff_percentage = H_sum_initial * SUM_ERROR;
+      //printf("Setting sum mass error to %16.8lg\n",upper_mass_diff_percentage);
+   }
+
+   double cpu_time_main_setup = cpu_timer_stop(tstart_setup);
+   #ifdef TIMING
+   mesh->parallel_output("CPU:  setup time               time was",cpu_time_main_setup, 0, "s");
+   #endif 
+
+   long long mem_used = memstats_memused();
+   #ifdef MEMORY
+   if (mem_used > 0) {
+      mesh->parallel_output("Memory used      in startup ",mem_used, 0, "kB");
+      mesh->parallel_output("Memory peak      in startup ",memstats_mempeak(), 0, "kB");
+      mesh->parallel_output("Memory free      at startup ",memstats_memfree(), 0, "kB");
+      mesh->parallel_output("Memory available at startup ",memstats_memtotal(), 0, "kB");
+   }
+   #endif
+
+   if (mype == 0) {
+      if (ncycle != 0){
+         printf("Iteration %3d timestep %lf Sim Time %lf cells %ld Mass Sum %14.12lg\n",
+            ncycle, deltaT, simTime, ncells, H_sum);
+      } else {
+         printf("Iteration   0 timestep      n/a Sim Time      0.0 cells %ld Mass Sum %14.12lg\n", ncells, H_sum);
+      }
+   }
+
+   for (int i = 0; i < MESH_COUNTER_SIZE; i++){
+      mesh->cpu_counters[i]=0;
+   }
+   for (int i = 0; i < MESH_TIMER_SIZE; i++){
+      mesh->cpu_timers[i]=0.0;
+   }
+
+   cpu_timer_start(&tstart_cpu);
+
+#ifdef HAVE_GRAPHICS
+   do_display_graphics = true;
+   set_display_mysize(ncells);
+   set_display_cell_coordinates(&mesh->x[0], &mesh->dx[0], &mesh->y[0], &mesh->dy[0]);
+   set_display_cell_data(&state->H[0]);
+   set_display_cell_proc(&mesh->proc[0]);
+
+   set_display_window((float)mesh->xmin, (float)mesh->xmax,
+                      (float)mesh->ymin, (float)mesh->ymax);
+   set_display_outline((int)outline);
+   set_display_viewmode(view_mode);
+#endif
+
+   if (ncycle == next_graphics_cycle){
+      set_graphics_outline(outline);
+      set_graphics_window((float)mesh->xmin, (float)mesh->xmax,
+                          (float)mesh->ymin, (float)mesh->ymax);
+      set_graphics_mysize(ncells);
+      set_graphics_cell_coordinates(&mesh->x[0], &mesh->dx[0],
+                                    &mesh->y[0], &mesh->dy[0]);
+      set_graphics_cell_data(&state->H[0]);
+      set_graphics_cell_proc(&mesh->proc[0]);
+      set_graphics_viewmode(view_mode);
+
+      if (mype == 0) {
+         init_graphics_output();
+         set_graphics_cell_proc(&mesh->proc[0]);
+         write_graphics_info(0,0,0.0,0,0);
+      }
+      next_graphics_cycle += graphic_outputInterval;
+   }
+
+#ifdef HAVE_GRAPHICS
+   set_display_circle_radius(circle_radius);
+   init_display(&argc, argv, "Shallow Water");
+   draw_scene();
+   //if (verbose) sleep(5);
+   sleep(2);
+
+   //  Clear superposition of circle on grid output.
+   circle_radius = -1.0;
+#endif
+   cpu_time_graphics += cpu_timer_stop(tstart_cpu);
+
+   //  Set flag to show mesh results rather than domain decomposition.
+   view_mode = 1;
+
+   if (ncycle == next_cp_cycle) store_crux_data(crux, ncycle); 
+
+   cpu_timer_start(&tstart);
+#ifdef HAVE_GRAPHICS
+   set_idle_function(&do_calc);
+   start_main_loop();
+#else
+#ifdef HAVE_ITTNOTIFY
+__itt_resume();
+__SSC_MARK(0x111);
+#endif
+   for (it = ncycle; it < 10000000; it++) {
+      do_calc();
+   }
+#ifdef HAVE_ITTNOTIFY
+__itt_pause();
+__SSC_MARK(0x222);
+#endif
+#endif
+   
+   return 0;
+}
+
+extern "C" void do_calc(void)
+{  double g     = 9.80;
+   double sigma = 0.95;
+   int icount, jcount;
+   static int rollback_attempt = 0;
+   static double total_program_time = 0;
+
+   //  Initialize state variables for GPU calculation.
+   size_t &ncells    = mesh->ncells;
+
+   vector<int>     mpot;
+   
+   size_t new_ncells = 0;
+   double H_sum = -1.0;
+
+   //  Main loop.
+   int endcycle = MIN3(niter, next_cp_cycle, next_graphics_cycle);
+
+   cpu_timer_start(&tstart_cpu);
+
+   for (int nburst = ncycle % outputInterval; nburst < outputInterval && ncycle < endcycle; nburst++, ncycle++) {
+
+#ifdef _OPENMP
+#pragma omp parallel
+      {
+#endif
+         //  Calculate the real time step for the current discrete time step.
+         double mydeltaT = state->set_timestep(g, sigma); // Private variable to avoid write conflict
+#ifdef _OPENMP
+#pragma omp barrier
+#pragma omp master
+         {
+#endif
+           deltaT = mydeltaT;
+           simTime += deltaT;
+#ifdef _OPENMP
+         }
+#endif
+
+         mesh->calc_neighbors(ncells);
+
+         cpu_timer_start(&tstart_partmeas);
+         mesh->partition_measure();
+
+#ifdef _OPENMP
+#pragma omp master
+#endif
+         cpu_time_partmeas += cpu_timer_stop(tstart_partmeas);
+
+         // Currently not working -- may need to be earlier?
+         //if (do_cpu_calc && ! mesh->have_boundary) {
+         //  state->add_boundary_cells(mesh);
+         //}
+
+         // Apply BCs is currently done as first part of gpu_finite_difference and so comparison won't work here
+
+         mesh->set_bounds(ncells);
+
+         //  Execute main kernel
+         if (face_based) {
+            state->calc_finite_difference_via_faces(deltaT);
+         } else {
+            state->calc_finite_difference(deltaT);
+         }
+
+         //  Size of arrays gets reduced to just the real cells in this call for have_boundary = 0
+         state->remove_boundary_cells();
+#ifdef _OPENMP
+      } // end parallel region
+#endif
+
+      mpot.resize(ncells);
+      new_ncells = state->calc_refine_potential(mpot, icount, jcount);
+
+      //  Resize the mesh, inserting cells where refinement is necessary.
+
+#ifdef _OPENMP
+#pragma omp parallel
+      {
+#endif
+      state->rezone_all(icount, jcount, mpot);
+
+      // Clear does not delete mpot, so have to swap with an empty vector to get
+      // it to delete the mpot memory. This is all to avoid valgrind from showing
+      // it as a reachable memory leak
+#ifdef _OPENMP
+#pragma omp master
+      {
+#endif
+      //mpot.clear();
+      vector<int>().swap(mpot);
+
+      mesh->ncells = new_ncells;
+      ncells = new_ncells;
+#ifdef _OPENMP
+      }
+#pragma omp barrier
+#endif
+      mesh->set_bounds(ncells);
+
+#ifdef _OPENMP
+#pragma omp master
+      {
+#endif
+   //cpu_timer_start(&tstart_check);
+      mesh->proc.resize(ncells);
+      if (icount)
+      {  vector<int> index(ncells);
+         mesh->partition_cells(numpe, index, cycle_reorder);
+         state->state_reorder(index);
+         state->memory_reset_ptrs();
+      }
+   //cpu_time_check += cpu_timer_stop(tstart_check);
+#ifdef _OPENMP
+      }
+#pragma omp barrier
+#endif
+
+#ifdef _OPENMP
+      } // end parallel region
+#endif
+      
+   } // End burst loop
+
+   cpu_time_calcs += cpu_timer_stop(tstart_cpu);
+
+   H_sum = state->mass_sum(enhanced_precision_sum);
+
+   int error_status = STATUS_OK;
+
+   if (isnan(H_sum)) {
+      printf("Got a NAN on cycle %d\n",ncycle);
+      error_status = STATUS_NAN;
+   }
+
+   double percent_mass_diff = fabs(H_sum - H_sum_initial)/H_sum_initial * 100.0;
+   if (percent_mass_diff >= upper_mass_diff_percentage) {
+      printf("Mass difference outside of acceptable range on cycle %d percent_mass_diff %lg upper limit %lg\n",ncycle,percent_mass_diff, upper_mass_diff_percentage);
+      error_status = STATUS_MASS_LOSS;
+   }
+
+   if (error_status != STATUS_OK){
+      if (crux_type != CRUX_NONE) {
+
+         rollback_attempt++;
+         if (rollback_attempt > num_of_rollback_states) {
+            printf("Can not recover from error from back up files. Killing program...\n");
+            total_program_time = cpu_timer_stop(total_exec);
+            FILE *fp = fopen(total_sim_time_log,"w");
+            fprintf(fp,"The total execution time of the program before failure was %g seconds\n", total_program_time);
+            fclose(fp);
+            state->print_failure_log(ncycle, simTime, H_sum_initial, H_sum, percent_mass_diff, true);
+            exit(-1);
+         }
+
+         if (graphic_outputInterval <= niter){
+            mesh->calc_spatial_coordinates(0);
+            set_graphics_mysize(ncells);
+            set_graphics_viewmode(view_mode);
+            set_graphics_cell_coordinates(&mesh->x[0], &mesh->dx[0], &mesh->y[0], &mesh->dy[0]);
+            set_graphics_cell_data(&state->H[0]);
+            set_graphics_cell_proc(&mesh->proc[0]);
+            write_graphics_info(ncycle/graphic_outputInterval,ncycle,simTime,1,rollback_attempt);
+         }
+
+         if((ncycle - (rollback_attempt)*checkpoint_outputInterval) < 0){
+            printf("Rolling simulation back to to ncycle 0\n");
+         }
+         else{
+            printf("Rolling simulation back to to ncycle %d\n", ncycle - (rollback_attempt*checkpoint_outputInterval));
+         }
+
+         state->print_rollback_log(ncycle, simTime, H_sum_initial, H_sum, percent_mass_diff, rollback_attempt, num_of_rollback_states, error_status);
+
+         int rollback_num = crux->get_rollback_number();
+
+         restore_crux_data_bootstrap(crux, NULL, rollback_num);
+         mesh->terminate();
+         state->terminate();
+         restore_crux_data(crux);
+
+
+      } else {
+         printf("failure.log has been created\n");
+         state->print_failure_log(ncycle, simTime, H_sum_initial, H_sum, percent_mass_diff, true);
+         exit(-1);
+      }
+   }
+
+   if (mype == 0 && ncycle % outputInterval == 0) {
+      printf("Iteration %3d timestep %lf Sim Time %lf cells %ld Mass Sum %14.12lg Mass Change %12.6lg\n",
+         ncycle, deltaT, simTime, ncells, H_sum, H_sum - H_sum_initial);
+   }
+
+   if (ncycle == next_cp_cycle) store_crux_data(crux, ncycle); 
+
+   cpu_timer_start(&tstart_cpu);
+
+   if(do_display_graphics || ncycle == next_graphics_cycle ||
+      (ncycle >= niter && graphic_outputInterval < niter) ){
+
+      mesh->calc_spatial_coordinates(0);
+   }
+
+   if(ncycle == next_graphics_cycle){
+      set_graphics_mysize(ncells);
+      set_graphics_viewmode(view_mode);
+      set_graphics_cell_coordinates(&mesh->x[0], &mesh->dx[0], &mesh->y[0], &mesh->dy[0]);
+      set_graphics_cell_data(&state->H[0]);
+      set_graphics_cell_proc(&mesh->proc[0]);
+
+      write_graphics_info(ncycle/graphic_outputInterval,ncycle,simTime,0,0);
+      next_graphics_cycle += graphic_outputInterval;
+   }
+
+#ifdef HAVE_GRAPHICS
+   if(ncycle % outputInterval == 0){
+      if(ncycle != next_graphics_cycle){
+         set_display_mysize(ncells);
+         set_display_viewmode(view_mode);
+         set_display_cell_coordinates(&mesh->x[0], &mesh->dx[0], &mesh->y[0], &mesh->dy[0]);
+         set_display_cell_data(&state->H[0]);
+         set_display_cell_proc(NULL);
+      }
+      set_display_circle_radius(circle_radius);
+      draw_scene();
+   }
+
+#endif
+
+   cpu_time_graphics += cpu_timer_stop(tstart_cpu);
+
+   //  Output final results and timing information.
+   if (ncycle >= niter) {
+      //free_display();
+      
+      if(graphic_outputInterval < niter){
+         cpu_timer_start(&tstart_cpu);
+
+#ifdef HAVE_GRAPHICS
+         set_display_viewmode(view_mode);
+         set_display_mysize(ncells);
+         set_display_cell_coordinates(&mesh->x[0], &mesh->dx[0], &mesh->y[0], &mesh->dy[0]);
+         set_display_cell_data(&state->H[0]);
+         set_display_cell_proc(NULL);
+#endif
+
+         if (mype == 0) {
+            write_graphics_info(ncycle/graphic_outputInterval,ncycle,simTime,0,0);
+         }
+         next_graphics_cycle += graphic_outputInterval;
+
+         cpu_time_graphics += cpu_timer_stop(tstart_cpu);
+      }
+
+      //  Get overall program timing.
+      double elapsed_time = cpu_timer_stop(tstart);
+      
+      long long mem_used = memstats_memused();
+      #ifdef MEMORY
+      if (mem_used > 0) {
+         printf("Memory used      %lld kB\n",mem_used);
+         printf("Memory peak      %lld kB\n",memstats_mempeak());
+         printf("Memory free      %lld kB\n",memstats_memfree());
+         printf("Memory available %lld kB\n",memstats_memtotal());
+      }
+      #endif
+      state->output_timing_info(do_cpu_calc, do_gpu_calc, elapsed_time);
+      #ifdef TIMING
+      mesh->parallel_output("CPU:  calc incl part meas     time was",cpu_time_calcs,    0, "s");
+      mesh->parallel_output("CPU:  calculation only        time was",cpu_time_calcs-cpu_time_partmeas,    0, "s");
+      mesh->parallel_output("CPU:  partition measure       time was",cpu_time_partmeas, 0, "s");
+      mesh->parallel_output("CPU:  graphics                time was",cpu_time_graphics, 0, "s");
+      //mesh->parallel_output("CPU:  check                   time was",cpu_time_check,    0, "s");
+      #endif
+
+      mesh->print_partition_measure();
+      mesh->print_calc_neighbor_type();
+      mesh->print_partition_type();
+
+      printf("CPU:  rezone frequency                \t %8.4f\tpercent\n",     (double)mesh->get_cpu_counter(MESH_COUNTER_REZONE)/(double)ncycle*100.0 );
+      printf("CPU:  calc neigh frequency            \t %8.4f\tpercent\n",     (double)mesh->get_cpu_counter(MESH_COUNTER_CALC_NEIGH)/(double)ncycle*100.0 );
+      printf("CPU:  refine_smooth_iter per rezone   \t %8.4f\t\n",            (double)mesh->get_cpu_counter(MESH_COUNTER_REFINE_SMOOTH)/(double)mesh->get_cpu_counter(MESH_COUNTER_REZONE) );
+
+      mesh->terminate();
+      state->terminate();
+
+      terminate_graphics_output();
+
+      delete mesh;
+      delete state;
+      delete crux;
+      delete parse;
+
+      total_program_time = cpu_timer_stop(total_exec);
+      FILE *fp = fopen(total_sim_time_log,"w");
+      fprintf(fp,"The total execution time of the program was %g seconds\n", total_program_time);
+      fclose(fp);
+      exit(0);
+   }  //  Complete final output.
+   
+} // end do_calc
+
+const int CRUX_CLAMR_VERSION = 101;
+const int num_int_vals       = 15;
+const int num_double_vals    =  5;
+
+MallocPlus clamr_bootstrap_memory;
+
+void store_crux_data(Crux *crux, int ncycle)
+{
+   size_t nsize = num_int_vals*sizeof(int) +
+                  num_double_vals*sizeof(double);
+   nsize += state->get_checkpoint_size();
+
+   next_cp_cycle += checkpoint_outputInterval;
+
+   int int_vals[num_int_vals];
+
+   int_vals[ 0] = CRUX_CLAMR_VERSION; // Version number
+   int_vals[ 1] = nx;
+   int_vals[ 2] = ny;
+   int_vals[ 3] = levmx;
+   int_vals[ 4] = ndim;
+   int_vals[ 5] = outputInterval;
+   int_vals[ 6] = enhanced_precision_sum;
+   int_vals[ 7] = niter;
+   int_vals[ 8] = it;
+   int_vals[ 9] = ncycle;
+   int_vals[10] = crux_type;
+   int_vals[11] = graphic_outputInterval;
+   int_vals[12] = checkpoint_outputInterval;
+   int_vals[13] = next_cp_cycle;
+   int_vals[14] = next_graphics_cycle;
+
+   double double_vals[num_double_vals];
+   double_vals[ 0] = circ_radius;
+   double_vals[ 1] = H_sum_initial;
+   double_vals[ 2] = simTime;
+   double_vals[ 3] = deltaT;
+   double_vals[ 4] = upper_mass_diff_percentage;
+
+   clamr_bootstrap_memory.memory_add(int_vals, size_t(num_int_vals), 4, "bootstrap_int_vals", RESTART_DATA);
+   clamr_bootstrap_memory.memory_add(double_vals, size_t(num_double_vals), 8, "bootstrap_double_vals", RESTART_DATA);
+
+   crux->store_begin(nsize, ncycle);
+
+   crux->store_MallocPlus(clamr_bootstrap_memory);
+
+   state->store_checkpoint(crux);
+
+   crux->store_end();
+
+   clamr_bootstrap_memory.memory_remove(int_vals);
+   clamr_bootstrap_memory.memory_remove(double_vals);
+}
+
+void restore_crux_data_bootstrap(Crux *crux, char *restart_file, int rollback_counter)
+{
+   crux->restore_begin(restart_file, rollback_counter);
+
+   int int_vals[num_int_vals];
+
+   double double_vals[num_double_vals];
+
+   clamr_bootstrap_memory.memory_add(int_vals, size_t(num_int_vals), 4, "bootstrap_int_vals", RESTART_DATA);
+   clamr_bootstrap_memory.memory_add(double_vals, size_t(num_double_vals), 8, "bootstrap_double_vals", RESTART_DATA);
+
+   crux->restore_MallocPlus(clamr_bootstrap_memory);
+
+   if (int_vals[ 0] != CRUX_CLAMR_VERSION) {
+      printf("CRUX version mismatch for clamr data, version on file is %d, version in code is %d\n",
+         int_vals[0], CRUX_CLAMR_VERSION);
+      exit(0);
+   }
+
+   nx                        = int_vals[ 1];
+   ny                        = int_vals[ 2];
+   levmx                     = int_vals[ 3];
+   ndim                      = int_vals[ 4];
+   outputInterval            = int_vals[ 5];
+   enhanced_precision_sum    = int_vals[ 6];
+   niter                     = int_vals[ 7];
+   it                        = int_vals[ 8];
+   ncycle                    = int_vals[ 9];
+   crux_type                 = int_vals[10];
+   graphic_outputInterval    = int_vals[11];
+   checkpoint_outputInterval = int_vals[12];
+   next_cp_cycle             = int_vals[13];
+   next_graphics_cycle       = int_vals[14];
+
+   circ_radius                = double_vals[ 0];
+   H_sum_initial              = double_vals[ 1];
+   simTime                    = double_vals[ 2];
+   deltaT                     = double_vals[ 3];
+   upper_mass_diff_percentage = double_vals[ 4];
+
+   // need to reset crux type, because initialize to none
+   // before checkpoint is read
+   crux->set_crux_type(crux_type);
+
+   clamr_bootstrap_memory.memory_remove(int_vals);
+   clamr_bootstrap_memory.memory_remove(double_vals);
+
+#ifdef DEBUG_RESTORE_VALS
+   if (DEBUG_RESTORE_VALS) {
+      const char *int_vals_descriptor[num_int_vals] = {
+         "CRUX_CLAMR_VERSION",
+         "nx",
+         "ny",
+         "levmx",
+         "ndim",
+         "outputInterval",
+         "enhanced_precision_sum",
+         "niter",
+         "it",
+         "ncycle",
+         "crux_type",
+         "graphic_outputInterval",
+         "checkpoint_outputInterval",
+         "next_cp_cycle",
+         "next_graphics_cycle"
+      };
+      printf("\n");
+      printf("       === Restored bootstrap int_vals ===\n");
+      for (int i = 0; i < num_int_vals; i++){
+         printf("       %-30s %d\n",int_vals_descriptor[i], int_vals[i]);
+      }
+      printf("       === Restored bootstrap int_vals ===\n");
+      printf("\n");
+   }
+#endif
+
+#ifdef DEBUG_RESTORE_VALS
+   if (DEBUG_RESTORE_VALS) {
+      const char *double_vals_descriptor[num_double_vals] = {
+         "circ_radius",
+         "H_sum_initial",
+         "simTime",
+         "deltaT",
+         "upper_mass_diff_percentage"
+      };
+      printf("\n");
+      printf("       === Restored bootstrap double_vals ===\n");
+      for (int i = 0; i < num_double_vals; i++){
+         printf("       %-30s %lg\n",double_vals_descriptor[i], double_vals[i]);
+      }
+      printf("       === Restored bootstrap double_vals ===\n");
+      printf("\n");
+   }
+#endif
+}
+
+void restore_crux_data(Crux *crux)
+{
+   state->restore_checkpoint(crux);
+
+   crux->restore_end();
+}
+
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/crux.cpp?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.cpp Mon Sep  4 07:25:36 2017
@@ -0,0 +1,1054 @@
+/*
+ *  Copyright (c) 2014, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  
+ *  Authors: Brian Atkinson          bwa at g.clemson.edu
+             Bob Robey        XCP-2  brobey at lanl.gov
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <algorithm>
+#include <assert.h>
+#include "PowerParser.hh"
+
+#include "crux.h"
+#include "timer.h"
+#include "fmemopen.h"
+
+#ifdef HAVE_HDF5
+#include "hdf5.h"
+#endif
+#ifdef HAVE_MPI
+#include "mpi.h"
+#endif
+
+const bool CRUX_TIMING = true;
+bool do_crux_timing = false;
+
+#define RESTORE_NONE     0
+#define RESTORE_RESTART  1
+#define RESTORE_ROLLBACK 2
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+#define DEBUG_RESTORE_VALS 1
+
+using namespace std;
+using PP::PowerParser;
+// Pointers to the various objects.
+PowerParser *parse;
+
+char checkpoint_directory[] = "checkpoint_output";
+int cp_num, rs_num;
+int *backup;
+void **crux_data;
+size_t *crux_data_size;
+#ifdef HAVE_HDF5
+bool USE_HDF5 = true; //MSB
+hid_t h5_fid;
+herr_t h5err;
+bool is_restart = false;
+
+hid_t create_hdf5_parallel_file_plist();
+
+void map_name_to_hdf5 (const char*, int, char*, char*);
+
+void access_named_hdf5_values (const char *name, int name_size,
+                              hsize_t rank, hsize_t *cur_size, 
+                              void *values, hid_t datatype,
+                              bool store);
+#endif
+
+
+FILE *crux_time_fp;
+struct timeval tcheckpoint_time;
+struct timeval trestore_time;
+int checkpoint_timing_count = 0;
+float checkpoint_timing_sum = 0.0f;
+float checkpoint_timing_size = 0.0f;
+int rollback_attempt = 0;
+FILE *store_fp, *restore_fp;
+#ifdef HAVE_MPI
+static MPI_File mpi_store_fp, mpi_restore_fp;
+#endif
+static int mype = 0, npes = 1;
+
+Crux::Crux(int crux_type_in, int num_of_rollback_states_in, bool restart)
+{
+#ifdef HAVE_MPI
+   MPI_Comm_rank(MPI_COMM_WORLD,&mype);
+   MPI_Comm_size(MPI_COMM_WORLD,&npes);
+#endif
+
+   num_of_rollback_states = num_of_rollback_states_in;
+   crux_type = crux_type_in;
+   checkpoint_counter = 0;
+
+   if (crux_type != CRUX_NONE || restart){
+      do_crux_timing = CRUX_TIMING;
+      struct stat stat_descriptor;
+      if (stat(checkpoint_directory,&stat_descriptor) == -1){
+        mkdir(checkpoint_directory,0777);
+      }
+   }
+
+   crux_data = (void **)malloc(num_of_rollback_states*sizeof(void *));
+   for (int i = 0; i < num_of_rollback_states; i++){
+      crux_data[i] = NULL;
+   }
+   crux_data_size = (size_t *)malloc(num_of_rollback_states*sizeof(size_t));
+
+
+   if (do_crux_timing){
+      char checkpointtimelog[60];
+      sprintf(checkpointtimelog,"%s/crux_timing.log",checkpoint_directory);
+      crux_time_fp = fopen(checkpointtimelog,"w");
+   }
+}
+
+Crux::~Crux()
+{
+   for (int i = 0; i < num_of_rollback_states; i++){
+      free(crux_data[i]);
+   }
+   free(crux_data);
+   free(crux_data_size);
+
+   if (do_crux_timing){
+      if (checkpoint_timing_count > 0) {
+         printf("CRUX checkpointing time averaged %f msec, bandwidth %f Mbytes/sec\n",
+                checkpoint_timing_sum/(float)checkpoint_timing_count*1.0e3,
+                checkpoint_timing_size/checkpoint_timing_sum*1.0e-6);
+
+         fprintf(crux_time_fp,"CRUX checkpointing time averaged %f msec, bandwidth %f Mbytes/sec\n",
+                checkpoint_timing_sum/(float)checkpoint_timing_count*1.0e3,
+                checkpoint_timing_size/checkpoint_timing_sum*1.0e-6);
+
+      fclose(crux_time_fp);
+      }
+   }
+}
+
+void Crux::store_MallocPlus(MallocPlus memory){
+
+    malloc_plus_memory_entry *memory_item;
+
+    for (memory_item = memory.memory_entry_by_name_begin(); 
+	 memory_item != memory.memory_entry_by_name_end();
+	 memory_item = memory.memory_entry_by_name_next() ){
+
+        void *mem_ptr = memory_item->mem_ptr;
+        if ((memory_item->mem_flags & RESTART_DATA) == 0) continue;
+
+
+
+        if (DEBUG) {
+            printf("MallocPlus ptr  %p: name %10s ptr %p dims %lu nelem (",
+                    mem_ptr,memory_item->mem_name,memory_item->mem_ptr,memory_item->mem_ndims);
+
+            char nelemstring[80];
+            char *str_ptr = nelemstring;
+            str_ptr += sprintf(str_ptr,"%lu", memory_item->mem_nelem[0]);
+            for (uint i = 1; i < memory_item->mem_ndims; i++){
+                str_ptr += sprintf(str_ptr,", %lu", memory_item->mem_nelem[i]);
+            }
+            printf("%12s",nelemstring);
+
+            printf(") elsize %lu flags %d capacity %lu\n",
+                    memory_item->mem_elsize,memory_item->mem_flags,memory_item->mem_capacity);
+        }
+
+#ifdef HAVE_HDF5
+        if(USE_HDF5) {
+            access_named_hdf5_values (memory_item->mem_name, 
+                              strlen (memory_item->mem_name),
+                              (hsize_t) memory_item->mem_ndims, 
+                              (hsize_t *) memory_item->mem_nelem, 
+                              mem_ptr, 
+                              memory_item->mem_elsize == 4 ? 
+                              H5T_NATIVE_INT : H5T_NATIVE_DOUBLE,
+                              true);
+        } else {
+#endif
+            int num_elements = 1;
+            for (uint i = 0; i < memory_item->mem_ndims; i++){
+                num_elements *= memory_item->mem_nelem[i];
+            }
+            store_field_header(memory_item->mem_name,30);
+            if (memory_item->mem_flags & REPLICATED_DATA) { 
+                if (memory_item->mem_elsize == 4){
+                    store_replicated_int_array((int *)mem_ptr, num_elements);
+                } else {
+                    store_replicated_double_array((double *)mem_ptr, num_elements);
+                }
+            } else {
+                if (memory_item->mem_elsize == 4){
+                    store_int_array((int *)mem_ptr, num_elements);
+                } else {
+                    store_double_array((double *)mem_ptr, num_elements);
+                }
+            }
+        }
+#ifdef HAVE_HDF5   
+    }
+#endif   
+}
+
+void Crux::store_begin(size_t nsize, int ncycle)
+{
+
+   int mype = 0;
+
+#ifdef HAVE_MPI
+   MPI_Comm_rank(MPI_COMM_WORLD,&mype);
+#endif
+
+   cp_num = checkpoint_counter % num_of_rollback_states;
+   cpu_timer_start(&tcheckpoint_time);
+
+   if(crux_type == CRUX_IN_MEMORY) {
+      if (crux_data[cp_num] != NULL) free(crux_data[cp_num]);
+      crux_data[cp_num] = (int *)malloc(nsize);
+      crux_data_size[cp_num] = nsize;
+      store_fp = fmemopen(crux_data[cp_num], nsize, "w");
+   } else if(crux_type == CRUX_DISK) {
+      char backup_file_w_dir[60];
+      char backup_file[40];
+#ifdef HAVE_HDF5
+      if(USE_HDF5) {
+
+	hid_t plist_id = create_hdf5_parallel_file_plist();
+	
+#ifdef HDF5_FF
+	if(is_restart)
+	  sprintf(backup_file_w_dir,"rbackup%05d.h5",ncycle);
+	else
+	  sprintf(backup_file_w_dir,"backup%05d.h5",ncycle);
+#else
+          sprintf(backup_file_w_dir,"%s/backup%05d.h5",checkpoint_directory,ncycle);
+          sprintf(backup_file,"backup%05d.h5",ncycle);
+#endif
+          if(!(h5_fid = H5Fcreate(backup_file_w_dir, H5F_ACC_TRUNC, H5P_DEFAULT, plist_id))) {
+              printf("HDF5: Could not write HDF5 %s at iteration %d\n",backup_file_w_dir,ncycle);
+          }
+          H5Pclose(plist_id);
+      } else {
+#endif
+          sprintf(backup_file_w_dir,"%s/backup%05d.crx",checkpoint_directory,ncycle);
+          sprintf(backup_file,"backup%05d.crx",ncycle);
+#ifdef HAVE_MPI
+          int iret = MPI_File_open(MPI_COMM_WORLD, backup_file_w_dir, MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &mpi_store_fp);
+          if(iret != MPI_SUCCESS) {
+              printf("Could not write %s at iteration %d\n",backup_file_w_dir,ncycle);
+          }
+#else
+          store_fp = fopen(backup_file_w_dir,"w");
+          if(!store_fp){
+              printf("Could not write %s at iteration %d\n",backup_file_w_dir,ncycle);
+          }
+#endif
+          if (mype == 0) {
+              char symlink_file[60];
+              sprintf(symlink_file,"%s/backup%1d.crx",checkpoint_directory,cp_num);
+              unlink(symlink_file);
+              symlink(backup_file, symlink_file);
+              //      int ireturn = symlink(backup_file, symlink_file);
+              //      if (ireturn == -1) {
+              //         printf("Warning: error returned with symlink call for file %s and symlink %s\n",
+              //                backup_file,symlink_file);
+              //      }
+          }
+      }
+#ifdef HAVE_HDF5
+    }
+#endif    
+   if (do_crux_timing) {
+      checkpoint_timing_size += nsize;
+   }
+}
+
+void Crux::store_field_header(const char *name, int name_size){
+#ifdef HAVE_MPI
+   assert(name != NULL);
+   MPI_Status status;
+   MPI_File_write_shared(mpi_store_fp, (void *)name, name_size, MPI_CHAR, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_CHAR, &count);
+   printf("%d:Wrote %d characters at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   assert(name != NULL && store_fp != NULL);
+   fwrite(name,sizeof(char),name_size,store_fp);
+#endif
+}
+
+#ifdef HAVE_HDF5
+hid_t create_hdf5_parallel_file_plist()
+{
+    hid_t plist_id = H5P_DEFAULT;
+
+    if( (plist_id = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+        printf("HDF5: Could not create property list \n");
+
+#ifdef HAVE_MPI
+    if( H5Pset_libver_bounds(plist_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+        printf("HDF5: Could set libver bounds \n");
+# ifdef HDF5_FF
+    H5Pset_fapl_daosm(plist_id, MPI_COMM_WORLD, MPI_INFO_NULL);
+    if(H5Pset_all_coll_metadata_ops(plist_id, true) < 0)
+        printf("HDF5: Could not set collective metadata \n");
+# else
+    H5Pset_fapl_mpio(plist_id, MPI_COMM_WORLD, MPI_INFO_NULL);
+#endif
+#endif
+    return plist_id;
+}
+
+void map_name_to_hdf5 (const char *name, int name_size,
+                        char *group,
+                        char *label)
+{
+    static const char * default_group = "default";
+    int i, j;
+    group[0] = '/';
+    for (i=0; i<name_size; i++)
+        if (name[i] == '_') break;
+    if (i < name_size) {
+        for (j=0; j<i; j++)
+            group[1+j] = name[j];
+        ++i;
+    } else {
+        for (j=0; default_group[j]; j++)
+            group[1+j] = default_group[j];
+        i=0;
+    }    
+    group[1+j] = '\0';
+    for (j=i; name[j]; j++)
+        label[j-i] = name[j];
+    label[j-i] = '\0';    
+}
+
+void access_named_hdf5_values (const char *name, int name_size,
+                              hsize_t rank, hsize_t *sizes, 
+                              void *values, hid_t datatype,
+                              bool store)
+{
+    size_t length = 0, count = 1, offset = 0;
+    char groupname[512], fieldname[512];
+    hid_t hid_group, hid_space, hid_mem, hid_dataset, hid_plist = H5P_DEFAULT;
+
+    map_name_to_hdf5(name, name_size, groupname, fieldname);
+    for (hsize_t i=0; i<rank; i++)
+        count *= sizes[i];
+#ifdef HAVE_MPI
+    hid_plist = H5Pcreate(H5P_DATASET_XFER);
+#   ifndef HDF5_FF
+    H5Pset_dxpl_mpio(hid_plist, H5FD_MPIO_COLLECTIVE);
+#   endif
+    if (npes > 1) {
+        size_t *counts = new size_t[npes];
+        MPI_Allgather (&count, sizeof(count), MPI_BYTE,
+                       counts, sizeof *counts, MPI_BYTE,
+                       MPI_COMM_WORLD);
+        for (int i=0; i<npes; i++) {
+            if (i == mype)
+                offset = length;
+            length += counts[i];
+        }
+        delete[] counts;
+    } else {
+#endif
+        length = count;
+#ifdef HAVE_MPI    
+    }
+#endif
+    
+#ifndef HDF5_FF
+    if (!store || H5Lexists(h5_fid, groupname, H5P_DEFAULT))
+      hid_group = H5Gopen (h5_fid, groupname, H5P_DEFAULT);
+    else
+      hid_group = H5Gcreate (h5_fid, groupname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+#else
+    int mpi_rank;
+    MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
+
+    if(store) {
+	    hbool_t ret;
+
+	    if(mpi_rank == 0)
+		    ret = H5Lexists(h5_fid, groupname, H5P_DEFAULT);
+
+	    MPI_Bcast(&ret, sizeof(hbool_t), MPI_BYTE, 0, MPI_COMM_WORLD);
+	    if(!ret)
+		    hid_group = H5Gcreate (h5_fid, groupname, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+	    else
+		    hid_group = H5Gopen (h5_fid, groupname, H5P_DEFAULT);
+    }	       
+    if (!store) {
+	    hid_group = H5Gopen (h5_fid, groupname, H5P_DEFAULT);
+    }
+#endif
+    if (hid_group == -1) {
+      fprintf(stderr, "Unable to create group: %30s\n", groupname);
+      exit(1);
+    }
+    hid_mem = H5Screate_simple (1, (hsize_t *) &count, NULL);
+    hid_space = H5Screate_simple (1, (hsize_t *) &length, NULL);
+    if (hid_space == -1) {
+        fprintf(stderr, "Unable to create space\n");
+        exit(1);
+    }
+    if (store) {
+        hid_dataset = H5Dcreate (hid_group, fieldname, datatype, hid_space,
+                             H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+    } else
+      hid_dataset = H5Dopen (hid_group, fieldname, H5P_DEFAULT);
+
+    if(hid_dataset == -1) {
+	    fprintf(stderr, "Unable to access dataset %s\n", fieldname);
+	    exit(1);
+    }
+
+    if (!hid_dataset) {
+        fprintf(stderr, "Unable to create/open dataset: %30s\n", fieldname);
+        exit(1);
+    }
+
+    herr_t status;
+    status = H5Sselect_hyperslab (hid_space, H5S_SELECT_SET,
+                                 (hsize_t *) &offset, NULL,
+                                 (hsize_t *) &count, NULL);
+    if(status < 0) {
+        fprintf(stderr, "Unable to select correct hyperslab\n");
+        exit(1);
+    }
+    if (store)
+        status = H5Dwrite (hid_dataset, datatype, hid_mem, hid_space, hid_plist, values);
+    else
+      status = H5Dread (hid_dataset, datatype, hid_mem, hid_space, hid_plist, values);
+
+    H5Dclose (hid_dataset);
+    H5Gclose (hid_group);
+    H5Sclose (hid_space);
+    H5Sclose (hid_mem);
+#ifdef HAVE_MPI
+    H5Pclose (hid_plist);
+#endif
+}
+#endif
+
+void Crux::store_named_ints(const char *name, int name_size, int *int_vals, size_t nelem)
+{
+#ifdef HAVE_HDF5
+    if (USE_HDF5) {
+        access_named_hdf5_values (name, name_size, 1, (hsize_t *) &nelem, 
+                                 int_vals, H5T_NATIVE_INT, true);
+
+    } else {
+#endif
+        store_field_header (name, name_size);
+        store_int_array (int_vals, nelem);
+#ifdef HAVE_HDF5
+    }
+#endif    
+}
+
+void Crux::restore_named_ints(const char *name, int name_size, int *int_vals, size_t nelem)
+{
+#ifdef HAVE_HDF5
+    if (USE_HDF5) {
+        access_named_hdf5_values (name, name_size, 1, (hsize_t *) &nelem, 
+                                 int_vals, H5T_NATIVE_INT, false);
+
+    } else {
+#endif
+        char fname[512];
+        restore_field_header (fname, name_size);
+        restore_int_array (int_vals, nelem);
+#ifdef HAVE_HDF5
+    }
+#endif    
+}
+
+void Crux::store_bools(bool *bool_vals, size_t nelem)
+{
+   assert(bool_vals != NULL && store_fp != NULL);
+   fwrite(bool_vals,sizeof(bool),nelem,store_fp);
+}
+
+void Crux::store_ints(int *int_vals, size_t nelem)
+{
+   assert(int_vals != NULL && store_fp != NULL);
+   fwrite(int_vals,sizeof(int),nelem,store_fp);
+}
+
+void Crux::store_longs(long long *long_vals, size_t nelem)
+{
+   assert(long_vals != NULL && store_fp != NULL);
+   fwrite(long_vals,sizeof(long long),nelem,store_fp);
+}
+
+void Crux::store_sizets(size_t *size_t_vals, size_t nelem)
+{
+   assert(size_t_vals != NULL && store_fp != NULL);
+   fwrite(size_t_vals,sizeof(size_t),nelem,store_fp);
+}
+
+void Crux::store_doubles(double *double_vals, size_t nelem)
+{
+   assert(double_vals != NULL && store_fp != NULL);
+   fwrite(double_vals,sizeof(double),nelem,store_fp);
+}
+
+void Crux::store_int_array(int *int_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   assert(int_array != NULL);
+   MPI_Status status;
+   MPI_File_write_shared(mpi_store_fp, int_array, (int)nelem, MPI_INT, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_INT, &count);
+   printf("%d:Wrote %d integers at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   assert(int_array != NULL && store_fp != NULL);
+   fwrite(int_array,sizeof(int),nelem,store_fp);
+#endif
+}
+
+void Crux::store_long_array(long long *long_array, size_t nelem)
+{
+   assert(long_array != NULL && store_fp != NULL);
+   fwrite(long_array,sizeof(long long),nelem,store_fp);
+}
+
+void Crux::store_float_array(float *float_array, size_t nelem)
+{
+   assert(float_array != NULL && store_fp != NULL);
+   fwrite(float_array,sizeof(float),nelem,store_fp);
+}
+
+void Crux::store_double_array(double *double_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   assert(double_array != NULL);
+   MPI_Status status;
+   MPI_File_write_shared(mpi_store_fp, double_array, (int)nelem, MPI_DOUBLE, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_DOUBLE, &count);
+   printf("%d:Wrote %d doubles at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   assert(double_array != NULL && store_fp != NULL);
+   fwrite(double_array,sizeof(double),nelem,store_fp);
+#endif
+}
+
+void Crux::store_replicated_int_array(int *int_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   assert(int_array != NULL);
+   MPI_Status status;
+   MPI_File_write_shared(mpi_store_fp, int_array, (int)nelem, MPI_INT, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_INT, &count);
+   printf("%d:Wrote %d integers at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   assert(int_array != NULL && store_fp != NULL);
+   fwrite(int_array,sizeof(int),nelem,store_fp);
+#endif
+}
+
+void Crux::store_replicated_double_array(double *double_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   assert(double_array != NULL);
+   MPI_Status status;
+   MPI_File_write_shared(mpi_store_fp, double_array, (int)nelem, MPI_DOUBLE, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_DOUBLE, &count);
+   printf("%d:Wrote %d doubles at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   assert(double_array != NULL && store_fp != NULL);
+   fwrite(double_array,sizeof(double),nelem,store_fp);
+#endif
+}
+
+#ifdef HAVE_MPI
+void Crux::store_distributed_int_array(int *int_array, size_t nelem, int flags)
+{
+   assert(int_array != NULL);
+   //MPI_Datatype datatype = get_crux_datatype(DISTRIBUTED_INT_DATA);
+   MPI_Status status;
+   //MPI_File_write_shared(mpi_store_fp, int_array, nelem, MPI_INT, &status);
+   printf("writing crux data type 8\n");
+   //MPI_File_write_shared(mpi_store_fp, int_array, 1, crux_datatype[8], &status);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_INT, &count);
+   printf("%d:Wrote %d integers at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+}
+void Crux::store_distributed_double_array(double *double_array, size_t nelem, int flags)
+{
+   assert(double_array != NULL);
+   //MPI_Datatype datatype = get_crux_datatype(DISTRIBUTED_DOUBLE_DATA);
+   MPI_Status status;
+   //MPI_File_write_shared(mpi_store_fp, double_array, nelem, datatype, &status);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_DOUBLE_PRECISION, &count);
+   printf("%d:Wrote %d doubles at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+}
+#endif
+
+void Crux::store_end(void)
+{
+#ifdef HAVE_HDF5
+   if(USE_HDF5) {
+    if(H5Fclose(h5_fid) != 0)
+       printf("HDF5: Could not close HDF5 file \n");
+   } else {
+#endif
+#ifdef HAVE_MPI
+       MPI_File_close(&mpi_store_fp);
+#else
+       assert(store_fp != NULL);
+       fclose(store_fp);
+#endif
+#ifdef HAVE_HDF5
+    }
+#endif    
+
+   double checkpoint_total_time = cpu_timer_stop(tcheckpoint_time);
+
+   if (do_crux_timing){
+      fprintf(crux_time_fp, "Total time for checkpointing was %g seconds\n", checkpoint_total_time);
+      checkpoint_timing_count++;
+      checkpoint_timing_sum += checkpoint_total_time;
+   }
+
+   checkpoint_counter++;
+}
+
+int restore_type = RESTORE_NONE;
+
+void Crux::restore_MallocPlus(MallocPlus memory){
+    char test_name[34];
+    malloc_plus_memory_entry *memory_item;
+    for (memory_item = memory.memory_entry_by_name_begin(); 
+	    memory_item != memory.memory_entry_by_name_end();
+	    memory_item = memory.memory_entry_by_name_next() ){
+        void *mem_ptr = memory_item->mem_ptr;
+        if ((memory_item->mem_flags & RESTART_DATA) == 0) continue;
+
+        if (DEBUG) {
+            printf("MallocPlus ptr  %p: name %10s ptr %p dims %lu nelem (",
+                    mem_ptr,memory_item->mem_name,memory_item->mem_ptr,memory_item->mem_ndims);
+
+            char nelemstring[80];
+            char *str_ptr = nelemstring;
+            str_ptr += sprintf(str_ptr,"%lu", memory_item->mem_nelem[0]);
+            for (uint i = 1; i < memory_item->mem_ndims; i++){
+                str_ptr += sprintf(str_ptr,", %lu", memory_item->mem_nelem[i]);
+            }
+            printf("%12s",nelemstring);
+
+            printf(") elsize %lu flags %d capacity %lu\n",
+                    memory_item->mem_elsize,memory_item->mem_flags,memory_item->mem_capacity);
+        }
+#ifdef HAVE_HDF5
+        if(USE_HDF5) {
+            access_named_hdf5_values (memory_item->mem_name, 
+                    strlen (memory_item->mem_name),
+                    (hsize_t) memory_item->mem_ndims, 
+                    (hsize_t *) memory_item->mem_nelem, 
+                    mem_ptr, 
+                    memory_item->mem_elsize == 4 ? 
+                    H5T_NATIVE_INT : H5T_NATIVE_DOUBLE, false);
+        } else {
+#endif
+            int num_elements = 1;
+            for (uint i = 0; i < memory_item->mem_ndims; i++){
+                num_elements *= memory_item->mem_nelem[i];
+            }
+            restore_field_header(test_name,30);
+            if (strcmp(test_name,memory_item->mem_name) != 0) {
+                printf("ERROR in restore checkpoint for %s %s\n",test_name,memory_item->mem_name);
+#ifdef HAVE_MPI
+                MPI_Finalize();
+#endif
+                exit(-1);
+            }
+            if (memory_item->mem_flags & REPLICATED_DATA) { 
+                if (memory_item->mem_elsize == 4){
+                    restore_replicated_int_array((int *)mem_ptr, num_elements);
+                } else {
+                    restore_replicated_double_array((double *)mem_ptr, num_elements);
+                }
+            } else {
+                if (memory_item->mem_elsize == 4){
+                    restore_int_array((int *)mem_ptr, num_elements);
+                } else {
+                    restore_double_array((double *)mem_ptr, num_elements);
+                }
+            }
+        }
+#ifdef HAVE_HDF5
+    }
+#endif    
+}
+
+void Crux::restore_begin(char *restart_file, int rollback_counter)
+{
+    rs_num = rollback_counter % num_of_rollback_states;
+
+    cpu_timer_start(&trestore_time);
+
+    if (restart_file != NULL){
+        if (mype == 0) {
+            printf("\n  ================================================================\n");
+            printf(  "  Restoring state from disk file %s\n",restart_file);
+            printf(  "  ================================================================\n\n");
+        }
+#ifdef HAVE_HDF5
+	is_restart = true;
+        if (USE_HDF5) {
+            hid_t plist_id = create_hdf5_parallel_file_plist();
+
+            if(!(h5_fid = H5Fopen(restart_file, H5F_ACC_RDWR, plist_id)))
+                printf("HDF5: Could not restart from HDF5 file: %s\n", restart_file);
+            H5Pclose(plist_id);
+        } else {
+#endif
+#ifdef HAVE_MPI
+            int iret = MPI_File_open(MPI_COMM_WORLD, restart_file, MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN, MPI_INFO_NULL, &mpi_restore_fp);
+            if(iret != MPI_SUCCESS){
+                //printf("Could not write %s at iteration %d\n",restart_file,crux_int_vals[8]);
+                printf("Could not open restart file %s\n",restart_file);
+            }
+#else
+            restore_fp = fopen(restart_file,"r");
+            if(!restore_fp){
+                //printf("Could not write %s at iteration %d\n",restart_file,crux_int_vals[8]);
+                printf("Could not open restart file %s\n",restart_file);
+            }
+#endif
+#ifdef HAVE_HDF5
+        }
+#endif    
+        restore_type = RESTORE_RESTART;
+    } else if(crux_type == CRUX_IN_MEMORY){
+        printf("Restoring state from memory rollback number %d rollback_counter %d\n",rs_num,rollback_counter);
+        restore_fp = fmemopen(crux_data[rs_num], crux_data_size[rs_num], "r");
+        restore_type = RESTORE_ROLLBACK;
+    } else if(crux_type == CRUX_DISK){
+        char backup_file_w_dir[60];
+
+        sprintf(backup_file_w_dir,"%s/backup%d.crx",checkpoint_directory,rs_num);
+        printf("Restoring state from disk file %s rollback_counter %d\n",backup_file_w_dir,rollback_counter);
+        restore_fp = fopen(backup_file_w_dir,"r");
+        if(!restore_fp){
+            //printf("Could not write %s at iteration %d\n",backup_file_w_dir,crux_int_vals[8]);
+            printf("Could not open restore file %s\n",backup_file_w_dir);
+        }
+        restore_type = RESTORE_ROLLBACK;
+    }
+}
+
+void Crux::restore_field_header(char *name, int name_size)
+{
+#ifdef HAVE_MPI
+   assert(name != NULL);
+   MPI_Status status;
+   MPI_File_read_shared(mpi_restore_fp, name, name_size, MPI_CHAR, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_CHAR, &count);
+   printf("%d:Read %d characters at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   int name_read = fread(name,sizeof(char),name_size,restore_fp);
+   if (name_read != name_size){
+      printf("Warning: number of elements read %d is not equal to request %d\n",name_read,name_size);
+   }
+#endif
+}
+
+void Crux::restore_bools(bool *bool_vals, size_t nelem)
+{
+   size_t nelem_read = fread(bool_vals,sizeof(bool),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+}
+
+void Crux::restore_ints(int *int_vals, size_t nelem)
+{
+   size_t nelem_read = fread(int_vals,sizeof(int),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+}
+
+void Crux::restore_longs(long long *long_vals, size_t nelem)
+{
+   size_t nelem_read = fread(long_vals,sizeof(long),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+}
+
+void Crux::restore_sizets(size_t *size_t_vals, size_t nelem)
+{
+   size_t nelem_read = fread(size_t_vals,sizeof(size_t),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+}
+
+void Crux::restore_doubles(double *double_vals, size_t nelem)
+{
+   size_t nelem_read = fread(double_vals,sizeof(double),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+}
+
+int *Crux::restore_int_array(int *int_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   assert(int_array != NULL);
+   MPI_Status status;
+   MPI_File_read_shared(mpi_restore_fp, int_array, (int)nelem, MPI_INT, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_INT, &count);
+   printf("%d:Read %d integers at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   size_t nelem_read = fread(int_array,sizeof(int),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+#endif
+   return(int_array);
+}
+
+long long *Crux::restore_long_array(long long *long_array, size_t nelem)
+{
+   size_t nelem_read = fread(long_array,sizeof(long long),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+   return(long_array);
+}
+
+float *Crux::restore_float_array(float *float_array, size_t nelem)
+{
+   size_t nelem_read = fread(float_array,sizeof(float),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+   return(float_array);
+}
+
+double *Crux::restore_double_array(double *double_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   MPI_Status status;
+   MPI_File_read_shared(mpi_restore_fp, double_array, (int)nelem, MPI_DOUBLE, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_DOUBLE, &count);
+   printf("%d:Read %d doubles at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+  
+#else
+   size_t nelem_read = fread(double_array,sizeof(double),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+#endif
+   return(double_array);
+}
+
+int *Crux::restore_replicated_int_array(int *int_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   assert(int_array != NULL);
+   MPI_Status status;
+   MPI_File_read_shared(mpi_restore_fp, int_array, (int)nelem, MPI_INT, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_INT, &count);
+   printf("%d:Read %d integers at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+#else
+   size_t nelem_read = fread(int_array,sizeof(int),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+#endif
+   return(int_array);
+}
+
+double *Crux::restore_replicated_double_array(double *double_array, size_t nelem)
+{
+#ifdef HAVE_MPI
+   MPI_Status status;
+   MPI_File_read_shared(mpi_restore_fp, double_array, (int)nelem, MPI_DOUBLE, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_DOUBLE, &count);
+   printf("%d:Read %d doubles at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+  
+#else
+   size_t nelem_read = fread(double_array,sizeof(double),nelem,restore_fp);
+   if (nelem_read != nelem){
+      printf("Warning: number of elements read %lu is not equal to request %lu\n",nelem_read,nelem);
+   }
+#endif
+   return(double_array);
+}
+
+#ifdef HAVE_MPI
+int *Crux::restore_distributed_int_array(int *int_array, size_t nelem, int flags)
+{
+   assert(int_array != NULL);
+   //MPI_Datatype datatype = get_crux_datatype(DISTRIBUTED_INT_DATA);
+   MPI_Status status;
+   //MPI_File_read_shared(mpi_restore_fp, int_array, (int)nelem, datatype, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_INT, &count);
+   printf("%d:Read %d integers at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+
+   return(int_array);
+}
+
+double *Crux::restore_distributed_double_array(double *double_array, size_t nelem, int flags)
+{
+   //MPI_Datatype datatype = get_crux_datatype(DISTRIBUTED_DOUBLE_DATA);
+   MPI_Status status;
+   //MPI_File_read_shared(mpi_restore_fp, double_array, (int)nelem, datatype, &status);
+   MPI_Barrier(MPI_COMM_WORLD);
+#ifdef DEBUG_RESTORE_VALS
+   int count;
+   MPI_Get_count(&status, MPI_DOUBLE, &count);
+   printf("%d:Read %d doubles at line %d in file %s\n",mype,count,__LINE__,__FILE__);
+#endif
+  
+   return(double_array);
+}
+#endif
+
+void Crux::restore_end(void)
+{
+   double restore_total_time = cpu_timer_stop(trestore_time);
+
+   if (do_crux_timing){
+      if (restore_type == RESTORE_RESTART) {
+         fprintf(crux_time_fp, "Total time for restore was %g seconds\n", restore_total_time);
+      } else if (restore_type == RESTORE_ROLLBACK){
+         fprintf(crux_time_fp, "Total time for rollback %d was %g seconds\n", rollback_attempt, restore_total_time);
+      }
+   }
+#ifdef HAVE_HDF5
+   if(USE_HDF5) {
+     if(H5Fclose(h5_fid) != 0) {
+       printf("HDF5: Could not close HDF5 file!!\n");
+     }
+   } else {
+#endif
+#ifdef HAVE_MPI
+       MPI_File_close(&mpi_store_fp);
+#else
+       assert(restore_fp != NULL);
+       fclose(restore_fp);
+#endif
+#ifdef HAVE_HDF5
+    }
+#endif
+}
+
+int Crux::get_rollback_number()
+{
+  rollback_attempt++;
+  return(checkpoint_counter % num_of_rollback_states);
+}
+
+void Crux::set_crux_type(int crux_type_in)
+{
+  crux_type = crux_type_in;
+}

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/crux.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/crux.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2014, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  
+ *  Authors: Brian Atkinson          bwa at g.clemson.edu
+             Bob Robey        XCP-2  brobey at lanl.gov
+ */
+
+#ifndef CRUX_H_
+#define CRUX_H_
+
+#include <stdio.h>
+#include "MallocPlus.h"
+
+enum crux_types{
+   CRUX_NONE,
+   CRUX_DISK,
+   CRUX_IN_MEMORY
+};
+
+class Crux
+{
+   int num_of_rollback_states;
+   int crux_type;
+   int checkpoint_counter;
+
+public:
+
+   Crux(int crux_type_in, int num_of_rollback_states_in, bool restart);
+   ~Crux();
+
+   void store_MallocPlus(MallocPlus memory);
+   void store_begin(size_t nsize, int ncycle);
+   void store_field_header(const char *name, int name_size);
+   void store_bools(bool *bool_vals, size_t nelem);
+   void store_ints(int *int_vals, size_t nelem);
+   void store_longs(long long *long_vals, size_t nelem);
+   void store_sizets(size_t *size_t_vals, size_t nelem);
+   void store_doubles(double *double_vals, size_t nelem);
+   void store_int_array(int *int_array, size_t nelem);
+   void store_long_array(long long *long_array, size_t nelem);
+   void store_float_array(float *float_array, size_t nelem);
+   void store_double_array(double *double_array, size_t nelem);
+   void store_replicated_int_array(int *int_array, size_t nelem);
+   void store_replicated_double_array(double *double_array, size_t nelem);
+   void store_named_ints(const char *name, int name_size, int *int_vals, size_t nelem);
+#ifdef HAVE_MPI
+   void store_distributed_int_array(int *int_array, size_t nelem, int flags);
+   void store_distributed_double_array(double *double_array, size_t nelem, int flags);
+#endif
+   void store_end(void);
+
+   void       restore_MallocPlus(MallocPlus memory);
+   void       restore_begin(char *restart_file, int rollback_counter);
+   void       restore_field_header(char *name, int name_size);
+   void       restore_bools(bool *bool_vals, size_t nelem);
+   void       restore_ints(int *int_vals, size_t nelem);
+   void       restore_longs(long long *long_vals, size_t nelem);
+   void       restore_sizets(size_t *size_t_vals, size_t nelem);
+   void       restore_doubles(double *double_vals, size_t nelem);
+   int       *restore_int_array(int *int_array, size_t nsize);
+   long long *restore_long_array(long long *long_array, size_t nsize);
+   float     *restore_float_array(float *float_array, size_t nsize);
+   double    *restore_double_array(double *double_array, size_t nsize);
+   int       *restore_replicated_int_array(int *int_array, size_t nsize);
+   double    *restore_replicated_double_array(double *double_array, size_t nsize);
+   void      restore_named_ints(const char *name, int name_size, int *int_vals, size_t nelem);
+#ifdef HAVE_MPI
+   int       *restore_distributed_int_array(int *int_array, size_t nsize, int flags);
+   double    *restore_distributed_double_array(double *double_array, size_t nsize, int flags);
+#endif
+   void       restore_end(void);
+
+   int get_rollback_number();
+   void set_crux_type(int crux_type_in);
+
+};
+#endif // CRUX_H_

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/fmemopen.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,114 @@
+//
+// Copyright 2011-2014 NimbusKit
+// Originally ported from https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __linux__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+
+struct fmem {
+  size_t pos;
+  size_t size;
+  char *buffer;
+};
+typedef struct fmem fmem_t;
+
+static int readfn(void *handler, char *buf, int size) {
+  fmem_t *mem = handler;
+  size_t available = mem->size - mem->pos;
+  
+  if (size > (int)available) {
+    size = available;
+  }
+  memcpy(buf, mem->buffer + mem->pos, sizeof(char) * size);
+  mem->pos += size;
+  
+  return size;
+}
+
+static int writefn(void *handler, const char *buf, int size) {
+  fmem_t *mem = handler;
+  size_t available = mem->size - mem->pos;
+
+  if (size > (int)available) {
+    size = available;
+  }
+  memcpy(mem->buffer + mem->pos, buf, sizeof(char) * size);
+  mem->pos += size;
+
+  return size;
+}
+
+static fpos_t seekfn(void *handler, fpos_t offset, int whence) {
+  size_t pos;
+  fmem_t *mem = handler;
+
+  switch (whence) {
+    case SEEK_SET: {
+      if (offset >= 0) {
+        pos = (size_t)offset;
+      } else {
+        pos = 0;
+      }
+      break;
+    }
+    case SEEK_CUR: {
+      if (offset >= 0 || (size_t)(-offset) <= mem->pos) {
+        pos = mem->pos + (size_t)offset;
+      } else {
+        pos = 0;
+      }
+      break;
+    }
+    case SEEK_END: pos = mem->size + (size_t)offset; break;
+    default: return -1;
+  }
+
+  if (pos > mem->size) {
+    return -1;
+  }
+
+  mem->pos = pos;
+  return (fpos_t)pos;
+}
+
+static int closefn(void *handler) {
+  free(handler);
+  return 0;
+}
+
+FILE *fmemopen(void *buf, size_t size, const char *mode) {
+  // Just to get rid of compiler warnings
+  if (1 == 2) printf("DEBUG -- mode %s\n", mode);
+
+  // This data is released on fclose.
+  fmem_t* mem = (fmem_t *) malloc(sizeof(fmem_t));
+
+  // Zero-out the structure.
+  memset(mem, 0, sizeof(fmem_t));
+
+  mem->size = size;
+  mem->buffer = buf;
+
+  // funopen's man page: https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/funopen.3.html
+  return funopen(mem, readfn, writefn, seekfn, closefn);
+}
+
+#endif // __linux__
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/fmemopen.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/fmemopen.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,35 @@
+#ifndef FMEMOPEN_H_
+#define FMEMOPEN_H_
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A BSD port of the fmemopen Linux method using funopen.
+ *
+ * man docs for fmemopen:
+ * http://linux.die.net/man/3/fmemopen
+ *
+ * man docs for funopen:
+ * https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/funopen.3.html
+ *
+ * This method is ported from ingenuitas' python-tesseract project.
+ *
+ * You must call fclose on the returned file pointer or memory will be leaked.
+ *
+ * @param buf The data that will be used to back the FILE* methods. Must be at least
+ *            @c size bytes.
+ * @param size The size of the @c buf data.
+ * @param mode The permitted stream operation modes.
+ * @return A pointer that can be used in the fread/fwrite/fseek/fclose family of methods.
+ *         If a failure occurred NULL will be returned.
+ * @ingroup NimbusMemoryMappping
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef FMEMOPEN_H_

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/genmalloc.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,281 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "genmalloc.h"
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+
+double ***gentrimatrix_double_p(int knum, int jnum, int inum, const char *file, const int line);
+int ***gentrimatrix_int_p(int knum, int jnum, int inum, const char *file, const int line);
+
+SLIST_HEAD(slist_genmalloc_memory_head, genmalloc_memory_entry) genmalloc_memory_head = SLIST_HEAD_INITIALIZER(genmalloc_memory_head);
+struct slist_genmalloc_memory_head *genmalloc_memory_headp;
+struct genmalloc_memory_entry {
+   void *mem_ptr;
+   size_t mem_size;
+   SLIST_ENTRY(genmalloc_memory_entry) genmalloc_memory_entries;
+} *genmalloc_memory_item;
+
+void *genvector_p(int inum, size_t elsize, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   void *out;
+   size_t mem_size;
+
+   mem_size = inum*elsize;
+   out      = (void *)calloc((size_t)inum, elsize);
+   genmalloc_memory_add(out, mem_size);
+
+   return (out);
+}
+
+void genvectorfree_p(void *var, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   genmalloc_memory_remove(var);
+}
+
+void **genmatrix_p(int jnum, int inum, size_t elsize, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   void **out;
+   size_t mem_size;
+  
+   mem_size = jnum*sizeof(void *);
+   out      = (void **)malloc(mem_size);
+   genmalloc_memory_add(out, mem_size);
+  
+   mem_size = jnum*inum*elsize;
+   out[0]    = (void *)calloc((size_t)jnum*(size_t)inum, elsize);
+   genmalloc_memory_add(out[0], mem_size);
+  
+   for (int i = 1; i < jnum; i++) {
+      out[i] = out[i-1] + inum*elsize;
+   }
+  
+   return (out);
+}
+
+void genmatrixfree_p(void **var, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   genmalloc_memory_remove(var[0]);
+   genmalloc_memory_remove(var);
+}
+
+void ***gentrimatrix_p(int knum, int jnum, int inum, size_t elsize, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   void ***out = NULL;
+   if (elsize == 8) {
+      out = (void ***)gentrimatrix_double_p(knum, jnum, inum, file, line);
+   } else if (elsize == 4) {
+      out = (void ***)gentrimatrix_int_p(knum, jnum, inum, file, line);
+   } else {
+      printf("Error -- element size not supported in genmalloc for call at %s line %d\n",file,line);
+   }
+
+   return(out);
+}
+
+double ***gentrimatrix_double_p(int knum, int jnum, int inum, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   double ***out;
+   size_t mem_size;
+   const size_t elsize = 8;
+
+   mem_size  = knum*sizeof(void **);
+   out       = (double ***)malloc(mem_size);
+   genmalloc_memory_add(out, mem_size);
+
+   mem_size  = knum*jnum*sizeof(void *);
+   out[0]    = (double **) malloc(mem_size);
+   genmalloc_memory_add(out[0], mem_size);
+
+   size_t nelems = knum*jnum*inum;
+   mem_size  = nelems*elsize;
+   out[0][0] = (void *)calloc(nelems, elsize);
+   genmalloc_memory_add(out[0][0], mem_size);
+
+   for (int k = 0; k < knum; k++)
+   {
+      if (k > 0)
+      {
+         out[k] = out[k-1] + jnum;
+         out[k][0] = out[k-1][0] + (jnum*inum);
+      }
+
+      for (int j = 1; j < jnum; j++)
+      {
+         out[k][j] = out[k][j-1] + inum;
+      }
+   }
+
+   return (out);
+}
+
+int ***gentrimatrix_int_p(int knum, int jnum, int inum, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   int ***out;
+   size_t mem_size;
+   const size_t elsize = 4;
+
+   mem_size  = knum*sizeof(void **);
+   out       = (int ***)malloc(mem_size);
+   genmalloc_memory_add(out, mem_size);
+
+   mem_size  = knum*jnum*sizeof(void *);
+   out[0]    = (int **) malloc(mem_size);
+   genmalloc_memory_add(out[0], mem_size);
+
+   size_t nelems = knum*jnum*inum;
+   mem_size  = nelems*elsize;
+   out[0][0] = (void *)calloc(nelems, elsize);
+   genmalloc_memory_add(out[0][0], mem_size);
+
+   for (int k = 0; k < knum; k++)
+   {
+      if (k > 0)
+      {
+         out[k] = out[k-1] + jnum;
+         out[k][0] = out[k-1][0] + (jnum*inum);
+      }
+
+      for (int j = 1; j < jnum; j++)
+      {
+         out[k][j] = out[k][j-1] + inum;
+      }
+   }
+
+   return (out);
+}
+
+void gentrimatrixfree_p(void ***var, const char *file, const int line)
+{
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   genmalloc_memory_remove(var[0][0]);
+   genmalloc_memory_remove(var[0]);
+   genmalloc_memory_remove(var);
+}
+
+void *genmalloc_memory_add_p(void *malloc_mem_ptr, size_t size, const char *file, const int line){
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   if (SLIST_EMPTY(&genmalloc_memory_head)) SLIST_INIT(&genmalloc_memory_head);
+
+   genmalloc_memory_item = malloc(sizeof(struct genmalloc_memory_entry));
+   genmalloc_memory_item->mem_ptr = malloc_mem_ptr;
+   genmalloc_memory_item->mem_size = size;
+   if (DEBUG) printf("GENMALLOC_MEMORY_ADD: DEBUG -- malloc memory pointer is %p called from file %s line %d\n",malloc_mem_ptr,file,line);
+
+   SLIST_INSERT_HEAD(&genmalloc_memory_head, genmalloc_memory_item, genmalloc_memory_entries);
+
+   return(malloc_mem_ptr);
+}
+
+void genmalloc_memory_remove_p(void *malloc_mem_ptr, const char *file, const int line){
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   SLIST_FOREACH(genmalloc_memory_item, &genmalloc_memory_head, genmalloc_memory_entries){
+      if (genmalloc_memory_item->mem_ptr == malloc_mem_ptr) {
+         if (DEBUG) printf("GENMALLOC_MEMORY_REMOVE: DEBUG -- freeing malloc memory pointer %p called from file %s line %d\n",malloc_mem_ptr,file,line);
+         free(malloc_mem_ptr);
+         SLIST_REMOVE(&genmalloc_memory_head, genmalloc_memory_item, genmalloc_memory_entry, genmalloc_memory_entries);
+         free(genmalloc_memory_item);
+         break;
+      }
+   }
+}
+
+void genmem_free_all_p(const char *file, const int line){
+   // Just to get rid of warning
+   if (1 == 2) printf("Warning file %s line %d\n", file, line);
+
+   while (!SLIST_EMPTY(&genmalloc_memory_head)) {
+      genmalloc_memory_item = SLIST_FIRST(&genmalloc_memory_head);
+      if (DEBUG) printf("GENMEM_FREE_ALL: DEBUG -- freeing genmalloc memory %p called from file %s line %d\n",genmalloc_memory_item->mem_ptr,file,line);
+      free(genmalloc_memory_item->mem_ptr);
+      SLIST_REMOVE_HEAD(&genmalloc_memory_head, genmalloc_memory_entries);
+      free(genmalloc_memory_item);
+   }
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/genmalloc.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/genmalloc.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* memory routines */
+#define genvector(  inum, elsize) \
+      ( genvector_p(inum, elsize, __FILE__, __LINE__) )
+#define genvectorfree(  var) \
+      ( genvectorfree_p(var, __FILE__, __LINE__) )
+#define genmatrix(  jnum, inum, elsize) \
+      ( genmatrix_p(jnum, inum, elsize, __FILE__, __LINE__) )
+#define gentrimatrix(  knum, jnum, inum, elsize) \
+      ( gentrimatrix_p(knum, jnum, inum, elsize, __FILE__, __LINE__) )
+#define genmatrixfree(  var) \
+      ( genmatrixfree_p(var, __FILE__, __LINE__) )
+#define gentrimatrixfree(  var) \
+      ( gentrimatrixfree_p(var, __FILE__, __LINE__) )
+
+#define genmalloc_memory_add(  malloc_mem_ptr, size) \
+      ( genmalloc_memory_add_p(malloc_mem_ptr, size, __FILE__, __LINE__) )
+#define genmalloc_memory_remove(  malloc_mem_ptr) \
+      ( genmalloc_memory_remove_p(malloc_mem_ptr, __FILE__, __LINE__) )
+#define genmem_free_all() \
+      ( genmem_free_all_p(__FILE__, __LINE__) ) 
+
+
+void *genvector_p(int inum, size_t elsize, const char *file, const int line);
+void genvectorfree_p(void *var, const char *file, const int line);
+void **genmatrix_p(int jnum, int inum, size_t elsize, const char *file, const int line);
+void ***gentrimatrix_p(int knum, int jnum, int inum, size_t elsize, const char *file, const int line);
+void genmatrixfree_p(void **var, const char *file, const int line);
+void gentrimatrixfree_p(void ***var, const char *file, const int line);
+
+void *genmalloc_memory_add_p(void *malloc_mem_ptr, size_t size, const char *file, const int line);
+void genmalloc_memory_remove_p(void *malloc_mem_ptr, const char *file, const int line);
+void genmem_free_all_p(const char *file, const int line);
+
+#ifdef __cplusplus
+}
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/glibc_compat_rand.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,60 @@
+/*===------------ glibc_compat_rand.c - glibc rand emulation --------------===*\
+ *
+ *                     The LLVM Compiler Infrastructure
+ *
+ * This file is distributed under the University of Illinois Open Source
+ * License. See LICENSE.TXT for details.
+ *
+\*===----------------------------------------------------------------------===*/
+
+#include "glibc_compat_rand.h"
+
+/**
+ * This rand implementation is designed to emulate the implementation of
+ * rand/srand in recent versions of glibc. This is used for programs which
+ * require this specific rand implementation in order to pass verification
+ * tests.
+ *
+ * For more information, see: http://www.mathstat.dal.ca/~selinger/random/
+ **/
+
+#define TABLE_SIZE 344
+static unsigned int table[TABLE_SIZE];
+static int next;
+
+int glibc_compat_rand(void) {
+  /* Calculate the indices i-3 and i-31 in the circular vector. */
+  int i3 = (next < 3) ? (TABLE_SIZE + next - 3) : (next - 3);
+  int i31 = (next < 31) ? (TABLE_SIZE + next - 31) : (next - 31);
+
+  table[next] = table[i3] + table[i31];
+  unsigned int r = table[next] >> 1;
+
+  ++next;
+  if (next >= TABLE_SIZE)
+    next = 0;
+
+  return r;
+}
+
+void glibc_compat_srand(unsigned int seed) {
+  if (seed == 0)
+    seed = 1;
+
+  table[0] = seed;
+
+  for (int i = 1; i < 31; i++) {
+    int r = (16807ll * table[i - 1]) % 2147483647;
+    if (r < 0)
+      r += 2147483647;
+
+    table[i] = r;
+  }
+
+  for (int i = 31; i < 34; i++)
+    table[i] = table[i - 31];
+  for (int i = 34; i < TABLE_SIZE; i++)
+    table[i] = table[i - 31] + table[i - 3];
+
+  next = 0;
+}

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/glibc_compat_rand.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/glibc_compat_rand.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,16 @@
+/*===------------- glibc_compat_rand.h- glibc rand emulation --------------===*\
+|*
+|*                     The LLVM Compiler Infrastructure
+|*
+|* This file is distributed under the University of Illinois Open Source
+|* License. See LICENSE.TXT for details.
+|*
+\*===----------------------------------------------------------------------===*/
+
+#ifndef GLIBC_COMPAT_RAND_H
+#define GLIBC_COMPAT_RAND_H
+
+int glibc_compat_rand(void);
+void glibc_compat_srand(unsigned int seed);
+
+#endif /* GLIBC_COMPAT_RAND_H */

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/graphics.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,706 @@
+/*
+ *  Copyright (c) 2011, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "graphics.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+static int magick_on = 0;
+
+#ifdef HAVE_MAGICKWAND
+#include <wand/MagickWand.h>
+
+#define MAGICK_NCOLORS 1280
+
+void Magick_Scale();
+
+//static int graphics_movie = 0;
+static MagickWand *magick_wand = NULL;
+static DrawingWand *draw_wand  = NULL;
+static PixelWand *pixel_wand   = NULL;
+
+struct MagickColorTable {
+   int Red;
+   int Blue;
+   int Green;
+};
+
+static struct MagickColorTable MagickRainbow[MAGICK_NCOLORS];
+#endif
+
+
+#define WINSIZE 800
+
+void DrawSquaresToFile(int graph_num, int ncycle, double simTime, int rollback_img, int rollback_num);
+
+/*
+ * Variables that I added to make everything work for getting graphics
+ * data output to files while running no graphics with CLAMR
+ * Brian Atkinson
+*/
+static int autoscale = 0;
+static double xconversion = 0.0;
+static double yconversion = 0.0;
+static int Ncolors = 256;
+static int iteration = 0;
+
+char *graphics_directory = "graphics_output";
+int graphics_type; // type of graphics output
+
+//static int mode = MOVE;
+
+static int width;
+static float graphics_xmin=0.0, graphics_xmax=0.0, graphics_ymin=0.0, graphics_ymax=0.0;
+
+static int graphics_outline   = 0;
+static int graphics_view_mode = 0;
+static int graphics_mysize    = 0;
+
+enum spatial_data_type {SPATIAL_DOUBLE, SPATIAL_FLOAT};
+static int spatial_type = SPATIAL_FLOAT;
+
+static double *x_double=NULL, *y_double=NULL, *dx_double=NULL, *dy_double=NULL;
+static float *x_float=NULL, *y_float=NULL, *dx_float=NULL, *dy_float=NULL;
+
+enum plot_data_type {DATA_DOUBLE, DATA_FLOAT};
+static int data_type = DATA_FLOAT;
+static double *data_double=NULL;
+static float *data_float=NULL;
+static int *graphics_proc=NULL;
+
+void init_graphics_output(void){
+   width = (WINSIZE / (graphics_ymax - graphics_ymin)) * (graphics_xmax - graphics_xmin);
+   xconversion = (double)WINSIZE/ (graphics_xmax - graphics_xmin);
+   yconversion = (double)WINSIZE/(graphics_ymax - graphics_ymin);
+
+   struct stat stat_descriptor;
+   if (stat(graphics_directory,&stat_descriptor) == -1){
+     mkdir(graphics_directory,0777);
+   }
+
+   if (graphics_type != GRAPHICS_DATA && graphics_type != GRAPHICS_NONE) magick_on = 1;
+
+#ifdef HAVE_MAGICKWAND
+   if (magick_on){
+      //MagickWandGenesis(); 
+      // Create wand
+      magick_wand = NewMagickWand();
+
+      Magick_Scale();
+   }
+#endif
+}
+
+void terminate_graphics_output(void){
+#ifdef HAVE_MAGICKWAND
+   if (magick_on){
+      magick_wand = DestroyMagickWand(magick_wand);
+      MagickWandTerminus();
+   }
+#endif
+}
+
+void set_graphics_window(float graphics_xmin_in, float graphics_xmax_in, float graphics_ymin_in, float graphics_ymax_in){
+   graphics_xmin = graphics_xmin_in;
+   graphics_xmax = graphics_xmax_in;
+   graphics_ymin = graphics_ymin_in;
+   graphics_ymax = graphics_ymax_in;
+}
+void set_graphics_cell_data_double(double *data_in){
+   data_type = DATA_DOUBLE;
+   data_double = data_in;
+}
+void set_graphics_cell_data_float(float *data_in){
+   data_type = DATA_FLOAT;
+   data_float = data_in;
+}
+void set_graphics_cell_proc(int *graphics_proc_in){
+   graphics_proc = graphics_proc_in;
+}
+void set_graphics_cell_coordinates_double(double *x_in, double *dx_in, double *y_in, double *dy_in){
+   spatial_type = SPATIAL_DOUBLE;
+   x_double = x_in;
+   dx_double = dx_in;
+   y_double = y_in;
+   dy_double = dy_in;
+}
+void set_graphics_cell_coordinates_float(float *x_in, float *dx_in, float *y_in, float *dy_in){
+   spatial_type = SPATIAL_FLOAT;
+   x_float = x_in;
+   dx_float = dx_in;
+   y_float = y_in;
+   dy_float = dy_in;
+}
+void set_graphics_viewmode(int graphics_view_mode_in){
+   graphics_view_mode = graphics_view_mode_in;
+}
+void set_graphics_mysize(int graphics_mysize_in){
+   graphics_mysize = graphics_mysize_in;
+}
+void set_graphics_outline(int graphics_outline_in){
+   graphics_outline = graphics_outline_in;
+}
+
+/*
+ * Created this function get graphics data while running
+ * the no graphic version of CLAMR. The output for the main
+ * cell data is written out to graph#.data files and the gridline
+ * data is writeen out to outline#.lin files.
+ * Brian Atkinson
+*/
+void DrawSquaresToFile(int graph_num, int ncycle, double simTime, int rollback_img, int rollback_num){
+#ifdef HAVE_MAGICKWAND
+   if (magick_on) {
+      draw_wand   = NewDrawingWand();
+      pixel_wand  = NewPixelWand();
+
+      MagickSetSize(magick_wand,WINSIZE,WINSIZE);
+      MagickSetColorspace(magick_wand,sRGBColorspace);
+      MagickReadImage(magick_wand,"xc:white");
+
+      DrawSetViewbox(draw_wand, 0, 0, WINSIZE, WINSIZE);
+      DrawScale(draw_wand, xconversion, -yconversion);
+      DrawTranslate(draw_wand, -graphics_xmin, graphics_ymin);
+
+      int npart = graphics_mysize/16;
+      for (int i=0; i<graphics_mysize; i++){
+         graphics_proc[i] = i/npart;
+      }
+
+      int magick_step = MAGICK_NCOLORS/(graphics_proc[graphics_mysize-1]+1);
+
+      if (graphics_outline) {
+         PixelGetBlack(pixel_wand);
+
+         DrawSetStrokeColor(draw_wand,pixel_wand);
+         DrawSetStrokeWidth(draw_wand,0.01);
+         DrawSetStrokeAntialias(draw_wand,1);
+         DrawSetStrokeOpacity(draw_wand,1);
+      }
+
+      if (data_type == DATA_DOUBLE){
+
+         for(int i = 0; i < graphics_mysize; i++) {
+            int magick_color = graphics_proc[i]*magick_step;
+            char cstring[40];
+            sprintf(cstring,"rgba(%d,%d,%d,%d)",MagickRainbow[magick_color].Red,
+                                                MagickRainbow[magick_color].Green,
+                                                MagickRainbow[magick_color].Blue,120);
+            PixelSetColor(pixel_wand, cstring);
+            
+
+            DrawSetFillColor(draw_wand, pixel_wand); 
+
+            DrawRectangle(draw_wand, x_double[i],              y_double[i],
+                                     x_double[i]+dx_double[i], y_double[i]+dy_double[i]);
+/*
+           printf("DEBUG -- i %d magick_color %d magick_step %d graphics_proc %d cstring %s corners %lg %lg %lg %lg\n",
+               i,magick_color,magick_step,graphics_proc[i],cstring,
+               x_double[i],              y_double[i],
+               x_double[i]+dx_double[i], y_double[i]+dy_double[i]);
+*/
+         }
+
+         if (graphics_outline) {
+	    PixelSetColor(pixel_wand,"black");
+	    DrawSetStrokeColor(draw_wand,pixel_wand);
+	    DrawSetStrokeWidth(draw_wand,0.01);
+
+            double xold = x_double[0]+0.5*dx_double[0];
+            double yold = y_double[0]+0.5*dy_double[0];
+
+            for(int i = 0; i < graphics_mysize; i++) {
+               char cstring[40];
+               sprintf(cstring,"%d",i);
+
+               double xnew = x_double[i]+0.5*dx_double[i];
+               double ynew = y_double[i]+0.5*dy_double[i];
+
+               DrawLine(draw_wand, xold, yold, xnew, ynew);
+
+               xold = xnew;
+               yold = ynew;
+            }
+         }
+
+/*
+         // Set up a 12 point black font 
+	 PixelSetColor(pixel_wand,"black");
+	 DrawSetFillColor(draw_wand,pixel_wand);
+	 DrawSetFont (draw_wand, "Courier" ) ;
+	 DrawSetFontSize(draw_wand,0.01);
+	 DrawSetStrokeColor(draw_wand,pixel_wand);
+	 DrawSetStrokeWidth(draw_wand,0.01);
+         DrawSetTextDirection(draw_wand, RightToLeftDirection);
+         DrawSetTextAlignment(draw_wand, CenterAlign);
+         DrawSetTextAntialias(draw_wand,MagickTrue);
+
+         for(int i = 1; i < graphics_mysize; i++) {
+            char cstring[40];
+            sprintf(cstring,"%d",i);
+
+
+            DrawAnnotation(draw_wand, x_double[i]+0.5*dx_double[i], y_double[i]+0.5*dy_double[i], cstring);
+         }
+*/
+
+      } else {
+
+         for(int i = 0; i < graphics_mysize; i++) {
+            int magick_color = graphics_proc[i]*magick_step;
+            char cstring[40];
+            sprintf(cstring,"rgba(%d,%d,%d,%d)",MagickRainbow[magick_color].Red,
+                                                MagickRainbow[magick_color].Green,
+                                                MagickRainbow[magick_color].Blue,120);
+            PixelSetColor(pixel_wand, cstring);
+
+            DrawSetFillColor(draw_wand, pixel_wand);
+
+            DrawRectangle(draw_wand, x_float[i],             y_float[i],
+                                     x_float[i]+dx_float[i], y_float[i]+dy_float[i]);
+         }
+
+         if (graphics_outline) {
+	    PixelSetColor(pixel_wand,"black");
+	    DrawSetStrokeColor(draw_wand,pixel_wand);
+	    DrawSetStrokeWidth(draw_wand,0.01);
+
+            float xold = x_float[0]+0.5*dx_float[0];
+            float yold = y_float[0]+0.5*dy_float[0];
+
+            for(int i = 0; i < graphics_mysize; i++) {
+               char cstring[40];
+               sprintf(cstring,"%d",i);
+
+               float xnew = x_float[i]+0.5*dx_float[i];
+               float ynew = y_float[i]+0.5*dy_float[i];
+
+               DrawLine(draw_wand, xold, yold, xnew, ynew);
+
+               xold = xnew;
+               yold = ynew;
+            }
+         }
+
+      }
+
+      MagickDrawImage(magick_wand, draw_wand);
+
+      char filename[50];
+      char graphics_file_extension[10];
+      if (graphics_type == GRAPHICS_BMP)  strcpy(graphics_file_extension,".bmp");
+      if (graphics_type == GRAPHICS_GIF)  strcpy(graphics_file_extension,".gif");
+      if (graphics_type == GRAPHICS_JPEG) strcpy(graphics_file_extension,".jpeg");
+      if (graphics_type == GRAPHICS_MPEG) strcpy(graphics_file_extension,".mpeg");
+      if (graphics_type == GRAPHICS_PDF)  strcpy(graphics_file_extension,".pdf");
+      if (graphics_type == GRAPHICS_PNG)  strcpy(graphics_file_extension,".png");
+      if (graphics_type == GRAPHICS_SVG)  strcpy(graphics_file_extension,".svg");
+      sprintf(filename,"%s/graph%05d%s", graphics_directory, graph_num, graphics_file_extension);
+      MagickWriteImage(magick_wand, filename);
+      //MagickDisplayImage(magick_wand, "x:");
+
+      draw_wand = DestroyDrawingWand(draw_wand);
+      pixel_wand = DestroyPixelWand(pixel_wand);
+   }
+#endif
+
+   if (graphics_type == GRAPHICS_DATA){
+      int i, color;
+      int step = Ncolors/(graphics_proc[graphics_mysize-1]+1);
+      int xloc, xwid, yloc, ywid;
+      int xloc1, xloc2, yloc1, yloc2;
+      char filename[50], filename2[50];
+   
+      if(rollback_img){
+         sprintf(filename,"%s/graph%dcp%05d.data", graphics_directory, graph_num, rollback_num);
+         sprintf(filename2,"%s/outline%dcp%05d.lin",graphics_directory, graph_num, rollback_num);
+      }
+      else{
+         sprintf(filename,"%s/graph%05d.data", graphics_directory, graph_num);
+         sprintf(filename2,"%s/outline%05d.lin",graphics_directory, graph_num);
+      }
+      FILE *fp = fopen(filename,"w");
+      FILE *fp2 = fopen(filename2,"w");
+      if(fp && fp2){
+         fprintf(fp,"%d,%lf\n",ncycle,simTime);
+         if (data_type == DATA_DOUBLE){
+            for(i = 0; i < graphics_mysize; i++) {
+               xloc = (int)((x_double[i]-graphics_xmin)*xconversion);
+               xwid = (int)((x_double[i]+dx_double[i]-graphics_xmin)*xconversion-xloc);
+               yloc = (int)((graphics_ymax-(y_double[i]+dy_double[i]))*yconversion);
+               ywid = (int)((graphics_ymax-y_double[i])*yconversion);
+               ywid -= yloc;
+               color = graphics_proc[i]*step;
+               //fprintf(fp,"%d,%d,%d,%d,%f\n",xloc,yloc,xwid,ywid,data[i]);
+               fprintf(fp,"%d,%d,%d,%d,%d\n",xloc,yloc,xwid,ywid,color);
+            
+               xloc1 = (int)((x_double[i]-graphics_xmin)*xconversion);
+               xloc2 = (int)((x_double[i]+dx_double[i]-graphics_xmin)*xconversion);
+               yloc1 = (int)((graphics_ymax-y_double[i])*yconversion);
+               yloc2 = (int)((graphics_ymax-(y_double[i]+dy_double[i]))*yconversion);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc2,xloc2,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc2,yloc1);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc1,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc2,yloc1,xloc2,yloc2);
+            }
+         } else {
+            for(i = 0; i < graphics_mysize; i++) {
+               xloc = (int)((x_float[i]-graphics_xmin)*xconversion);
+               xwid = (int)((x_float[i]+dx_float[i]-graphics_xmin)*xconversion-xloc);
+               yloc = (int)((graphics_ymax-(y_float[i]+dy_float[i]))*yconversion);
+               ywid = (int)((graphics_ymax-y_float[i])*yconversion);
+               ywid -= yloc;
+               color = graphics_proc[i]*step;
+               //fprintf(fp,"%d,%d,%d,%d,%f\n",xloc,yloc,xwid,ywid,data[i]);
+               fprintf(fp,"%d,%d,%d,%d,%d\n",xloc,yloc,xwid,ywid,color);
+         
+               xloc1 = (int)((x_float[i]-graphics_xmin)*xconversion);
+               xloc2 = (int)((x_float[i]+dx_float[i]-graphics_xmin)*xconversion);
+               yloc1 = (int)((graphics_ymax-y_float[i])*yconversion);
+               yloc2 = (int)((graphics_ymax-(y_float[i]+dy_float[i]))*yconversion);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc2,xloc2,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc2,yloc1);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc1,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc2,yloc1,xloc2,yloc2);
+            }
+         }
+         fclose(fp);
+         fclose(fp2);
+         iteration++;
+      }   
+      else{
+            if(fp == NULL){
+               printf("Could not create %s in DrawSqaures\n", filename);
+            }
+            else{
+               printf("Could not create %s in DrawSqaures\n", filename2);
+            }
+      }
+   }
+}
+
+/*
+ * Created this function get graphics data while running
+ * the no graphic version of CLAMR. The output for the main
+ * cell data is written out to graph#.data files and the gridline
+ * data is writeen out to outline#.lin files.
+ * Brian Atkinson
+*/
+void DisplayStateToFile(int graph_num, int ncycle, double simTime, int rollback_img, int rollback_num){
+#ifdef HAVE_MAGICKWAND
+   if (magick_on) {
+      double scaleMax = 25.0, scaleMin = 0.0;
+
+      draw_wand   = NewDrawingWand();
+      pixel_wand  = NewPixelWand();
+
+      MagickSetSize(magick_wand,WINSIZE,WINSIZE);
+      MagickSetColorspace(magick_wand,sRGBColorspace);
+      MagickReadImage(magick_wand,"xc:white");
+
+      DrawSetViewbox(draw_wand, 0, 0, WINSIZE, WINSIZE);
+      DrawScale(draw_wand, xconversion, -yconversion);
+      DrawTranslate(draw_wand, -graphics_xmin, graphics_ymin);
+
+      if (autoscale) {
+         scaleMax=-1.0e30;
+         scaleMin=1.0e30;
+         if (data_type == DATA_DOUBLE){
+            for(int i = 0; i<graphics_mysize; i++) {
+               if (data_double[i] > scaleMax) scaleMax = data_double[i];
+               if (data_double[i] < scaleMin) scaleMin = data_double[i];
+            }
+         } else {
+            for(int i = 0; i<graphics_mysize; i++) {
+               if (data_float[i] > scaleMax) scaleMax = data_float[i];
+               if (data_float[i] < scaleMin) scaleMin = data_float[i];
+            }
+         }
+      }
+
+      int magick_step = MAGICK_NCOLORS/(scaleMax - scaleMin);
+
+      if (graphics_outline) {
+         PixelGetBlack(pixel_wand);
+
+         DrawSetStrokeColor(draw_wand,pixel_wand);
+         DrawSetStrokeWidth(draw_wand,0.01);
+         DrawSetStrokeAntialias(draw_wand,1);
+         DrawSetStrokeOpacity(draw_wand,1);
+      }
+
+      if (data_type == DATA_DOUBLE){
+
+         for(int i = 0; i < graphics_mysize; i++) {
+            int magick_color;
+            if (data_type == DATA_DOUBLE){
+               magick_color = (int)(data_double[i]-scaleMin)*magick_step;
+            } else {
+               magick_color = (int)(data_float[i]-scaleMin)*magick_step;
+            }
+            magick_color = MAGICK_NCOLORS-magick_color;
+            if (magick_color < 0) {
+               magick_color=0;
+            }
+            if (magick_color >= MAGICK_NCOLORS) magick_color = MAGICK_NCOLORS-1;
+
+            char cstring[40];
+            sprintf(cstring,"rgba(%d,%d,%d,%d)",MagickRainbow[magick_color].Red,
+                                                MagickRainbow[magick_color].Green,
+                                                MagickRainbow[magick_color].Blue,120);
+            PixelSetColor(pixel_wand, cstring);
+
+            DrawSetFillColor(draw_wand, pixel_wand);
+
+            DrawRectangle(draw_wand, x_double[i],              y_double[i],
+                                     x_double[i]+dx_double[i], y_double[i]+dy_double[i]);
+/*
+           printf("DEBUG -- i %d magick_color %d magick_step %d graphics_proc %d cstring %s corners %lg %lg %lg %lg\n",
+               i,magick_color,magick_step,graphics_proc[i],cstring,
+               x_double[i],              y_double[i],
+               x_double[i]+dx_double[i], y_double[i]+dy_double[i]);
+*/
+         }
+      } else {
+
+         for(int i = 0; i < graphics_mysize; i++) {
+            int magick_color;
+            if (data_type == DATA_DOUBLE){
+               magick_color = (int)(data_double[i]-scaleMin)*magick_step;
+            } else {
+               magick_color = (int)(data_float[i]-scaleMin)*magick_step;
+            }
+            magick_color = MAGICK_NCOLORS-magick_color;
+            if (magick_color < 0) {
+               magick_color=0;
+            }
+            if (magick_color >= MAGICK_NCOLORS) magick_color = MAGICK_NCOLORS-1;
+
+            char cstring[40];
+            sprintf(cstring,"rgba(%d,%d,%d,%d)",MagickRainbow[magick_color].Red,
+                                                MagickRainbow[magick_color].Green,
+                                                MagickRainbow[magick_color].Blue,120);
+            PixelSetColor(pixel_wand, cstring);
+
+            DrawSetFillColor(draw_wand, pixel_wand);
+
+            DrawRectangle(draw_wand, x_float[i],             y_float[i],
+                                     x_float[i]+dx_float[i], y_float[i]+dy_float[i]);
+         }
+      }
+
+      MagickDrawImage(magick_wand, draw_wand);
+
+      char filename[50];
+      char graphics_file_extension[10];
+      if (graphics_type == GRAPHICS_BMP)  strcpy(graphics_file_extension,".bmp");
+      if (graphics_type == GRAPHICS_GIF)  strcpy(graphics_file_extension,".gif");
+      if (graphics_type == GRAPHICS_JPEG) strcpy(graphics_file_extension,".jpeg");
+      if (graphics_type == GRAPHICS_MPEG) strcpy(graphics_file_extension,".mpeg");
+      if (graphics_type == GRAPHICS_PDF)  strcpy(graphics_file_extension,".pdf");
+      if (graphics_type == GRAPHICS_PNG)  strcpy(graphics_file_extension,".png");
+      if (graphics_type == GRAPHICS_SVG)  strcpy(graphics_file_extension,".svg");
+      sprintf(filename,"%s/graph%05d%s", graphics_directory, graph_num, graphics_file_extension);
+      MagickWriteImage(magick_wand, filename);
+      //MagickDisplayImage(magick_wand, "x:");
+
+      draw_wand = DestroyDrawingWand(draw_wand);
+      pixel_wand = DestroyPixelWand(pixel_wand);
+   }
+#endif
+   if (graphics_type == GRAPHICS_DATA){
+      double scaleMax = 25.0, scaleMin = 0.0;
+      int i;
+      int color;
+      char filename[50], filename2[50];
+   
+      if(rollback_img){
+         sprintf(filename,"%s/graph%dcp%05d.data", graphics_directory, graph_num, rollback_num);
+         sprintf(filename2,"%s/outline%dcp%05d.lin",graphics_directory, graph_num, rollback_num);
+      }
+      else{
+         sprintf(filename,"%s/graph%05d.data", graphics_directory, graph_num);
+         sprintf(filename2,"%s/outline%05d.lin",graphics_directory, graph_num);
+      }
+      FILE *fp = fopen(filename,"w");
+      FILE *fp2 = fopen(filename2,"w");
+      if(fp && fp2){
+         fprintf(fp,"%d,%lf\n",ncycle,simTime);
+         if (autoscale) {
+            scaleMax=-1.0e30;
+            scaleMin=1.0e30;
+            if (data_type == DATA_DOUBLE){
+               for(i = 0; i<graphics_mysize; i++) {
+                  if (data_double[i] > scaleMax) scaleMax = data_double[i];
+                  if (data_double[i] < scaleMin) scaleMin = data_double[i];
+               }
+            } else {
+               for(i = 0; i<graphics_mysize; i++) {
+                  if (data_float[i] > scaleMax) scaleMax = data_float[i];
+                  if (data_float[i] < scaleMin) scaleMin = data_float[i];
+               }
+            }
+         }
+
+         double step = Ncolors/(scaleMax - scaleMin);
+         int xloc, xwid, yloc, ywid;
+         int xloc1, xloc2, yloc1, yloc2;
+         for(i = 0; i < graphics_mysize; i++) {
+            if (data_type == DATA_DOUBLE){
+               color = (int)(data_double[i]-scaleMin)*step;
+            } else {
+               color = (int)(data_float[i]-scaleMin)*step;
+            }
+            color = Ncolors-color;
+            if (color < 0) {
+               color=0;
+            }
+            if (color >= Ncolors) color = Ncolors-1;
+
+            if (data_type == DATA_DOUBLE){
+               xloc = (int)((x_double[i]-graphics_xmin)*xconversion);
+               xwid = (int)((x_double[i]+dx_double[i]-graphics_xmin)*xconversion-xloc);
+               yloc = (int)((graphics_ymax-(y_double[i]+dy_double[i]))*yconversion);
+               ywid = (int)((graphics_ymax-y_double[i])*yconversion);
+               ywid -= yloc;
+               //fprintf(fp,"%d,%d,%d,%d,%f\n",xloc,yloc,xwid,ywid,data[i]);
+               fprintf(fp,"%d,%d,%d,%d,%d\n",xloc,yloc,xwid,ywid,color);
+         
+               xloc1 = (int)((x_double[i]-graphics_xmin)*xconversion);
+               xloc2 = (int)((x_double[i]+dx_double[i]-graphics_xmin)*xconversion);
+               yloc1 = (int)((graphics_ymax-y_double[i])*yconversion);
+               yloc2 = (int)((graphics_ymax-(y_double[i]+dy_double[i]))*yconversion);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc2,xloc2,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc2,yloc1);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc1,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc2,yloc1,xloc2,yloc2);
+            } else {
+               xloc = (int)((x_float[i]-graphics_xmin)*xconversion);
+               xwid = (int)((x_float[i]+dx_float[i]-graphics_xmin)*xconversion-xloc);
+               yloc = (int)((graphics_ymax-(y_float[i]+dy_float[i]))*yconversion);
+               ywid = (int)((graphics_ymax-y_float[i])*yconversion);
+               ywid -= yloc;
+               //fprintf(fp,"%d,%d,%d,%d,%f\n",xloc,yloc,xwid,ywid,data[i]);
+               fprintf(fp,"%d,%d,%d,%d,%d\n",xloc,yloc,xwid,ywid,color);
+         
+               xloc1 = (int)((x_float[i]-graphics_xmin)*xconversion);
+               xloc2 = (int)((x_float[i]+dx_float[i]-graphics_xmin)*xconversion);
+               yloc1 = (int)((graphics_ymax-y_float[i])*yconversion);
+               yloc2 = (int)((graphics_ymax-(y_float[i]+dy_float[i]))*yconversion);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc2,xloc2,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc2,yloc1);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc1,yloc1,xloc1,yloc2);
+               fprintf(fp2,"%d,%d,%d,%d\n",xloc2,yloc1,xloc2,yloc2);
+            }
+         }
+         fclose(fp);
+         fclose(fp2);   
+         iteration++;
+     }
+     else{
+        if(fp == NULL){
+            printf("Could not open %s in DisplayStateToFile\n", filename);
+        }
+        else{
+            printf("Could not open %s in DisplayStateToFile\n", filename2);
+        }
+     }
+  }
+}
+
+void write_graphics_info(int graph_num, int ncycle, double simTime, int rollback_img, int rollback_num){
+   if (graphics_view_mode == 0) {
+      DrawSquaresToFile(graph_num, ncycle, simTime, rollback_img, rollback_num);
+   } else {
+      DisplayStateToFile(graph_num, ncycle, simTime, rollback_img, rollback_num);
+   }
+}
+
+#ifdef HAVE_MAGICKWAND
+void Magick_Scale() {
+   int i, r;
+   for (i=0, r=0;   i<256; i++, r++) {
+         MagickRainbow[     i].Red   = 0;
+         MagickRainbow[     i].Green = r;
+         MagickRainbow[     i].Blue  = 255;
+   }
+   for (i=0, r=255; i<256; i++, r--) {
+         MagickRainbow[ 256+i].Red   = 0;
+         MagickRainbow[ 256+i].Green = 255;
+         MagickRainbow[ 256+i].Blue  = r;
+   }
+   for (i=0, r=0;   i<256; i++, r++) {
+         MagickRainbow[ 512+i].Red   = r;
+         MagickRainbow[ 512+i].Green = 255;
+         MagickRainbow[ 512+i].Blue  = 0;
+   }
+   for (i=0, r=255; i<256; i++, r--) {
+         MagickRainbow[ 768+i].Red   = 255;
+         MagickRainbow[ 768+i].Green = r;
+         MagickRainbow[ 768+i].Blue  = 0;
+   }
+   for (i=0, r=0;   i<256; i++, r++) {
+         MagickRainbow[1024+i].Red   = 255;
+         MagickRainbow[1024+i].Green = 0;
+         MagickRainbow[1024+i].Blue  = r;
+   }
+}
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/graphics.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/graphics.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,102 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+#ifndef _GRAPHICS_H_
+#define _GRAPHICS_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+enum graphics_file_type{
+   GRAPHICS_NONE,
+   GRAPHICS_DATA,
+   GRAPHICS_BMP,
+   GRAPHICS_GIF,
+   GRAPHICS_JPEG,
+   GRAPHICS_MPEG,
+   GRAPHICS_PDF,
+   GRAPHICS_PNG,
+   GRAPHICS_SVG
+};
+
+void set_graphics_window(float graphics_xmin_in, float graphics_xmax_in,
+                         float graphics_ymin_in, float graphics_ymax_in);
+void init_graphics_output(void);
+void terminate_graphics_output(void);
+void set_graphics_viewmode(int graphics_view_mode_in);
+void set_graphics_mysize(int graphics_mysize_in);
+void set_graphics_outline(int graphics_outline_in);
+void set_graphics_cell_data_double(double *data_in);
+void set_graphics_cell_data_float(float *data_in);
+void set_graphics_cell_proc(int *graphics_proc_in);
+void set_graphics_cell_coordinates_double(double *x_in, double *dx_in,
+                                          double *y_in, double *dy_in);
+void set_graphics_cell_coordinates_float(float *x_in, float *dx_in,
+                                         float *y_in, float *dy_in);
+void write_graphics_info(int graph_num, int ncycle, double simTime,
+                         int rollback_img, int rollback_num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/hash.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,1277 @@
+//#if defined __INTEL_COMPILER
+
+#include <stdio.h>
+#define __USE_XOPEN
+#include <stdlib.h>
+#include "hash.h"
+#include "genmalloc.h"
+#ifdef HAVE_OPENCL
+#include "hashlib_kern.inc"
+#include "hashlib_source_kern.inc"
+#endif
+
+#ifndef NO_GLIBC_COMPAT_RAND
+#include "glibc_compat_rand.h"
+#define rand glibc_compat_rand
+#define srand glibc_compat_srand
+#define drand48() (1.0 * rand() / RAND_MAX)
+#define srand48(x) srand(x)
+#endif
+
+static ulong AA;
+static ulong BB;
+static ulong prime=4294967291;
+static uint hashtablesize;
+static uint hash_stride;
+static uint hash_ncells;
+static uint write_hash_collisions;
+static uint read_hash_collisions;
+static double write_hash_collisions_runsum = 0.0;
+static double read_hash_collisions_runsum = 0.0;
+static uint write_hash_collisions_count = 0;
+static uint read_hash_collisions_count = 0;
+static uint hash_report_level = 2;
+static uint hash_queries;
+static int hash_method = METHOD_UNSET;
+static uint hash_jump_prime = 41;
+static double hash_mult = 3.0;
+
+size_t hash_header_size = 16;
+
+#ifdef HAVE_OPENCL
+cl_mem dev_hash_header = NULL;
+#endif
+
+float mem_opt_factor;
+
+int   choose_hash_method = METHOD_UNSET;
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+int (*read_hash)(ulong, int *);
+void (*write_hash)(uint, ulong, int *);
+
+int get_hash_method(void) {
+  return(hash_method);
+}
+
+long long get_hashtablesize(void) {
+  return(hashtablesize);
+}
+
+int *compact_hash_init(int ncells, uint isize, uint jsize, uint report_level){
+   hash_ncells = 0;
+   write_hash_collisions = 0;
+   read_hash_collisions = 0;
+   hash_queries = 0;
+   hash_report_level = report_level;
+   hash_stride = isize;
+   int *hash = NULL;
+
+   if (choose_hash_method != METHOD_UNSET) hash_method = choose_hash_method;
+
+   uint compact_hash_size = (uint)((double)ncells*hash_mult);
+   uint perfect_hash_size = (uint)(isize*jsize);
+
+   if (hash_method == METHOD_UNSET){
+      float hash_mem_factor = 20.0;
+      float hash_mem_ratio = (double)perfect_hash_size/(double)compact_hash_size;
+      if (mem_opt_factor != 1.0) hash_mem_factor /= (mem_opt_factor*0.2); 
+      hash_method = (hash_mem_ratio < hash_mem_factor) ? PERFECT_HASH : QUADRATIC;
+
+      if (hash_report_level >= 2) printf("DEBUG hash_method %d hash_mem_ratio %f hash_mem_factor %f mem_opt_factor %f perfect_hash_size %u compact_hash_size %u\n",
+         hash_method,hash_mem_ratio,hash_mem_factor,mem_opt_factor,perfect_hash_size,compact_hash_size);
+   }
+
+   int do_compact_hash = (hash_method == PERFECT_HASH) ? 0 : 1;
+
+   if (hash_report_level >= 2) printf("DEBUG do_compact_hash %d hash_method %d perfect_hash_size %u compact_hash_size %u\n",
+      do_compact_hash,hash_method,perfect_hash_size,compact_hash_size);
+
+   if (do_compact_hash) {
+      hashtablesize = compact_hash_size;
+      AA = (ulong)(1.0+(double)(prime-1)*drand48());
+      BB = (ulong)(0.0+(double)(prime-1)*drand48());
+      if (AA > prime-1 || BB > prime-1) exit(0);
+      if (hash_report_level > 1) printf("Factors AA %lu BB %lu\n",AA,BB);
+
+      hash = (int *)genvector(2*hashtablesize,sizeof(int));
+      for (uint ii = 0; ii<2*hashtablesize; ii+=2){
+         hash[ii] = -1;
+      }
+
+      if (hash_method == LINEAR){
+         if (hash_report_level == 0){
+            read_hash  = read_hash_linear;
+            write_hash = write_hash_linear;
+         } else if (hash_report_level == 1){
+            read_hash  = read_hash_linear_report_level_1;
+            write_hash = write_hash_linear_report_level_1;
+         } else if (hash_report_level == 2){
+            read_hash  = read_hash_linear_report_level_2;
+            write_hash = write_hash_linear_report_level_2;
+         } else if (hash_report_level == 3){
+            read_hash  = read_hash_linear_report_level_3;
+            write_hash = write_hash_linear_report_level_3;
+         }
+      } else if (hash_method == QUADRATIC) {
+         if (hash_report_level == 0){
+            read_hash  = read_hash_quadratic;
+            write_hash = write_hash_quadratic;
+         } else if (hash_report_level == 1){
+            read_hash  = read_hash_quadratic_report_level_1;
+            write_hash = write_hash_quadratic_report_level_1;
+         } else if (hash_report_level == 2){
+            read_hash  = read_hash_quadratic_report_level_2;
+            write_hash = write_hash_quadratic_report_level_2;
+         } else if (hash_report_level == 3){
+            read_hash  = read_hash_quadratic_report_level_3;
+            write_hash = write_hash_quadratic_report_level_3;
+         }
+      } else if (hash_method == PRIME_JUMP) {
+         if (hash_report_level == 0){
+            read_hash  = read_hash_primejump;
+            write_hash = write_hash_primejump;
+         } else if (hash_report_level == 1){
+            read_hash  = read_hash_primejump_report_level_1;
+            write_hash = write_hash_primejump_report_level_1;
+         } else if (hash_report_level == 2){
+            read_hash  = read_hash_primejump_report_level_2;
+            write_hash = write_hash_primejump_report_level_2;
+         } else if (hash_report_level == 3){
+            read_hash  = read_hash_primejump_report_level_3;
+            write_hash = write_hash_primejump_report_level_3;
+         }
+      }
+   } else {
+      hashtablesize = perfect_hash_size;
+
+      hash = (int *)genvector(hashtablesize,sizeof(int));
+      for (uint ii = 0; ii<hashtablesize; ii++){
+         hash[ii] = -1;
+      }
+
+      read_hash  = read_hash_perfect;
+      write_hash = write_hash_perfect;
+   }
+
+   if (hash_report_level >= 2) {
+      printf("Hash table size %u perfect hash table size %u memory savings %d by percentage %lf\n",
+        hashtablesize,isize*jsize,(int)isize*(int)jsize-(int)hashtablesize,
+        (double)hashtablesize/(double)(isize*jsize) * 100.0);
+   }
+
+   return(hash);
+}
+
+#ifdef _OPENMP
+int *compact_hash_init_openmp(int ncells, uint isize, uint jsize, uint report_level){
+   static int *hash = NULL;
+
+   static float hash_mem_factor;
+   static float hash_mem_ratio;
+   static int do_compact_hash;
+   static uint compact_hash_size;
+   static uint perfect_hash_size;
+
+#pragma omp barrier
+#pragma omp master
+   {
+
+      hash_ncells = 0;
+      write_hash_collisions = 0;
+      read_hash_collisions = 0;
+      hash_queries = 0;
+      hash_report_level = report_level;
+      hash_stride = isize;
+
+      if (choose_hash_method != METHOD_UNSET) hash_method = choose_hash_method;
+
+      compact_hash_size = (uint)((double)ncells*hash_mult);
+      perfect_hash_size = (uint)(isize*jsize);
+
+      if (hash_method == METHOD_UNSET){
+         hash_mem_factor = 20.0;
+         hash_mem_ratio = (double)perfect_hash_size/(double)compact_hash_size;
+         if (mem_opt_factor != 1.0) hash_mem_factor /= (mem_opt_factor*0.2); 
+         hash_method = (hash_mem_ratio < hash_mem_factor) ? PERFECT_HASH : QUADRATIC;
+         //hash_method = QUADRATIC;
+
+         if (hash_report_level >= 2) printf("DEBUG hash_method %d hash_mem_ratio %f hash_mem_factor %f mem_opt_factor %f perfect_hash_size %u compact_hash_size %u\n",
+            hash_method,hash_mem_ratio,hash_mem_factor,mem_opt_factor,perfect_hash_size,compact_hash_size);
+      }
+
+      do_compact_hash = (hash_method == PERFECT_HASH) ? 0 : 1;
+
+      if (hash_report_level >= 2) printf("DEBUG do_compact_hash %d hash_method %d perfect_hash_size %u compact_hash_size %u\n",
+         do_compact_hash,hash_method,perfect_hash_size,compact_hash_size);
+
+   } // end omp master
+#pragma omp barrier
+
+   if (do_compact_hash) {
+#pragma omp master
+      {
+         hashtablesize = compact_hash_size;
+         //srand48(0);
+         AA = (ulong)(1.0+(double)(prime-1)*drand48());
+         BB = (ulong)(0.0+(double)(prime-1)*drand48());
+         if (AA > prime-1 || BB > prime-1) exit(0);
+         if (hash_report_level > 1) printf("Factors AA %lu BB %lu\n",AA,BB);
+
+         hash = (int *)genvector(2*hashtablesize,sizeof(int));
+      } // end omp master
+#pragma omp barrier
+
+#pragma omp for
+      for (uint ii = 0; ii<hashtablesize; ii++){
+         hash[2*ii] = -1;
+      }
+
+#pragma omp master
+      {
+         if (hash_method == LINEAR){
+            if (hash_report_level == 0){
+               read_hash  = read_hash_linear;
+               write_hash = write_hash_linear_openmp;
+            } else if (hash_report_level == 1){
+               read_hash  = read_hash_linear_report_level_1;
+               write_hash = write_hash_linear_openmp_report_level_1;
+            } else if (hash_report_level == 2){
+               read_hash  = read_hash_linear_report_level_2;
+               write_hash = write_hash_linear_openmp_report_level_2;
+            } else if (hash_report_level == 3){
+               read_hash  = read_hash_linear_report_level_3;
+               write_hash = write_hash_linear_openmp_report_level_3;
+            }
+         } else if (hash_method == QUADRATIC) {
+            if (hash_report_level == 0){
+               read_hash  = read_hash_quadratic;
+               write_hash = write_hash_quadratic_openmp;
+            } else if (hash_report_level == 1){
+               read_hash  = read_hash_quadratic_report_level_1;
+               write_hash = write_hash_quadratic_openmp_report_level_1;
+            } else if (hash_report_level == 2){
+               read_hash  = read_hash_quadratic_report_level_2;
+               write_hash = write_hash_quadratic_openmp_report_level_2;
+            } else if (hash_report_level == 3){
+               read_hash  = read_hash_quadratic_report_level_3;
+               write_hash = write_hash_quadratic_openmp_report_level_3;
+            }
+         } else if (hash_method == PRIME_JUMP) {
+            if (hash_report_level == 0){
+               read_hash  = read_hash_primejump;
+               write_hash = write_hash_primejump_openmp;
+            } else if (hash_report_level == 1){
+               read_hash  = read_hash_primejump_report_level_1;
+               write_hash = write_hash_primejump_openmp_report_level_1;
+            } else if (hash_report_level == 2){
+               read_hash  = read_hash_primejump_report_level_2;
+               write_hash = write_hash_primejump_openmp_report_level_2;
+            } else if (hash_report_level == 3){
+               read_hash  = read_hash_primejump_report_level_3;
+               write_hash = write_hash_primejump_openmp_report_level_3;
+            }
+         }
+      } // end omp master
+#pragma omp barrier
+
+   } else {
+
+#pragma omp master
+      {
+         hashtablesize = perfect_hash_size;
+
+         hash = (int *)genvector(hashtablesize,sizeof(int));
+      } // end omp master
+#pragma omp barrier
+
+#pragma omp for
+      for (uint ii = 0; ii<hashtablesize; ii++){
+         hash[ii] = -1;
+      }
+
+#pragma omp master
+      {
+         read_hash  = read_hash_perfect;
+         write_hash = write_hash_perfect;
+      } // end omp master
+#pragma omp barrier
+   }
+
+#pragma omp master
+   {
+      if (hash_report_level >= 2) {
+         printf("Hash table size %u perfect hash table size %u memory savings %u by percentage %lf\n",
+           hashtablesize,isize*jsize,isize*jsize-hashtablesize,
+           (double)hashtablesize/(double)(isize*jsize));
+      }
+   }
+#pragma omp barrier
+
+   return(hash);
+}
+#endif
+
+void write_hash_perfect(uint ic, ulong hashkey, int *hash){
+   hash[hashkey] = ic;
+}
+
+void write_hash_linear(uint ic, ulong hashkey, int *hash){
+   uint hashloc;
+
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc++,hashloc = hashloc%hashtablesize);
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_linear_report_level_1(uint ic, ulong hashkey, int *hash){
+   uint hashloc;
+
+   hash_ncells++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc++,hashloc = hashloc%hashtablesize){
+      write_hash_collisions++;
+   }
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_linear_report_level_2(uint ic, ulong hashkey, int *hash){
+   uint hashloc;
+
+   hash_ncells++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc++,hashloc = hashloc%hashtablesize){
+      write_hash_collisions++;
+   }
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_linear_report_level_3(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   hash_ncells++;
+   hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc++,hashloc = hashloc%hashtablesize){
+      int hashloctmp = hashloc+1;
+      hashloctmp = hashloctmp%hashtablesize;
+      printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+      icount++;
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_quadratic(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize) {
+      icount++;
+   }
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_quadratic_report_level_1(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   hash_ncells++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_quadratic_report_level_2(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   hash_ncells++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_quadratic_report_level_3(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   hash_ncells++;
+   hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+      int hashloctmp = hashloc+icount*icount;
+      hashloctmp = hashloctmp%hashtablesize;
+      printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_primejump(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize) {
+      icount++;
+   }
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_primejump_report_level_1(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   hash_ncells++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_primejump_report_level_2(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   hash_ncells++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+void write_hash_primejump_report_level_3(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   hash_ncells++;
+   hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != -1 && hash[2*hashloc]!= (int)hashkey; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+      int hashloctmp = hashloc+1;
+      hashloctmp = hashloctmp%hashtablesize;
+      printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   }
+   write_hash_collisions += icount;
+
+   hash[2*hashloc] = hashkey;
+   hash[2*hashloc+1] = ic;
+}
+
+#ifdef _OPENMP
+void write_hash_linear_openmp(uint ic, ulong hashkey, int *hash){
+   int icount;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc++;
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+}
+
+void write_hash_linear_openmp_report_level_1(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc++;
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+      icount++;
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_linear_openmp_report_level_2(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc++;
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+      icount++;
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_linear_openmp_report_level_3(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;;
+   printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc++;
+      hashloc %= hashtablesize;
+      printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+      icount++;
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_quadratic_openmp(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*icount);
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+}
+
+void write_hash_quadratic_openmp_report_level_1(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*icount);
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_quadratic_openmp_report_level_2(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*icount);
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_quadratic_openmp_report_level_3(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*icount);
+      hashloc %= hashtablesize;
+      printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_primejump_openmp(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint jump = 1+hashkey%hash_jump_prime;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*jump);
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+}
+
+void write_hash_primejump_openmp_report_level_1(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint jump = 1+hashkey%hash_jump_prime;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*jump);
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_primejump_openmp_report_level_2(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint jump = 1+hashkey%hash_jump_prime;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*jump);
+      hashloc %= hashtablesize;
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+
+void write_hash_primejump_openmp_report_level_3(uint ic, ulong hashkey, int *hash){
+   int icount = 0;
+   uint jump = 1+hashkey%hash_jump_prime;
+   uint hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+
+   int MaxTries = 1000;
+
+   int old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   //printf("old_key is %d\n",old_key);
+
+   for (icount = 1; old_key != hashkey && old_key != -1 && icount < MaxTries; icount++){
+      hashloc+=(icount*jump);
+      hashloc %= hashtablesize;
+      printf("%d: cell %d hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,ic,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+
+      old_key = __sync_val_compare_and_swap(&hash[2*hashloc], -1, hashkey); 
+   }
+
+   if (icount < MaxTries) hash[2*hashloc+1] = ic;
+
+#pragma omp atomic
+   write_hash_collisions += icount;;
+#pragma omp atomic
+   hash_ncells++;
+}
+#endif
+
+int read_hash_perfect(ulong hashkey, int *hash){
+   return(hash[hashkey]);
+}
+
+int read_hash_linear(ulong hashkey, int *hash){
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_linear_report_level_1(ulong hashkey, int *hash){
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   hash_queries++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_linear_report_level_2(ulong hashkey, int *hash){
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   hash_queries++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+      icount++;
+      if (icount > max_collisions_allowed) {
+         printf("Error -- too many read hash collisions\n");
+         exit(0);
+      }
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_linear_report_level_3(ulong hashkey, int *hash){
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   hash_queries++;
+   hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+      icount++;
+      uint hashloctmp = hashloc+1;
+      hashloctmp = hashloctmp%hashtablesize;
+      printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+      if (icount > max_collisions_allowed) {
+         printf("Error -- too many read hash collisions\n");
+         exit(0);
+      }
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_quadratic(ulong hashkey, int *hash){
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_quadratic_report_level_1(ulong hashkey, int *hash){
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   hash_queries++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_quadratic_report_level_2(ulong hashkey, int *hash){
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   hash_queries++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+      if (icount > max_collisions_allowed) {
+         printf("Error -- too many read hash collisions\n");
+         exit(0);
+      }
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_quadratic_report_level_3(ulong hashkey, int *hash){
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   hash_queries++;
+   hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+      icount++;
+      uint hashloctmp = hashloc+1;
+      hashloctmp = hashloctmp%hashtablesize;
+      printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+      if (icount > max_collisions_allowed) {
+         printf("Error -- too many read hash collisions\n");
+         exit(0);
+      }
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_primejump(ulong hashkey, int *hash){
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_primejump_report_level_1(ulong hashkey, int *hash){
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   hash_queries++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_primejump_report_level_2(ulong hashkey, int *hash){
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   hash_queries++;
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+      if (icount > max_collisions_allowed) {
+         printf("Error -- too many read hash collisions\n");
+         exit(0);
+      }
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+int read_hash_primejump_report_level_3(ulong hashkey, int *hash){
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+
+   uint jump = 1+hashkey%hash_jump_prime;
+   hash_queries++;
+   hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+   printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+   for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+      icount++;
+      uint hashloctmp = hashloc+1;
+      hashloctmp = hashloctmp%hashtablesize;
+      printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+      if (icount > max_collisions_allowed) {
+         printf("Error -- too many read hash collisions\n");
+         exit(0);
+      }
+   }
+   read_hash_collisions += icount;
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+
+void compact_hash_delete(int *hash){
+   read_hash = NULL;
+   genvectorfree((void *)hash);
+   hash_method = METHOD_UNSET;
+}
+
+void write_hash_collision_report(void){
+   if (hash_method == PERFECT_HASH) return;
+   if (hash_report_level == 1) {
+      write_hash_collisions_runsum += (double)write_hash_collisions/(double)hash_ncells;
+      write_hash_collisions_count++;
+   } else if (hash_report_level >= 2) {
+      printf("Write hash collision report -- collisions per cell %lf, collisions %d cells %d\n",(double)write_hash_collisions/(double)hash_ncells,write_hash_collisions,hash_ncells);
+   }
+}
+
+void read_hash_collision_report(void){
+   //printf("hash table size  bytes %ld\n",hashtablesize*sizeof(int));
+   if (hash_method == PERFECT_HASH) return;
+   if (hash_report_level == 1) {
+      read_hash_collisions_runsum += (double)read_hash_collisions/(double)hash_queries;
+      read_hash_collisions_count++;
+   } else if (hash_report_level >= 2) {
+      printf("Read hash collision report -- collisions per cell %lf, collisions %d cells %d\n",(double)read_hash_collisions/(double)hash_queries,read_hash_collisions,hash_queries);
+      hash_queries = 0;
+      read_hash_collisions = 0;
+   }
+}
+
+void final_hash_collision_report(void){
+   printf("hash table size  bytes %ld\n",hashtablesize*sizeof(int));
+   if (hash_report_level >= 1 && read_hash_collisions_count > 0) { 
+      printf("Final hash collision report -- write/read collisions per cell %lf/%lf\n",write_hash_collisions_runsum/(double)write_hash_collisions_count,read_hash_collisions_runsum/(double)read_hash_collisions_count);
+   }
+}
+
+#ifdef HAVE_OPENCL
+const char *get_hash_kernel_source_string(void)
+{
+   return(hashlib_source_kern_source);
+}
+#endif
+
+#ifdef HAVE_OPENCL
+static cl_kernel kernel_hash_init;
+void hash_lib_init(void){
+   cl_context context = ezcl_get_context();
+
+   const char *defines = NULL;
+   cl_program program = ezcl_create_program_wsource(context, defines, hashlib_kern_source);
+
+   kernel_hash_init = ezcl_create_kernel_wprogram(program, "hash_init_cl");
+
+   ezcl_program_release(program);
+}
+
+void hash_lib_terminate(void){
+   ezcl_kernel_release(kernel_hash_init);
+}
+
+cl_mem gpu_compact_hash_init(ulong ncells, int imaxsize, int jmaxsize, int gpu_hash_method, uint hash_report_level_in,
+   ulong *gpu_hashtablesize, ulong *hashsize, cl_mem *dev_hash_header_in)
+{
+   hash_report_level = hash_report_level_in;
+
+   uint gpu_compact_hash_size = (uint)((double)ncells*hash_mult);
+   uint gpu_perfect_hash_size = (uint)(imaxsize*jmaxsize);
+
+   if (gpu_hash_method == METHOD_UNSET) {
+      float gpu_hash_mem_factor = 20.0;
+      float gpu_hash_mem_ratio = (double)gpu_perfect_hash_size/(double)gpu_compact_hash_size;
+      if (mem_opt_factor != 1.0) gpu_hash_mem_factor /= (mem_opt_factor*0.2);
+      gpu_hash_method = (gpu_hash_mem_ratio < gpu_hash_mem_factor) ? PERFECT_HASH : QUADRATIC;
+   }
+
+   int gpu_do_compact_hash = (gpu_hash_method == PERFECT_HASH) ? 0 : 1;
+
+   ulong gpu_AA = 1;
+   ulong gpu_BB = 0;
+   if (gpu_do_compact_hash){
+      (*gpu_hashtablesize) = gpu_compact_hash_size;
+      gpu_AA = (ulong)(1.0+(double)(prime-1)*drand48());
+      gpu_BB = (ulong)(0.0+(double)(prime-1)*drand48());
+      //if ( gpu_AA > prime-1 || gpu_BB > prime-1) exit(0);
+      (*hashsize) = 2*gpu_compact_hash_size;
+   } else {
+      (*gpu_hashtablesize) = gpu_perfect_hash_size;
+      (*hashsize) = gpu_perfect_hash_size;
+   }
+
+   hashtablesize = (*hashsize);
+
+   const uint TILE_SIZE = 128;
+
+   cl_command_queue command_queue = ezcl_get_command_queue();
+
+   cl_mem dev_hash = ezcl_malloc(NULL, "dev_hash", hashsize, sizeof(cl_int),  CL_MEM_READ_WRITE, 0);
+   ulong *gpu_hash_header = (ulong *)genvector(hash_header_size, sizeof(ulong));
+   gpu_hash_header[0] = (ulong)gpu_hash_method; 
+   gpu_hash_header[1] =        (*gpu_hashtablesize);
+   gpu_hash_header[2] =        gpu_AA;
+   gpu_hash_header[3] =        gpu_BB;
+   dev_hash_header = ezcl_malloc(NULL, "dev_hash_header", &hash_header_size, sizeof(cl_ulong),  CL_MEM_READ_WRITE, 0);
+   ezcl_enqueue_write_buffer(command_queue, dev_hash_header, CL_TRUE, 0, hash_header_size*sizeof(cl_ulong), &gpu_hash_header[0], NULL);
+
+   genvectorfree(gpu_hash_header);
+
+   (*dev_hash_header_in) = dev_hash_header;
+
+   size_t hash_local_work_size  = MIN((*hashsize), TILE_SIZE);
+   size_t hash_global_work_size = (((*hashsize)+hash_local_work_size - 1) /hash_local_work_size) * hash_local_work_size;
+
+   ezcl_set_kernel_arg(kernel_hash_init, 0, sizeof(cl_int),  (void *)hashsize);
+   ezcl_set_kernel_arg(kernel_hash_init, 1, sizeof(cl_mem),  (void *)&dev_hash);
+   ezcl_enqueue_ndrange_kernel(command_queue, kernel_hash_init,   1, NULL, &hash_global_work_size, &hash_local_work_size, NULL);
+
+   return(dev_hash);
+}
+
+void gpu_compact_hash_delete(cl_mem dev_hash, cl_mem dev_hash_header){
+   ezcl_device_memory_delete(dev_hash);
+   ezcl_device_memory_delete(dev_hash_header);
+   hash_method = METHOD_UNSET;
+}
+
+cl_mem gpu_get_hash_header(void){
+   return(dev_hash_header);
+}
+#endif
+
+int read_dev_hash(int hash_method, ulong hashtablesize, ulong AA, ulong BB, ulong hashkey, int *hash){
+   //int hash_report_level = 3;
+   int max_collisions_allowed = 1000;
+   int hashval = -1;
+   uint hashloc;
+   int icount=0;
+   if (hash_method == PERFECT_HASH) {
+      return(hash[hashkey]);
+   }
+   if (hash_method == LINEAR) {
+      if (hash_report_level == 0) {
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+            icount++;
+         }
+      } else if (hash_report_level == 1) {
+         hash_queries++;
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+            icount++;
+         }
+         read_hash_collisions += icount;
+      } else if (hash_report_level == 2) {
+         hash_queries++;
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+            icount++;
+            if (icount > max_collisions_allowed) {
+               printf("Error -- too many read hash collisions\n");
+               exit(0);
+            }
+         }
+         read_hash_collisions += icount;
+      } else if (hash_report_level == 3) {
+         hash_queries++;
+         hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+         printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc++,hashloc = hashloc%hashtablesize){
+            icount++;
+            uint hashloctmp = hashloc+1;
+            hashloctmp = hashloctmp%hashtablesize;
+            printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+            if (icount > max_collisions_allowed) {
+               printf("Error -- too many read hash collisions\n");
+               exit(0);
+            }
+         }
+         read_hash_collisions += icount;
+      } else {
+         printf("Error -- Illegal value of hash_report_level %d\n",hash_report_level);
+         exit(1);
+      }
+   } else if (hash_method == QUADRATIC) {
+      if (hash_report_level == 0) {
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+            icount++;
+         }
+      } else if (hash_report_level == 1) {
+         hash_queries++;
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+            icount++;
+         }
+         read_hash_collisions += icount;
+      } else if (hash_report_level == 2) {
+         hash_queries++;
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+            icount++;
+            if (icount > max_collisions_allowed) {
+               printf("Error -- too many read hash collisions\n");
+               exit(0);
+            }
+         }
+         read_hash_collisions += icount;
+      } else if (hash_report_level == 3) {
+         hash_queries++;
+         hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+         printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*icount),hashloc = hashloc%hashtablesize){
+            icount++;
+            uint hashloctmp = hashloc+1;
+            hashloctmp = hashloctmp%hashtablesize;
+            printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+            if (icount > max_collisions_allowed) {
+               printf("Error -- too many read hash collisions\n");
+               exit(0);
+            }
+         }
+         read_hash_collisions += icount;
+      } else {
+         printf("Error -- Illegal value of hash_report_level %d\n",hash_report_level);
+         exit(1);
+      }
+   } else if (hash_method == PRIME_JUMP) {
+      uint jump = 1+hashkey%hash_jump_prime;
+      if (hash_report_level == 0) {
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+            icount++;
+         }
+      } else if (hash_report_level == 1) {
+         hash_queries++;
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+            icount++;
+         }
+         read_hash_collisions += icount;
+      } else if (hash_report_level == 2) {
+         hash_queries++;
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+            icount++;
+            if (icount > max_collisions_allowed) {
+               printf("Error -- too many read hash collisions\n");
+               exit(0);
+            }
+         }
+         read_hash_collisions += icount;
+      } else if (hash_report_level == 3) {
+         hash_queries++;
+         hashloc = (hashkey*AA+BB)%prime%hashtablesize;
+         printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloc,hash[2*hashloc],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+         for (hashloc = (hashkey*AA+BB)%prime%hashtablesize; hash[2*hashloc] != (int)hashkey && hash[2*hashloc] != -1; hashloc+=(icount*jump),hashloc = hashloc%hashtablesize){
+            icount++;
+            uint hashloctmp = hashloc+1;
+            hashloctmp = hashloctmp%hashtablesize;
+            printf("%d: hashloc is %d hash[2*hashloc] = %d hashkey %lu ii %lu jj %lu\n",icount,hashloctmp,hash[2*hashloctmp],hashkey,hashkey%hash_stride,hashkey/hash_stride);
+            if (icount > max_collisions_allowed) {
+               printf("Error -- too many read hash collisions\n");
+               exit(0);
+            }
+         }
+         read_hash_collisions += icount;
+      } else {
+         printf("Error -- Illegal value of hash_report_level %d\n",hash_report_level);
+         exit(1);
+      }
+   } else {
+      printf("Error -- Illegal value of hash_method %d\n",hash_method);
+      exit(1);
+   }
+
+   if (hash[2*hashloc] != -1) hashval = hash[2*hashloc+1];
+   return(hashval);
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/hash.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hash.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,108 @@
+// Uses LANL Copyright Disclosure C14043/LA-CC-14-003
+
+#ifndef _HASH_H
+#define _HASH_H
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+
+#ifdef HAVE_OPENCL
+#include "ezcl/ezcl.h"
+#endif
+
+enum choose_hash_method
+{  METHOD_UNSET = 0,            //  use 0 for no method set
+   PERFECT_HASH,                //  perfect hash 1
+   LINEAR,                      //  linear hash 2
+   QUADRATIC,                   //  quadratic hash 3
+   PRIME_JUMP  };               //  prime_jump hash 4
+
+typedef unsigned int uint;
+typedef unsigned long ulong;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int *compact_hash_init(int ncells, uint isize, uint jsize, uint report_level);
+
+#ifdef _OPENMP
+   int *compact_hash_init_openmp(int ncells, uint isize, uint jsize, uint report_level);
+#endif
+
+int get_hash_method(void);
+long long get_hash_table_size(void);
+
+void write_hash_perfect(uint ic, ulong hashkey, int *hash);
+void write_hash_linear(uint ic, ulong hashkey, int *hash);
+void write_hash_linear_report_level_1(uint ic, ulong hashkey, int *hash);
+void write_hash_linear_report_level_2(uint ic, ulong hashkey, int *hash);
+void write_hash_linear_report_level_3(uint ic, ulong hashkey, int *hash);
+void write_hash_quadratic(uint ic, ulong hashkey, int *hash);
+void write_hash_quadratic_report_level_1(uint ic, ulong hashkey, int *hash);
+void write_hash_quadratic_report_level_2(uint ic, ulong hashkey, int *hash);
+void write_hash_quadratic_report_level_3(uint ic, ulong hashkey, int *hash);
+void write_hash_primejump(uint ic, ulong hashkey, int *hash);
+void write_hash_primejump_report_level_1(uint ic, ulong hashkey, int *hash);
+void write_hash_primejump_report_level_2(uint ic, ulong hashkey, int *hash);
+void write_hash_primejump_report_level_3(uint ic, ulong hashkey, int *hash);
+extern void (*write_hash)(uint ic, ulong hashkey, int *hash); // declared in hash.c
+
+#ifdef _OPENMP
+   void write_hash_linear_openmp(uint ic, ulong hashkey, int *hash);
+   void write_hash_linear_openmp_report_level_1(uint ic, ulong hashkey, int *hash);
+   void write_hash_linear_openmp_report_level_2(uint ic, ulong hashkey, int *hash);
+   void write_hash_linear_openmp_report_level_3(uint ic, ulong hashkey, int *hash);
+   void write_hash_quadratic_openmp(uint ic, ulong hashkey, int *hash);
+   void write_hash_quadratic_openmp_report_level_1(uint ic, ulong hashkey, int *hash);
+   void write_hash_quadratic_openmp_report_level_2(uint ic, ulong hashkey, int *hash);
+   void write_hash_quadratic_openmp_report_level_3(uint ic, ulong hashkey, int *hash);
+   void write_hash_primejump_openmp(uint ic, ulong hashkey, int *hash);
+   void write_hash_primejump_openmp_report_level_1(uint ic, ulong hashkey, int *hash);
+   void write_hash_primejump_openmp_report_level_2(uint ic, ulong hashkey, int *hash);
+   void write_hash_primejump_openmp_report_level_3(uint ic, ulong hashkey, int *hash);
+   extern void (*write_hash)(uint ic, ulong hashkey, int *hash); // declared in hash.c
+#endif
+
+int read_hash_perfect(ulong hashkey, int *hash);
+int read_hash_linear(ulong hashkey, int *hash);
+int read_hash_linear_report_level_1(ulong hashkey, int *hash);
+int read_hash_linear_report_level_2(ulong hashkey, int *hash);
+int read_hash_linear_report_level_3(ulong hashkey, int *hash);
+int read_hash_quadratic(ulong hashkey, int *hash);
+int read_hash_quadratic_report_level_1(ulong hashkey, int *hash);
+int read_hash_quadratic_report_level_2(ulong hashkey, int *hash);
+int read_hash_quadratic_report_level_3(ulong hashkey, int *hash);
+int read_hash_primejump(ulong hashkey, int *hash);
+int read_hash_primejump_report_level_1(ulong hashkey, int *hash);
+int read_hash_primejump_report_level_2(ulong hashkey, int *hash);
+int read_hash_primejump_report_level_3(ulong hashkey, int *hash);
+extern int (*read_hash)(ulong hashkey, int *hash); // declared in hash.c
+
+void compact_hash_delete(int *hash);
+
+void write_hash_collision_report(void);
+void read_hash_collision_report(void);
+void final_hash_collision_report(void);
+
+const char *get_hash_kernel_source_string(void);
+void hash_lib_init(void);
+void hash_lib_terminate(void);
+
+#ifdef HAVE_OPENCL
+cl_mem gpu_compact_hash_init(ulong ncells, int imaxsize, int jmaxsize, int gpu_hash_method, uint hash_report_level_in,
+   ulong *gpu_hash_table_size, ulong *hashsize, cl_mem *dev_hash_header_in);
+cl_mem gpu_get_hash_header(void);
+void gpu_compact_hash_delete(cl_mem dev_hash, cl_mem dev_hash_header);
+#endif
+int read_dev_hash(int hash_method, ulong hash_table_size, ulong AA, ulong BB, ulong hashkey, int *hash);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // _HASH_H
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/hsfc.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,279 @@
+/* ---------------------------------------------------------------------
+Author:     H. Carter Edwards 
+            hcedwar at sandia.gov
+
+Copyright:  Copyright (C) 1997   H. Carter Edwards
+            Graduate Student
+            University of Texas
+
+Re-release: Copyright (C) 2011-2012   H. Carter Edwards
+
+Purpose:    Domain paritioning based upon Hilbert Space-Filling Curve
+            ordering.
+
+License:    Re-release under the less-restrictive CLAMR software terms.
+            Permitted by email with H. Carter Edwards on 9/13/2011
+
+Disclaimer:
+
+    These routines comes with ABSOLUTELY NO WARRANTY;
+    This is free software, and you are welcome to redistribute it
+    under certain conditions. See License terms in file 'LICENSE'.
+--------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------
+Description:
+  Inverse of the Hilbert Space-Filling Curve Map from a 2D or 3D
+domain to the 1D domain.  Two different 2D and 3D domains are
+supported.
+
+For the routines 'hsfc2d' and 'hsfc3d' the 2D and 3D domains are
+defined as follows.
+Note that
+  *     0   is the minimum value of an unsigned integer
+  *   ~(0u) is the maximum value of an unsigned integer - all bits set
+thus the 2D and 3D domains are
+  *   [0,~(0u)] x [0,~(0u)]
+  *   [0,~(0u)] x [0,~(0u)] x [0,~(0u)]
+respectively.
+
+For the routines 'fhsfc2d' and 'fhsfc3d' the 2D and 3D domains are
+defines as:
+  *   [0.0,1.0] x [0.0,1.0]
+  *   [0.0,1.0] x [0.0,1.0] x [0.0,1.0]
+respectively.
+
+The 1D domain is a multiword (array of unsigned integers) key.
+This key is essentially an unsigned integer of an arbitrary
+number of bits.  The most significant bit is the leading bit
+of the first (0th) word of the key.  The least significant
+bit is the trailing bit of the last word.
+
+----------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <limits.h>
+
+/* Bits per unsigned word */
+
+#define MaxBits ( sizeof(unsigned) * CHAR_BIT )
+
+/*--------------------------------------------------------------------*/
+/* 2D Hilbert Space-filling curve */
+
+void hsfc2d(
+  unsigned   coord[] , /* IN: Normalized integer coordinates */
+  unsigned   nkey ,    /* IN: Word length of key */
+  unsigned   key[] )   /* OUT: space-filling curve key */
+{
+  static int init = 0 ;
+  static unsigned char gray_inv[ 2 * 2 ] ;
+
+  const unsigned NKey  = ( 2 < nkey ) ? 2 : (nkey) ;
+  const unsigned NBits = ( MaxBits * NKey ) / 2 ;
+
+  unsigned i ;
+  unsigned char order[2+2] ;
+  unsigned char reflect ;
+  
+  /* GRAY coding */
+
+  if ( ! init ) {
+    unsigned char gray[ 2 * 2 ] ;
+    register unsigned k ;
+    register unsigned j ;
+
+    gray[0] = 0 ;
+    for ( k = 1 ; k < sizeof(gray) ; k <<= 1 ) {
+      for ( j = 0 ; j < k ; j++ ) gray[k+j] = k | gray[k-(j+1)] ;
+    }
+    for ( k = 0 ; k < sizeof(gray) ; k++ ) gray_inv[ gray[k] ] = k ;
+    init = 1 ;
+  }
+
+  /* Zero out the key */
+
+  for ( i = 0 ; i < NKey ; ++i ) key[i] = 0 ;
+
+  order[0] = 0 ;
+  order[1] = 1 ;
+  reflect = ( 0 << 0 ) | ( 0 );
+
+  for ( i = 1 ; i <= NBits ; i++ ) {
+    const unsigned s = MaxBits - i ;
+    const unsigned c = gray_inv[ reflect ^ (
+      ( ( ( coord[0] >> s ) & 01 ) << order[0] ) |
+      ( ( ( coord[1] >> s ) & 01 ) << order[1] ) ) ];
+     
+    const unsigned off   = 2 * i ;                   /* Bit offset */
+    const unsigned which = off / MaxBits ;           /* Which word to update */
+    const unsigned shift = MaxBits - off % MaxBits ; /* Which bits to update */
+
+    /* Set the two bits */
+
+    if ( shift == MaxBits ) { /* Word boundary */
+      key[ which - 1 ] |= c ;
+    }
+    else {
+      key[ which ] |= c << shift ;
+    }
+
+    /* Determine the recursive quadrant */
+
+    switch( c ) {
+    case 3:
+      reflect ^= 03 ;
+    case 0:
+      order[2+0] = order[0] ;
+      order[2+1] = order[1] ;
+      order[0] = order[2+1] ;
+      order[1] = order[2+0] ;
+      break ;
+    }
+  }
+}
+
+/*--------------------------------------------------------------------*/
+/* 3D Hilbert Space-filling curve */
+
+void hsfc3d(
+  unsigned   coord[] , /* IN: Normalized integer coordinates */
+  unsigned   nkey ,    /* IN: Word length of 'key' */
+  unsigned   key[] )   /* OUT: space-filling curve key */
+{
+  static int init = 0 ;
+  static unsigned char gray_inv[ 2*2*2 ] ;
+
+  const unsigned NKey  = ( 3 < nkey ) ? 3 : (nkey) ;
+  const unsigned NBits = ( MaxBits * NKey ) / 3 ;
+
+  unsigned i ;
+  unsigned char axis[3+3] ;
+  
+  /* GRAY coding */
+
+  if ( ! init ) {
+    unsigned char gray[ 2*2*2 ] ;
+    register unsigned k ;
+    register unsigned j ;
+
+    gray[0] = 0 ;
+    for ( k = 1 ; k < sizeof(gray) ; k <<= 1 ) {
+      for ( j = 0 ; j < k ; j++ ) gray[k+j] = k | gray[k-(j+1)] ;
+    }
+    for ( k = 0 ; k < sizeof(gray) ; k++ ) gray_inv[ gray[k] ] = k ;
+    init = 1 ;
+  }
+
+  /* Zero out the key */
+
+  for ( i = 0 ; i < NKey ; ++i ) key[i] = 0 ;
+
+  axis[0] = 0 << 1 ;
+  axis[1] = 1 << 1 ;
+  axis[2] = 2 << 1 ;
+
+  for ( i = 1 ; i <= NBits ; i++ ) {
+    const unsigned s = MaxBits - i ;
+    const unsigned c = gray_inv[
+      (((( coord[ axis[0] >> 1 ] >> s ) ^ axis[0] ) & 01 ) << 0 ) |
+      (((( coord[ axis[1] >> 1 ] >> s ) ^ axis[1] ) & 01 ) << 1 ) |
+      (((( coord[ axis[2] >> 1 ] >> s ) ^ axis[2] ) & 01 ) << 2 ) ];
+    unsigned n ;
+
+    /* Set the 3bits */
+
+    for ( n = 0 ; n < 3 ; ++n ) {
+      const unsigned bit   = 01 & ( c >> ( 2 - n ) );  /* Bit value  */
+      const unsigned off   = 3 * i + n ;               /* Bit offset */
+      const unsigned which = off / MaxBits ;           /* Which word */
+      const unsigned shift = MaxBits - off % MaxBits ; /* Which bits */
+
+      if ( MaxBits == shift ) { /* Word boundary */
+        key[ which - 1 ] |= bit ;
+      }
+      else {
+        key[ which ] |= bit << shift ;
+      }
+    }
+
+    /* Determine the recursive quadrant */
+
+    axis[3+0] = axis[0] ;
+    axis[3+1] = axis[1] ;
+    axis[3+2] = axis[2] ;
+
+    switch( c ) {
+    case 0:
+      axis[0] = axis[3+2];
+      axis[1] = axis[3+1];
+      axis[2] = axis[3+0];
+      break ;
+    case 1:
+      axis[0] = axis[3+0];
+      axis[1] = axis[3+2];
+      axis[2] = axis[3+1];
+      break ;
+    case 2:
+      axis[0] = axis[3+0];
+      axis[1] = axis[3+1];
+      axis[2] = axis[3+2];
+      break ;
+    case 3:
+      axis[0] = axis[3+2] ^ 01 ;
+      axis[1] = axis[3+0] ^ 01 ;
+      axis[2] = axis[3+1];
+      break ;
+    case 4:
+      axis[0] = axis[3+2];
+      axis[1] = axis[3+0] ^ 01 ;
+      axis[2] = axis[3+1] ^ 01 ;
+      break ;
+    case 5:
+      axis[0] = axis[3+0];
+      axis[1] = axis[3+1];
+      axis[2] = axis[3+2];
+      break ;
+    case 6:
+      axis[0] = axis[3+0];
+      axis[1] = axis[3+2] ^ 01 ;
+      axis[2] = axis[3+1] ^ 01 ;
+      break ;
+    case 7:
+      axis[0] = axis[3+2] ^ 01 ;
+      axis[1] = axis[3+1];
+      axis[2] = axis[3+0] ^ 01 ;
+      break ;
+    default:
+      exit(-1);
+    }
+  }
+}
+
+/*--------------------------------------------------------------------*/
+
+void fhsfc2d(
+  double     coord[] , /* IN: Normalized floating point coordinates */
+  unsigned   nkey ,    /* IN: Word length of key */
+  unsigned   key[] )   /* OUT: space-filling curve key */
+{
+  const double imax = ~(0u);
+  unsigned c[2] ;
+  c[0] = coord[0] * imax ;
+  c[1] = coord[1] * imax ;
+  hsfc2d( c , nkey , key );
+}
+
+void fhsfc3d(
+  double     coord[] , /* IN: Normalized floating point coordinates */
+  unsigned   nkey ,    /* IN: Word length of key */
+  unsigned   key[] )   /* OUT: space-filling curve key */
+{
+  const double imax = ~(0u);
+  unsigned c[3] ;
+  c[0] = coord[0] * imax ;
+  c[1] = coord[1] * imax ;
+  c[2] = coord[2] * imax ;
+  hsfc3d( c , nkey , key );
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/hsfc.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfc.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,86 @@
+/* ---------------------------------------------------------------------
+Author:     H. Carter Edwards 
+            hcedwar at sandia.gov
+
+Copyright:  Copyright (C) 1997   H. Carter Edwards
+            Graduate Student
+            University of Texas
+
+Re-release: Copyright (C) 2011-2012   H. Carter Edwards
+
+Purpose:    Domain paritioning based upon Hilbert Space-Filling Curve
+            ordering.
+
+License:    Re-release under the less-restrictive CLAMR software terms.
+            Permitted by email with H. Carter Edwards on 9/13/2011
+
+Disclaimer:
+
+    These routines comes with ABSOLUTELY NO WARRANTY;
+    This is free software, and you are welcome to redistribute it
+    under certain conditions. See License terms in file 'LICENSE'.
+--------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------
+Description:
+  Inverse of the Hilbert Space-Filling Curve Map from a 2D or 3D
+domain to the 1D domain.  Two different 2D and 3D domains are
+supported.
+
+For the routines 'hsfc2d' and 'hsfc3d' the 2D and 3D domains are
+defined as follows.
+Note that
+  *     0   is the minimum value of an unsigned integer
+  *   ~(0u) is the maximum value of an unsigned integer - all bits set
+thus the 2D and 3D domains are
+  *   [0,~(0u)] x [0,~(0u)]
+  *   [0,~(0u)] x [0,~(0u)] x [0,~(0u)]
+respectively.
+
+For the routines 'fhsfc2d' and 'fhsfc3d' the 2D and 3D domains are
+defines as:
+  *   [0.0,1.0] x [0.0,1.0]
+  *   [0.0,1.0] x [0.0,1.0] x [0.0,1.0]
+respectively.
+
+The 1D domain is a multiword (array of unsigned integers) key.
+This key is essentially an unsigned integer of an arbitrary
+number of bits.  The most significant bit is the leading bit
+of the first (0th) word of the key.  The least significant
+bit is the trailing bit of the last word.
+
+----------------------------------------------------------------------*/
+
+#ifndef __HILBERT_SPACE_FILLING_CURVE_MAPPING__
+#define __HILBERT_SPACE_FILLING_CURVE_MAPPING__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void hsfc2d(
+  unsigned   coord[] , /* IN: Normalized integer 2D coordinate */
+  unsigned   nkey ,    /* IN: Word length of key */
+  unsigned   key[] );  /* OUT: space-filling curve key */
+
+extern void hsfc3d(
+  unsigned   coord[] , /* IN: Normalized integer 3D coordinate */
+  unsigned   nkey ,    /* IN: Word length of 'key' */
+  unsigned   key[] );  /* OUT: space-filling curve key */
+
+extern void fhsfc2d(
+  double     coord[] , /* IN: Normalized floating point 2D coordinate */
+  unsigned   nkey ,    /* IN: Word length of key */
+  unsigned   key[] );  /* OUT: space-filling curve key */
+
+extern void fhsfc3d(
+  double     coord[] , /* IN: Normalized floating point 3D coordinate */
+  unsigned   nkey ,    /* IN: Word length of key */
+  unsigned   key[] );  /* OUT: space-filling curve key */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfcsort.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/hsfcsort.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfcsort.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/hsfcsort.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,268 @@
+/* ---------------------------------------------------------------------
+Author:     H. Carter Edwards 
+            hcedwar at sandia.gov
+
+Copyright:  Copyright (C) 1997   H. Carter Edwards
+            Graduate Student
+            University of Texas
+
+Re-release: Copyright (C) 2011-2012   H. Carter Edwards
+
+Purpose:    Domain paritioning based upon Hilbert Space-Filling Curve
+            ordering.
+
+License:    Re-release under the less-restrictive CLAMR software terms.
+            Permitted by email with H. Carter Edwards on 9/13/2011
+
+Disclaimer:
+
+    These routines comes with ABSOLUTELY NO WARRANTY;
+    This is free software, and you are welcome to redistribute it
+    under certain conditions. See License terms in file 'LICENSE'.
+--------------------------------------------------------------------- */
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include "hsfc.h"
+
+/*--------------------------------------------------------------------*/
+/* Make it callable from FORTRAN:
+ *   Interface types: INTEGER and REAL*8
+ */
+
+void hsfc2sort(
+               const int      N ,     /* IN: Number of points */
+               const double * X ,     /* IN: array of X-Coordinates */
+               const double * Y ,     /* IN: array of Y-Coordinates */
+               const int      ibase,  /* 0 for C and 1 for Fortran */
+               int          * Info ,  /* OUT: (1 <= LDInfo) [ HSFC ordering ]
+                                 (2 <= LDInfo) [ HSFC index, #1 ]
+                                 (3 <= LDInfo) [ HSFC index, #2 ] */
+               int            LDInfo /* IN:  Leading dimension of Info */
+               );
+
+/*--------------------------------------------------------------------*/
+
+#define MaxBits ( sizeof(unsigned) * CHAR_BIT )
+
+#define NBITC     (32)  /* 32 Bits per coordinate, resolve data at 2^31 */
+#define NKEY(ND)  ((NBITC * ND + MaxBits - 1) / MaxBits)
+
+/*--------------------------------------------------------------------*/
+
+static int ui1comp( const void * const I1 , const void * const I2 )
+{
+  return (
+    ( ((const unsigned *)I1)[0] != ((const unsigned *)I2)[0] ) ? (
+    ( ((const unsigned *)I1)[0] <  ((const unsigned *)I2)[0] ) ? -1 : 1 ) : (
+       0 ));
+}
+
+static int ui2comp( const void * const I1 , const void * const I2 )
+{
+  return (
+    ( ((const unsigned *)I1)[0] != ((const unsigned *)I2)[0] ) ? (
+    ( ((const unsigned *)I1)[0] <  ((const unsigned *)I2)[0] ) ? -1 : 1 ) : (
+    ( ((const unsigned *)I1)[1] != ((const unsigned *)I2)[1] ) ? (
+    ( ((const unsigned *)I1)[1] <  ((const unsigned *)I2)[1] ) ? -1 : 1 ) : (
+       0 )));
+}
+
+/*--------------------------------------------------------------------*/
+
+static int ui3comp( const void * const I1 , const void * const I2 )
+{
+  return (
+    ( ((const unsigned *)I1)[0] != ((const unsigned *)I2)[0] ) ? (
+    ( ((const unsigned *)I1)[0] <  ((const unsigned *)I2)[0] ) ? -1 : 1 ) : (
+    ( ((const unsigned *)I1)[1] != ((const unsigned *)I2)[1] ) ? (
+    ( ((const unsigned *)I1)[1] <  ((const unsigned *)I2)[1] ) ? -1 : 1 ) : (
+    ( ((const unsigned *)I1)[2] != ((const unsigned *)I2)[2] ) ? (
+    ( ((const unsigned *)I1)[2] <  ((const unsigned *)I2)[2] ) ? -1 : 1 ) : (
+       0 ))));
+}
+
+static int N_uiNcomp = 0 ;
+
+static int uiNcomp( const void * const I1 , const void * const I2 )
+{
+  const int N = N_uiNcomp ;
+  register int i ;
+
+  for ( i = 0 ; i < N &&
+    ((const unsigned *)I1)[i] != ((const unsigned *)I2)[i] ; ++i );
+
+  return ( i < N ) ? (
+    ( ((const unsigned *)I1)[i] < ((const unsigned *)I2)[i] ) ? -1 : 1 ) : 0 ;
+}
+
+/*--------------------------------------------------------------------*/
+
+void hsfc2sort(
+  const int      N ,     /* IN: Number of points */
+  const double * X ,     /* IN: array of X-Coordinates */
+  const double * Y ,     /* IN: array of Y-Coordinates */
+  const int      ibase,  /* 0 for C and 1 for Fortran */
+        int    * Info ,  /* OUT: (1 <= LDInfo) [ HSFC ordering ]
+                                   (2 <= LDInfo) [ HSFC index, #1 ]
+                                   (3 <= LDInfo) [ HSFC index, #2 ] */
+        int      LDInfo )/* IN:  Leading dimension of Info */
+{
+  /*------------------------------------------------------------------*/
+
+  const double imax = ((double) ~(0u)) ;
+
+  const unsigned ldinfo = LDInfo ;
+  const unsigned long long npt    = N ;
+  const unsigned nkey   = NKEY(2) ;
+  const unsigned ldT    = nkey + 1 ;
+
+  unsigned * const T = (unsigned *) malloc( sizeof(unsigned) * ldT * npt );
+
+  int i , ix , iy , ii , it ;
+
+  /* Fill SFC table */
+
+  for ( i = it = ix = iy = 0 ; (unsigned long long)i < npt ;
+        ++i , ix++ , iy++ , it += ldT ) {
+    double xy[2] ;
+    unsigned coord[2] ;
+
+    xy[0] = X[ix] ;
+    xy[1] = Y[iy] ;
+
+    coord[0] = xy[0] * imax ;
+    coord[1] = xy[1] * imax ;
+
+    hsfc2d( coord , nkey , T + it );
+    T[it+nkey] = i ;
+  }
+
+  /* SFC Key output */
+  
+  if ( 2 < ldinfo && 1 < nkey ) {
+    for ( ii = 1, it = 0, i = 0 ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT ) {
+      Info[ii]   = T[it];
+      Info[ii+1] = T[it+1];
+    }
+  }
+  else if ( 1 < ldinfo ) {
+    for ( ii = 1, it = 0 ,i = 0 ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT ) {
+      Info[ii] = T[it] ;
+    }
+  }
+
+  /* Sort */
+
+  switch ( nkey ) {
+  case 0: break ;
+  case 1: qsort( T , npt , sizeof(unsigned) * ldT , ui1comp ); break ;
+  case 2: qsort( T , npt , sizeof(unsigned) * ldT , ui2comp ); break ;
+  case 3: qsort( T , npt , sizeof(unsigned) * ldT , ui3comp ); break ;
+  default:
+    N_uiNcomp = nkey ;
+    qsort( T , npt , sizeof(unsigned) * ldT , uiNcomp );
+    N_uiNcomp = 0 ;
+    break ;
+  }
+
+  for (ii = 0, i = 0, it = nkey ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT) {
+    Info[ii] = T[it] + ibase; /* 1 -- FORTRAN convention, 0 -- C */
+  }
+
+  free( (void *) T );
+
+  return ;
+}
+
+/*--------------------------------------------------------------------*/
+
+void hsfc3sort(
+  const int      N ,     /* IN: Number of points */
+  const double * X ,     /* IN: array of X-Coordinates */
+  const double * Y ,     /* IN: array of Y-Coordinates */
+  const double * Z ,     /* IN: array of Y-Coordinates */
+  const int      ibase ,    /* IN: Stride for Y array */
+        int    * Info ,  /* OUT: (1 <= LDInfo) [ HSFC ordering ]
+                                   (2 <= LDInfo) [ HSFC index, #1 ]
+                                   (3 <= LDInfo) [ HSFC index, #2 ]
+                                   (4 <= LDInfo) [ HSFC index, #3 ] */
+        int      LDInfo )/* IN:  Leading dimension of Info */
+{
+  /*------------------------------------------------------------------*/
+
+  const double imax = ((double) ~(0u)) ;
+
+  const unsigned ldinfo = LDInfo ;
+  const unsigned long long npt    = N ;
+  const unsigned nkey   = NKEY(3) ;
+  const unsigned ldT    = nkey + 1 ;
+
+  unsigned * const T = (unsigned *) malloc( sizeof(unsigned) * ldT * npt );
+
+  int i , ix , iy , iz , ii , it ;
+
+  /* Fill SFC table */
+
+  for ( i = it = ix = iy = iz = 0 ; (unsigned long long)i < npt ;
+        ++i , ix++ , iy++ , iz++ , it += ldT ) {
+    double xyz[3] ;
+    unsigned coord[3] ;
+
+    xyz[0] = X[ix] ;
+    xyz[1] = Y[iy] ;
+    xyz[2] = Z[iz] ;
+
+    coord[0] = xyz[0] * imax ;
+    coord[1] = xyz[1] * imax ;
+    coord[2] = xyz[2] * imax ;
+
+    hsfc3d( coord , nkey , T + it );
+    T[it+nkey] = i ;
+  }
+
+  /* SFC Key output */
+  
+  if ( 3 < ldinfo && 2 < nkey ) {
+    for ( ii = 1, it = 0, i = 0 ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT ) {
+      Info[ii]   = T[it];
+      Info[ii+1] = T[it+1];
+      Info[ii+2] = T[it+2];
+    }
+  }
+  else if ( 2 < ldinfo && 1 < nkey ) {
+    for ( ii = 1, it = 0, i = 0 ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT ) {
+      Info[ii]   = T[it];
+      Info[ii+1] = T[it+1];
+    }
+  }
+  else if ( 1 < ldinfo ) {
+    for ( ii = 1, it = 0 ,i = 0 ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT ) {
+      Info[ii] = T[it] ;
+    }
+  }
+
+  /* Sort */
+
+  switch ( nkey ) {
+  case 0: break ;
+  case 1: qsort( T , npt , sizeof(unsigned) * ldT , ui1comp ); break ;
+  case 2: qsort( T , npt , sizeof(unsigned) * ldT , ui2comp ); break ;
+  case 3: qsort( T , npt , sizeof(unsigned) * ldT , ui3comp ); break ;
+  default:
+    N_uiNcomp = nkey ;
+    qsort( T , npt , sizeof(unsigned) * ldT , uiNcomp );
+    N_uiNcomp = 0 ;
+    break ;
+  }
+
+  for (ii = 0, i = 0, it = nkey ; (unsigned long long)i < npt ; ++i, ii += ldinfo, it += ldT) {
+    Info[ii] = T[it] + ibase ; /* FORTRAN convention */
+  }
+
+  free( (void *) T );
+
+  return ;
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.cpp
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/input.cpp?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.cpp (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.cpp Mon Sep  4 07:25:36 2017
@@ -0,0 +1,513 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ *  
+ *  This file and the associated header is based on a file from the capablanca
+ *  project available under the MIT open-source license.  As author of that code,
+ *  I, Neal Davis, permit repurposing and redistribution for CLAMR under the New
+ *  BSD License used above.
+ *      http://code.google.com/p/capablanca/
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "state.h"
+#include "partition.h"
+#include "mesh.h"
+#include "hash.h"
+#include "crux.h"
+//#include "graphics/display.h"
+#include "graphics.h"
+
+#include <fstream>
+#include <iostream>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <sys/stat.h>
+#include <limits.h>
+
+#define OUTPUT_INTERVAL 100
+#define COARSE_GRID_RES 128
+#define MAX_TIME_STEP 3000
+
+using namespace std;
+
+//  Global variables.
+char progName[12];      //  Program name.
+char progVers[8];       //  Program version.
+
+//  External global variables.
+extern bool verbose,
+            localStencil,
+            outline,
+            face_based,
+            dynamic_load_balance_on,
+            h5_spoutput,
+            neighbor_remap,
+            restart;
+extern int  outputInterval,
+            crux_type,
+            enhanced_precision_sum,
+            tmax,
+            levmx,
+            nx,
+            ny,
+            niter,
+            measure_type,
+            lttrace_on,
+            do_quo_setup,
+            calc_neighbor_type,
+	    choose_hash_method,
+            initial_order,
+            graphic_outputInterval,
+            graphics_type,
+            checkpoint_outputInterval,
+            num_of_rollback_states,
+            cycle_reorder;
+extern float
+            mem_opt_factor;
+extern double
+            upper_mass_diff_percentage;
+
+extern char* restart_file;
+
+void outputHelp()
+{   cout << "CLAMR is an experimental adaptive mesh refinement code for the GPU." << endl
+         #ifdef PACKAGE_VERSION 
+         << "Version is " << PACKAGE_VERSION << endl << endl 
+         #endif
+         << "Usage:  " << progName << " [options]..." << endl
+         << "  -b <B>            Number of rollback images, disk or in memory (default 2);" << endl
+         << "  -c <C>            Checkpoint to disk at interval specified;" << endl
+         << "  -C <C>            Checkpoint to memory at interval specified;" << endl
+         << "  -d                turn on LTTRACE;" << endl
+         << "  -D                turn on dynamic load balancing using LTTRACE;" << endl
+         << "  -e <E>            force hash_method, ie linear, quadratic..." <<endl          
+         << "      \"perfect\"" << endl
+         << "      \"linear\"" << endl
+         << "      \"quadratic\"" << endl
+         << "      \"prime_jump\"" << endl
+         << "  -f                face-based finite difference;" << endl
+         << "  -g <g>            specify I step between saving graphics information for post processing;" << endl
+         << "  -G <G>            specify graphics file type for post processing;" << endl
+         << "      \"bmp\"" << endl
+         << "      \"gif\"" << endl
+         << "      \"jpeg\"" << endl
+         << "      \"mpeg\"" << endl
+         << "      \"pdf\"" << endl
+         << "      \"png\"" << endl
+         << "      \"svg\"" << endl
+         << "      \"data\"" << endl
+         << "  -h                display this help message;" << endl
+         << "  -i <I>            specify I steps between output files;" << endl
+         << "  -l <l>            max number of levels;" << endl
+         << "  -M <M>            memory optimization factor 1.0 <= M <=100.0 (default 1.0 -- represents 1/20 perfect hash);" << endl
+         << "  -m <m>            specify partition measure type;" << endl
+         << "      \"with_duplicates\"" << endl
+         << "      \"without_duplicates\"" << endl
+         << "  -N <n>            specify calc neighbor type;" << endl
+         << "      \"hash_table\"" << endl
+         << "      \"kdtree\"" << endl
+         << "  -n <N>            specify coarse grid resolution of NxN;" << endl
+         << "  -o                turn off outlines;" << endl
+         << "  -P <P>            specify initial order P;" << endl
+         << "      \"original_order\"" << endl
+         << "      \"hilbert_sort\"" << endl
+         << "      \"hilbert_partition\"" << endl
+         << "      \"z_order\"" << endl
+         << "  -p <p>            specify ordering P every cycle;" << endl
+         << "      \"original_order\"" << endl
+         << "      \"hilbert_sort\"" << endl
+         << "      \"hilbert_partition\"" << endl
+         << "      \"local_hilbert\"" << endl
+         << "      \"local_fixed\"" << endl
+         << "      \"z_order\"" << endl
+         << "  -q                turn on quo;" << endl
+         << "  -r                regular sum instead of enhanced precision sum (Kahan sum);" << endl
+         << "  -R                restart simulation from the backup file specified;" << endl
+         << "  -s <s>            specify space-filling curve method S;" << endl
+         << "  -S                write out double precision data as single precision;" << endl
+         << "  -T                execute with TVD;" << endl
+         << "  -t <t>            specify T time steps to run;" << endl
+         << "  -u                allowed percentage of difference between total mass between iterations." << endl
+         << "                    the default value for this parameter is 2.6e-13;" << endl
+         << "  -V                use verbose output;" << endl
+         << "  -v                display version information." << endl
+         << "  -z                force recalculation of neighbors." << endl; }
+
+void outputVersion()
+{   cout << progName << " " << progVers << endl; }
+
+/*  parseInput(const int argc, char** argv)
+ *  
+ *  Interpret the command line input.
+ */
+void parseInput(const int argc, char** argv)
+{   strcpy(progName, "clamr");
+    #ifdef PACKAGE_VERSION
+    strcpy(progVers, PACKAGE_VERSION);
+   #endif
+    //	Reconstruct command line argument as a string.
+    char progCL[256];       //  Complete program command line.
+    strcpy(progCL, argv[0]);
+    for (int i = 1; i < argc; i++)
+    {   strcat(progCL, " ");
+        strcat(progCL, argv[i]); }
+    
+    //  Set variables to defaults, which may be overridden by CLI.
+    verbose                 = false;
+    localStencil            = true;
+    outline                 = true;
+#ifdef HAVE_LTTRACE
+    lttrace_on              = 0;
+#endif
+#ifdef HAVE_QUO
+    do_quo_setup            = 0;
+#endif
+    dynamic_load_balance_on = false;
+    crux_type               = CRUX_NONE;
+    face_based              = false;
+    restart                 = false;
+    restart_file            = NULL;
+    outputInterval          = OUTPUT_INTERVAL;
+    nx                      = COARSE_GRID_RES;
+    ny                      = COARSE_GRID_RES;
+    niter                   = MAX_TIME_STEP;
+    neighbor_remap          = true;
+    //measure_type            = CSTARVALUE;
+    measure_type            = NO_PARTITION_MEASURE;
+    calc_neighbor_type      = HASH_TABLE;
+    choose_hash_method      = METHOD_UNSET;
+    initial_order           = HILBERT_SORT;
+    cycle_reorder           = ORIGINAL_ORDER;
+    graphic_outputInterval  = INT_MAX;
+    graphics_type           = GRAPHICS_NONE;
+    checkpoint_outputInterval = INT_MAX;
+    num_of_rollback_states  = 2;
+    levmx                   = 1;
+    mem_opt_factor          = 1.0;
+    upper_mass_diff_percentage = -1.0;
+    enhanced_precision_sum  = SUM_KAHAN;
+    
+    char   *val;
+    if (argc > 1)
+    {   int i = 1;
+        val = strtok(argv[i++], " ,.-");
+        while (val != NULL){
+            switch (val[0]){
+               case 'b':     //  Number of rollback images, disk or in memory (default 2)
+                    sprintf(val,"0");
+                    if (i < argc) val = strtok(argv[i++], " ,");
+                    if(atoi(val) < 1){
+                        printf("backup number must be at least 1, setting to default value 2\n");
+                    }
+                    else{
+                        num_of_rollback_states = atoi(val);
+                    }
+                    break;
+                case 'c':   //  Checkpoint to disk at interval specified
+                    val = strtok(argv[i++], " ,.-");
+                    checkpoint_outputInterval = atoi(val);
+                    crux_type = CRUX_DISK;
+                    break;
+
+                case 'C':   //  Checkpoint to memory at interval specified
+                    val = strtok(argv[i++], " ,.-");
+                    checkpoint_outputInterval = atoi(val);
+                    crux_type = CRUX_IN_MEMORY;
+                    break;
+
+                case 'd':   //  Turn on lttrace.
+                            //  This is provided as a separate option to measure
+                            //  the overhead of having lttrace on.
+#ifdef HAVE_LTTRACE
+                    lttrace_on = 1;
+#endif
+                    break;
+
+                case 'D':   //  Turn on dynamic load balancing.
+                            //  This forces on lttrace.
+#ifdef HAVE_LTTRACE
+                    lttrace_on = true;
+                    dynamic_load_balance_on = true;
+#endif
+                    break;
+
+                case 'e':   //  hash method specified.
+                    val = strtok(argv[i++], " ,");
+                    if (! strcmp(val,"perfect") ) {
+                       choose_hash_method = PERFECT_HASH;
+                    } else if (! strcmp(val,"linear") ) {
+                       choose_hash_method = LINEAR;
+                    } else if (! strcmp(val,"quadratic") ) {
+                       choose_hash_method = QUADRATIC;
+                    } else if (! strcmp(val,"prime_jump") ) {
+                       choose_hash_method = PRIME_JUMP;
+                    }
+                    break;
+
+                case 'f':   // Use face-based finite difference
+                    face_based = true;
+                    break;
+                
+                case 'g':   //  Save graphics data to files during simulation.
+                    val = strtok(argv[i++], " ,.-");
+                    graphic_outputInterval = atoi(val);
+                    if (graphics_type == GRAPHICS_NONE) graphics_type = GRAPHICS_DATA;
+                    break;
+
+                case 'G':   //  Graphics data file type.
+                    val = strtok(argv[i++], " ,.-");
+                    if (! strcmp(val,"none") ) {
+                       graphics_type = GRAPHICS_NONE;
+                       graphic_outputInterval  = INT_MAX;
+                    } else if (! strcmp(val,"data") ) {
+                       graphics_type = GRAPHICS_DATA;
+#ifdef HAVE_MAGICKWAND
+                    } else if (! strcmp(val,"bmp") ) {
+                       graphics_type = GRAPHICS_BMP;
+                    } else if (! strcmp(val,"gif") ) {
+                       graphics_type = GRAPHICS_GIF;
+                    } else if (! strcmp(val,"jpeg") ) {
+                       graphics_type = GRAPHICS_JPEG;
+                    } else if (! strcmp(val,"mpeg") ) {
+                       graphics_type = GRAPHICS_MPEG;
+                    } else if (! strcmp(val,"pdf") ) {
+                       graphics_type = GRAPHICS_PDF;
+                    } else if (! strcmp(val,"png") ) {
+                       graphics_type = GRAPHICS_PNG;
+                    } else if (! strcmp(val,"svg") ) {
+                       graphics_type = GRAPHICS_SVG;
+#endif
+                    } else {
+                       printf("Unrecognized option for graphics file type %s\n",val);
+                       exit(-1);
+                    }
+                    break;
+
+                case 'h':   //  Output help.
+                    outputHelp();
+                    cout.flush();
+                    exit(EXIT_SUCCESS);
+                    break;
+                    
+                case 'i':   //  Output interval specified.
+                    val = strtok(argv[i++], " ,.-");
+                    outputInterval = atoi(val);
+                    break;
+                    
+                case 'l':   //  max level specified.
+                    val = strtok(argv[i++], " ,");
+                    levmx = atoi(val);
+                    break;
+                    
+                case 'M':   //  memory optimization factor
+                    val = strtok(argv[i++], " ,");
+                    mem_opt_factor = atof(val);
+                    break;
+                    
+                case 'm':   //  partition measure specified.
+                    val = strtok(argv[i++], " ,");
+                    if (! strcmp(val,"no_partition_measure") ) {
+                       measure_type = NO_PARTITION_MEASURE;
+                    } else if (! strcmp(val,"with_duplicates") ) {
+                       measure_type = WITH_DUPLICATES;
+                    } else if (! strcmp(val,"without_duplicates") ) {
+                       measure_type = WITHOUT_DUPLICATES;
+                    } else if (! strcmp(val,"cvalue") ) {
+                       measure_type = CVALUE;
+                    } else if (! strcmp(val,"cstarvalue") ) {
+                       measure_type = CSTARVALUE;
+                    }
+                    break;
+                    
+                case 'N':   //  calc neighbor type specified.
+                    val = strtok(argv[i++], " ,");
+                    if (! strcmp(val,"hash_table") ) {
+                       calc_neighbor_type = HASH_TABLE;
+                    } else if (! strcmp(val,"kdtree") ) {
+                       calc_neighbor_type = KDTREE;
+                    }
+                    break;
+                    
+                case 'n':   //  Domain grid resolution specified.
+                    val = strtok(argv[i++], " ,");
+                    nx = atoi(val);
+                    ny = nx;
+                    break;
+                    
+                case 'o':   //  Turn off outlines on mesh drawing.
+                    outline = false;
+                    break;
+                    
+                case 'P':   //  Initial order specified.
+                    val = strtok(argv[i++], " ,");
+                    if (! strcmp(val,"original_order") ) {
+                       initial_order = ORIGINAL_ORDER;
+                    } else if (! strcmp(val,"hilbert_sort") ) {
+                       initial_order = HILBERT_SORT;
+                    } else if (! strcmp(val,"hilbert_partition") ) {
+                       initial_order = HILBERT_PARTITION;
+                    } else if (! strcmp(val,"z_order") ) {
+                       initial_order = ZORDER;
+                    }
+                    break;
+                    
+                case 'p':   //  Initial order specified.
+                    val = strtok(argv[i++], " ,");
+                    if (! strcmp(val,"original_order") ) {
+                       cycle_reorder = ORIGINAL_ORDER;
+                       localStencil = false;
+                    } else if (! strcmp(val,"hilbert_sort") ) {
+                       cycle_reorder = HILBERT_SORT;
+                       localStencil = false;
+                    } else if (! strcmp(val,"hilbert_partition") ) {
+                       cycle_reorder = HILBERT_PARTITION;
+                       localStencil = false;
+                    } else if (! strcmp(val,"local_hilbert") ) {
+                       cycle_reorder = ORIGINAL_ORDER;
+                       localStencil = true;
+                    } else if (! strcmp(val,"local_fixed") ) {
+                       cycle_reorder = ORIGINAL_ORDER;
+                       localStencil = false;
+                    } else if (! strcmp(val,"z_order") ) {
+                       cycle_reorder = ZORDER;
+                       localStencil = false;
+                    }
+                    break;
+   
+                case 'q':   //  turn on quo package.
+#ifdef HAVE_QUO
+                    do_quo_setup = 1;
+#endif
+                    break;
+                    
+                case 'r':   //  Regular sum instead of enhanced precision sum.
+                    val = strtok(argv[i++], " ,");
+                    if (! strcmp(val,"regular_sum") ) {
+                       enhanced_precision_sum = SUM_REGULAR;
+                    } else if (! strcmp(val,"kahan_sum") ) {
+                       enhanced_precision_sum = SUM_KAHAN;
+                    } else {
+                       printf("Error with sum argument %s\n",val);
+                       exit(0);
+                    }
+                    break;
+
+                case 'R':  //  Restart application from last checkpoint
+                    restart = true;
+                    restart_file = strtok(argv[i++], " ,");
+
+#ifndef HDF5_FF
+                    struct stat stat_descriptor;
+                    if (stat(restart_file,&stat_descriptor) == -1){
+                       printf("Error -- restart file %s does not exist\n",restart_file);
+                       exit(0);
+                    }
+#endif
+                    break;
+
+                case 's':   //  Space-filling curve method specified (default HILBERT_SORT).
+                //  Add different problem setups such as sloped wave in x, y and diagonal directions to help check algorithm
+                    //  HILBERT_SORT
+                    break;
+                    
+                case 'T':   //  TVD inclusion specified.
+                    break;
+                    
+                case 't':   //  Number of time steps specified.
+                    val = strtok(argv[i++], " ,.-");
+                    niter = atoi(val);
+                    break;
+
+                case 'u':   //  Allowed percentage of difference in mass per iteration
+                    val = strtok(argv[i++], " ,");
+                    upper_mass_diff_percentage = atof(val);
+                    break;
+                    
+                case 'V':   //  Verbose output desired.
+                    verbose = true;
+                    break;
+                    
+                case 'v':   //  Version.
+                    outputVersion();
+                    cout.flush();
+                    exit(EXIT_SUCCESS);
+                    break;
+
+                case 'z':  // Neighbor remap -- default is true, -z sets to false
+                    neighbor_remap = false;
+                    break;
+                    
+                default:    //  Unknown parameter encountered.
+                    cout << "⚠ Unknown input parameter " << val << endl;
+                    outputHelp();
+                    cout.flush();
+                    exit(EXIT_FAILURE);
+                    break; }
+            
+            val = strtok(argv[i++], " ,.-");
+        }
+     }
+
+/*
+    if(upper_mass_diff_percentage < 0){
+             upper_mass_diff_percentage = 1.0e-12;
+    }
+*/
+}

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/input.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/input.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ *  
+ *  This file and the associated header is based on a file from the capablanca
+ *  project available under the MIT open-source license.  As author of that code,
+ *  I, Neal Davis, permit repurposing and redistribution for CLAMR under the New
+ *  BSD License used above.
+ *      http://code.google.com/p/capablanca/
+ */
+#ifndef _INPUT_H
+#define	_INPUT_H
+
+void outputHelp();
+void outputVersion();
+void parseInput(const int argc, char** argv);
+
+#endif	/* _INPUT_H */
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.c
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/memstats.c?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.c (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.c Mon Sep  4 07:25:36 2017
@@ -0,0 +1,347 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef __APPLE_CC__
+#include <mach/mach_host.h>
+#include <mach/task.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "memstats.h"
+
+pid_t pid;
+FILE *stat_fp = NULL, *meminfo_fp = NULL;
+
+long long memstats_memused(){
+   long long mem_current=0;
+#ifdef __APPLE_CC__
+/* This is all memory used and we want the memory for only our process -- do alternate
+   vm_size_t page_size;
+   mach_port_t mach_port;
+   mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
+
+   host_page_size(mach_port, &page_size);
+   vm_statistics_data_t vmstat;
+   host_statistics (mach_host_self (), HOST_VM_INFO, (host_info_t) &vmstat, &count);
+
+   mem_current = (vmstat.wire_count + vmstat.active_count + vmstat.inactive_count)*page_size/1024;
+*/
+
+   struct task_basic_info t_info;
+   mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
+   task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
+
+   mem_current = t_info.resident_size;
+#else
+   char proc_stat_file[50];
+   char *p;
+   int err;
+   int memdebug = 0;
+   //long long page_size = 1; //4096
+
+   if (!stat_fp){
+      pid = getpid();
+      sprintf(proc_stat_file, "/proc/%d/status", pid);
+      stat_fp = fopen(proc_stat_file, "r");
+      if (!stat_fp){
+         //printf("fopen %s failed: \n", proc_stat_file);
+         return(-1);
+      }
+   }
+
+   err = fflush(stat_fp);
+   if (err) {
+      printf("fflush %s failed: %s\n", proc_stat_file, strerror(err));
+      return(-1);
+   }
+   err = fseek(stat_fp, 0L, 0);
+   if (err) {
+      printf("fseek %s failed: %s\n", proc_stat_file, strerror(err));
+      return(-1);
+   }
+
+   char *str = (char *)malloc(140*sizeof(char));
+   while (!feof(stat_fp)){
+      str = fgets(str, 132, stat_fp);
+      if (str == NULL){
+         printf("Warning: Error in reading %s for memory stats\n",proc_stat_file);
+      }
+      p = strtok(str,":");
+      //printf("p is |%s|\n",p);
+      if (!strcmp(p, "VmRSS")) {
+         p = strtok('\0'," ");
+         p = strtok('\0'," ");
+         //mem_current = atoll(p)*1024; // Size is in kB 
+         mem_current = atoll(p); // Size is in kB 
+         if (memdebug) {
+            printf("VmRSS %lld\n",mem_current);
+         }
+         break;
+      }
+   }
+   free(str);
+
+   fclose(stat_fp);
+   stat_fp = NULL;
+#endif
+
+   return(mem_current);
+}
+
+long long memstats_mempeak(){
+   char proc_stat_file[50];
+   char *p;
+   int err;
+   int memdebug = 0;
+   long long mem_current=0;
+   //long long page_size = 1; //4096
+
+   if (!stat_fp){
+      pid = getpid();
+      sprintf(proc_stat_file, "/proc/%d/status", pid);
+      stat_fp = fopen(proc_stat_file, "r");
+      if (!stat_fp){
+         //printf("fopen %s failed: \n", proc_stat_file);
+         return(-1);
+      }
+   }
+
+   err = fflush(stat_fp);
+   if (err) {
+      printf("fflush %s failed: %s\n", proc_stat_file, strerror(err));
+      return(-1);
+   }
+   err = fseek(stat_fp, 0L, 0);
+   if (err) {
+      printf("fseek %s failed: %s\n", proc_stat_file, strerror(err));
+      return(-1);
+   }
+
+   char *str = (char *)malloc(140*sizeof(char));
+   while (!feof(stat_fp)){
+      str = fgets(str, 132, stat_fp);
+      if (str == NULL){
+         printf("Warning: Error in reading %s for memory stats\n",proc_stat_file);
+      }
+      p = strtok(str,":");
+      //printf("p is |%s|\n",p);
+      if (!strcmp(p, "VmHWM")) {
+         p = strtok('\0'," ");
+         p = strtok('\0'," ");
+         //mem_current = atoll(p)*1024; // Size is in kB 
+         mem_current = atoll(p); // Size is in kB 
+         if (memdebug) {
+            printf("VmRSS %lld\n",mem_current);
+         }
+         break;
+      }
+   }
+
+   fclose(stat_fp);
+   stat_fp = NULL;
+   free(str);
+
+   return(mem_current);
+}
+
+#define TIMER_ONEK 1024
+long long memstats_memfree(){
+   long long freemem;
+#ifdef __APPLE_CC__
+   vm_size_t page_size;
+   mach_port_t mach_port;
+   mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
+
+   mach_port = mach_host_self();
+   host_page_size(mach_port, &page_size);
+   vm_statistics64_data_t vmstat;
+   host_statistics64 (mach_port, HOST_VM_INFO, (host_info_t) &vmstat, &count);
+
+   freemem = vmstat.free_count*page_size/1024;
+#else
+   int err;
+   int memdebug = 0;
+   char buf[260];
+   char *p;
+
+   freemem = -1;
+
+   if (!meminfo_fp){
+      meminfo_fp = fopen("/proc/meminfo", "r");
+      if (!meminfo_fp){
+         printf("fopen failed: \n");
+         return(-1);
+      }
+   }
+
+   err = fflush(meminfo_fp);
+   if (err) {
+      printf("fflush failed: %s\n", strerror(err));
+      return(-1);
+   }
+   err = fseek(meminfo_fp, 0L, 0);
+   if (err) {
+      printf("fseek failed: %s\n", strerror(err));
+      return(-1);
+   }
+
+   while (!feof(meminfo_fp)) {
+      if (fgets(buf, 255, meminfo_fp)) { /* read header */
+         //printf("buf is %s\n",buf);
+         p = strtok(buf, ":");
+         if (memdebug){
+            printf("p: |%s|\n",p);
+         }
+         if (!strcmp(p, "MemFree")) {
+            p = strtok('\0', " ");
+            //printf("p is %s\n",p);
+            freemem = atoll(p); // in kB
+            break;
+         }
+      }
+   }
+
+   //return(freemem+cachedmem);
+
+   fclose(meminfo_fp);
+   meminfo_fp = NULL;
+#endif
+
+   return(freemem);
+}
+
+long long memstats_memtotal(){
+   long long totalmem;
+#ifdef __APPLE_CC__
+/*
+   vm_size_t page_size;
+   mach_port_t mach_port;
+   mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
+
+   host_page_size(mach_port, &page_size);
+   vm_statistics_data_t vmstat;
+   host_statistics (mach_host_self (), HOST_VM_INFO, (host_info_t) &vmstat, &count);
+
+   totalmem = (vmstat.wire_count + vmstat.active_count + vmstat.inactive_count + vmstat.free_count)
+              *page_size/1024;
+*/
+// alternate
+   int mib[2];
+   mib[0] = CTL_HW;
+   mib[1] = HW_MEMSIZE;
+   size_t length = sizeof(long long);
+   sysctl(mib, 2, &totalmem, &length, NULL, 0);
+   totalmem /= 1024;
+#else
+   int err;
+   int memdebug = 0;
+   char buf[260];
+   char *p;
+
+   totalmem = -1;
+
+   if (!meminfo_fp){
+      meminfo_fp = fopen("/proc/meminfo", "r");
+      if (!meminfo_fp){
+         printf("fopen failed: \n");
+         return(-1);
+      }
+   }
+
+   err = fflush(meminfo_fp);
+   if (err) {
+      printf("fflush failed: %s\n", strerror(err));
+      return(-1);
+   }
+   err = fseek(meminfo_fp, 0L, 0);
+   if (err) {
+      printf("fseek failed: %s\n", strerror(err));
+      return(-1);
+   }
+
+   while (!feof(meminfo_fp)) {
+      if (fgets(buf, 255, meminfo_fp)) { /* read header */
+         //printf("buf is %s\n",buf);
+         p = strtok(buf, ":");
+         if (memdebug){
+            printf("p: |%s|\n",p);
+         }
+         if (!strcmp(p, "MemTotal")) {
+            p = strtok('\0', " ");
+            //printf("p is %s\n",p);
+            totalmem = atoll(p); // in kB
+            break;
+         }
+      }
+   }
+
+   fclose(meminfo_fp);
+   meminfo_fp = NULL;
+#endif
+
+   return(totalmem);
+}
+

Added: test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.h
URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C%2B%2B/CLAMR/memstats.h?rev=312488&view=auto
==============================================================================
--- test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.h (added)
+++ test-suite/trunk/MultiSource/Benchmarks/DOE-ProxyApps-C++/CLAMR/memstats.h Mon Sep  4 07:25:36 2017
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (c) 2011-2012, Los Alamos National Security, LLC.
+ *  All rights Reserved.
+ *
+ *  Copyright 2011-2012. Los Alamos National Security, LLC. This software was produced 
+ *  under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National 
+ *  Laboratory (LANL), which is operated by Los Alamos National Security, LLC 
+ *  for the U.S. Department of Energy. The U.S. Government has rights to use, 
+ *  reproduce, and distribute this software.  NEITHER THE GOVERNMENT NOR LOS 
+ *  ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR 
+ *  ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE.  If software is modified
+ *  to produce derivative works, such modified software should be clearly marked,
+ *  so as not to confuse it with the version available from LANL.
+ *
+ *  Additionally, redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the Los Alamos National Security, LLC, Los Alamos 
+ *       National Laboratory, LANL, the U.S. Government, nor the names of its 
+ *       contributors may be used to endorse or promote products derived from 
+ *       this software without specific prior written permission.
+ *  
+ *  THIS SOFTWARE IS PROVIDED BY THE LOS ALAMOS NATIONAL SECURITY, LLC AND 
+ *  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
+ *  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL
+ *  SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ *  
+ *  CLAMR -- LA-CC-11-094
+ *  This research code is being developed as part of the 
+ *  2011 X Division Summer Workshop for the express purpose
+ *  of a collaborative code for development of ideas in
+ *  the implementation of AMR codes for Exascale platforms
+ *  
+ *  AMR implementation of the Wave code previously developed
+ *  as a demonstration code for regular grids on Exascale platforms
+ *  as part of the Supercomputing Challenge and Los Alamos 
+ *  National Laboratory
+ *  
+ *  Authors: Bob Robey       XCP-2   brobey at lanl.gov
+ *           Neal Davis              davis68 at lanl.gov, davis68 at illinois.edu
+ *           David Nicholaeff        dnic at lanl.gov, mtrxknight at aol.com
+ *           Dennis Trujillo         dptrujillo at lanl.gov, dptru10 at gmail.com
+ * 
+ */
+#ifndef _MEMSTATS_H
+#define _MEMSTATS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+long long memstats_memused();
+long long memstats_mempeak();
+long long memstats_memfree();
+long long memstats_memtotal();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _MEMSTATS_H */
+




More information about the llvm-commits mailing list