Skip to content
Snippets Groups Projects
Forked from gmsh / gmsh
18770 commits behind the upstream repository.
AdaptiveViews.cpp 12.36 KiB
//
// Copyright (C) 1997-2004 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>.

// Don't indent this file
// *INDENT-OFF*
				       
#include <stdio.h>
#include <math.h>
#include <list>
#include <set>
#include "Views.h"
#include "Plugin.h"

// A recursive effective implementation

void computeShapeFunctions ( Double_Matrix *coeffs, Double_Matrix *eexps , double u, double v, double *sf);

std::set<_point> _point::all_points;
std::list<_triangle*> _triangle::all_triangles;

_point * _point::New ( double x, double y, double z, Double_Matrix *coeffs, Double_Matrix *eexps) 
{
  _point p;
  p.x=x; p.y=y; p.z=z;
  std::set<_point> :: iterator it = all_points.find ( p );
  if ( it == all_points.end() )
    {
      all_points.insert (p);
      it = all_points.find ( p );
      double *kkk = (double*)(it->shape_functions);
      computeShapeFunctions (coeffs, eexps , x,y,kkk);
      return (_point*) & (*it);
    }
  else
    return (_point*) & (*it);
}
void _triangle::clean ()
{    
  std::list<_triangle*>::iterator it =  all_triangles.begin();
  std::list<_triangle*>::iterator ite =  all_triangles.end();
  for (;it!=ite;++it)
    {
      delete *it;
    }
  all_triangles.clear();
  _point::all_points.clear();
}
void _triangle::Create (int maxlevel, Double_Matrix *coeffs, Double_Matrix *eexps) 
{
  printf("creating the sub-elements\n");
  int level = 0;
  clean();
  _point *p1 = _point::New ( 0,0,0, coeffs, eexps);
  _point *p2 = _point::New ( 0,1,0, coeffs, eexps);
  _point *p3 = _point::New ( 1,0,0, coeffs, eexps);
  _triangle *t = new _triangle(p1,p2,p3);
  Recur_Create (t, maxlevel,level,coeffs,eexps) ;

  printf("%d _triangle and %d _point created\n",(int)_triangle::all_triangles.size(),(int)_point::all_points.size());
}
void _triangle::Recur_Create (_triangle *t, int maxlevel, int level , Double_Matrix *coeffs, Double_Matrix *eexps) 
{
  all_triangles.push_back(t);
  if (level++ >= maxlevel)
    return;

  /*

  p3


  p13   p23


  p1    p12    p2


  */
  
  _point *p1  = t->p[0]; 
  _point *p2  = t->p[1]; 
  _point *p3  = t->p[2]; 
  _point *p12 = _point::New ( (p1->x+p2->x)*0.5,(p1->y+p2->y)*0.5,0, coeffs, eexps);
  _point *p13 = _point::New ( (p1->x+p3->x)*0.5,(p1->y+p3->y)*0.5,0, coeffs, eexps);
  _point *p23 = _point::New ( (p3->x+p2->x)*0.5,(p3->y+p2->y)*0.5,0, coeffs, eexps);
  _triangle *t1 = new _triangle (p1,p13,p12);
  Recur_Create (t1, maxlevel,level,coeffs,eexps);
  _triangle *t2 = new _triangle (p12,p23,p2);
  Recur_Create (t2, maxlevel,level,coeffs,eexps); 
  _triangle *t3 = new _triangle (p23,p13,p3);
  Recur_Create (t3, maxlevel,level,coeffs,eexps); 
  _triangle *t4 = new _triangle (p12,p13,p23);
  Recur_Create (t4, maxlevel,level,coeffs,eexps);
  t->t[0]=t1;t->t[1]=t2;t->t[2]=t3;t->t[3]=t4;      

}

void _triangle::Error ( double AVG , double tol )
{
  _triangle *t = *all_triangles.begin();
  Recur_Error (t,AVG,tol);
}

