From d90eb095be3a0f095607db5e8ba70457f77604bd Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Fri, 6 Aug 2004 14:48:33 +0000
Subject: [PATCH] *** empty log message ***

---
 Fltk/Callbacks.cpp          |  12 +-
 Geo/Makefile                |   4 +-
 Graphics/Geom.cpp           |  10 +-
 Graphics/Makefile           |   4 +-
 Parser/OpenFile.cpp         |   9 +-
 Plugin/Plugin.cpp           |   4 +-
 Plugin/Plugin.h             |   6 +-
 Plugin/StructuralSolver.cpp | 407 ++++++++++++++++++++++++++----------
 Plugin/StructuralSolver.h   |  55 ++++-
 benchmarks/1d/ligne.geo     |   5 +
 10 files changed, 391 insertions(+), 125 deletions(-)

diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index d546b9da70..808850d320 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.261 2004-08-03 15:22:18 remacle Exp $
+// $Id: Callbacks.cpp,v 1.262 2004-08-06 14:48:32 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -42,6 +42,7 @@
 #include "GUI.h"
 #include "Callbacks.h"
 #include "Plugin.h"
+#include "PluginManager.h"
 #include "Visibility.h"
 #include "MinMax.h"
 
@@ -2461,6 +2462,14 @@ static void _add_physical(char *what)
     if(ib == 'e') {
       if(List_Nbr(List1)) {
         add_physical(List1, CTX.filename, type, &num);
+
+	GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
+	if (sp)
+	  {
+	    sp->receiveNewPhysicalGroup(type,num);
+	    sp->writeSolverFile(CTX.filename);
+	  }
+
         List_Reset(List1);
         ZeroHighlight(THEM);
         Draw();
@@ -2484,6 +2493,7 @@ void geometry_physical_add_cb(CALLBACK_ARGS)
 
 void geometry_physical_add_point_cb(CALLBACK_ARGS)
 {
+  WID->call_for_solver_plugin(0);
   _add_physical("Point");
 }
 
diff --git a/Geo/Makefile b/Geo/Makefile
index 3e915c8889..ddf4cd1fa4 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.53 2004-07-16 18:59:52 geuzaine Exp $
+# $Id: Makefile,v 1.54 2004-08-06 14:48:32 remacle Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -23,7 +23,7 @@ include ../variables
 
 LIB     = ../lib/libGmshGeo.a
 INCLUDE = -I../Common -I../DataStr -I../Geo -I../Mesh -I../Numeric -I../NR\
-          -I../Parser -I../Fltk
+          -I../Parser -I../Fltk 
 CFLAGS  = ${OPTIM} ${FLAGS} ${INCLUDE}
 
 SRC = CAD.cpp \
diff --git a/Graphics/Geom.cpp b/Graphics/Geom.cpp
index b439ae5f8c..dbd6e5ac81 100644
--- a/Graphics/Geom.cpp
+++ b/Graphics/Geom.cpp
@@ -1,4 +1,4 @@
-// $Id: Geom.cpp,v 1.68 2004-06-23 18:52:45 geuzaine Exp $
+// $Id: Geom.cpp,v 1.69 2004-08-06 14:48:32 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -29,6 +29,8 @@
 #include "Draw.h"
 #include "Context.h"
 #include "Interpolation.h"
+#include "Plugin.h"
+#include "PluginManager.h"
 #include "STL.h"
 #include "gl2ps.h"
 
@@ -76,6 +78,12 @@ void Draw_Geo_Point(void *a, void *b)
       glVertex3d(v->Pos.X, v->Pos.Y, v->Pos.Z);
       glEnd();
     }
+
+    GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
+    if (sp)
+      {
+	sp-> GL_enhancePoint (v);
+      }
   }
 
   if(CTX.geom.points_num) {
diff --git a/Graphics/Makefile b/Graphics/Makefile
index fa447d3c09..dd2d4c2d1f 100644
--- a/Graphics/Makefile
+++ b/Graphics/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.60 2004-07-16 18:59:52 geuzaine Exp $
+# $Id: Makefile,v 1.61 2004-08-06 14:48:33 remacle Exp $
 #
 # Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 #
@@ -23,7 +23,7 @@ include ../variables
 
 LIB     = ../lib/libGmshGraphics.a
 INCLUDE = -I../Common -I../DataStr -I../Geo -I../Graphics\
-          -I../Fltk -I../Mesh -I../Numeric -I../Parser
+          -I../Fltk -I../Mesh -I../Numeric -I../Parser -I../Plugin
 CFLAGS  = ${OPTIM} ${FLAGS} ${INCLUDE}
 
 SRC = Draw.cpp \
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index 4eff8d4710..5316da3a38 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.60 2004-07-02 20:48:42 geuzaine Exp $
+// $Id: OpenFile.cpp,v 1.61 2004-08-06 14:48:33 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -25,6 +25,7 @@
 #include "Parser.h"
 #include "OpenFile.h"
 #include "CommandLine.h"
+#include "PluginManager.h"
 #include "Geo.h"
 #include "Mesh.h"
 #include "Views.h"
@@ -148,6 +149,12 @@ int ParseFile(char *f, int silent, int close, int warn_if_missing)
   yyerrorstate = yyerrorstate_old;
   yylineno = yylineno_old;
 
+  GMSH_Solve_Plugin *sp = GMSH_PluginManager::instance()->findSolverPlugin();
+  if (sp)
+    {
+      sp->readSolverFile(f);
+    }
+
   return status;
 }
 
