From fbcd55760c55489124282c3fb0257a087d875444 Mon Sep 17 00:00:00 2001
From: Brian Helenbrook <bhelenbr@clarkson.edu>
Date: Tue, 18 Nov 2008 15:05:18 +0000
Subject: [PATCH] Added uniform refinement routines

---
 Common/CommandLine.cpp |   5 +
 Fltk/Callbacks.cpp     |   8 ++
 Fltk/Callbacks.h       |   1 +
 Fltk/GUI.cpp           |   5 +-
 Mesh/HighOrder.h       |   2 +
 Mesh/Refine.cpp        | 245 +++++++++++++++++++++++++++++++++++++++++
 contrib/NR/Makefile    |   2 +-
 7 files changed, 265 insertions(+), 3 deletions(-)
 create mode 100644 Mesh/Refine.cpp

diff --git a/Common/CommandLine.cpp b/Common/CommandLine.cpp
index a24d686c2f..fd89bc4fd8 100644
--- a/Common/CommandLine.cpp
+++ b/Common/CommandLine.cpp
@@ -42,6 +42,7 @@ void Print_Usage(const char *name)
   Msg::Direct("  -tol float            Set geometrical tolerance");
   Msg::Direct("Mesh options:");
   Msg::Direct("  -1, -2, -3            Perform 1D, 2D or 3D mesh generation, then exit");
+  Msg::Direct("  -refine               Perform uniform mesh refinement, then exit");
   Msg::Direct("  -part                 Partition after batch mesh generation");
   Msg::Direct("  -saveall              Save all elements (discard physical group definitions)");
   Msg::Direct("  -o file               Specify mesh output file name");
@@ -202,6 +203,10 @@ void Get_Options(int argc, char *argv[])
         else
 	  Msg::Fatal("Missing string");
         CTX.batch = 5;
+      }
+	  else if(!strcmp(argv[i] + 1, "refine")) {
+		  CTX.batch = 6;
+		  i++;
       }
       else if(!strcmp(argv[i] + 1, "part")) {
         CTX.batchAfterMesh = 1;
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 40b7c46eea..d9046f8409 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -3826,6 +3826,14 @@ void mesh_optimize_cb(CALLBACK_ARGS)
   Msg::StatusBar(2, false, " ");
 }
 