void _triangle::Recur_Error ( _triangle *t, double AVG, double tol )
{
  if(!t->t[0])t->visible = true; 
  else
    {
      double vr;
      if (!t->t[0]->t[0])
	{
	  double v1 = t->t[0]->V();
	  double v2 = t->t[1]->V();
	  double v3 = t->t[2]->V();
	  double v4 = t->t[3]->V();
	  vr = (2*v1 + 2*v2 + 2*v3 + v4)/7.;
	  double v =  t->V();
	  if ( fabs(v - vr) > AVG * tol ) 
	    //if ( fabs(v - vr) > ((fabs(v) + fabs(vr) + AVG * tol) * tol ) ) 
	    {
	      t->visible = false;
	      Recur_Error (t->t[0],AVG,tol);
	      Recur_Error (t->t[1],AVG,tol);
	      Recur_Error (t->t[2],AVG,tol);
	      Recur_Error (t->t[3],AVG,tol);
	    } 
	  else
	    t->visible = true;
	}
      else
	{
	  double v11 = t->t[0]->t[0]->V();
	  double v12 = t->t[0]->t[1]->V();
	  double v13 = t->t[0]->t[2]->V();
	  double v14 = t->t[0]->t[3]->V();
	  double v21 = t->t[1]->t[0]->V();
	  double v22 = t->t[1]->t[1]->V();
	  double v23 = t->t[1]->t[2]->V();
	  double v24 = t->t[1]->t[3]->V();
	  double v31 = t->t[2]->t[0]->V();
	  double v32 = t->t[2]->t[1]->V();
	  double v33 = t->t[2]->t[2]->V();
	  double v34 = t->t[2]->t[3]->V();
	  double v41 = t->t[3]->t[0]->V();
	  double v42 = t->t[3]->t[1]->V();
	  double v43 = t->t[3]->t[2]->V();
	  double v44 = t->t[3]->t[3]->V();
	  double vr1 = (2*v11 + 2*v12 + 2*v13 + v14)/7.;
	  double vr2 = (2*v21 + 2*v22 + 2*v23 + v24)/7.;
	  double vr3 = (2*v31 + 2*v32 + 2*v33 + v34)/7.;
	  double vr4 = (2*v41 + 2*v42 + 2*v43 + v44)/7.;
	  vr = (2*vr1+2*vr2+2*vr3+vr4)/7.;
	  if ( fabs(t->t[0]->V() - vr1) > AVG * tol  || 
	       fabs(t->t[1]->V() - vr2) > AVG * tol  || 
	       fabs(t->t[2]->V() - vr3) > AVG * tol  || 
	       fabs(t->t[3]->V() - vr4) > AVG * tol  || 
	       fabs(t->V() - vr) > AVG * tol ) 
	    //if ( fabs(t->t[0]->V() - vr1) > (fabs(t->t[0]->V())+fabs(vr1)+AVG * tol)*tol  || 
	    //		 fabs(t->t[1]->V() - vr2) > (fabs(t->t[1]->V())+fabs(vr2)+AVG * tol)*tol  || 
	    //		 fabs(t->t[2]->V() - vr3) > (fabs(t->t[2]->V())+fabs(vr3)+AVG * tol)*tol  || 
	    //		 fabs(t->t[3]->V() - vr4) > (fabs(t->t[3]->V())+fabs(vr4)+AVG * tol)*tol  || 
	    //		 fabs(t->V() - vr) > (fabs(t->V())+fabs(vr)+AVG * tol ) *tol)
	    {
	      t->visible = false;
	      Recur_Error (t->t[0],AVG,tol);
	      Recur_Error (t->t[1],AVG,tol);
	      Recur_Error (t->t[2],AVG,tol);
	      Recur_Error (t->t[3],AVG,tol);
	    }
	  else
	    t->visible = true;	      
	}
    }
}

static double t0,t1,t2,t3;