diff --git a/Plugin/Plugin.cpp b/Plugin/Plugin.cpp
index 2bc716db27..fdc697b867 100644
--- a/Plugin/Plugin.cpp
+++ b/Plugin/Plugin.cpp
@@ -1,4 +1,4 @@
-// $Id: Plugin.cpp,v 1.56 2004-08-03 15:22:18 remacle Exp $
+// $Id: Plugin.cpp,v 1.57 2004-08-06 14:48:33 remacle Exp $
 //
 // Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
 //
@@ -155,7 +155,7 @@ GMSH_PluginManager *GMSH_PluginManager::instance()
 void GMSH_PluginManager::registerDefaultPlugins()
 {
   // SOLVE PLUGINS
-  //  allPlugins.insert(std::pair < char *, GMSH_Plugin * >
+  //    allPlugins.insert(std::pair < char *, GMSH_Plugin * >
   //		    ("StructuralSolver", GMSH_RegisterStructuralSolverPlugin()));
   // POST PLUGINS
   allPlugins.insert(std::pair < char *, GMSH_Plugin * >
diff --git a/Plugin/Plugin.h b/Plugin/Plugin.h
index 5c0b3b99f6..b6de60036f 100644
--- a/Plugin/Plugin.h
+++ b/Plugin/Plugin.h
@@ -39,6 +39,7 @@
 #include "Views.h"
 
 class PluginDialogBox;
+class Vertex;
 
 class GMSH_Plugin
 {
@@ -112,8 +113,9 @@ public:
   virtual void run() {};// do nothing
   virtual void popupPropertiesForPhysicalEntity (int dim) = 0;// popup dialog box
   virtual void receiveNewPhysicalGroup (int dim, int id) = 0;// add the given group to the solver data's
-  virtual void loadSolverFile  ( FILE *f ) = 0;  // load the solver input file related to the gmsh geo file
-  virtual void writeSolverFile ( FILE *f ) const = 0;  // save the solver file 
+  virtual void readSolverFile  ( const char * ) = 0;  // load the solver input file related to the gmsh geo file
+  virtual void writeSolverFile ( const char *) const = 0;  // save the solver file  
+  virtual bool GL_enhancePoint ( Vertex *v) {}; // enhance graphics for a giver geo point
 };
 
 #endif
diff --git a/Plugin/StructuralSolver.cpp b/Plugin/StructuralSolver.cpp
index af51a2165c..8e410d047d 100644
--- a/Plugin/StructuralSolver.cpp
+++ b/Plugin/StructuralSolver.cpp
@@ -1,5 +1,7 @@
 #include "StructuralSolver.h"
-
+#include "Context.h"
+#include "Tools.h"
+#include "Draw.h"
 
 #if defined(HAVE_FLTK)
 #include <FL/Fl.H>
@@ -7,6 +9,7 @@
 #endif
 
 extern Mesh *THEM;
+extern Context_T CTX;
 
 
 extern "C"
@@ -72,6 +75,37 @@ void StructuralSolver :: RegisterBeamSections ()
 
 }
 
+
+void StructuralSolver :: RegisterMaterials ()
+{
+#if defined(HAVE_FLTK)
+  char *homeplugins = getenv("GMSHPLUGINSHOME");
+  char temp[256];
+  int nbpar;
+  sprintf(temp, "%s/%s", homeplugins,"Materials");
+  FILE *f = fopen (temp,"r");  
+  if (!f) return;
+  while(!feof(f))
+    {
+      Structural_Material material;
+      fscanf(f,"%s %d",temp,&nbpar);
+      material.name = std::string(temp);
+      for (int i=0;i<nbpar;++i)
+	{
+	  double param;
+	  fscanf(f,"%lf",&param);
+	  material.par.push_back(param);	  
+	}
+      materials.push_back(material);
+    }
+  fclose(f);
+  
+
+#endif
+
+}
+
+
 void StructuralSolver::getName(char *name) const
 {
   strcpy(name, "Structural Solver");
@@ -92,10 +126,13 @@ void StructuralSolver::getInfos(char *author, char *copyright,
 }
 
 
-
 StructuralSolver :: StructuralSolver ()
+#ifdef HAVE_FLTK 
+  : _window(0), MAX_FORCE(0),MAX_DISPLACEMENT(0)
+#endif
 {
   RegisterBeamSections ();
+  RegisterMaterials ();
 }
 StructuralSolver :: ~StructuralSolver ()
 {
@@ -106,116 +143,274 @@ StructuralSolver :: ~StructuralSolver ()
     {
       delete *it;
     }
-
+#ifdef HAVE_FLTK 
+  if(_window)delete _window;;
+#endif
 }
 
+
+#define BEAM_SECTION_ 3
+#define BEAM_MATERIAL_ 4
+#define POINT_X_ 0
+#define POINT_Y_ 1
+#define POINT_Z_ 2
+#define X_A_ 0
+#define X_B_ 1
+#define Y_A_ 2
+#define Y_B_ 3
+#define Z_A_ 4
+#define Z_B_ 5
+
 void StructuralSolver ::popupPropertiesForPhysicalEntity (int dim)
 { 
+#ifdef HAVE_FLTK 
   static Fl_Group *g[10];
   int i;
+  int fontsize = CTX.fontsize;
+
+#define WINDOW_BOX FL_FLAT_BOX
+#define BH (2*fontsize+1) // button height
+#define WB (6)            // window border
+#define IW (17*fontsize)  // input field width
+  
+  if(_window) {
+    for(i = 0; i < 2; i++)
+      g[i]->hide();
+    g[dim]->show();
+    _window->show();
+    return;
+  }
+  
+  int width = 31 * fontsize;
+  int height = 5 * WB + 9 * BH;
+
+  _window = new Fl_Window(width, height, "Structural Solver");
+  _window->box(WINDOW_BOX);
+  {
+    Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
+    // 0: 
+    {
+      g[0] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Physical Point");
+      
+      static Fl_Menu_Item _type[] = {
+	{"Displacement fixed", 0, 0, 0},
+	{"Load fixed", 0, 0, 0},
+	{0}
+      };
+      _choice[POINT_X_] = new Fl_Choice(2 * WB, 2 * WB + 1 * BH, IW, BH, "X-component");
+      _choice[POINT_X_]->menu(_type);
+      _choice[POINT_X_]->align(FL_ALIGN_RIGHT);
+      
+      _value[X_A_] = new Fl_Value_Input(2 * WB, 2 * WB + 2 * BH, IW/2, BH,       "");
+      _value[X_A_]->align(FL_ALIGN_RIGHT);
+      _value[X_B_] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 2 * BH, IW/2, BH, "VAL = A * X + B");
+      _value[X_B_]->align(FL_ALIGN_RIGHT);
+      
+      _choice[POINT_Y_] = new Fl_Choice(2 * WB, 2 * WB + 3 * BH, IW, BH, "Y-component");
+      _choice[POINT_Y_]->menu(_type);
+      _choice[POINT_Y_]->align(FL_ALIGN_RIGHT);
+      
+      
+      _value[Y_A_] = new Fl_Value_Input(2 * WB, 2 * WB + 4 * BH, IW/2, BH,       "");
+      _value[Y_A_]->align(FL_ALIGN_RIGHT);
+      _value[Y_B_] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 4 * BH, IW/2, BH, "VAL = A * X + B");
+      _value[Y_B_]->align(FL_ALIGN_RIGHT);
+      
+      _choice[POINT_Z_] = new Fl_Choice(2 * WB, 2 * WB + 5 * BH, IW, BH, "Z-component (moment)");
+      _choice[POINT_Z_]->menu(_type);
+      _choice[POINT_Z_]->align(FL_ALIGN_RIGHT);
+      
+      _value[Z_A_] = new Fl_Value_Input(2 * WB, 2 * WB + 6 * BH, IW/2, BH,       "");
+      _value[Z_A_]->align(FL_ALIGN_RIGHT);
+      _value[Z_B_] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 6 * BH, IW/2, BH, "VAL = A * X + B");
+      _value[Z_B_]->align(FL_ALIGN_RIGHT);
+      
+      
+      g[0]->end();
+    }
+    // 2: Physical Line
+    {
+      g[1] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Physical Line");
+      {
+	_choice[BEAM_SECTION_] = new Fl_Choice(2 * WB, 2 * WB + 1 * BH, IW, BH, "Beam Section");      
+	std::list<struct Structural_BeamSection* > :: iterator it  = beam_sections.begin();
+	std::list<struct Structural_BeamSection* > :: iterator ite = beam_sections.end();      
+	for (;it!=ite;++it)
+	  {
+	    _choice[BEAM_SECTION_]->add ((*it)->name.c_str());
+	  }
+	_choice[BEAM_SECTION_]->align(FL_ALIGN_RIGHT);
+      }
+      {
+	_choice[BEAM_MATERIAL_] = new Fl_Choice(2 * WB, 2 * WB + 2 * BH, IW, BH, "Material");      
+	std::list<struct Structural_Material > :: iterator it  = materials.begin();
+	std::list<struct Structural_Material > :: iterator ite = materials.end();      
+	for (;it!=ite;++it)
+	  {
+	    _choice[BEAM_MATERIAL_]->add ((*it).name.c_str());
+	  }
+	_choice[BEAM_MATERIAL_]->align(FL_ALIGN_RIGHT);
+      }
+      _value[6] = new Fl_Value_Input(2 * WB, 2 * WB + 3 * BH, IW/2, BH,       "");
+      _value[6]->value(0.0);
+      _value[6]->align(FL_ALIGN_RIGHT);
+      _value[7] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 3 * BH, IW/2, BH, "X-Load");
+      _value[7]->value(0.0);
+      _value[7]->align(FL_ALIGN_RIGHT);
+      _value[8] = new Fl_Value_Input(2 * WB, 2 * WB + 4 * BH, IW/2, BH,       "");
+      _value[8]->value(0.0);
+      _value[8]->align(FL_ALIGN_RIGHT);
+      _value[9] = new Fl_Value_Input(2 * WB+IW/2, 2 * WB + 4 * BH, IW/2, BH, "Y-Load");
+      _value[9]->value(0.0);
+      _value[9]->align(FL_ALIGN_RIGHT);
+      
+      g[1]->end();
+    }    
+  }
+#endif
+}
+
+void StructuralSolver :: addPhysicalLine (int id)
+{ 
+#ifdef HAVE_FLTK 
+  PhysicalLineInfo info;
+  info.section = std::string(_choice[BEAM_SECTION_] ->mvalue()->text);  
+  info.material= std::string(_choice[BEAM_MATERIAL_]->mvalue()->text); 
+  lines[id] = info;
+#endif  
+}
+void StructuralSolver :: addPhysicalPoint (int id)
+{ 
+  PhysicalPointInfo info;
+
+  info.disp[0] = _choice[POINT_X_] ->value();
+  info.disp[1] = _choice[POINT_Y_] ->value();
+  info.disp[2] = _choice[POINT_Z_] ->value();
+  info.val[0] = _value[X_A_]->value();
+  info.val[1] = _value[X_B_]->value();
+  info.val[2] = _value[Y_A_]->value();
+  info.val[3] = _value[Y_B_]->value();
+  info.val[4] = _value[Z_A_]->value();
+  info.val[5] = _value[Z_B_]->value();
+
+  if (info.disp[0] == 0)
+    MAX_FORCE = (MAX_FORCE>info.val[0])?MAX_FORCE:info.val[0];
+  if (info.disp[1] == 0)
+    MAX_FORCE = (MAX_FORCE>info.val[1])?MAX_FORCE:info.val[1];
+  if (info.disp[2] == 0)
+    MAX_FORCE = (MAX_FORCE>info.val[2])?MAX_FORCE:info.val[2];
+
+
+  points[id] = info;
+
+  
+}
+void StructuralSolver :: writeSolverFile ( const char *geom_file ) const
+{
+  char name[256];
+  sprintf(name,"%s.str",geom_file);
+  FILE *f = fopen(name,"w");  
+  {
+    std::map<int,struct PhysicalLineInfo>  :: const_iterator it  = lines.begin();
+    std::map<int,struct PhysicalLineInfo > :: const_iterator ite = lines.end();      
+    for (;it!=ite;++it)
+      {
+	const PhysicalLineInfo &i = (*it).second;
+	int id = (*it).first;
+	fprintf(f,"BEAM PHYSICAL %d SECTION %s MATERIAL %s LOADS %g %g %g %g\n",id,i.section.c_str(),i.material.c_str(),i.fx1,i.fy1,i.fx2,i.fy2);
+      }
+  }
+  {
+    std::map<int,struct PhysicalPointInfo>  :: const_iterator it  = points.begin();
+    std::map<int,struct PhysicalPointInfo > :: const_iterator ite = points.end();      
+    for (;it!=ite;++it)
+      {
+	const PhysicalPointInfo &i = (*it).second;
+	int id = (*it).first;
+	fprintf(f,"NODE PHYSICAL %d DEPLX %d %g %g DEPLY %d %g %g DEPLZ %d %g %g\n",id,i.disp[0],i.val[0],i.val[1],i.disp[1],i.val[2],i.val[3],i.disp[2],i.val[4],i.val[5]);
+      }
+  }
+  fclose(f);  
+}
+
+void StructuralSolver :: readSolverFile ( const char *geom_file ) 
+{
+  char name[256],line[256],a1[24],a2[24],a3[24],a4[240],a5[24],a6[240],a7[24];
+  sprintf(name,"%s.str",geom_file);
+  FILE *f = fopen(name,"r");  
+  if (!f)return;
+  while(!feof(f))
+    {
+      fgets(line,256,f);
+      printf("%s\n",line);
+      sscanf (line,"%s",name);
+      if (!strcmp(name,"BEAM"))
+	{
+	  int id;
+	  PhysicalLineInfo info;
+	  sscanf(line,"%s %s %d %s %s %s %s %s %lf %lf %lf %lf\n",a1,a2,&id,a3,a4,a5,a6,a7,&info.fx1,&info.fy1,&info.fx2,&info.fy2);
+	  info.material = std::string(a6);
+	  info.section  = std::string(a4);
+	  lines[id] = info;
+	}
+      if (!strcmp(name,"NODE"))
+	{
+	  int id;
+	  PhysicalPointInfo info;
+	  sscanf(line,"%s %s %d %s %d %lf %lf %s %d %lf %lf %s %d %lf %lf\n",a1,a2,&id,
+		 a3,&info.disp[0],&info.val[0],&info.val[1],
+		 a4,&info.disp[1],&info.val[2],&info.val[3],
+		 a5,&info.disp[2],&info.val[4],&info.val[5]);
+	  points[id] = info;
+	  if (info.disp[0] == 0)
+	    MAX_FORCE = (MAX_FORCE>info.val[0])?MAX_FORCE:info.val[0];
+	  if (info.disp[1] == 0)
+	    MAX_FORCE = (MAX_FORCE>info.val[1])?MAX_FORCE:info.val[1];
+	  if (info.disp[2] == 0)
+	    MAX_FORCE = (MAX_FORCE>info.val[2])?MAX_FORCE:info.val[2];
 
-//   if(context_geometry_window) {
-//     for(i = 0; i < 6; i++)
-//       g[i]->hide();
-//     g[num]->show();
-//     context_geometry_window->show();
-//     return;
-//   }
-
-//   int width = 31 * fontsize;
-//   int height = 5 * WB + 9 * BH;
-
-//   context_geometry_window = new Fl_Window(width, height, "Contextual geometry definitions");
-//   context_geometry_window->box(WINDOW_BOX);
-//   {
-//     Fl_Tabs *o = new Fl_Tabs(WB, WB, width - 2 * WB, height - 3 * WB - BH);
-//     // 0: Parameter
-//     {
-//       g[0] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Parameter");
-//       context_geometry_input[0] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Name");
-//       context_geometry_input[0]->value("lc");
-//       context_geometry_input[1] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Value");
-//       context_geometry_input[1]->value("1.0");
-//       for(i = 0; i < 2; i++) {
-//         context_geometry_input[i]->align(FL_ALIGN_RIGHT);
-//       }
-//       {
-//         Fl_Return_Button *o = new Fl_Return_Button(width - BB - 2 * WB, 2 * WB + 7 * BH, BB, BH, "Add");
-//         o->callback(con_geometry_define_parameter_cb);
-//       }
-//       g[0]->end();
-//     }
-//     // 1: Point
-//     {
-//       g[1] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Point");
-//       context_geometry_input[2] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X coordinate");
-//       context_geometry_input[2]->value("0.0");
-//       context_geometry_input[3] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y coordinate");
-//       context_geometry_input[3]->value("0.0");
-//       context_geometry_input[4] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z coordinate");
-//       context_geometry_input[4]->value("0.0");
-//       context_geometry_input[5] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Characteristic length");
-//       context_geometry_input[5]->value("1.0");
-//       for(i = 2; i < 6; i++) {
-//         context_geometry_input[i]->align(FL_ALIGN_RIGHT);
-//       }
-//       {
-//         Fl_Return_Button *o = new Fl_Return_Button(width - BB - 2 * WB, 2 * WB + 7 * BH, BB, BH, "Add");
-//         o->callback(con_geometry_define_point_cb);
-//       }
-//       g[1]->end();
-//     }
-//     // 2: Translation
-//     {
-//       g[2] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Translation");
-//       context_geometry_input[6] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X component");
-//       context_geometry_input[6]->value("0.0");
-//       context_geometry_input[7] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y component");
-//       context_geometry_input[7]->value("0.0");
-//       context_geometry_input[8] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z component");
-//       context_geometry_input[8]->value("1.0");
-//       for(i = 6; i < 9; i++) {
-//         context_geometry_input[i]->align(FL_ALIGN_RIGHT);
-//       }
-//       g[2]->end();
-//     }
-//     // 3: Rotation
-//     {
-//       g[3] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Rotation");
-//       context_geometry_input[9] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X coordinate of an axis point");
-//       context_geometry_input[9]->value("0.0");
-//       context_geometry_input[10] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y coordinate of an axis point");
-//       context_geometry_input[10]->value("0.0");
-//       context_geometry_input[11] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z coordinate of an axis point");
-//       context_geometry_input[11]->value("0.0");
-//       context_geometry_input[12] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "X component of direction");
-//       context_geometry_input[12]->value("0.0");
-//       context_geometry_input[13] = new Fl_Input(2 * WB, 2 * WB + 5 * BH, IW, BH, "Y component of direction");
-//       context_geometry_input[13]->value("1.0");
-//       context_geometry_input[14] = new Fl_Input(2 * WB, 2 * WB + 6 * BH, IW, BH, "Z component of direction");
-//       context_geometry_input[14]->value("0.0");
-//       context_geometry_input[15] = new Fl_Input(2 * WB, 2 * WB + 7 * BH, IW, BH, "Angle in radians");
-//       context_geometry_input[15]->value("Pi/4");
-//       for(i = 9; i < 16; i++) {
-//         context_geometry_input[i]->align(FL_ALIGN_RIGHT);
-//       }
-//       g[3]->end();
-//     }
-//     // 4: Scale
-//     {
-//       g[4] = new Fl_Group(WB, WB + BH, width - 2 * WB, height - 3 * WB - 2 * BH, "Scale");
-//       context_geometry_input[16] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "X component of direction");
-//       context_geometry_input[16]->value("1.0");
-//       context_geometry_input[17] = new Fl_Input(2 * WB, 2 * WB + 2 * BH, IW, BH, "Y component of direction");
-//       context_geometry_input[17]->value("0.0");
-//       context_geometry_input[18] = new Fl_Input(2 * WB, 2 * WB + 3 * BH, IW, BH, "Z component of direction");
-//       context_geometry_input[18]->value("0.0");
-//       context_geometry_input[19] = new Fl_Input(2 * WB, 2 * WB + 4 * BH, IW, BH, "Factor");
-//       context_geometry_input[19]->value("2.0");
-//       for(i = 16; i < 20; i++) {
-//         context_geometry_input[i]->align(FL_ALIGN_RIGHT);
-//       }
-//       g[4]->end();
-//     }
+	}
+      if (feof(f) )break;
+    }
+  fclose(f);
 }
 
