From ba2b523bf4b7c4dc91aac2d0ea61c3e4966594ea Mon Sep 17 00:00:00 2001
From: Richard Berger <richard.berger@temple.edu>
Date: Thu, 8 Sep 2016 01:00:53 -0400
Subject: [PATCH] Use factory for region style creation

---
 src/domain.cpp | 71 ++++++++++++++++++++++++++------------------------
 src/domain.h   |  9 +++++++
 src/info.cpp   |  9 ++++---
 3 files changed, 51 insertions(+), 38 deletions(-)

diff --git a/src/domain.cpp b/src/domain.cpp
index 0590b956dd..2c3f61401d 100644
--- a/src/domain.cpp
+++ b/src/domain.cpp
@@ -105,6 +105,15 @@ Domain::Domain(LAMMPS *lmp) : Pointers(lmp)
   regions = NULL;
 
   copymode = 0;
+
+  region_map = new RegionCreatorMap();
+
+#define REGION_CLASS
+#define RegionStyle(key,Class) \
+  (*region_map)[#key] = &region_creator<Class>;
+#include "style_region.h"
+#undef RegionStyle
+#undef REGION_CLASS
 }
 
 /* ---------------------------------------------------------------------- */
@@ -116,6 +125,8 @@ Domain::~Domain()
   delete lattice;
   for (int i = 0; i < nregion; i++) delete regions[i];
   memory->sfree(regions);
+
+  delete region_map;
 }
 
 /* ---------------------------------------------------------------------- */
@@ -1524,51 +1535,33 @@ void Domain::add_region(int narg, char **arg)
     if (lmp->suffix) {
       char estyle[256];
       sprintf(estyle,"%s/%s",arg[1],lmp->suffix);
-
-      if (0) return;
-
-#define REGION_CLASS
-#define RegionStyle(key,Class) \
-      else if (strcmp(estyle,#key) == 0) { \
-            regions[nregion] = new Class(lmp,narg,arg); \
-            regions[nregion]->init(); \
-            nregion++; \
-            return; \
+      if (region_map->find(estyle) != region_map->end()) {
+        RegionCreator region_creator = (*region_map)[estyle];
+        regions[nregion] = region_creator(lmp, narg, arg);
+        regions[nregion]->init();
+        nregion++;
+        return;
       }
-#include "style_region.h"
-#undef RegionStyle
-#undef REGION_CLASS
     }
 
     if (lmp->suffix2) {
       char estyle[256];
       sprintf(estyle,"%s/%s",arg[1],lmp->suffix2);
-
-      if (0) return;
-
-#define REGION_CLASS
-#define RegionStyle(key,Class) \
-      else if (strcmp(estyle,#key) == 0) { \
-            regions[nregion] = new Class(lmp,narg,arg); \
-            regions[nregion]->init(); \
-            nregion++; \
-            return; \
+      if (region_map->find(estyle) != region_map->end()) {
+        RegionCreator region_creator = (*region_map)[estyle];
+        regions[nregion] = region_creator(lmp, narg, arg);
+        regions[nregion]->init();
+        nregion++;
+        return;
       }
-#include "style_region.h"
-#undef RegionStyle
-#undef REGION_CLASS
     }
   }
 
   if (strcmp(arg[1],"none") == 0) error->all(FLERR,"Unknown region style");
-
-#define REGION_CLASS
-#define RegionStyle(key,Class) \
-  else if (strcmp(arg[1],#key) == 0) \
-    regions[nregion] = new Class(lmp,narg,arg);
-#include "style_region.h"
-#undef REGION_CLASS
-
+  if (region_map->find(arg[1]) != region_map->end()) {
+    RegionCreator region_creator = (*region_map)[arg[1]];
+    regions[nregion] = region_creator(lmp, narg, arg);
+  }
   else error->all(FLERR,"Unknown region style");
 
   // initialize any region variables via init()
@@ -1578,6 +1571,16 @@ void Domain::add_region(int narg, char **arg)
   nregion++;
 }
 
+/* ----------------------------------------------------------------------
+   one instance per region style in style_region.h
+------------------------------------------------------------------------- */
+
+template <typename T>
+Region *Domain::region_creator(LAMMPS *lmp, int narg, char ** arg)
+{
+  return new T(lmp, narg, arg);
+}
+
 /* ----------------------------------------------------------------------
    delete a region
 ------------------------------------------------------------------------- */
diff --git a/src/domain.h b/src/domain.h
index 8654b59168..ef3de42071 100644
--- a/src/domain.h
+++ b/src/domain.h
@@ -16,6 +16,8 @@
 
 #include <math.h>
 #include "pointers.h"
+#include <map>
+#include <string>
 
 namespace LAMMPS_NS {
 
@@ -92,6 +94,10 @@ class Domain : protected Pointers {
 
   int copymode;
 
+  typedef Region *(*RegionCreator)(LAMMPS *,int,char**);
+  typedef std::map<std::string,RegionCreator> RegionCreatorMap;
+  RegionCreatorMap *region_map;
+
   Domain(class LAMMPS *);
   virtual ~Domain();
   virtual void init();
@@ -151,6 +157,9 @@ class Domain : protected Pointers {
 
  protected:
   double small[3];                  // fractions of box lengths
+
+ private:
+  template <typename T> static Region *region_creator(LAMMPS *,int,char**);
 };
 
 }
diff --git a/src/info.cpp b/src/info.cpp
index 22cb432acc..c150e0a886 100644
--- a/src/info.cpp
+++ b/src/info.cpp
@@ -722,10 +722,11 @@ void Info::region_styles(FILE * out)
   fprintf(out, "\nRegion styles:\n");
 
   vector<string> styles;
-#define REGION_CLASS
-#define RegionStyle(key,Class) styles.push_back(#key);
-#include "style_region.h"
-#undef REGION_CLASS
+
+  for(Domain::RegionCreatorMap::iterator it = domain->region_map->begin(); it != domain->region_map->end(); ++it) {
+    styles.push_back(it->first);
+  }
+
   print_columns(out, styles);
   fprintf(out, "\n\n\n");
 }
-- 
GitLab