void Adaptive_Post_View:: zoomElement (Post_View * view ,
				       int ielem ,
				       int level, 
				       GMSH_Post_Plugin *plug)
{
  std::set<_point>::iterator it  = _point::all_points.begin();
  std::set<_point>::iterator ite = _point::all_points.end();

  double c0 = Cpu();

  const int N = _coefs->size1();
  Double_Vector val ( N ), res(_point::all_points.size());
  Double_Matrix xyz (3,3);
  Double_Matrix XYZ (_point::all_points.size(),3);

  for ( int k=0;k<3;++k)
    {
      xyz(k,0) = (*_STposX) ( ielem , k );
      xyz(k,1) = (*_STposY) ( ielem , k );
      xyz(k,2) = (*_STposZ) ( ielem , k );
    }

  for ( int k=0;k<N;++k)
    {
      val(k) = (*_STval )( ielem , k );
    }	        
  _Interpolate->mult(val,res);
  _Geometry->mult(xyz,XYZ);
  
  double c1 = Cpu();

  int kk=0;
  for ( ; it !=ite ; ++it)
    {
      _point *p = (_point*) &(*it);
      p->val = res(kk);
      p->X = XYZ(kk,0);
      p->Y = XYZ(kk,1);
      p->Z = XYZ(kk,2);

      /// -----------------------------------------------
      ///  TEST TEST ZZUT CHIOTTE VIREZ MOI CA VITE FAIT
      /// -----------------------------------------------
      //      p->val = p->X * p->X + p->Y*p->Y - 1;

      if (min > p->val) min = p->val;
      if (max < p->val) max = p->val;
      kk++;
    }

  double c2 = Cpu();

  std::list<_triangle*>::iterator itt  = _triangle::all_triangles.begin();
  std::list<_triangle*>::iterator itte = _triangle::all_triangles.end();

  for ( ;itt != itte ; itt++)
    {
      (*itt)->visible = false;
    }


  if (plug)
    plug->assign_specific_visibility ();
  else
    _triangle::Error ( max-min, tol );
 
  double c3 = Cpu();
  itt  = _triangle::all_triangles.begin();
  for ( ;itt != itte ; itt++)
    {
      if ((*itt)->visible)
	{
	  _point *p1 = (*itt)->p[0];
	  _point *p2 = (*itt)->p[1];
	  _point *p3 = (*itt)->p[2];
	  List_Add ( view->ST , &p1->X );
	  List_Add ( view->ST , &p2->X );
	  List_Add ( view->ST , &p3->X );
	  List_Add ( view->ST , &p1->Y );
	  List_Add ( view->ST , &p2->Y );
	  List_Add ( view->ST , &p3->Y );
	  List_Add ( view->ST , &p1->Z );
	  List_Add ( view->ST , &p2->Z );
	  List_Add ( view->ST , &p3->Z );
	  List_Add ( view->ST , &p1->val );
	  List_Add ( view->ST , &p2->val );
	  List_Add ( view->ST , &p3->val );
	  view->NbST++;
	}
    }
  double c4 = Cpu();

  t0 += c1-c0;
  t1 += c2-c1;
  t2 += c3-c2;
  t3 += c4-c3;

}

void Adaptive_Post_View:: setAdaptiveResolutionLevel (Post_View * view , int level, GMSH_Post_Plugin *plug)
{
  if (!view->ST)return;

  if (presentTol==tol && presentZoomLevel == level && !plug)return;

  _triangle::Create ( level, _coefs, _eexps );

  std::set<_point>::iterator it  = _point::all_points.begin();
  std::set<_point>::iterator ite = _point::all_points.end();

  const int N = _coefs->size1();
  if (_Interpolate)
    delete _Interpolate;
  if (_Geometry)
    delete _Geometry;
  _Interpolate = new Double_Matrix ( _point::all_points.size(), N);
  _Geometry    = new Double_Matrix ( _point::all_points.size(), 3);

  int kk=0;
  for ( ; it !=ite ; ++it)
    {
      _point *p = (_point*) &(*it);
      for ( int k=0;k<N;++k)
	{
	  (*_Interpolate)(kk,k) = p->shape_functions[k];
	}
      (*_Geometry)(kk,0) = ( 1.-p->x-p->y);
      (*_Geometry)(kk,1) = p->x;
      (*_Geometry)(kk,2) = p->y;
      kk++;	  
    }

  List_Delete(view->ST); view->ST = 0;  
  view->NbST = 0;
  /// for now, that's all we do, 1 TS
  view->NbTimeStep=1;
  int nbelm = _STposX->size1();
  view->ST = List_Create ( nbelm * 4, nbelm , sizeof(double));


  t0=t1 = t2 = t3 = 0;

  for ( int i=0;i<nbelm;++i)
    {
      zoomElement ( view , i , level, plug);
    }  

  printf("finished %g %g %g %g\n",t0,t1,t2,t3);

  view->Changed = 1;
  presentZoomLevel = level;
  presentTol = tol;
}
		      