+bool StructuralSolver :: GL_enhancePoint ( Vertex *v) 
+{
+#ifdef HAVE_FLTK  
+  PhysicalGroup *p;
+  for(int i = 0; i < List_Nbr(THEM->PhysicalGroups); i++) 
+    { 
+      char Num[100];
+      List_Read(THEM->PhysicalGroups, i, &p);
+      if(p->Typ == MSH_PHYSICAL_POINT) {
+	if(List_Search(p->Entities, &v->Num, fcmp_absint)) { 
+	  std::map<int,struct PhysicalPointInfo>::const_iterator it = points.find(p->Num);
+	  if (it !=points.end())
+	    {	      
+	      for (int icomp=0;icomp<3;++icomp)
+		{
+		  double dv[3] = {0,0,0};
+		  if (it->second.disp[icomp] == 1)
+		    {
+		      double offset = 0.5 * CTX.gl_fontsize * CTX.pixel_equiv_x;
+		      
+		      dv[icomp] =  (CTX.max[0]-CTX.min[0])*it->second.val[1+2*icomp]*.2 / (MAX_FORCE *CTX.s[icomp]);
+
+		      Draw_Vector (CTX.vector_type,  0, CTX.arrow_rel_head_radius, 
+				   CTX.arrow_rel_stem_length, CTX.arrow_rel_stem_radius,
+				   v->Pos.X, v->Pos.Y, v->Pos.Z,
+				   dv[0], dv[1], dv[2], NULL, CTX.geom.light);
+		      sprintf(Num, "%g kN", it->second.val[1]);
+		      glRasterPos3d((v->Pos.X + dv[0])+ offset / CTX.s[0],
+				    (v->Pos.Y + dv[1])+ offset / CTX.s[1],
+				    (v->Pos.Z + dv[2])+ offset / CTX.s[2]);
+		      Draw_String(Num);
+		    } 
+		}
+	    }
+	}
+      }
+    }
+#endif
+}
diff --git a/Plugin/StructuralSolver.h b/Plugin/StructuralSolver.h
index 75f02bf07d..be5dd38a78 100644
--- a/Plugin/StructuralSolver.h
+++ b/Plugin/StructuralSolver.h
@@ -19,7 +19,10 @@
 // 
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
+#include <map>
 #include <list>