+void mesh_refine_cb(CALLBACK_ARGS)
+{
+	Refine(GModel::current(), CTX.mesh.second_order_linear);
+	CTX.mesh.changed |= (ENT_LINE | ENT_SURFACE | ENT_VOLUME);
+	Draw();
+	Msg::StatusBar(2, false, " ");
+}
+
 void mesh_optimize_netgen_cb(CALLBACK_ARGS)
 {
   if(CTX.threads_lock) {
diff --git a/Fltk/Callbacks.h b/Fltk/Callbacks.h
index d9a199a05d..f1b9ffad22 100644
--- a/Fltk/Callbacks.h
+++ b/Fltk/Callbacks.h
@@ -232,6 +232,7 @@ void mesh_remesh_cb(CALLBACK_ARGS);
 void mesh_update_edges_cb(CALLBACK_ARGS); 
 void mesh_parameterize_cb(CALLBACK_ARGS);
 void mesh_degree_cb(CALLBACK_ARGS); 
+void mesh_refine_cb(CALLBACK_ARGS);
 void mesh_optimize_cb(CALLBACK_ARGS); 
 void mesh_optimize_netgen_cb(CALLBACK_ARGS); 
 void mesh_partition_cb(CALLBACK_ARGS);
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 4c9fb61cb1..78d7e2c264 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -304,6 +304,7 @@ Context_Item menu_mesh[] = {
   {"3D",           (Fl_Callback *)mesh_3d_cb} , 
   {"First order",  (Fl_Callback *)mesh_degree_cb, (void*)1 } , 
   {"Second order", (Fl_Callback *)mesh_degree_cb, (void*)2 } , 
+  {"Refine",       (Fl_Callback *)mesh_refine_cb} ,
   {"Optimize",     (Fl_Callback *)mesh_optimize_cb} , 
 #if defined(HAVE_NETGEN)
   {"Optimize (Netgen)", (Fl_Callback *)mesh_optimize_netgen_cb} , 
@@ -4819,8 +4820,8 @@ void GUI::create_about_window()
         sprintf(buffer, "@c@.Build options: %s", lines[i].c_str());
       else
         sprintf(buffer, "@c@.%s", lines[i].c_str());
-      o->add(buffer);
-    }
+        o->add(buffer);
+      }
     sprintf(buffer, "@c@.Packaged by: %s", Get_GmshPackager());
     o->add(buffer);
     o->add(" ");
diff --git a/Mesh/HighOrder.h b/Mesh/HighOrder.h
index 98d2d62653..6e1d1a678d 100644
--- a/Mesh/HighOrder.h
+++ b/Mesh/HighOrder.h
@@ -13,4 +13,6 @@ void SetOrderN(GModel *m, int order, bool linear=true, bool incomplete=false);
 void checkHighOrderTriangles(GModel *m);
 bool reparamOnFace(MVertex *v, GFace *gf, SPoint2 &param);
 
+void Refine(GModel *m, bool linear=true);
+
 #endif
diff --git a/Mesh/Refine.cpp b/Mesh/Refine.cpp
new file mode 100644
index 0000000000..ccefea7346
--- /dev/null
+++ b/Mesh/Refine.cpp
@@ -0,0 +1,245 @@
+/*
+ *  refine.cpp
+ *  GMSH
+ *
+ *  Created by Brian Helenbrook on 11/13/08.
+ *  Copyright 2008 Clarkson University. All rights reserved.
+ *
+ */
+#include "HighOrder.h"
+#include "meshGFaceOptimize.h"
+#include "MElement.h"
+#include "GmshMessage.h"
+#include "OS.h"
+#include "Numeric.h"
+#include "Context.h"
+#include "GmshMatrix.h"
+#include "FunctionSpace.h"
+
+void Subdivide(GEdge *ge)
+{
+	std::vector<MLine *> lines2;
+	for(unsigned int i = 0; i < ge->lines.size(); i++){
+		MLine3 *l = dynamic_cast<MLine3 *>(ge->lines[i]);
+		lines2.push_back(new MLine(l->getVertex(0), l->getVertex(2)));
+		lines2.push_back(new MLine(l->getVertex(2), l->getVertex(1)));
+		delete l;
+	}
+	ge->lines = lines2;
+	ge->deleteVertexArrays();
+}
+
+void Subdivide(GFace *gf)
+{
+	std::vector<MTriangle*> triangles2;
+	for(unsigned int i = 0; i < gf->triangles.size(); i++){
+		MTriangle6 *t = dynamic_cast<MTriangle6 *>(gf->triangles[i]);
+		triangles2.push_back
+		(new MTriangle(t->getVertex(0), t->getVertex(3), t->getVertex(5)));
+		triangles2.push_back
+		(new MTriangle(t->getVertex(3), t->getVertex(4), t->getVertex(5)));
+		triangles2.push_back
+		(new MTriangle(t->getVertex(3), t->getVertex(1), t->getVertex(4)));
+		triangles2.push_back
+		(new MTriangle(t->getVertex(5), t->getVertex(4), t->getVertex(2)));
+		delete t;
+	}
+	gf->triangles = triangles2;
+	
+	std::vector<MQuadrangle*> quadrangles2;
+	for(unsigned int i = 0; i < gf->quadrangles.size(); i++){
+		MQuadrangle9 *q = dynamic_cast<MQuadrangle9 *>(gf->quadrangles[i]);
+		quadrangles2.push_back
+		(new MQuadrangle(q->getVertex(0), q->getVertex(4), q->getVertex(8), q->getVertex(7)));
+		quadrangles2.push_back
+		(new MQuadrangle(q->getVertex(4), q->getVertex(1), q->getVertex(5), q->getVertex(8)));
+		quadrangles2.push_back
+		(new MQuadrangle(q->getVertex(8), q->getVertex(5), q->getVertex(2), q->getVertex(6)));
+		quadrangles2.push_back
+		(new MQuadrangle(q->getVertex(7), q->getVertex(8), q->getVertex(6), q->getVertex(3)));
+		
+		delete q;
+	}
+	gf->quadrangles = quadrangles2;
+	gf->deleteVertexArrays();
+}
+
+void Subdivide(GRegion *gr)
+{
+	
+	std::vector<MTetrahedron*> tetrahedra2;
+	for(unsigned int i = 0; i < gr->tetrahedra.size(); i++){
+		MTetrahedron10 *t = dynamic_cast<MTetrahedron10 *>(gr->tetrahedra[i]);
+		
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(0), t->getVertex(4), t->getVertex(7), t->getVertex(6)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(1), t->getVertex(4), t->getVertex(5), t->getVertex(9)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(2), t->getVertex(5), t->getVertex(6), t->getVertex(8)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(3), t->getVertex(7), t->getVertex(9), t->getVertex(8)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(5), t->getVertex(8), t->getVertex(7), t->getVertex(9)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(5), t->getVertex(7), t->getVertex(4), t->getVertex(9)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(7), t->getVertex(8), t->getVertex(5), t->getVertex(6)));
+		tetrahedra2.push_back
+		(new MTetrahedron(t->getVertex(4), t->getVertex(7), t->getVertex(5), t->getVertex(6)));
+		delete t;
+	}
+	gr->tetrahedra = tetrahedra2;
+	
+	std::vector<MHexahedron*> hexahedra2;
+	for(unsigned int i = 0; i < gr->hexahedra.size(); i++){
+		MHexahedron27 *h = dynamic_cast<MHexahedron27 *>(gr->hexahedra[i]);
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(0), h->getVertex(8), h->getVertex(20), h->getVertex(9),
+					     h->getVertex(10), h->getVertex(21), h->getVertex(26), h->getVertex(22)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(10), h->getVertex(21), h->getVertex(26), h->getVertex(22),
+					     h->getVertex(4), h->getVertex(16), h->getVertex(25), h->getVertex(17)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(8), h->getVertex(1), h->getVertex(11), h->getVertex(20),
+					     h->getVertex(21), h->getVertex(12), h->getVertex(23), h->getVertex(26)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(21), h->getVertex(12), h->getVertex(23), h->getVertex(26),
+					     h->getVertex(16), h->getVertex(5), h->getVertex(18), h->getVertex(25)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(9), h->getVertex(20), h->getVertex(13), h->getVertex(3),
+					     h->getVertex(22), h->getVertex(26), h->getVertex(24), h->getVertex(15)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(22), h->getVertex(26), h->getVertex(24), h->getVertex(15),
+					     h->getVertex(17), h->getVertex(25), h->getVertex(19), h->getVertex(7)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(20), h->getVertex(11), h->getVertex(2), h->getVertex(13),
+					     h->getVertex(26), h->getVertex(23), h->getVertex(14), h->getVertex(24)));
+		hexahedra2.push_back
+		(new MHexahedron(h->getVertex(26), h->getVertex(23), h->getVertex(14), h->getVertex(24),
+					     h->getVertex(25), h->getVertex(18), h->getVertex(6), h->getVertex(19)));
+		delete h;
+	}
+	gr->hexahedra = hexahedra2;
+	
+	std::vector<MPrism*> prisms2;
+	for(unsigned int i = 0; i < gr->prisms.size(); i++){
+		MPrism18 *p = dynamic_cast<MPrism18 *>(gr->prisms[i]);
+
+		prisms2.push_back
+		(new MPrism(p->getVertex(0), p->getVertex(6), p->getVertex(7), 
+					p->getVertex(8), p->getVertex(15), p->getVertex(16)));
+		prisms2.push_back
+		(new MPrism(p->getVertex(8), p->getVertex(15), p->getVertex(16), 
+					p->getVertex(3), p->getVertex(12), p->getVertex(13)));		
+		prisms2.push_back
+		(new MPrism(p->getVertex(6), p->getVertex(1), p->getVertex(9), 
+					p->getVertex(15), p->getVertex(10), p->getVertex(17)));		
+		prisms2.push_back
+		(new MPrism(p->getVertex(15), p->getVertex(10), p->getVertex(17), 
+					p->getVertex(12), p->getVertex(4), p->getVertex(14)));		
+		prisms2.push_back
+		(new MPrism(p->getVertex(7), p->getVertex(9), p->getVertex(2), 
+					p->getVertex(16), p->getVertex(17), p->getVertex(11)));		
+		prisms2.push_back
+		(new MPrism(p->getVertex(16), p->getVertex(17), p->getVertex(11), 
+					p->getVertex(13), p->getVertex(14), p->getVertex(5)));		
+		prisms2.push_back
+		(new MPrism(p->getVertex(9), p->getVertex(7), p->getVertex(6), 
+					p->getVertex(17), p->getVertex(16), p->getVertex(15)));		
+		prisms2.push_back
+		(new MPrism(p->getVertex(17), p->getVertex(16), p->getVertex(15), 
+					p->getVertex(14), p->getVertex(13), p->getVertex(12)));
+			  
+		delete p;
+	}
+	gr->prisms = prisms2;
+
+
+	std::vector<MPyramid*> pyramids2;
+	for(unsigned int i = 0; i < gr->pyramids.size(); i++){
+		MPyramid14 *p = dynamic_cast<MPyramid14 *>(gr->pyramids[i]);
+		
+		/* BASE */
+		pyramids2.push_back
+		(new MPyramid(p->getVertex(0), p->getVertex(5), p->getVertex(13), p->getVertex(6), p->getVertex(7)));
+		pyramids2.push_back
+		(new MPyramid(p->getVertex(5), p->getVertex(1), p->getVertex(8), p->getVertex(13), p->getVertex(9)));
+		pyramids2.push_back
+		(new MPyramid(p->getVertex(13), p->getVertex(8), p->getVertex(2), p->getVertex(10), p->getVertex(11)));
+		pyramids2.push_back
+		(new MPyramid(p->getVertex(6), p->getVertex(13), p->getVertex(10), p->getVertex(3), p->getVertex(12)));
+
+		/* Split remaining into tets */
+		/* Top */
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(7), p->getVertex(9), p->getVertex(12), p->getVertex(4))));
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(9), p->getVertex(11), p->getVertex(12), p->getVertex(4))));		
+		
+		/* Upside down one */
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(9), p->getVertex(12), p->getVertex(11), p->getVertex(13))));
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(7), p->getVertex(12), p->getVertex(9), p->getVertex(13))));	
+								  
+								  
+		 /* Four tets around bottom perimeter */
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(7), p->getVertex(9), p->getVertex(5), p->getVertex(13))));
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(9), p->getVertex(11), p->getVertex(8), p->getVertex(13))));	
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(12), p->getVertex(10), p->getVertex(11), p->getVertex(13))));
+		gr->tetrahedra.push_back(
+		(new MTetrahedron(p->getVertex(7), p->getVertex(6), p->getVertex(12), p->getVertex(13))));	
+		delete p;
+	}
+	gr->pyramids = pyramids2;
+	gr->deleteVertexArrays();
+}
+
+
+
+
+
+
+void Refine(GModel *m, bool linear)
+{
+	//   refine all edges in a mesh by inserting a point on the midpoint
+	//   then recreate edge, face, and region definitions
+	//
+	// - if linear is set to true, new vertices are created by linear
+	//   interpolation between existing ones. If not, new vertices are
+	//   created on the exact geometry, provided that the geometrical
+	//   edges/faces are discretized with 1D/2D elements. (I.e., if
+	//   there are only 3D elements in the mesh then any new vertices on
+	//   the boundary will always be created by linear interpolation,
+	//   whether linear is set or not.)
+
+	
+#if !defined(HAVE_GSL)
+	Msg::Error("Mesh refinement requires the GSL");
+	return;
+#endif
+		
+	Msg::StatusBar(1, true, "Generating refined mesh ...");
+	double t1 = Cpu();
+	
+	// first, set order to 2 to generate vertex positions
+	SetOrderN(m, 2, linear, false);
+	
+    // Now subdivide entities to create linear mesh
+	for(GModel::eiter it = m->firstEdge(); it != m->lastEdge(); ++it)
+		Subdivide(*it);
+
+	for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it)
+		Subdivide(*it);
+	
+	for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it)
+		Subdivide(*it);
+		
+	double t2 = Cpu();
+	Msg::Info("Mesh refinement complete (%g s)", t2 - t1);
+	Msg::StatusBar(1, true, "Mesh");
+}
diff --git a/contrib/NR/Makefile b/contrib/NR/Makefile
index a3e8bcad58..5438a4f1fd 100644
--- a/contrib/NR/Makefile
+++ b/contrib/NR/Makefile
@@ -58,4 +58,4 @@ lnsrch.o: lnsrch.cpp nrutil.h
 lubksb.o: lubksb.cpp
 ludcmp.o: ludcmp.cpp nrutil.h
 newt.o: newt.cpp nrutil.h
-nrutil.o: nrutil.cpp ../../Common/Message.h
+nrutil.o: nrutil.cpp ../../Common/GmshMessage.h
-- 
GitLab