void computeShapeFunctions ( Double_Matrix *coeffs, Double_Matrix *eexps , double u, double v, double *sf)
{

  static double powsuv[256];
  for (int j=0;j<coeffs->size2();++j)
    {
      double powu = (*eexps) ( j, 0);
      double powv = (*eexps) ( j, 1);
      powsuv[j] = pow(u,powu) *pow(v,powv);
    }

  for (int i=0;i<coeffs->size1();++i)
    {
      sf[i] = 0.0;
      for (int j=0;j<coeffs->size2();++j)
	{
	  sf[i] += (*coeffs)(i,j) * powsuv[j];
	}
    }
}

void Adaptive_Post_View:: initWithLowResolution (Post_View *view)
{

  List_T *myList = view->ST;
  int nbelm = view->NbST;
  int nbnod = 3;

  min = VAL_INF;
  max = -VAL_INF;

  int nb = List_Nbr(myList) / (nbelm);

  _STposX = new Double_Matrix ( nbelm , nbnod        );
  _STposY = new Double_Matrix ( nbelm , nbnod        );
  _STposZ = new Double_Matrix ( nbelm , nbnod        );
  _STval  = new Double_Matrix ( nbelm , nb-3*nbnod   );

  /// Store non interpolated data
  int k=0;
  for (int i=0;i<List_Nbr(myList);i+=nb)
    {    
      double *x = (double*)List_Pointer_Fast (view->ST,i);
      double *y = (double*)List_Pointer_Fast (view->ST,i+nbnod); 
      double *z = (double*)List_Pointer_Fast (view->ST,i+2*nbnod); 
      (*_STposX) ( k , 0) = x[0]; (*_STposX) ( k , 1) = x[1]; (*_STposX) ( k , 2) = x[2]; 
      (*_STposY) ( k , 0) = y[0]; (*_STposY) ( k , 1) = y[1]; (*_STposY) ( k , 2) = y[2]; 
      (*_STposZ) ( k , 0) = z[0]; (*_STposZ) ( k , 1) = z[1]; (*_STposZ) ( k , 2) = z[2]; 
      double *val = (double*)List_Pointer_Fast (view->ST,i+3*nbnod);
      for (int j=0;j<nb-3*nbnod;j++){
	(*_STval)(k,j)=val[j];      
      }      
      k++;
    }
  setAdaptiveResolutionLevel(view,0);
}

Adaptive_Post_View:: Adaptive_Post_View (Post_View *view, List_T *_c , List_T *_pol)  
  : tol(1.e-3)
{

  _Interpolate = _Geometry = 0;
  _coefs = new Double_Matrix ( List_Nbr (_c) , List_Nbr (_c)  );
  _eexps  = new Double_Matrix ( List_Nbr (_c) , 3  );

  for (int i=0; i< List_Nbr ( _c ); ++i)
    {
      List_T **line = (List_T **) List_Pointer_Fast ( _c,i); 
      List_T **eexp = (List_T **) List_Pointer_Fast ( _pol,i); 

      double dpowu,dpowv,dpoww;
      List_Read (*eexp, 0, &dpowu);
      List_Read (*eexp, 1, &dpowv);
      List_Read (*eexp, 2, &dpoww);

      (*_eexps) ( i , 0 ) = dpowu;
      (*_eexps) ( i , 1 ) = dpowv;
      (*_eexps) ( i , 2 ) = dpoww;

      for (int j=0;j < List_Nbr ( *line ); ++j)
	{
	  double val;
	  List_Read ( *line, j, &val);
	  (*_coefs) ( i , j ) = val;
	}
    }

  initWithLowResolution (view);  
}

Adaptive_Post_View::~Adaptive_Post_View()
{
  delete _coefs;
  delete _eexps;
  delete _STposX;
  delete _STposY;
  delete _STposZ;
  delete _STval;
  if(_Interpolate)delete _Interpolate;
  if(_Geometry)delete _Geometry;
  _triangle::clean();
}