+#include <vector>
+#include "Geo.h"
 #include "Mesh.h"
 #include "Plugin.h"
 #include <string>
@@ -66,16 +69,45 @@ struct Structural_BeamSection
   ~Structural_BeamSection();
 };
 
+struct Structural_Material
+{
+  std::string name;
+  std::vector<double> par;
+};
+
+
+struct PhysicalPointInfo 
+{
+  int disp[3];
+  double val[6];
+};
+
+struct PhysicalLineInfo 
+{
+  PhysicalLineInfo() : fx1(0),fy1(0),fx2(0),fy2(0){}
+  std::string material, section;
+  double fx1,fx2,fy1,fy2;
+};
+
 
 class StructuralSolver : public GMSH_Solve_Plugin
 {
-  std::list < struct Structural_BeamSection* > beam_sections;
-  void RegisterBeamSections ();
+  std::list < struct Structural_BeamSection*     > beam_sections;
+  std::list < struct Structural_Material  > materials;
+  std::map <int, struct PhysicalPointInfo  > points;
+  std::map <int, struct PhysicalLineInfo   > lines;
+  void RegisterBeamSections     ();
+  void RegisterMaterials        ();
+  void addPhysicalPoint         (int id);
+  void addPhysicalLine          (int id);
 #ifdef HAVE_FLTK 
-  Fl_Window        *context_mesh_window ;
-  Fl_Input         *context_mesh_input[20] ;
-  Fl_Choice        *context_mesh_choice[20] ;
+  Fl_Window        *_window ;
+  Fl_Value_Input         *_value[20] ;
+  Fl_Choice        *_choice[20] ;
 #endif
+  double MAX_FORCE;
+  double MAX_DISPLACEMENT;
+
 public:
   StructuralSolver();
   ~StructuralSolver();
@@ -86,9 +118,16 @@ public:
   // show the message and hopefully continue
   virtual void catchErrorMessage(char *errorMessage) const;
   virtual void popupPropertiesForPhysicalEntity (int dim);
-  virtual void receiveNewPhysicalGroup (int dim, int id){}
-  virtual void writeSolverFile ( FILE *f ) const{} 
-  virtual void loadSolverFile  ( FILE *f ){}
+  virtual void receiveNewPhysicalGroup (int dim, int id)
+  {
+    switch(dim){
+    case ENT_POINT:addPhysicalPoint(id);break;
+    case ENT_LINE:addPhysicalLine(id);break;
+    }      
+  }
+  virtual void writeSolverFile ( const char *geom_file ) const; 
+  virtual void readSolverFile  ( const char *geom_file );
+  bool GL_enhancePoint ( Vertex *v) ;
 };
 
 #endif
diff --git a/benchmarks/1d/ligne.geo b/benchmarks/1d/ligne.geo
index 37a82f7f19..b7f9f100d4 100644
--- a/benchmarks/1d/ligne.geo
+++ b/benchmarks/1d/ligne.geo
@@ -13,3 +13,8 @@ Physical Point(10) = {1};
 Physical Line(11) = {1};
 Physical Line(12) = {1};
 Physical Line(13) = {1};
+Physical Line(14) = {1};
+Physical Line(15) = {1};
+Physical Line(16) = {1};
+Physical Line(17) = {1};
+Physical Point(18) = {2};
-- 
GitLab