Skip to content
Snippets Groups Projects
Select Git revision
  • bf29e24c390cff1a6c6826d060ba9525d39ba3f4
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

Scale.cpp

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    • Christophe Geuzaine's avatar
      bf29e24c
      · bf29e24c
      Christophe Geuzaine authored
      For all our mechanical engineering friends out there, I just cleaned up the stuff
      I did with Sean last year, i.e., allow to draw a vector field as a displacement
      map, with another scalar field displayed instead of the displacement norm.
      
      It's basically the same as Plugin(DisplacementRaise), but it does not modify the
      actual data inside the view (so e.g. you cannot save it). Instead, it's implemented
      as an alternative "Vector display" mode. This allows to easily animate deformed meshed
      with arbitrary scalar fields drawn on them. (The GUI for this is kinda lame, but
      it works: just select Vector display->Raised scalar view, select the scalar view
      number, et voila.)
      
      I also generalized the smooth normal code path a little, so that we can have smooth
      normals for vector-as-displacement and tensor-as-von-mises plots, too.
      bf29e24c
      History
      Christophe Geuzaine authored
      For all our mechanical engineering friends out there, I just cleaned up the stuff
      I did with Sean last year, i.e., allow to draw a vector field as a displacement
      map, with another scalar field displayed instead of the displacement norm.
      
      It's basically the same as Plugin(DisplacementRaise), but it does not modify the
      actual data inside the view (so e.g. you cannot save it). Instead, it's implemented
      as an alternative "Vector display" mode. This allows to easily animate deformed meshed
      with arbitrary scalar fields drawn on them. (The GUI for this is kinda lame, but
      it works: just select Vector display->Raised scalar view, select the scalar view
      number, et voila.)
      
      I also generalized the smooth normal code path a little, so that we can have smooth
      normals for vector-as-displacement and tensor-as-von-mises plots, too.
    meshGEdge.cpp 11.03 KiB
    // $Id: meshGEdge.cpp,v 1.45 2007-10-11 08:59:22 remacle Exp $
    //
    // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    // USA.
    // 
    // Please report all bugs and problems to <gmsh@geuz.org>.
    
    #include "Gmsh.h"
    #include "meshGEdge.h"
    #include "GEdge.h"
    #include "GFace.h"
    #include "BackgroundMesh.h"
    #include "Message.h"
    
    typedef struct{
      int Num;
      double t, lc, p;
    }IntPoint;
    
    struct xi2lc
    {
      double xi, lc;
      xi2lc(const double &_xi,const double _lc)
        : xi(_xi), lc(_lc)
      { 
      }
      bool operator < (const xi2lc &other)
      {
        return xi < other.xi; 
      }
    };
    
    static std::vector<xi2lc> interpLc;
    
    void smoothInterpLc(bool periodic, int nbSmooth)
    {
      if(periodic){
        for(int i = 0; i < (int)interpLc.size() * nbSmooth; i++){	  	  
          xi2lc &left = interpLc[(i - 1) % interpLc.size()];
          xi2lc &mid = interpLc[i % interpLc.size()];
          xi2lc &right = interpLc[(i + 1) % interpLc.size()];
          if(1. / mid.lc > 1.1 * 1. / left.lc) mid.lc = left.lc/ 1.1;
          if(1. / mid.lc > 1.1 * 1. / right.lc) mid.lc = right.lc/ 1.1;
        }
      } 
      else{
        for(int j = 0; j < nbSmooth; j++){
          for(int i = 0 ; i < (int)interpLc.size(); i++){	  	  
    	xi2lc &left = (i == 0) ? interpLc[0] : interpLc[i - 1];
    	xi2lc &mid = interpLc[i];
    	xi2lc &right = (i == (int)interpLc.size() - 1) ?
    	  interpLc[interpLc.size() - 1] : interpLc[i+1];
    	if(1. / mid.lc > 1.1 * 1. / left.lc) mid.lc = left.lc / 1.1;
    	if(1. / mid.lc > 1.1 * 1. / right.lc) mid.lc = right.lc / 1.1;
          }
        } 
      }
    }
    
    void printInterpLc(const char *name)
    {
      FILE *f = fopen(name,"w");
      for(unsigned int i = 0; i < interpLc.size(); i++){	  	  
        xi2lc &interp = interpLc[i];
        fprintf(f,"%12.5E %12.5E\n", interp.xi, 1 / interp.lc);
      }
      fclose(f);
    }
    
    void buildInterpLc(List_T *lcPoints)
    {
      IntPoint p;
      interpLc.clear();
      for(int i = 0; i < List_Nbr(lcPoints); i++){
        List_Read(lcPoints, i, &p);
        interpLc.push_back(xi2lc( p.t, p.lc));
      }
    }
    
    double F_Lc_usingInterpLc(GEdge *ge, double t)
    {
      std::vector<xi2lc>::iterator it = std::lower_bound(interpLc.begin(),
    						     interpLc.end(), xi2lc(t, 0));
      double t1 = it->xi;
      double l1 = it->lc;
      it++;
      SVector3 der = ge->firstDer(t);
      const double d = norm(der);
      if(it == interpLc.end()) return d * l1;
      double t2 = it->xi;
      double l2 = it->lc;
      double l = l1 + ((t - t1) / (t2 - t1)) * (l2 - l1);
      return d * l;
    }
    
    double F_Lc_usingInterpLcBis(GEdge *ge, double t)
    {
      GPoint p = ge->point(t);
      double lc_here;
    
      Range<double> bounds = ge->parBounds(0);
      double t_begin = bounds.low();
      double t_end = bounds.high();
    
      if(t == t_begin)
        lc_here = BGM_MeshSize(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
      else if(t == t_end)
        lc_here = BGM_MeshSize(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
      else
        lc_here = BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z());
    
      return 1 / lc_here;
    }
    
    double F_Lc(GEdge *ge, double t)
    {
      GPoint p = ge->point(t);
      double lc_here;
    
      Range<double> bounds = ge->parBounds(0);
      double t_begin = bounds.low();
      double t_end = bounds.high();
    
      if(t == t_begin)
        lc_here = BGM_MeshSize(ge->getBeginVertex(), t, 0, p.x(), p.y(), p.z());
      else if(t == t_end)
        lc_here = BGM_MeshSize(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z());
      else
        lc_here = BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z());
    
      SVector3 der = ge->firstDer(t);
      const double d = norm(der);
      return d / lc_here;
    }
    
    double F_Transfinite(GEdge *ge, double t)
    {
      double val, r;
    
      SVector3 der = ge->firstDer(t) ;
      double d = norm(der);
    
      double coef = ge->meshAttributes.coeffTransfinite;
      int type = ge->meshAttributes.typeTransfinite;
      int nbpt = ge->meshAttributes.nbPointsTransfinite;
    
      if(coef <= 0.0 || coef == 1.0) {
        // coef < 0 should never happen
        val = d * coef / ge->length();
      }
      else {
        switch (abs(type)) {
    
        case 1: // Geometric progression ar^i; Sum of n terms = length = a (r^n-1)/(r-1)
          {
    	if(sign(type) >= 0)
    	  r = coef;
    	else
    	  r = 1. / coef;
    	double a = ge->length() * (r - 1.) / (pow(r, nbpt - 1.) - 1.);
    	int i = (int)(log(t * ge->length() / a * (r - 1.) + 1.) / log(r));
    	val = d / (a * pow(r, (double)i));
          }
          break;
    	
        case 2: // Bump
          {
    	double a;
    	if(coef > 1.0) {
    	  a = -4. * sqrt(coef - 1.) *
    	    atan2(1., sqrt(coef - 1.)) /
    	    ((double)nbpt *  ge->length());
    	}
    	else {
    	  a = 2. * sqrt(1. - coef) *
    	    log(fabs((1. + 1. / sqrt(1. - coef))
    		     / (1. - 1. / sqrt(1. - coef))))
    	    / ((double)nbpt * ge->length());
    	}
    	double b = -a * ge->length() * ge->length() / (4. * (coef - 1.));
    	val = d / (-a * DSQR(t * ge->length() - (ge->length()) * 0.5) + b);
          }
          break;
          
        default:
          Msg(WARNING, "Unknown case in Transfinite Line mesh");
          val = 1.;
          break;
        }
      }
      return val;
    }
    
    double F_One(GEdge *ge, double t)
    {
      SVector3 der = ge->firstDer(t) ;
      return norm(der);
    }
    
    double trapezoidal(IntPoint * P1, IntPoint * P2)
    {
      return (0.5 * (P1->lc + P2->lc) * (P2->t - P1->t));
    }
    
    void RecursiveIntegration(GEdge *ge, IntPoint * from, IntPoint * to,
                              double (*f) (GEdge *e, double X), List_T * pPoints,
                              double Prec, int *depth)
    {
      IntPoint P, p1;
    
      (*depth)++;
    
      P.t = 0.5 * (from->t + to->t);
      P.lc = f(ge, P.t);
    
      double val1 = trapezoidal(from, to);
      double val2 = trapezoidal(from, &P);
      double val3 = trapezoidal(&P, to);
      double err = fabs(val1 - val2 - val3);
    
      if(((err < Prec) && (*depth > 1)) || (*depth > 25)) {
        List_Read(pPoints, List_Nbr(pPoints) - 1, &p1);
        P.p = p1.p + val2;
        List_Add(pPoints, &P);
    
        List_Read(pPoints, List_Nbr(pPoints) - 1, &p1);
        to->p = p1.p + val3;
        List_Add(pPoints, to);
      }
      else {
        RecursiveIntegration(ge, from, &P, f, pPoints, Prec, depth);
        RecursiveIntegration(ge, &P, to, f, pPoints, Prec, depth);
      }
    
      (*depth)--;
    }
    
    double Integration(GEdge *ge, double t1, double t2, 
    		   double (*f) (GEdge *e, double X),
                       List_T * pPoints, double Prec)
    {
      IntPoint from, to;
    
      int depth = 0;
    
      from.t = t1;
      from.lc = f(ge, from.t);
      from.p = 0.0;
      List_Add(pPoints, &from);
    
      to.t = t2;
      to.lc = f(ge, to.t);
      RecursiveIntegration(ge, &from, &to, f, pPoints, Prec, &depth);
    
      List_Read(pPoints, List_Nbr(pPoints) - 1, &to);
      return to.p;
    }
    
    void deMeshGEdge::operator() (GEdge *ge) 
    {
      if(ge->geomType() == GEntity::DiscreteCurve) return;
    
      for (unsigned int i = 0; i < ge->mesh_vertices.size(); i++) 
        delete ge->mesh_vertices[i];
      ge->mesh_vertices.clear();
      for (unsigned int i = 0; i < ge->lines.size(); i++) 
        delete ge->lines[i];
      ge->lines.clear();
      ge->deleteVertexArrays();
    }
    
    void meshGEdge::operator() (GEdge *ge) 
    {  
      if(ge->geomType() == GEntity::DiscreteCurve) return;
      if(ge->geomType() == GEntity::BoundaryLayerCurve) return;
    
      // Send a messsage to the GMSH environment
      Msg(INFO, "Meshing curve %d", ge->tag());
    
      deMeshGEdge dem;
      dem(ge);
    
      if(MeshExtrudedCurve(ge)) return;
    
      // Create a list of integration points
      List_T *Points = List_Create(10, 10, sizeof(IntPoint));
      // Create a list of points for interpolating the LC Field
      List_T *lcPoints = List_Create(10, 10, sizeof(IntPoint));
    
      // compute bounds
      Range<double> bounds = ge->parBounds(0);
      double t_begin = bounds.low();
      double t_end = bounds.high();
      
      // first compute the length of the curve by integrating one
      double length = Integration(ge, t_begin, t_end, F_One, Points, 1.e-8);
      ge->setLength(length);
    
      List_Reset(Points);
        
      // Integrate detJ/lc du 
      double a;
      int N;
      if(ge->meshAttributes.Method == TRANSFINI){
        a = Integration(ge, t_begin, t_end, F_Transfinite, Points, 1.e-8);
        N = ge->meshAttributes.nbPointsTransfinite;
      }
      else{
        if(CTX.mesh.lc_integration_precision > 1.e-8){
          Integration(ge, t_begin, t_end, F_Lc_usingInterpLcBis, lcPoints, 
    		  CTX.mesh.lc_integration_precision);
          buildInterpLc(lcPoints);
          printInterpLc("toto1.dat");
          smoothInterpLc(ge->periodic(), 20);
          printInterpLc("toto2.dat");
          a = Integration(ge, t_begin, t_end, F_Lc_usingInterpLc, Points, 1.e-8);
        }
        else{
          a = Integration(ge, t_begin, t_end, F_Lc, Points, 1.e-8);
        }
        N = std::max(ge->minimumMeshSegments() + 1, (int)(a + 1.));
      }
    
      // if the curve is periodic and if the begin vertex is identical to
      // the end vertex and if this vertex has only one model curve
      // adjacent to it, then the vertex is not connecting any other
      // curve. So, the mesh vertex and its associated geom vertex are not
      // necessary at the same location
      GPoint beg_p, end_p;
      if(ge->getBeginVertex() == ge->getEndVertex() && 
         ge->getBeginVertex()->edges().size() == 1){
        end_p = beg_p = ge->point(t_begin);
      }
      else{
        MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
        MVertex *v1 = ge->getEndVertex()->mesh_vertices[0];
        beg_p = GPoint(v0->x(), v0->y(), v0->z());
        end_p = GPoint(v1->x(), v1->y(), v1->z());
      }
    
      // do not consider the first and the last vertex (those are not
      // classified on this mesh edge)
      if(N > 1){
        const double b = a / (double)(N - 1);
        int count = 1, NUMP = 1;
        IntPoint P1, P2;
        ge->mesh_vertices.resize(N - 2);
        while(NUMP < N - 1) {
          List_Read(Points, count - 1, &P1);
          List_Read(Points, count, &P2);
          const double d = (double)NUMP * b;
          if((fabs(P2.p) >= fabs(d)) && (fabs(P1.p) < fabs(d))) {
            double dt = P2.t - P1.t;
    	double dlc = P2.lc - P1.lc;
            double dp = P2.p - P1.p;
            double t   = P1.t + dt / dp * (d - P1.p);
    	SVector3 der = ge->firstDer(t);
    	const double d = norm(der);  
            double lc  = d/(P1.lc + dlc / dp * (d - P1.p));
            GPoint V = ge->point(t);
    	ge->mesh_vertices[NUMP - 1] = new MEdgeVertex(V.x(), V.y(), V.z(), ge, t, lc);
    	//	printf("lc = %12.5E %12.5E \n",lc,P1.lc,P2.lc);
            NUMP++;
          }
          else {
            count++;
          }
        }
        ge->mesh_vertices.resize(NUMP - 1);
      }
      List_Delete(Points);
      List_Delete(lcPoints);
    
      for(unsigned int i = 0; i < ge->mesh_vertices.size() + 1; i++){
        MVertex *v0 = (i == 0) ? 
          ge->getBeginVertex()->mesh_vertices[0] : ge->mesh_vertices[i - 1];
        MVertex *v1 = (i == ge->mesh_vertices.size()) ? 
          ge->getEndVertex()->mesh_vertices[0] : ge->mesh_vertices[i];
        ge->lines.push_back(new MLine(v0, v1));
      }
    
      if(ge->getBeginVertex() == ge->getEndVertex() && 
         ge->getBeginVertex()->edges().size() == 1){
        MVertex *v0 = ge->getBeginVertex()->mesh_vertices[0];
        v0->x() = beg_p.x();
        v0->y() = beg_p.y();
        v0->z() = beg_p.z();
      }
    }