Forked from
gmsh / gmsh
18770 commits behind the upstream repository.
-
Jean-François Remacle authoredJean-François Remacle authored
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();
}