diff --git a/Common/AdaptiveViews.cpp b/Common/AdaptiveViews.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c77a27715ef8c07a6aeb4b1c0bfe887f11f0be04 --- /dev/null +++ b/Common/AdaptiveViews.cpp @@ -0,0 +1,1191 @@ +// +// 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 <stdio.h> +#include <math.h> +#include <list> +#include <set> +#include "AdaptiveViews.h" +#include "Plugin.h" +#include "OS.h" + +// A recursive effective implementation + +void computeShapeFunctions(Double_Matrix * coeffs, Double_Matrix * eexps, + double u, double v, double w, double *sf); + +std::set < adapt_point > adapt_point::all_points; +std::list < adapt_edge * >adapt_edge::all_elems; +std::list < adapt_triangle * >adapt_triangle::all_elems; +std::list < adapt_tet * >adapt_tet::all_elems; +std::list < adapt_quad * >adapt_quad::all_elems; +std::list < adapt_hex * >adapt_hex::all_elems; +#define MAX_NB_NOD 8 +int adapt_edge::nbNod = 2; +int adapt_triangle::nbNod = 3; +int adapt_tet::nbNod = 4; +int adapt_quad::nbNod = 4; +int adapt_hex::nbNod = 8; + +adapt_point *adapt_point::New(double x, double y, double z, + Double_Matrix * coeffs, Double_Matrix * eexps) +{ + adapt_point p; + p.x = x; + p.y = y; + p.z = z; + std::set < adapt_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, z, kkk); + return (adapt_point *) & (*it); + } + else + return (adapt_point *) & (*it); +} + +void adapt_edge::Create(int maxlevel, Double_Matrix * coeffs, + Double_Matrix * eexps) +{ + int level = 0; + cleanElement < adapt_edge > (); + adapt_point *p1 = adapt_point::New(-1, 0, 0, coeffs, eexps); + adapt_point *p2 = adapt_point::New(1, 0, 0, coeffs, eexps); + adapt_edge *t = new adapt_edge(p1, p2); + Recur_Create(t, maxlevel, level, coeffs, eexps); +} + +void adapt_triangle::Create(int maxlevel, Double_Matrix * coeffs, + Double_Matrix * eexps) +{ + int level = 0; + cleanElement < adapt_triangle > (); + adapt_point *p1 = adapt_point::New(0, 0, 0, coeffs, eexps); + adapt_point *p2 = adapt_point::New(0, 1, 0, coeffs, eexps); + adapt_point *p3 = adapt_point::New(1, 0, 0, coeffs, eexps); + adapt_triangle *t = new adapt_triangle(p1, p2, p3); + Recur_Create(t, maxlevel, level, coeffs, eexps); +} + +void adapt_quad::Create(int maxlevel, Double_Matrix * coeffs, + Double_Matrix * eexps) +{ + int level = 0; + cleanElement < adapt_quad > (); + adapt_point *p1 = adapt_point::New(-1, -1, 0, coeffs, eexps); + adapt_point *p2 = adapt_point::New(1, -1, 0, coeffs, eexps); + adapt_point *p3 = adapt_point::New(1, 1, 0, coeffs, eexps); + adapt_point *p4 = adapt_point::New(-1, 1, 0, coeffs, eexps); + adapt_quad *q = new adapt_quad(p1, p2, p3, p4); + Recur_Create(q, maxlevel, level, coeffs, eexps); +} + +void adapt_tet::Create(int maxlevel, Double_Matrix * coeffs, + Double_Matrix * eexps) +{ + int level = 0; + cleanElement < adapt_tet > (); + adapt_point *p1 = adapt_point::New(0, 0, 0, coeffs, eexps); + adapt_point *p2 = adapt_point::New(0, 1, 0, coeffs, eexps); + adapt_point *p3 = adapt_point::New(1, 0, 0, coeffs, eexps); + adapt_point *p4 = adapt_point::New(0, 0, 1, coeffs, eexps); + adapt_tet *t = new adapt_tet(p1, p2, p3, p4); + Recur_Create(t, maxlevel, level, coeffs, eexps); +} + +void adapt_hex::Create(int maxlevel, Double_Matrix * coeffs, + Double_Matrix * eexps) +{ + int level = 0; + cleanElement < adapt_hex > (); + adapt_point *p1 = adapt_point::New(-1, -1, -1, coeffs, eexps); + adapt_point *p2 = adapt_point::New(-1, 1, -1, coeffs, eexps); + adapt_point *p3 = adapt_point::New(1, 1, -1, coeffs, eexps); + adapt_point *p4 = adapt_point::New(1, -1, -1, coeffs, eexps); + adapt_point *p11 = adapt_point::New(-1, -1, 1, coeffs, eexps); + adapt_point *p21 = adapt_point::New(-1, 1, 1, coeffs, eexps); + adapt_point *p31 = adapt_point::New(1, 1, 1, coeffs, eexps); + adapt_point *p41 = adapt_point::New(1, -1, 1, coeffs, eexps); + adapt_hex *h = new adapt_hex(p1, p2, p3, p4, p11, p21, p31, p41); + Recur_Create(h, maxlevel, level, coeffs, eexps); +} + +void adapt_edge::Recur_Create(adapt_edge * e, int maxlevel, int level, + Double_Matrix * coeffs, Double_Matrix * eexps) +{ + all_elems.push_back(e); + if(level++ >= maxlevel) + return; + + /* + p1 p12 p2 + */ + + adapt_point *p1 = e->p[0]; + adapt_point *p2 = e->p[1]; + adapt_point *p12 = + adapt_point::New((p1->x + p2->x) * 0.5, (p1->y + p2->y) * 0.5, + (p1->z + p2->z) * 0.5, coeffs, eexps); + adapt_edge *e1 = new adapt_edge(p1, p12); + Recur_Create(e1, maxlevel, level, coeffs, eexps); + adapt_edge *e2 = new adapt_edge(p12, p2); + Recur_Create(e2, maxlevel, level, coeffs, eexps); + e->e[0] = e1; + e->e[1] = e2; +} + +void adapt_triangle::Recur_Create(adapt_triangle * t, int maxlevel, int level, + Double_Matrix * coeffs, + Double_Matrix * eexps) +{ + all_elems.push_back(t); + if(level++ >= maxlevel) + return; + + /* + p3 + + p13 p23 + + p1 p12 p2 + */ + + adapt_point *p1 = t->p[0]; + adapt_point *p2 = t->p[1]; + adapt_point *p3 = t->p[2]; + adapt_point *p12 = adapt_point::New((p1->x + p2->x) * 0.5, (p1->y + p2->y) * 0.5, 0, + coeffs, eexps); + adapt_point *p13 = adapt_point::New((p1->x + p3->x) * 0.5, (p1->y + p3->y) * 0.5, 0, + coeffs, eexps); + adapt_point *p23 = adapt_point::New((p3->x + p2->x) * 0.5, (p3->y + p2->y) * 0.5, 0, + coeffs, eexps); + adapt_triangle *t1 = new adapt_triangle(p1, p12, p13); + Recur_Create(t1, maxlevel, level, coeffs, eexps); + adapt_triangle *t2 = new adapt_triangle(p2, p23, p12); + Recur_Create(t2, maxlevel, level, coeffs, eexps); + adapt_triangle *t3 = new adapt_triangle(p3, p13, p23); + Recur_Create(t3, maxlevel, level, coeffs, eexps); + adapt_triangle *t4 = new adapt_triangle(p12, p23, p13); + Recur_Create(t4, maxlevel, level, coeffs, eexps); + t->e[0] = t1; + t->e[1] = t2; + t->e[2] = t3; + t->e[3] = t4; +} + +void adapt_quad::Recur_Create(adapt_quad * q, int maxlevel, int level, + Double_Matrix * coeffs, Double_Matrix * eexps) +{ + all_elems.push_back(q); + if(level++ >= maxlevel) + return; + + /* + p4 p34 p3 + + p14 pc p23 + + p1 p12 p2 + */ + + adapt_point *p1 = q->p[0]; + adapt_point *p2 = q->p[1]; + adapt_point *p3 = q->p[2]; + adapt_point *p4 = q->p[3]; + adapt_point *p12 = adapt_point::New((p1->x + p2->x) * 0.5, (p1->y + p2->y) * 0.5, 0, + coeffs, eexps); + adapt_point *p23 = adapt_point::New((p2->x + p3->x) * 0.5, (p2->y + p3->y) * 0.5, 0, + coeffs, eexps); + adapt_point *p34 = adapt_point::New((p3->x + p4->x) * 0.5, (p3->y + p4->y) * 0.5, 0, + coeffs, eexps); + adapt_point *p14 = adapt_point::New((p1->x + p4->x) * 0.5, (p1->y + p4->y) * 0.5, 0, + coeffs, eexps); + adapt_point *pc = adapt_point::New((p1->x + p2->x + p3->x + p4->x) * 0.25, + (p1->y + p2->y + p3->y + p4->y) * 0.25, 0, + coeffs, eexps); + adapt_quad *q1 = new adapt_quad(p1, p12, pc, p14); + Recur_Create(q1, maxlevel, level, coeffs, eexps); + adapt_quad *q2 = new adapt_quad(p2, p23, pc, p12); + Recur_Create(q2, maxlevel, level, coeffs, eexps); + adapt_quad *q3 = new adapt_quad(p3, p34, pc, p23); + Recur_Create(q3, maxlevel, level, coeffs, eexps); + adapt_quad *q4 = new adapt_quad(p4, p14, pc, p34); + Recur_Create(q4, maxlevel, level, coeffs, eexps); + q->e[0] = q1; + q->e[1] = q2; + q->e[2] = q3; + q->e[3] = q4; +} + +void adapt_tet::Recur_Create(adapt_tet * t, int maxlevel, int level, + Double_Matrix * coeffs, Double_Matrix * eexps) +{ + all_elems.push_back(t); + if(level++ >= maxlevel) + return; + + adapt_point *p0 = t->p[0]; + adapt_point *p1 = t->p[1]; + adapt_point *p2 = t->p[2]; + adapt_point *p3 = t->p[3]; + adapt_point *pe0 = adapt_point::New((p0->x + p1->x) * 0.5, (p0->y + p1->y) * 0.5, + (p0->z + p1->z) * 0.5, coeffs, eexps); + adapt_point *pe1 = adapt_point::New((p0->x + p2->x) * 0.5, (p0->y + p2->y) * 0.5, + (p0->z + p2->z) * 0.5, coeffs, eexps); + adapt_point *pe2 = adapt_point::New((p0->x + p3->x) * 0.5, (p0->y + p3->y) * 0.5, + (p0->z + p3->z) * 0.5, coeffs, eexps); + adapt_point *pe3 = adapt_point::New((p1->x + p2->x) * 0.5, (p1->y + p2->y) * 0.5, + (p1->z + p2->z) * 0.5, coeffs, eexps); + adapt_point *pe4 = adapt_point::New((p1->x + p3->x) * 0.5, (p1->y + p3->y) * 0.5, + (p1->z + p3->z) * 0.5, coeffs, eexps); + adapt_point *pe5 = adapt_point::New((p2->x + p3->x) * 0.5, (p2->y + p3->y) * 0.5, + (p2->z + p3->z) * 0.5, coeffs, eexps); + + adapt_tet *t1 = new adapt_tet(p0, pe0, pe2, pe1); + Recur_Create(t1, maxlevel, level, coeffs, eexps); + adapt_tet *t2 = new adapt_tet(p1, pe0, pe3, pe4); + Recur_Create(t2, maxlevel, level, coeffs, eexps); + adapt_tet *t3 = new adapt_tet(p2, pe3, pe1, pe5); + Recur_Create(t3, maxlevel, level, coeffs, eexps); + adapt_tet *t4 = new adapt_tet(p3, pe2, pe4, pe5); + Recur_Create(t4, maxlevel, level, coeffs, eexps); + + adapt_tet *t5 = new adapt_tet(pe3, pe5, pe2, pe4); + Recur_Create(t5, maxlevel, level, coeffs, eexps); + adapt_tet *t6 = new adapt_tet(pe3, pe2, pe0, pe4); + Recur_Create(t6, maxlevel, level, coeffs, eexps); + adapt_tet *t7 = new adapt_tet(pe2, pe5, pe3, pe1); + Recur_Create(t7, maxlevel, level, coeffs, eexps); + adapt_tet *t8 = new adapt_tet(pe0, pe2, pe3, pe1); + Recur_Create(t8, maxlevel, level, coeffs, eexps); + + t->e[0] = t1; + t->e[1] = t2; + t->e[2] = t3; + t->e[3] = t4; + t->e[4] = t5; + t->e[5] = t6; + t->e[6] = t7; + t->e[7] = t8; +} + +void adapt_hex::Recur_Create(adapt_hex * h, int maxlevel, int level, + Double_Matrix * coeffs, Double_Matrix * eexps) +{ + all_elems.push_back(h); + if(level++ >= maxlevel) + return; + + adapt_point *p0 = h->p[0]; + adapt_point *p1 = h->p[1]; + adapt_point *p2 = h->p[2]; + adapt_point *p3 = h->p[3]; + adapt_point *p4 = h->p[4]; + adapt_point *p5 = h->p[5]; + adapt_point *p6 = h->p[6]; + adapt_point *p7 = h->p[7]; + adapt_point *p01 = adapt_point::New((p0->x + p1->x) * 0.5, (p0->y + p1->y) * 0.5, + (p0->z + p1->z) * 0.5, coeffs, eexps); + adapt_point *p12 = adapt_point::New((p1->x + p2->x) * 0.5, (p1->y + p2->y) * 0.5, + (p1->z + p2->z) * 0.5, coeffs, eexps); + adapt_point *p23 = adapt_point::New((p2->x + p3->x) * 0.5, (p2->y + p3->y) * 0.5, + (p2->z + p3->z) * 0.5, coeffs, eexps); + adapt_point *p03 = adapt_point::New((p3->x + p0->x) * 0.5, (p3->y + p0->y) * 0.5, + (p3->z + p0->z) * 0.5, coeffs, eexps); + adapt_point *p45 = adapt_point::New((p4->x + p5->x) * 0.5, (p4->y + p5->y) * 0.5, + (p4->z + p5->z) * 0.5, coeffs, eexps); + adapt_point *p56 = adapt_point::New((p5->x + p6->x) * 0.5, (p5->y + p6->y) * 0.5, + (p5->z + p6->z) * 0.5, coeffs, eexps); + adapt_point *p67 = adapt_point::New((p6->x + p7->x) * 0.5, (p6->y + p7->y) * 0.5, + (p6->z + p7->z) * 0.5, coeffs, eexps); + adapt_point *p47 = adapt_point::New((p7->x + p4->x) * 0.5, (p7->y + p4->y) * 0.5, + (p7->z + p4->z) * 0.5, coeffs, eexps); + adapt_point *p04 = adapt_point::New((p4->x + p0->x) * 0.5, (p4->y + p0->y) * 0.5, + (p4->z + p0->z) * 0.5, coeffs, eexps); + adapt_point *p15 = adapt_point::New((p5->x + p1->x) * 0.5, (p5->y + p1->y) * 0.5, + (p5->z + p1->z) * 0.5, coeffs, eexps); + adapt_point *p26 = adapt_point::New((p6->x + p2->x) * 0.5, (p6->y + p2->y) * 0.5, + (p6->z + p2->z) * 0.5, coeffs, eexps); + adapt_point *p37 = adapt_point::New((p7->x + p3->x) * 0.5, (p7->y + p3->y) * 0.5, + (p7->z + p3->z) * 0.5, coeffs, eexps); + + adapt_point *p0145 = adapt_point::New((p45->x + p01->x) * 0.5, (p45->y + p01->y) * 0.5, + (p45->z + p01->z) * 0.5, coeffs, eexps); + adapt_point *p1256 = adapt_point::New((p12->x + p56->x) * 0.5, (p12->y + p56->y) * 0.5, + (p12->z + p56->z) * 0.5, coeffs, eexps); + adapt_point *p2367 = adapt_point::New((p23->x + p67->x) * 0.5, (p23->y + p67->y) * 0.5, + (p23->z + p67->z) * 0.5, coeffs, eexps); + adapt_point *p0347 = adapt_point::New((p03->x + p47->x) * 0.5, (p03->y + p47->y) * 0.5, + (p03->z + p47->z) * 0.5, coeffs, eexps); + adapt_point *p4756 = adapt_point::New((p47->x + p56->x) * 0.5, (p47->y + p56->y) * 0.5, + (p47->z + p56->z) * 0.5, coeffs, eexps); + adapt_point *p0312 = adapt_point::New((p03->x + p12->x) * 0.5, (p03->y + p12->y) * 0.5, + (p03->z + p12->z) * 0.5, coeffs, eexps); + + adapt_point *pc = + adapt_point::New((p0->x + p1->x + p2->x + p3->x + p4->x + p5->x + p6->x + p7->x) * 0.125, + (p0->y + p1->y + p2->y + p3->y + p4->y + p5->y + p6->y + p7->y) * 0.125, + (p0->z + p1->z + p2->z + p3->z + p4->z + p5->z + p6->z + p7->z) * 0.125, + coeffs, eexps); + + adapt_hex *h1 = new adapt_hex(p0, p01, p0312, p03, p04, p0145, pc, p0347); //p0 + Recur_Create(h1, maxlevel, level, coeffs, eexps); + adapt_hex *h2 = new adapt_hex(p01, p0145, p15, p1, p0312, pc, p1256, p12); //p1 + Recur_Create(h2, maxlevel, level, coeffs, eexps); + adapt_hex *h3 = new adapt_hex(p04, p4, p45, p0145, p0347, p47, p4756, pc); //p4 + Recur_Create(h3, maxlevel, level, coeffs, eexps); + adapt_hex *h4 = new adapt_hex(p0145, p45, p5, p15, pc, p4756, p56, p1256); //p5 + Recur_Create(h4, maxlevel, level, coeffs, eexps); + adapt_hex *h5 = new adapt_hex(p0347, p47, p4756, pc, p37, p7, p67, p2367); //p7 + Recur_Create(h5, maxlevel, level, coeffs, eexps); + adapt_hex *h6 = new adapt_hex(pc, p4756, p56, p1256, p2367, p67, p6, p26); //p6 + Recur_Create(h6, maxlevel, level, coeffs, eexps); + adapt_hex *h7 = new adapt_hex(p03, p0347, pc, p0312, p3, p37, p2367, p23); //p3 + Recur_Create(h7, maxlevel, level, coeffs, eexps); + adapt_hex *h8 = new adapt_hex(p0312, pc, p1256, p12, p23, p2367, p26, p2); //p2 + Recur_Create(h8, maxlevel, level, coeffs, eexps); + + h->e[0] = h1; + h->e[1] = h2; + h->e[2] = h3; + h->e[3] = h4; + h->e[4] = h5; + h->e[5] = h6; + h->e[6] = h7; + h->e[7] = h8; +} + +void adapt_edge::Error(double AVG, double tol) +{ + adapt_edge *e = *all_elems.begin(); + Recur_Error(e, AVG, tol); +} + +void adapt_triangle::Error(double AVG, double tol) +{ + adapt_triangle *t = *all_elems.begin(); + Recur_Error(t, AVG, tol); +} + +void adapt_quad::Error(double AVG, double tol) +{ + adapt_quad *q = *all_elems.begin(); + Recur_Error(q, AVG, tol); +} + +void adapt_tet::Error(double AVG, double tol) +{ + adapt_tet *t = *all_elems.begin(); + Recur_Error(t, AVG, tol); +} +void adapt_hex::Error(double AVG, double tol) +{ + adapt_hex *h = *all_elems.begin(); + Recur_Error(h, AVG, tol); +} + +void adapt_edge::Recur_Error(adapt_edge * e, double AVG, double tol) +{ + if(!e->e[0]) + e->visible = true; + else { + double vr; + if(!e->e[0]->e[0]) { + double v1 = e->e[0]->V(); + double v2 = e->e[1]->V(); + vr = (v1 + v2) / 2.; + double v = e->V(); + if(fabs(v - vr) > AVG * tol) + //if (fabs(v - vr) > ((fabs(v) + fabs(vr) + AVG * tol) * tol)) + { + e->visible = false; + Recur_Error(e->e[0], AVG, tol); + Recur_Error(e->e[1], AVG, tol); + } + else + e->visible = true; + } + else { + double v11 = e->e[0]->e[0]->V(); + double v12 = e->e[0]->e[1]->V(); + + double v21 = e->e[1]->e[0]->V(); + double v22 = e->e[1]->e[1]->V(); + + double vr1 = (v11 + v12) / 2.; + double vr2 = (v21 + v22) / 2.; + vr = (vr1 + vr2) / 2.; + if(fabs(e->e[0]->V() - vr1) > AVG * tol || + fabs(e->e[1]->V() - vr2) > AVG * tol || + fabs(e->V() - vr) > AVG * tol) { + e->visible = false; + Recur_Error(e->e[0], AVG, tol); + Recur_Error(e->e[1], AVG, tol); + } + else + e->visible = true; + } + } +} + +void adapt_triangle::Recur_Error(adapt_triangle * t, double AVG, double tol) +{ + if(!t->e[0]) + t->visible = true; + else { + double vr; + if(!t->e[0]->e[0]) { + double v1 = t->e[0]->V(); + double v2 = t->e[1]->V(); + double v3 = t->e[2]->V(); + double v4 = t->e[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->e[0], AVG, tol); + Recur_Error(t->e[1], AVG, tol); + Recur_Error(t->e[2], AVG, tol); + Recur_Error(t->e[3], AVG, tol); + } + else + t->visible = true; + } + else { + double v11 = t->e[0]->e[0]->V(); + double v12 = t->e[0]->e[1]->V(); + double v13 = t->e[0]->e[2]->V(); + double v14 = t->e[0]->e[3]->V(); + double v21 = t->e[1]->e[0]->V(); + double v22 = t->e[1]->e[1]->V(); + double v23 = t->e[1]->e[2]->V(); + double v24 = t->e[1]->e[3]->V(); + double v31 = t->e[2]->e[0]->V(); + double v32 = t->e[2]->e[1]->V(); + double v33 = t->e[2]->e[2]->V(); + double v34 = t->e[2]->e[3]->V(); + double v41 = t->e[3]->e[0]->V(); + double v42 = t->e[3]->e[1]->V(); + double v43 = t->e[3]->e[2]->V(); + double v44 = t->e[3]->e[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->e[0]->V() - vr1) > AVG * tol || + fabs(t->e[1]->V() - vr2) > AVG * tol || + fabs(t->e[2]->V() - vr3) > AVG * tol || + fabs(t->e[3]->V() - vr4) > AVG * tol || + fabs(t->V() - vr) > AVG * tol) + //if (fabs(t->e[0]->V() - vr1) > (fabs(t->e[0]->V())+fabs(vr1)+AVG * tol)*tol || + // fabs(t->e[1]->V() - vr2) > (fabs(t->e[1]->V())+fabs(vr2)+AVG * tol)*tol || + // fabs(t->e[2]->V() - vr3) > (fabs(t->e[2]->V())+fabs(vr3)+AVG * tol)*tol || + // fabs(t->e[3]->V() - vr4) > (fabs(t->e[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->e[0], AVG, tol); + Recur_Error(t->e[1], AVG, tol); + Recur_Error(t->e[2], AVG, tol); + Recur_Error(t->e[3], AVG, tol); + } + else + t->visible = true; + } + } +} + +void adapt_quad::Recur_Error(adapt_quad * q, double AVG, double tol) +{ + if(!q->e[0]) + q->visible = true; + else { + double vr; + if(!q->e[0]->e[0]) { + double v1 = q->e[0]->V(); + double v2 = q->e[1]->V(); + double v3 = q->e[2]->V(); + double v4 = q->e[3]->V(); + vr = (v1 + v2 + v3 + v4) / 4.; + double v = q->V(); + if(fabs(v - vr) > AVG * tol) + //if (fabs(v - vr) > ((fabs(v) + fabs(vr) + AVG * tol) * tol)) + { + q->visible = false; + Recur_Error(q->e[0], AVG, tol); + Recur_Error(q->e[1], AVG, tol); + Recur_Error(q->e[2], AVG, tol); + Recur_Error(q->e[3], AVG, tol); + } + else + q->visible = true; + } + else { + double v11 = q->e[0]->e[0]->V(); + double v12 = q->e[0]->e[1]->V(); + double v13 = q->e[0]->e[2]->V(); + double v14 = q->e[0]->e[3]->V(); + double v21 = q->e[1]->e[0]->V(); + double v22 = q->e[1]->e[1]->V(); + double v23 = q->e[1]->e[2]->V(); + double v24 = q->e[1]->e[3]->V(); + double v31 = q->e[2]->e[0]->V(); + double v32 = q->e[2]->e[1]->V(); + double v33 = q->e[2]->e[2]->V(); + double v34 = q->e[2]->e[3]->V(); + double v41 = q->e[3]->e[0]->V(); + double v42 = q->e[3]->e[1]->V(); + double v43 = q->e[3]->e[2]->V(); + double v44 = q->e[3]->e[3]->V(); + double vr1 = (v11 + v12 + v13 + v14) / 4.; + double vr2 = (v21 + v22 + v23 + v24) / 4.; + double vr3 = (v31 + v32 + v33 + v34) / 4.; + double vr4 = (v41 + v42 + v43 + v44) / 4.; + vr = (vr1 + vr2 + vr3 + vr4) / 4.; + if(fabs(q->e[0]->V() - vr1) > AVG * tol || + fabs(q->e[1]->V() - vr2) > AVG * tol || + fabs(q->e[2]->V() - vr3) > AVG * tol || + fabs(q->e[3]->V() - vr4) > AVG * tol || + fabs(q->V() - vr) > AVG * tol) + //if (fabs(t->e[0]->V() - vr1) > (fabs(t->e[0]->V())+fabs(vr1)+AVG * tol)*tol || + // fabs(t->e[1]->V() - vr2) > (fabs(t->e[1]->V())+fabs(vr2)+AVG * tol)*tol || + // fabs(t->e[2]->V() - vr3) > (fabs(t->e[2]->V())+fabs(vr3)+AVG * tol)*tol || + // fabs(t->e[3]->V() - vr4) > (fabs(t->e[3]->V())+fabs(vr4)+AVG * tol)*tol || + // fabs(t->V() - vr) > (fabs(t->V())+fabs(vr)+AVG * tol) *tol) + { + q->visible = false; + Recur_Error(q->e[0], AVG, tol); + Recur_Error(q->e[1], AVG, tol); + Recur_Error(q->e[2], AVG, tol); + Recur_Error(q->e[3], AVG, tol); + } + else + q->visible = true; + } + } +} + +void adapt_tet::Recur_Error(adapt_tet * t, double AVG, double tol) +{ + if(!t->e[0]) + t->visible = true; + else { + const double v1 = t->e[0]->V(); + const double v2 = t->e[1]->V(); + const double v3 = t->e[2]->V(); + const double v4 = t->e[3]->V(); + const double v5 = t->e[4]->V(); + const double v6 = t->e[5]->V(); + const double v7 = t->e[6]->V(); + const double v8 = t->e[7]->V(); + const double vr = (v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8) * .125; + const double v = t->V(); + if(!t->e[0]->e[0]) { + if(fabs(v - vr) > AVG * tol) { + t->visible = false; + Recur_Error(t->e[0], AVG, tol); + Recur_Error(t->e[1], AVG, tol); + Recur_Error(t->e[2], AVG, tol); + Recur_Error(t->e[3], AVG, tol); + Recur_Error(t->e[4], AVG, tol); + Recur_Error(t->e[5], AVG, tol); + Recur_Error(t->e[6], AVG, tol); + Recur_Error(t->e[7], AVG, tol); + } + else + t->visible = true; + } + else { + double vi[8][8]; + for(int k = 0; k < 8; k++) + for(int l = 0; l < 8; l++) + vi[k][l] = t->e[k]->e[l]->V(); + double vri[8]; + for(int k = 0; k < 8; k++) { + vri[k] = 0.0; + for(int l = 0; l < 8; l++) { + vri[k] += vi[k][l]; + } + vri[k] /= 8.0; + } + if(fabs(t->e[0]->V() - vri[0]) > AVG * tol || + fabs(t->e[1]->V() - vri[1]) > AVG * tol || + fabs(t->e[2]->V() - vri[2]) > AVG * tol || + fabs(t->e[3]->V() - vri[3]) > AVG * tol || + fabs(t->e[4]->V() - vri[4]) > AVG * tol || + fabs(t->e[5]->V() - vri[5]) > AVG * tol || + fabs(t->e[6]->V() - vri[6]) > AVG * tol || + fabs(t->e[7]->V() - vri[7]) > AVG * tol || + fabs(v - vr) > AVG * tol) { + t->visible = false; + Recur_Error(t->e[0], AVG, tol); + Recur_Error(t->e[1], AVG, tol); + Recur_Error(t->e[2], AVG, tol); + Recur_Error(t->e[3], AVG, tol); + Recur_Error(t->e[4], AVG, tol); + Recur_Error(t->e[5], AVG, tol); + Recur_Error(t->e[6], AVG, tol); + Recur_Error(t->e[7], AVG, tol); + } + else + t->visible = true; + } + } +} + +void adapt_hex::Recur_Error(adapt_hex * h, double AVG, double tol) +{ + if(!h->e[0]) + h->visible = true; + else { + double vr; + double v1 = h->e[0]->V(); + double v2 = h->e[1]->V(); + double v3 = h->e[2]->V(); + double v4 = h->e[3]->V(); + double v5 = h->e[4]->V(); + double v6 = h->e[5]->V(); + double v7 = h->e[6]->V(); + double v8 = h->e[7]->V(); + vr = (v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8) * .125; + double v = h->V(); + if(fabs(v - vr) > AVG * tol) { + h->visible = false; + Recur_Error(h->e[0], AVG, tol); + Recur_Error(h->e[1], AVG, tol); + Recur_Error(h->e[2], AVG, tol); + Recur_Error(h->e[3], AVG, tol); + Recur_Error(h->e[4], AVG, tol); + Recur_Error(h->e[5], AVG, tol); + Recur_Error(h->e[6], AVG, tol); + Recur_Error(h->e[7], AVG, tol); + } + else + h->visible = true; + } +} + +static double t0, t1, t2, t3; + +template < class ELEM > +int Adaptive_Post_View::zoomElement(Post_View * view, + int ielem, + int level, + int levelmax, + GMSH_Post_Plugin * plug, + List_T * theList, int *counter) +{ + const int nbNod = ELEM::nbNod; + + typename std::set < adapt_point >::iterator it = adapt_point::all_points.begin(); + typename std::set < adapt_point >::iterator ite = adapt_point::all_points.end(); + + double c0 = Cpu(); + + const int N = _coefs->size1(); + Double_Vector val(N), res(adapt_point::all_points.size()); + Double_Vector valx(N), resx(adapt_point::all_points.size()); + Double_Vector valy(N), resy(adapt_point::all_points.size()); + Double_Vector valz(N), resz(adapt_point::all_points.size()); + Double_Matrix xyz(nbNod,3); + Double_Matrix XYZ(adapt_point::all_points.size(),3); + + for(int k = 0; k < nbNod; ++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); + + if(_STvalX){ + for(int k = 0; k < N; ++k){ + valx(k) = (*_STvalX)(ielem, k); + valy(k) = (*_STvalY)(ielem, k); + valz(k) = (*_STvalZ)(ielem, k); + } + _Interpolate->mult(valx, resx); + _Interpolate->mult(valy, resy); + _Interpolate->mult(valz, resz); + } + + _Geometry->mult(xyz, XYZ); + + double c1 = Cpu(); + + int kk = 0; + for (; it !=ite; ++it){ + adapt_point *p = (adapt_point*) &(*it); + p->val = res(kk); + if (_STvalX){ + p->valx = resx(kk); + p->valy = resy(kk); + p->valz = resz(kk); + } + p->val = res(kk); + p->X = XYZ(kk, 0); + p->Y = XYZ(kk, 1); + p->Z = XYZ(kk, 2); + if (minval > p->val) minval = p->val; + if (maxval < p->val) maxval = p->val; + kk++; + } + double c2 = Cpu(); + + typename std::list < ELEM * >::iterator itt = ELEM::all_elems.begin(); + typename std::list < ELEM * >::iterator itte = ELEM::all_elems.end(); + + for(; itt != itte; itt++) { + (*itt)->visible = false; + } + + if(!plug || tol != 0.0) { + ELEM::Error(maxval - minval, tol); + } + + if(plug) + plug->assign_specific_visibility(); + + double c3 = Cpu(); + itt = ELEM::all_elems.begin(); + + for(; itt != itte; itt++) { + if((*itt)->visible && !(*itt)->e[0] && level != levelmax) + return 0; + } + + itt = ELEM::all_elems.begin(); + adapt_point **p; + + for(; itt != itte; itt++){ + if((*itt)->visible){ + p = (*itt)->p; + for(int k=0; k < nbNod; ++k) List_Add(theList, &p[k]->X); + for(int k=0; k < nbNod; ++k) List_Add(theList, &p[k]->Y); + for(int k=0; k < nbNod; ++k) List_Add(theList, &p[k]->Z); + if(_STvalX){ + for(int k = 0; k < nbNod; ++k){ + List_Add(theList, &p[k]->valx); + List_Add(theList, &p[k]->valy); + List_Add(theList, &p[k]->valz); + } + } + else{ + for (int k = 0; k < nbNod; ++k) List_Add(theList, &p[k]->val); + } + (*counter)++; + } + } + + double c4 = Cpu(); + + t0 += c1 - c0; + t1 += c2 - c1; + t2 += c3 - c2; + t3 += c4 - c3; + + return 1; +} + + +/* + We first do the adaptive stuff at level 2 and will only process + elements that have reached the maximal recursion level + + We compute first the matrix at max recursion level (those should be stored + on disk once in the GMSHPLUGINSHOME directory, i'll do that at some point). +*/ + +void Adaptive_Post_View::setAdaptiveResolutionLevel(Post_View * view, + int level, + GMSH_Post_Plugin * plug) +{ + + if(presentTol == tol && presentZoomLevel == level && !plug) + return; + + printf + ("calling setAdaptive with level = %d and plug = %p tol %g presentTol %g\n", + level, (void *)plug, tol, presentTol); + + int *done = new int[_STposX->size1()]; + for(int i = 0; i < _STposX->size1(); ++i) + done[i] = 0; + int level_act = (level > 2) ? 2 : level; + int nbelm = _STposX->size1(); + + int TYP = 0; + if(view->NbSL) { + TYP = 7; + List_Delete(view->SL); + view->NbSL = 0; + view->SL = List_Create(nbelm * 8, nbelm, sizeof(double)); + } + if (view->NbVT) { + TYP = 5; + List_Delete(view->VT); + view->NbVT = 0; + view->VT =List_Create ( nbelm * 36, nbelm , sizeof(double)); + } + if(view->NbST) { + TYP = 1; + List_Delete(view->ST); + view->NbST = 0; + view->ST = List_Create(nbelm * 4, nbelm, sizeof(double)); + } + if(view->NbSS) { + TYP = 3; + List_Delete(view->SS); + view->NbSS = 0; + view->SS = List_Create(nbelm * 4, nbelm, sizeof(double)); + } + if(view->NbSQ) { + TYP = 2; + List_Delete(view->SQ); + view->NbSQ = 0; + view->SQ = List_Create(nbelm * 20, nbelm * 20, sizeof(double)); + } + if(view->NbVQ) { + TYP = 6; + List_Delete(view->VQ); + view->NbVQ = 0; + view->VQ = List_Create(nbelm * 60, nbelm * 20, sizeof(double)); + } + if(view->NbSH) { + TYP = 4; + List_Delete(view->SH); + view->NbSH = 0; + view->SH = List_Create(nbelm * 4, nbelm, sizeof(double)); + } + + view->NbTimeStep = 1; + + t0 = t1 = t2 = t3 = 0; + + while (1){ + if(TYP == 7) + setAdaptiveResolutionLevel_TEMPL < adapt_edge > (view, level_act, level, plug, + &(view->SL), &(view->NbSL), done); + if (TYP == 1) + setAdaptiveResolutionLevel_TEMPL <adapt_triangle> (view, level_act, level, plug, + &(view->ST), &(view->NbST), done); + if (TYP == 5) + setAdaptiveResolutionLevel_TEMPL <adapt_triangle> (view, level_act, level, plug, + &(view->VT), &(view->NbVT), done); + if (TYP == 2) + setAdaptiveResolutionLevel_TEMPL <adapt_quad> (view, level_act, level, plug, + &(view->SQ), &(view->NbSQ), done); + if (TYP == 6) + setAdaptiveResolutionLevel_TEMPL <adapt_quad> (view, level_act, level, plug, + &(view->VQ), &(view->NbVQ), done); + if (TYP == 4) + setAdaptiveResolutionLevel_TEMPL <adapt_hex> (view, level_act, level, plug, + &(view->SH), &(view->NbSH), done); + if (TYP == 3) + setAdaptiveResolutionLevel_TEMPL <adapt_tet> (view, level_act, level, plug, + &(view->SS), &(view->NbSS), done); + int nbDone = 0; + for(int i=0; i < _STposX->size1(); ++i) nbDone += done[i]; + printf("adaptive %d %d %d %d\n", level, level_act, nbDone, _STposX->size1()); + if (nbDone ==_STposX->size1()) break; + if (level_act >= level) break; + level_act ++; + } + + // recompute min/max, etc.: + view->Min = VAL_INF; + view->Max = -VAL_INF; + EndView(view, 0, view->FileName, view->Name); + view->Changed = 1; + presentZoomLevel = level; + presentTol = tol; + + printf("finished %g %g %g %g\n", t0, t1, t2, t3); + delete[]done; +} + +template < class ELEM > +void Adaptive_Post_View::setAdaptiveResolutionLevel_TEMPL(Post_View * view, + int level, + int levelmax, + GMSH_Post_Plugin * + plug, + List_T ** myList, + int *counter, + int *done) +{ + const int N = _coefs->size1(); + + const int nbelm = _STposX->size1(); + + double sf[100]; + ELEM::Create(level, _coefs, _eexps); + std::set < adapt_point >::iterator it = adapt_point::all_points.begin(); + std::set < adapt_point >::iterator ite = adapt_point::all_points.end(); + + if(_Interpolate) + delete _Interpolate; + if(_Geometry) + delete _Geometry; + _Interpolate = new Double_Matrix(adapt_point::all_points.size(), N); + _Geometry = new Double_Matrix(adapt_point::all_points.size(), ELEM::nbNod); + + int kk = 0; + for(; it != ite; ++it) { + adapt_point *p = (adapt_point *) & (*it); + for(int k = 0; k < N; ++k) { + (*_Interpolate) (kk, k) = p->shape_functions[k]; + } + ELEM::GSF(p->x, p->y, p->z, sf); + for(int k = 0; k < ELEM::nbNod; k++) + (*_Geometry) (kk, k) = sf[k]; + kk++; + } + + for(int i = 0; i < nbelm; ++i) { + if(!done[i]) + done[i] = + zoomElement < ELEM > (view, i, level, levelmax, plug, *myList, + counter); + } +} + +void computeShapeFunctions(Double_Matrix * coeffs, Double_Matrix * eexps, + double u, double v, double w, double *sf) +{ + static double powsuvw[256]; + for(int j = 0; j < coeffs->size2(); ++j) { + double powu = (*eexps) (j, 0); + double powv = (*eexps) (j, 1); + double poww = (*eexps) (j, 2); + powsuvw[j] = pow(u, powu) * pow(v, powv) * pow(w, poww); + } + + 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) * powsuvw[j]; + } + } +} + +void Adaptive_Post_View::initWithLowResolution(Post_View * view) +{ + List_T *myList; + int nbelm; + int nbnod; + + int nbComp = 1; + + if (view->NbST){ + myList = view->ST; + nbelm = view->NbST; + nbnod = 3; + } + else if(view->NbSL){ + myList = view->SL; + nbelm = view->NbSL; + nbnod = 2; + } + else if (view->NbVT){ + myList = view->VT; + nbelm = view->NbVT; + nbnod = 3; + nbComp = 3; + } + else if (view->NbVQ){ + myList = view->VQ; + nbelm = view->NbVQ; + nbnod = 4; + nbComp = 3; + } + else if (view->NbSS){ + myList = view->SS; + nbelm = view->NbSS; + nbnod = 4; + } + else if (view->NbSQ){ + myList = view->SQ; + nbelm = view->NbSQ; + nbnod = 4; + } + else if (view->NbSH){ + myList = view->SH; + nbelm = view->NbSH; + nbnod = 8; + } + else return; + + // if there exists a polynomial representation + // of the geometry , then use it + if (_coefsGeom) + { + nbnod = _coefsGeom -> size1 (); + } + + + minval = VAL_INF; + maxval = -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)/nbComp ); + + if (nbComp == 3){ + _STvalX = new Double_Matrix ( nbelm , (nb-3*nbnod)/nbComp ); + _STvalY = new Double_Matrix ( nbelm , (nb-3*nbnod)/nbComp ); + _STvalZ = new Double_Matrix ( nbelm , (nb-3*nbnod)/nbComp ); + } + /// Store non interpolated data + + int k=0; + for (int i=0;i<List_Nbr(myList);i+=nb){ + double *x = (double*)List_Pointer_Fast (myList,i); + double *y = (double*)List_Pointer_Fast (myList,i+nbnod); + double *z = (double*)List_Pointer_Fast (myList,i+2*nbnod); + for (int NN=0;NN<nbnod;NN++){ + (*_STposX) ( k , NN) = x[NN]; + (*_STposY) ( k , NN) = y[NN]; + (*_STposZ) ( k , NN) = z[NN]; + } + double *val = (double*)List_Pointer_Fast (myList,i+3*nbnod); + if (nbComp == 1){ + for (int j=0;j<(nb-3*nbnod)/nbComp;j++){ + (*_STval)(k,j)=val[j]; + } + } + else if (nbComp == 3){ + int size = (nb-3*nbnod)/3; + for (int j=0;j<size;j++){ + int index1 = j; + int index2 = j+size; + int index3 = j+2*size; + // adaptation of the visualization mesh bases on the norm squared of the vector + (*_STval)(k,j)=(val[index1]*val[index1] + val[index2]*val[index2] + + val[index3]*val[index3]); + (*_STvalX)(k,j)=val[index1]; + (*_STvalY)(k,j)=val[index2]; + (*_STvalZ)(k,j)=val[index3]; + } + } + k++; + } + setAdaptiveResolutionLevel(view, 0); +} + +Adaptive_Post_View::Adaptive_Post_View(Post_View * view, + List_T * _c, + List_T * _pol, + List_T * _cGeom, + List_T * _polGeom) + :tol(1.e-3),_coefsGeom(0),_eexpsGeom(0) +{ + + _Interpolate = _Geometry = 0; + _coefs = new Double_Matrix ( List_Nbr (_c) , List_Nbr (_c) ); + _eexps = new Double_Matrix ( List_Nbr (_c) , 3 ); + + _STvalX = _STvalY = _STvalZ =0; + + 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; + } + } + + if (_cGeom && _polGeom) + { + _coefsGeom = new Double_Matrix ( List_Nbr (_cGeom) , List_Nbr (_cGeom) ); + _eexpsGeom = new Double_Matrix ( List_Nbr (_cGeom) , 3 ); + for(int i = 0; i < List_Nbr(_cGeom); ++i) { + List_T **line = (List_T **) List_Pointer_Fast(_cGeom, i); + List_T **eexp = (List_T **) List_Pointer_Fast(_polGeom, i); + + double dpowu, dpowv, dpoww; + + List_Read(*eexp, 0, &dpowu); + List_Read(*eexp, 1, &dpowv); + List_Read(*eexp, 2, &dpoww); + + (*_eexpsGeom) (i, 0) = dpowu; + (*_eexpsGeom) (i, 1) = dpowv; + (*_eexpsGeom) (i, 2) = dpoww; + + for(int j = 0; j < List_Nbr(*line); ++j) { + double val; + List_Read(*line, j, &val); + (*_coefsGeom) (i, j) = val; + } + } + } + initWithLowResolution(view); +} + +Adaptive_Post_View::~Adaptive_Post_View() +{ + delete _coefs; + delete _eexps; + delete _STposX; + delete _STposY; + delete _STposZ; + delete _STval; + + if (_coefsGeom) + delete _coefsGeom; + if (_eexpsGeom) + delete _eexpsGeom; + + if(_Interpolate) + delete _Interpolate; + if(_Geometry) + delete _Geometry; + cleanElement < adapt_edge > (); + cleanElement < adapt_triangle > (); + cleanElement < adapt_tet > (); + cleanElement < adapt_hex > (); + cleanElement < adapt_quad > (); +} diff --git a/Common/AdaptiveViews.h b/Common/AdaptiveViews.h new file mode 100644 index 0000000000000000000000000000000000000000..53effd4b2860d3f1f5b777ee002aa04de475c936 --- /dev/null +++ b/Common/AdaptiveViews.h @@ -0,0 +1,320 @@ +#ifndef _ADAPTIVE_VIEWS_H_ +#define _ADAPTIVE_VIEWS_H_ + +// 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 <list> +#include "List.h" +#include "GmshMatrix.h" + +#define MAX_LEVEL_OF_ZOOM 8 + +class Post_View; +class GMSH_Post_Plugin; + +// On a triangle, we suppose that there exists an interpolation scheme +// such that u = \sum_i u_i \phi_i, phi_i being polynomials of order +// p, i goes from 1...(p+1)(p+2)/2 and phi_i = \sum_j coeffs_{ij} +// monomials_j and monomials are 1,x,y,x^2,xy,y^2,x^3,x^2y,xy^2,y^3... + +class adapt_point +{ +public : + double x,y,z; + double X,Y,Z,val,valx,valy,valz; + double shape_functions[128]; + static adapt_point * New (double x, double y, double z, + Double_Matrix *coeffs, Double_Matrix *eexps); + void print () const + { + printf("p %g %g\n" ,x,y); + } + bool operator < (const adapt_point & other) const + { + if(other.x < x) return true; + if(other.x > x) return false; + if(other.y < y) return true; + if(other.y > y) return false; + if(other.z < z) return true; + return false; + } + static std::set<adapt_point> all_points; +}; + +class adapt_edge +{ +public: + adapt_edge (adapt_point *p1,adapt_point *p2) + : visible(false) + { + p[0] = p1; + p[1] = p2; + e[0] = e[1] = 0; + } + inline double V () const + { + return (p[0]->val + p[1]->val)/2.; + } + inline static void GSF (const double u, const double v, double w, double sf[]) + { + sf[0] = (1-u)/2.; + sf[1] = (1+u)/2.; + } + void print () + { + printf("p1 %g %g p2 %g %g\n", p[0]->x, p[0]->y, p[1]->x, p[1]->y); + } + static void Create (int maxlevel, Double_Matrix *coeffs, Double_Matrix *eexps) ; + static void Recur_Create (adapt_edge *e, int maxlevel, int level, + Double_Matrix *coeffs, Double_Matrix *eexps); + static void Error (double AVG , double tol ); + static void Recur_Error (adapt_edge *e, double AVG, double tol); + bool visible; + adapt_point *p[2]; + adapt_edge *e[2]; + static std::list<adapt_edge*> all_elems; + static int nbNod; +}; + +class adapt_triangle +{ +public: + adapt_triangle (adapt_point *p1, adapt_point *p2, adapt_point *p3) + : visible (false) + { + p[0] = p1; + p[1] = p2; + p[2] = p3; + e[0] = e[1] = e[2] = e[3] = 0; + } + inline double V () const + { + return (p[0]->val + p[1]->val + p[2]->val)/3.; + } + inline static void GSF (const double u, const double v, double w, double sf[]) + { + sf[0] = 1. - u - v; + sf[1] = u; + sf[2] = v; + } + void print () + { + printf("p1 %g %g p2 %g %g p3 %g %g\n", + p[0]->x, p[0]->y, p[1]->x, p[1]->y, p[2]->x, p[2]->y); + } + static void Create (int maxlevel, Double_Matrix *coeffs, Double_Matrix *eexps); + static void Recur_Create (adapt_triangle *t, int maxlevel, int level, + Double_Matrix *coeffs, Double_Matrix *eexps); + static void Error (double AVG, double tol); + static void Recur_Error (adapt_triangle *t, double AVG, double tol); + bool visible; + adapt_point *p[3]; + adapt_triangle *e[4]; + static std::list<adapt_triangle*> all_elems; + static int nbNod; +}; + +class adapt_quad +{ +public: + adapt_quad (adapt_point *p1, adapt_point *p2, adapt_point *p3, adapt_point *p4) + : visible (false) + { + p[0] = p1; + p[1] = p2; + p[2] = p3; + p[3] = p4; + e[0] = e[1] = e[2] = e[3] = 0; + } + inline double V () const + { + return (p[0]->val + p[1]->val + p[2]->val + p[3]->val)/4.; + } + inline static void GSF (const double u, const double v, double w, double sf[]) + { + sf[0] = 0.25 * (1. - u) * (1. - v); + sf[1] = 0.25 * (1. + u) * (1. - v); + sf[2] = 0.25 * (1. + u) * (1. + v); + sf[3] = 0.25 * (1. - u) * (1. + v); + } + void print () + { + printf("p1 %g %g p2 %g %g p3 %g %g\n", + p[0]->x, p[0]->y, p[1]->x, p[1]->y, p[2]->x, p[2]->y); + } + static void Create (int maxlevel, Double_Matrix *coeffs, Double_Matrix *eexps); + static void Recur_Create (adapt_quad *q, int maxlevel, int level, + Double_Matrix *coeffs, Double_Matrix *eexps); + static void Error (double AVG, double tol); + static void Recur_Error (adapt_quad *q, double AVG, double tol); + bool visible; + adapt_point *p[4]; + adapt_quad *e[4]; + static std::list<adapt_quad*> all_elems; + static int nbNod; +}; + +class adapt_tet +{ +public: + adapt_tet (adapt_point *p1, adapt_point *p2, adapt_point *p3, adapt_point *p4) + : visible (false) + { + p[0] = p1; + p[1] = p2; + p[2] = p3; + p[3] = p4; + e[0] = e[1] = e[2] = e[3] = 0; + e[4] = e[5] = e[6] = e[7] = 0; + } + inline static void GSF (const double u, const double v, double w, double sf[]) + { + sf[0] = 1. - u - v - w; + sf[1] = u; + sf[2] = v; + sf[3] = w; + } + inline double V () const + { + return (p[0]->val + p[1]->val + p[2]->val + p[3]->val)/4.; + } + void print () + { + printf("p1 %g %g p2 %g %g p3 %g %g\n", + p[0]->x, p[0]->y, p[1]->x, p[1]->y, p[2]->x, p[2]->y); + } + static void Create (int maxlevel, Double_Matrix *coeffs, Double_Matrix *eexps); + static void Recur_Create (adapt_tet *t, int maxlevel, int level, + Double_Matrix *coeffs, Double_Matrix *eexps); + static void Error (double AVG, double tol); + static void Recur_Error (adapt_tet *t, double AVG, double tol); + bool visible; + adapt_point *p[4]; + adapt_tet *e[8]; + static std::list<adapt_tet*> all_elems; + static int nbNod; +}; + +class adapt_hex +{ +public: + adapt_hex (adapt_point *p1, adapt_point *p2, adapt_point *p3, adapt_point *p4, + adapt_point *p5, adapt_point *p6, adapt_point *p7, adapt_point *p8) + : visible (false) + { + p[0] = p1; + p[1] = p2; + p[2] = p3; + p[3] = p4; + p[4] = p5; + p[5] = p6; + p[6] = p7; + p[7] = p8; + e[0] = e[1] = e[2] = e[3] = 0; + e[4] = e[5] = e[6] = e[7] = 0; + } + inline static void GSF (const double u, const double v, double w, double sf[]) + { + sf[0] = 0.125 * (1 - u) * (1 - v) * (1 - w); + sf[1] = 0.125 * (1 + u) * (1 - v) * (1 - w); + sf[2] = 0.125 * (1 + u) * (1 + v) * (1 - w); + sf[3] = 0.125 * (1 - u) * (1 + v) * (1 - w); + sf[4] = 0.125 * (1 - u) * (1 - v) * (1 + w); + sf[5] = 0.125 * (1 + u) * (1 - v) * (1 + w); + sf[6] = 0.125 * (1 + u) * (1 + v) * (1 + w); + sf[7] = 0.125 * (1 - u) * (1 + v) * (1 + w); + } + inline double V () const + { + return (p[0]->val + p[1]->val + p[2]->val+ p[3]->val + + p[4]->val + p[5]->val + p[6]->val+ p[7]->val)/8.; + } + void print () + { + printf("p1 %g %g p2 %g %g p3 %g %g\n", + p[0]->x, p[0]->y, p[1]->x, p[1]->y, p[2]->x, p[2]->y); + } + static void Create (int maxlevel, Double_Matrix *coeffs, Double_Matrix *eexps); + static void Recur_Create (adapt_hex *h, int maxlevel, int level, + Double_Matrix *coeffs, Double_Matrix *eexps); + static void Error (double AVG, double tol); + static void Recur_Error (adapt_hex *h, double AVG, double tol); + bool visible; + adapt_point *p[8]; + adapt_hex *e[8]; + static std::list<adapt_hex*> all_elems; + static int nbNod; +}; + +class Adaptive_Post_View +{ + double tol; + double minval, maxval; + int presentZoomLevel; + double presentTol; + Double_Matrix * _eexps; + Double_Matrix * _coefs; + Double_Matrix * _coefsGeom; + Double_Matrix * _eexpsGeom; + Double_Matrix * _STposX; + Double_Matrix * _STposY; + Double_Matrix * _STposZ; + Double_Matrix * _STval; + // for vectors + Double_Matrix * _STvalX; + Double_Matrix * _STvalY; + Double_Matrix * _STvalZ; + Double_Matrix * _Interpolate; + Double_Matrix * _Geometry; +public: + Adaptive_Post_View (Post_View *view, List_T *_coeffs, List_T *_eexps, List_T *_coeffsGeom=0, List_T *_eexpsGeom=0); + ~Adaptive_Post_View (); + int getGlobalResolutionLevel () const { return presentZoomLevel; } + void setGlobalResolutionLevel (Post_View * view, int level) + { + setAdaptiveResolutionLevel(view, level); + } + template <class ELEM> + void setAdaptiveResolutionLevel_TEMPL(Post_View * view, int level, int lemvelmax, + GMSH_Post_Plugin *plug, List_T **myList, + int *counter, int *done); + void setAdaptiveResolutionLevel (Post_View * view , int levelmax, + GMSH_Post_Plugin *plug = 0); + void initWithLowResolution (Post_View *view); + void setTolerance (const double eps) { tol=eps; } + double getTolerance () const { return tol; } + template <class ELEM> + int zoomElement (Post_View * view, int ielem, int level, int levelmax, + GMSH_Post_Plugin *plug, List_T *theList, int *counter); +}; + +template <class ELEM> +void cleanElement () +{ + typename std::list<ELEM*>::iterator it = ELEM::all_elems.begin(); + typename std::list<ELEM*>::iterator ite = ELEM::all_elems.end(); + for (; it != ite; ++it){ + delete *it; + } + ELEM::all_elems.clear(); + adapt_point::all_points.clear(); +} + +#endif diff --git a/Common/ColorTable.cpp b/Common/ColorTable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a0f0f9862811f494b52e60c5a99c2b78ce908a64 --- /dev/null +++ b/Common/ColorTable.cpp @@ -0,0 +1,464 @@ +// $Id: ColorTable.cpp,v 1.33 2006-11-27 22:22:07 geuzaine 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>. +// +// Contributor(s): +// David Colignon +// + +// These colortable routines were inspired by those provided in Vis5d, +// a program for visualizing five dimensional gridded data sets +// Copyright (C) 1990 - 1995 Bill Hibbard, Brian Paul, Dave Santek, +// and Andre Battaiola. + +#include "Gmsh.h" +#include "ColorTable.h" +#include "Context.h" +#include "Numeric.h" + +extern Context_T CTX; + +void ColorTable_InitParam(int number, GmshColorTable * ct) +{ + ct->size = 255; + for(int i = 0; i < COLORTABLE_NBMAX_PARAM; i++){ + ct->ipar[i] = 0; + ct->dpar[i] = 0.; + } + ct->ipar[COLORTABLE_MODE] = COLORTABLE_RGB; + ct->ipar[COLORTABLE_NUMBER] = number; + ct->dpar[COLORTABLE_ALPHA] = 1.0; +} + +static double gray(double s) +{ + return s < 0. ? 0. : (s < 1. ? s : 1.); +} + +static double hot_r(double s) +{ + return s < 0. ? 0. : (s < 3./8. ? 8./3. * s : 1.); +} + +static double hot_g(double s) +{ + return s < 3./8. ? 0. : (s < 6./8. ? 8./3. * (s - 3./8.) : 1.); +} + +static double hot_b(double s) +{ + return s < 6./8. ? 0. : (s < 1. ? 8./2. * (s - 6./8.) : 1.); +} + +static double cubic(double a, double b, double c, double d, double x) +{ + return a + b * x + c * x * x + d * x * x * x; +} + +void ColorTable_Recompute(GmshColorTable * ct) +{ + double s, t, gamma; + int r, g, b, a; + + double bias = ct->dpar[COLORTABLE_BIAS]; + double curvature = ct->dpar[COLORTABLE_CURVATURE]; + int rotation = ct->ipar[COLORTABLE_ROTATION]; + + for(int i = 0; i < ct->size; i++) { + + if(ct->size > 1) { + if(i + rotation < 0) + s = (double)(i + rotation + ct->size) / (double)(ct->size - 1); + else if(i + rotation > ct->size - 1) + s = (double)(i + rotation - ct->size) / (double)(ct->size - 1); + else + s = (double)(i + rotation) / (double)(ct->size - 1); + } + else + s = 0.; + + if(ct->ipar[COLORTABLE_SWAP]) + s = 1.0 - s; + + switch (ct->ipar[COLORTABLE_NUMBER]) { + case 0: // all black + r = g = b = 0; + break; + case 1: // vis5d + t = (curvature + 1.4) * (s - (1. + bias) / 2.); + r = (int)(128.0 + 127.0 * atan(7.0 * t) / 1.57); + g = (int)(128.0 + 127.0 * (2 * exp(-7 * t * t) - 1)); + b = (int)(128.0 + 127.0 * atan(-7.0 * t) / 1.57); + break; + case 2: // matlab "jet" + { + double ii = (double)(s-bias)*128.; + if(ii < 0) ii = 0; + if(ii > 128) ii = 128; + double rr = + ii <= 46 ? 0. : + ii >= 111 ? -0.03125*(ii - 111) + 1. : + ii >= 78 ? 1. : + 0.03125*(ii - 46); + double gg = + ii <= 14 || ii >= 111 ? 0. : + ii >= 79 ? -0.03125*(ii - 111) : + ii <= 46 ? 0.03125*(ii - 14) : + 1.; + double bb = + ii >= 79 ? 0. : + ii >= 47 ? -0.03125*(ii - 79) : + ii <= 14 ? 0.03125*(ii - 14) + 1.: + 1.; + r = (int)(rr*255.); + g = (int)(gg*255.); + b = (int)(bb*255.); + } + break; + case 3: // lucie, samcef (?) + if(s - bias <= 0.) { + r = 0; + g = 0; + b = 255; + } + else if(s - bias <= 0.40) { + r = 0; + g = (int)((s - bias) * 637.5); + b = (int)(255. - (s - bias) * 637.5); + } + else if(s - bias <= 0.60) { + r = (int)(1275. * (s - bias - 0.4)); + g = 255; + b = 0; + } + else if(s - bias <= 1.) { + r = 255; + g = (int)(255. - 637.5 * (s - bias - 0.6)); + b = 0; + } + else { + r = 255; + g = 0; + b = 0; + } + break; + case 4: // rainbow + if(s - bias <= 0.) { + r = 0; + g = 0; + b = 255; + } + else if(s - bias <= 0.25 + curvature) { + curvature = (curvature == -0.25) ? -0.26 : curvature; + r = 0; + g = (int)((s - bias) * (255. / (0.25 + curvature))); + b = 255; + } + else if(s - bias <= 0.50) { + curvature = (curvature == 0.25) ? 0.26 : curvature; + r = 0; + g = 255; + b = (int)(255. - (255. / (0.25 - curvature)) * (s - bias - 0.25 - curvature)); + } + else if(s - bias <= 0.75 - curvature) { + curvature = (curvature == 0.25) ? 0.26 : curvature; + r = (int)((s - bias - 0.5) * (255. / (0.25 - curvature))); + g = 255; + b = 0; + } + else if(s - bias <= 1.) { + curvature = (curvature == -0.25) ? -0.26 : curvature; + r = 255; + g = (int)(255. - (255. / (0.25 + curvature)) * (s - bias - 0.75 + curvature)); + b = 0; + } + else { + r = 255; + g = 0; + b = 0; + } + break; + case 5: // emc2000 (rainbow with black and white) + if(s - bias <= 0.) { + r = 0; + g = 0; + b = 0; + } + else if(s - bias <= 0.2) { + r = (int)(57 * (1 - 100 * ((s - bias) - 0.1) * ((s - bias) - 0.1))); + g = 0; + b = (int)((s - bias) * (255. / 0.2)); + } + else if(s - bias <= 0.3624) { + r = 0; + g = (int)((s - bias - 0.2) * (255. / 0.1624)); + b = 255; + } + else if(s - bias <= 0.50) { + r = 0; + g = 255; + b = (int)(255. - (255. / 0.1376) * (s - bias - 0.3624)); + } + else if(s - bias <= 0.6376) { + r = (int)((s - bias - 0.5) * (255. / 0.1376)); + g = 255; + b = 0; + } + else if(s - bias <= 0.8) { + r = 255; + g = (int)(255. - (255. / 0.1624) * (s - bias - 0.6376)); + b = 0; + } + else if(s - bias <= 1.0) { + r = 255; + g = (int)((255. / 0.2) * (s - bias - 0.8)); + b = (int)(-3187.66 * (s - bias) * (s - bias) + 7012.76 * (s - bias) - 3570.61); + } + else { + r = 255; + g = 255; + b = 255; + } + break; + case 6: // darkblue->red->yellow->white + r = (int)(255. * cubic(-0.0506169, 2.81633, -1.87033, 0.0524573, s-bias)); + g = (int)(255. * cubic(0.0485868, -1.26109, 6.3074, -4.12498, s-bias)); + b = (int)(255. * cubic(0.364662, 1.50814, -7.36756, 6.51847, s-bias)); + break; + case 7: // matlab "hot" + r = (int)(255. * hot_r(s-bias)); + g = (int)(255. * hot_g(s-bias)); + b = (int)(255. * hot_b(s-bias)); + break; + case 8: // matlab "pink" + r = (int)(255. * sqrt((2.*gray(s-bias) + hot_r(s-bias))/3.)); + g = (int)(255. * sqrt((2.*gray(s-bias) + hot_g(s-bias))/3.)); + b = (int)(255. * sqrt((2.*gray(s-bias) + hot_b(s-bias))/3.)); + break; + case 9: // grayscale + if(s - bias <= 0.) { + r = g = b = 0; + } + else if(s - bias <= 1.) { + r = g = b = (int)(255 * (1. - curvature) * (s - bias)); + } + else { + r = g = b = (int)(255 * (1. - curvature)); + } + break; + case 10: // all white + r = g = b = 255; + break; + case 11: // matlab "hsv" + { + double H = 6. * s + 1.e-10, R, G, B; + HSV_to_RGB(H, 1., 1., &R, &G, &B); + r = (int)(255 * R); + g = (int)(255 * G); + b = (int)(255 * B); + } + break; + case 12: // spectrum (truncated hsv) + { + double H = 5. * s + 1.e-10, R, G, B; + HSV_to_RGB(H, 1., 1., &R, &G, &B); + r = (int)(255 * R); + g = (int)(255 * G); + b = (int)(255 * B); + } + break; + case 13: // matlab "bone" + r = (int)(255. * (7.*gray(s-bias) + hot_b(s-bias))/8.); + g = (int)(255. * (7.*gray(s-bias) + hot_g(s-bias))/8.); + b = (int)(255. * (7.*gray(s-bias) + hot_r(s-bias))/8.); + break; + case 14: // matlab "spring" + r = (int)(255. * 1.); + g = (int)(255. * gray(s-bias)); + b = (int)(255. * (1. - gray(s-bias))); + break; + case 15: // matlab "summer" + r = (int)(255. * gray(s-bias)); + g = (int)(255. * (0.5+gray(s-bias)/2.)); + b = (int)(255. * 0.4); + break; + case 16: // matlab "autumn" + r = (int)(255. * 1.); + g = (int)(255. * gray(s-bias)); + b = (int)(255. * 0.); + break; + case 17: // matlab "winter" + r = (int)(255. * 0.); + g = (int)(255. * gray(s-bias)); + b = (int)(255. * (0.5+(1.-gray(s-bias))/2.)); + break; + case 18: // matlab "cool" + r = (int)(255. * gray(s-bias)); + g = (int)(255. * (1.-gray(s-bias))); + b = (int)(255. * 1.); + break; + case 19: // matlab "copper" + r = (int)(255. * DMIN(1., gray(s-bias) * 1.25)); + g = (int)(255. * DMIN(1., gray(s-bias) * 0.7812)); + b = (int)(255. * DMIN(1., gray(s-bias) * 0.4975)); + break; + default: + r = g = b = 0; + break; + } + + double aa = 1.0; + if(ct->dpar[COLORTABLE_ALPHAPOW]) + aa = pow(s ? s : 1.e-10, ct->dpar[COLORTABLE_ALPHAPOW]); + a = (int)(255. * aa * ct->dpar[COLORTABLE_ALPHA]); + + if(ct->dpar[COLORTABLE_BETA]) { + if(ct->dpar[COLORTABLE_BETA] > 0.0) + gamma = 1. - ct->dpar[COLORTABLE_BETA]; + else + gamma = 1. / (1.001 + ct->dpar[COLORTABLE_BETA]); // beta is thresholded to [-1,1] + r = (int)(255. * pow((double)r / 255., gamma)); + g = (int)(255. * pow((double)g / 255., gamma)); + b = (int)(255. * pow((double)b / 255., gamma)); + } + + if(ct->ipar[COLORTABLE_INVERT]) { + r = 255 - r; + g = 255 - g; + b = 255 - b; + } + + // clamp to [0,255] + r = r < 0 ? 0 : (r > 255 ? 255 : r); + g = g < 0 ? 0 : (g > 255 ? 255 : g); + b = b < 0 ? 0 : (b > 255 ? 255 : b); + a = a < 0 ? 0 : (a > 255 ? 255 : a); + + ct->table[i] = CTX.PACK_COLOR(r, g, b, a); + } + +} + +static GmshColorTable clip; + +void ColorTable_Copy(GmshColorTable * ct) +{ + clip.size = ct->size; + memcpy(clip.table, ct->table, ct->size * sizeof(unsigned int)); + memcpy(clip.ipar, ct->ipar, COLORTABLE_NBMAX_PARAM * sizeof(int)); + memcpy(clip.dpar, ct->dpar, COLORTABLE_NBMAX_PARAM * sizeof(double)); +} + +void ColorTable_Paste(GmshColorTable * ct) +{ + ct->size = clip.size; + memcpy(ct->table, clip.table, clip.size * sizeof(unsigned int)); + memcpy(ct->ipar, clip.ipar, COLORTABLE_NBMAX_PARAM * sizeof(int)); + memcpy(ct->dpar, clip.dpar, COLORTABLE_NBMAX_PARAM * sizeof(double)); +} + +int ColorTable_Diff(GmshColorTable * ct1, GmshColorTable * ct2) +{ + if(ct1->size != ct2->size) return 1; + for(int i = 0; i < ct1->size; i++) + if(ct1->table[i] != ct2->table[i]) return 1; + return 0; +} + +void ColorTable_Print(GmshColorTable * ct, FILE * fp) +{ + int i, r, g, b, a; + char tmp1[1024], tmp2[1024]; + + strcpy(tmp1, ""); + for(i = 0; i < ct->size; i++) { + r = CTX.UNPACK_RED(ct->table[i]); + g = CTX.UNPACK_GREEN(ct->table[i]); + b = CTX.UNPACK_BLUE(ct->table[i]); + a = CTX.UNPACK_ALPHA(ct->table[i]); + if(i && !(i % 4)) { + if(fp) + fprintf(fp, "%s\n", tmp1); + else + Msg(DIRECT, tmp1); + strcpy(tmp1, ""); + } + sprintf(tmp2, "{%d, %d, %d, %d}", r, g, b, a); + strcat(tmp1, tmp2); + if(i != ct->size - 1) + strcat(tmp1, ", "); + } + if(fp) + fprintf(fp, "%s\n", tmp1); + else + Msg(DIRECT, tmp1); +} + +int ColorTable_IsAlpha(GmshColorTable * ct) +{ + int i, a; + for(i = 0; i < ct->size; i++) { + a = CTX.UNPACK_ALPHA(ct->table[i]); + if(a < 255) + return 1; + } + return 0; +} + +// HSV/RBG conversion routines + +void HSV_to_RGB(double H, double S, double V, + double *R, double *G, double *B) +{ + if(S < 5.0e-6) { + *R = *G = *B = V; + } + else { + int i = (int)H; + double f = H - (float)i; + double p1 = V*(1.0-S); + double p2 = V*(1.0-S*f); + double p3 = V*(1.0-S*(1.0-f)); + switch(i){ + case 0: *R = V; *G = p3; *B = p1; break; + case 1: *R = p2; *G = V; *B = p1; break; + case 2: *R = p1; *G = V; *B = p3; break; + case 3: *R = p1; *G = p2; *B = V; break; + case 4: *R = p3; *G = p1; *B = V; break; + case 5: *R = V; *G = p1; *B = p2; break; + } + } +} + +void RGB_to_HSV(double R, double G, double B, + double *H, double *S, double *V) +{ + double maxv = R > G ? R : G; if(B > maxv) maxv = B; + *V = maxv; + if(maxv>0){ + double minv = R < G ? R : G; if(B < minv) minv = B; + *S = 1.0 - double(minv)/maxv; + if(maxv > minv){ + if(maxv == R){ *H = (G-B)/double(maxv-minv); if (*H<0) *H += 6.0; } + else if(maxv == G) *H = 2.0+(B-R)/double(maxv-minv); + else *H = 4.0+(R-G)/double(maxv-minv); + } + } +} diff --git a/Common/ColorTable.h b/Common/ColorTable.h new file mode 100644 index 0000000000000000000000000000000000000000..11bde849ec16469597f95aaaadeff0657c139dd5 --- /dev/null +++ b/Common/ColorTable.h @@ -0,0 +1,67 @@ +#ifndef _COLORTABLE_H_ +#define _COLORTABLE_H_ + +// 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>. + +#define COLORTABLE_NBMAX_PARAM 10 +#define COLORTABLE_NBMAX_COLOR 1024 + +typedef struct{ + unsigned int table[COLORTABLE_NBMAX_COLOR]; + int size; // must be >= 2 + int ipar[COLORTABLE_NBMAX_PARAM]; + double dpar[COLORTABLE_NBMAX_PARAM]; +}GmshColorTable; + +// COLORTABLE_MODE + +#define COLORTABLE_RGB 1 +#define COLORTABLE_HSV 2 + +// integrer parameters indices + +#define COLORTABLE_NUMBER 0 // predefined curve index +#define COLORTABLE_INVERT 1 // invert (rbg<->255-rgb) +#define COLORTABLE_SWAP 2 // swap (min<->max) +#define COLORTABLE_ROTATION 3 // rotation +#define COLORTABLE_MODE 4 // mode (rgb, hsv) + +// double parameters indices + +#define COLORTABLE_CURVATURE 0 // curvature +#define COLORTABLE_BIAS 1 // offset +#define COLORTABLE_ALPHA 2 // alpha channel value +#define COLORTABLE_BETA 3 // beta coeff for brighten +#define COLORTABLE_ALPHAPOW 4 // alpha channel power value + +void ColorTable_InitParam(int number, GmshColorTable *ct); +void ColorTable_Recompute(GmshColorTable *ct); +void ColorTable_Copy(GmshColorTable *ct); +void ColorTable_Paste(GmshColorTable *ct); +void ColorTable_Print(GmshColorTable *ct, FILE *fp) ; +int ColorTable_IsAlpha(GmshColorTable *ct) ; +int ColorTable_Diff(GmshColorTable *ct1, GmshColorTable *ct2); + +void RGB_to_HSV(double R, double G, double B, + double *H, double *S, double *V); +void HSV_to_RGB(double H, double S, double V, + double *R, double *G, double *B); + +#endif diff --git a/Common/OctreePost.cpp b/Common/OctreePost.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8f6b61e6ba1bf592317ed22590d924430245215 --- /dev/null +++ b/Common/OctreePost.cpp @@ -0,0 +1,405 @@ +// $Id: OctreePost.cpp,v 1.2 2006-11-27 22:22:07 geuzaine 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 "Octree.h" +#include "OctreePost.h" +#include "List.h" +#include "Views.h" +#include "Numeric.h" +#include "Message.h" +#include "ShapeFunctions.h" + +static void minmax(int n, double *X, double *Y, double *Z, + double *min, double *max) +{ + min[0] = X[0]; + min[1] = Y[0]; + min[2] = Z[0]; + max[0] = X[0]; + max[1] = Y[0]; + max[2] = Z[0]; + + for(int i = 1; i < n; i++) { + min[0] = (X[i] < min[0]) ? X[i] : min[0]; + min[1] = (Y[i] < min[1]) ? Y[i] : min[1]; + min[2] = (Z[i] < min[2]) ? Z[i] : min[2]; + max[0] = (X[i] > max[0]) ? X[i] : max[0]; + max[1] = (Y[i] > max[1]) ? Y[i] : max[1]; + max[2] = (Z[i] > max[2]) ? Z[i] : max[2]; + } +} + +static void centroid(int n, double *X, double *Y, double *Z, double *c) +{ + const double oc = 1./(double)n; + c[0] = X[0]; + c[1] = Y[0]; + c[2] = Z[0]; + for(int i = 1; i < n; i++) { + c[0] += X[i]; + c[1] += Y[i]; + c[2] += Z[i]; + } + c[0] *= oc; + c[1] *= oc; + c[2] *= oc; +} + +void linBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[2], *Z = &X[4]; + minmax(2, X, Y, Z, min, max); +} + +void triBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[3], *Z = &X[6]; + minmax(3, X, Y, Z, min, max); +} + +void quaBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[4], *Z = &X[8]; + minmax(4, X, Y, Z, min, max); +} + +void tetBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[4], *Z = &X[8]; + minmax(4, X, Y, Z, min, max); +} + +void hexBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[8], *Z = &X[16]; + minmax(8, X, Y, Z, min, max); +} + +void priBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[6], *Z = &X[12]; + minmax(6, X, Y, Z, min, max); +} + +void pyrBB(void *a, double *min, double *max) +{ + double *X = (double*) a, *Y = &X[5], *Z = &X[10]; + minmax(5, X, Y, Z, min, max); +} + +int linInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[2], *Z = &X[4], uvw[3]; + line lin(X, Y, Z); + lin.xyz2uvw(x, uvw); + return lin.isInside(uvw[0], uvw[1], uvw[2]); +} + +int triInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[3], *Z = &X[6], uvw[3]; + triangle tri(X, Y, Z); + tri.xyz2uvw(x, uvw); + return tri.isInside(uvw[0], uvw[1], uvw[2]); +} + +int quaInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[4], *Z = &X[8], uvw[3]; + quadrangle qua(X, Y, Z); + qua.xyz2uvw(x, uvw); + return qua.isInside(uvw[0], uvw[1], uvw[2]); +} + +int tetInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[4], *Z = &X[8], uvw[3]; + tetrahedron tet(X, Y, Z); + tet.xyz2uvw(x, uvw); + return tet.isInside(uvw[0], uvw[1], uvw[2]); +} + +int hexInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[8], *Z = &X[16], uvw[3]; + hexahedron hex(X, Y, Z); + hex.xyz2uvw(x, uvw); + return hex.isInside(uvw[0], uvw[1], uvw[2]); +} + +int priInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[6], *Z = &X[12], uvw[3]; + prism pri(X, Y, Z); + pri.xyz2uvw(x, uvw); + return pri.isInside(uvw[0], uvw[1], uvw[2]); +} + +int pyrInEle(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[5], *Z = &X[10], uvw[3]; + pyramid pyr(X, Y, Z); + pyr.xyz2uvw(x, uvw); + return pyr.isInside(uvw[0], uvw[1], uvw[2]); +} + +void linCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[2], *Z = &X[4]; + centroid(2, X, Y, Z, x); +} + +void triCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[3], *Z = &X[6]; + centroid(3, X, Y, Z, x); +} + +void quaCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[4], *Z = &X[8]; + centroid(4, X, Y, Z, x); +} + +void tetCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[4], *Z = &X[8]; + centroid(4, X, Y, Z, x); +} + +void hexCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[8], *Z = &X[16]; + centroid(8, X, Y, Z, x); +} + +void priCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[6], *Z = &X[12]; + centroid(6, X, Y, Z, x); +} + +void pyrCentroid(void *a, double *x) +{ + double *X = (double*) a, *Y = &X[5], *Z = &X[10]; + centroid(5, X, Y, Z, x); +} + +static void addListOfStuff(Octree *o, List_T *l, int nbelm) +{ + if(!l) return; + + for(int i = 0; i < List_Nbr(l); i += nbelm){ + double * X = (double *)List_Pointer_Fast(l, i); + Octree_Insert(X, o); + } +} + +OctreePost::~OctreePost() +{ + Octree_Delete(ST); Octree_Delete(VT); Octree_Delete(TT); + Octree_Delete(SQ); Octree_Delete(VQ); Octree_Delete(TQ); + Octree_Delete(SS); Octree_Delete(VS); Octree_Delete(TS); + Octree_Delete(SH); Octree_Delete(VH); Octree_Delete(TH); + Octree_Delete(SI); Octree_Delete(VI); Octree_Delete(TI); + Octree_Delete(SY); Octree_Delete(VY); Octree_Delete(TY); +} + +OctreePost::OctreePost(Post_View *v) + : theView(v) +{ + double min [3] = {v->BBox[0], v->BBox[2], v->BBox[4]}; + + double size[3] = {v->BBox[1] - v->BBox[0], + v->BBox[3] - v->BBox[2], + v->BBox[5] - v->BBox[4]}; + + const int maxElePerBucket = 100; // memory vs. speed trade-off + + SL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle); + addListOfStuff(SL, v->SL, 6 + 2 * v->NbTimeStep); + Octree_Arrange(SL); + VL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle); + addListOfStuff(VL, v->VL, 6 + 6 * v->NbTimeStep); + Octree_Arrange(VL); + TL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle); + addListOfStuff(TL, v->TL, 6 + 18 * v->NbTimeStep); + Octree_Arrange(TL); + + ST = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle); + addListOfStuff(ST, v->ST, 9 + 3 * v->NbTimeStep); + Octree_Arrange(ST); + VT = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle); + addListOfStuff(VT, v->VT, 9 + 9 * v->NbTimeStep); + Octree_Arrange(VT); + TT = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle); + addListOfStuff(TT, v->TT, 9 + 27 * v->NbTimeStep); + Octree_Arrange(TT); + + SQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle); + addListOfStuff(SQ, v->SQ, 12 + 4 * v->NbTimeStep); + Octree_Arrange(SQ); + VQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle); + addListOfStuff(VQ, v->VQ, 12 + 12 * v->NbTimeStep); + Octree_Arrange(VQ); + TQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle); + addListOfStuff(TQ, v->TQ, 12 + 36 * v->NbTimeStep); + Octree_Arrange(TQ); + + SS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle); + addListOfStuff(SS, v->SS, 12 + 4 * v->NbTimeStep); + Octree_Arrange(SS); + VS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle); + addListOfStuff(VS, v->VS, 12 + 12 * v->NbTimeStep); + Octree_Arrange(VS); + TS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle); + addListOfStuff(TS, v->TS, 12 + 36 * v->NbTimeStep); + Octree_Arrange(TS); + + SH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle); + addListOfStuff(SH, v->SH, 24 + 8 * v->NbTimeStep); + Octree_Arrange(SH); + VH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle); + addListOfStuff(VH, v->VH, 24 + 24 * v->NbTimeStep); + Octree_Arrange(VH); + TH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle); + addListOfStuff(TH, v->TH, 24 + 72 * v->NbTimeStep); + Octree_Arrange(TH); + + SI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle); + addListOfStuff(SI, v->SI, 18 + 6 * v->NbTimeStep); + Octree_Arrange(SI); + VI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle); + addListOfStuff(VI, v->VI, 18 + 18 * v->NbTimeStep); + Octree_Arrange(VI); + TI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle); + addListOfStuff(TI, v->TI, 18 + 54 * v->NbTimeStep); + Octree_Arrange(TI); + + SY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle); + addListOfStuff(SY, v->SY, 15 + 5 * v->NbTimeStep); + Octree_Arrange(SY); + VY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle); + addListOfStuff(VY, v->VY, 15 + 15 * v->NbTimeStep); + Octree_Arrange(VY); + TY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle); + addListOfStuff(TY, v->TY, 15 + 45 * v->NbTimeStep); + Octree_Arrange(TY); +} + +bool OctreePost::getValue(void *in, int dim, int nbNod, int nbComp, + double P[3], int timestep, double *values, double *size_elem) +{ + if(!in) return false; + + double *X = (double*)in, *Y = &X[nbNod], *Z = &X[2*nbNod], *V = &X[3*nbNod], U[3]; + + elementFactory factory; + element *e = factory.create(nbNod, dim, X, Y, Z); + if(!e) return false; + + e->xyz2uvw(P, U); + if(timestep < 0){ + for(int i = 0; i < theView->NbTimeStep; i++) + for(int j = 0; j < nbComp; j++) + values[nbComp * i + j] = e->interpolate(&V[nbNod * nbComp * i + j], + U[0], U[1], U[2], nbComp); + } + else{ + for(int j = 0; j < nbComp; j++) + values[j] = e->interpolate(&V[nbNod * nbComp * timestep + j], + U[0], U[1], U[2], nbComp); + } + + if(size_elem) + *size_elem = e->maxEdgeLength(); + + delete e; + return true; +} + +bool OctreePost::searchScalar(double x, double y, double z, double *values, + int timestep, double *size_elem) +{ + double P[3] = {x, y, z}; + + if(timestep < 0) + for(int i = 0; i < theView->NbTimeStep; i++) + values[i] = 0.0; + else + values[0] = 0.0; + + if(getValue(Octree_Search(P, SS), 3, 4, 1, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, SH), 3, 8, 1, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, SI), 3, 6, 1, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, SY), 3, 5, 1, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, ST), 2, 3, 1, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, SQ), 2, 4, 1, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, SL), 1, 2, 1, P, timestep, values, size_elem)) return true; + + return false; +} + +bool OctreePost::searchVector(double x, double y, double z, double *values, + int timestep, double *size_elem) +{ + double P[3] = {x, y, z}; + + if(timestep < 0) + for(int i = 0; i < 3 * theView->NbTimeStep; i++) + values[i] = 0.0; + else + for(int i = 0; i < 3; i++) + values[i] = 0.0; + + if(getValue(Octree_Search(P, VS), 3, 4, 3, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, VH), 3, 8, 3, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, VI), 3, 6, 3, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, VY), 3, 5, 3, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, VT), 2, 3, 3, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, VQ), 2, 4, 3, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, VL), 1, 2, 3, P, timestep, values, size_elem)) return true; + + return false; +} + +bool OctreePost::searchTensor(double x, double y, double z, double *values, + int timestep, double *size_elem) +{ + double P[3] = {x, y, z}; + + if(timestep < 0) + for(int i = 0; i < 9 * theView->NbTimeStep; i++) + values[i] = 0.0; + else + for(int i = 0; i < 9; i++) + values[i] = 0.0; + + if(getValue(Octree_Search(P, TS), 3, 4, 9, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, TH), 3, 8, 9, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, TI), 3, 6, 9, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, TY), 3, 5, 9, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, TT), 2, 3, 9, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, TQ), 2, 4, 9, P, timestep, values, size_elem)) return true; + if(getValue(Octree_Search(P, TL), 1, 2, 9, P, timestep, values, size_elem)) return true; + + return false; +} diff --git a/Common/OctreePost.h b/Common/OctreePost.h new file mode 100644 index 0000000000000000000000000000000000000000..e7960d984f14026a2d5e86f7377d7b5c37bf866c --- /dev/null +++ b/Common/OctreePost.h @@ -0,0 +1,55 @@ +#ifndef _OCTREE_POST_H_ +#define _OCTREE_POST_H_ + +// 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 "Octree.h" + +class Post_View; + +class OctreePost +{ + Octree *SL, *VL, *TL; + Octree *ST, *VT, *TT; + Octree *SQ, *VQ, *TQ; + Octree *SS, *VS, *TS; + Octree *SH, *VH, *TH; + Octree *SI, *VI, *TI; + Octree *SY, *VY, *TY; + Post_View *theView; + bool getValue(void *in, int dim, int nbNod, int nbComp, + double P[3], int timestep, double *values, double *size_elem); + public : + OctreePost(Post_View *); + ~OctreePost(); + // search for the value of the View at point x, y, z. Values are + // interpolated using standard first order shape functions in the + // post element. If several time steps are present, they are all + // interpolated unless time step is set to a different value than + // -1. + bool searchScalar(double x, double y, double z, double *values, + int timestep = -1, double *size_elem = 0); + bool searchVector(double x, double y, double z, double *values, + int timestep = -1, double *size_elem = 0); + bool searchTensor(double x, double y, double z, double *values, + int timestep = -1, double *size_elem = 0); +}; + +#endif diff --git a/Common/Views.cpp b/Common/Views.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e77b7f8f1bd1405e86ac78a12c839962b4975d9 --- /dev/null +++ b/Common/Views.cpp @@ -0,0 +1,1489 @@ +// $Id: Views.cpp,v 1.195 2007-04-21 19:39:59 geuzaine 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>. +// +// Contributor(s): +// Nicolas Tardieu + +#include <set> +#include "Gmsh.h" +#include "Numeric.h" +#include "Views.h" +#include "Context.h" +#include "Options.h" +#include "ColorTable.h" +#include "SmoothData.h" +#include "BackgroundMesh.h" + +#if defined(HAVE_MATH_EVAL) +#include "matheval.h" +#endif + +extern Context_T CTX; + +#if defined(HAVE_FLTK) +void UpdateViewsInGUI(); +#endif + +// Static reference view + +Post_View *Post_ViewReference = NULL; + +// FIXME: the whole View interface should be rewritten in C++... + +int fcmpPostViewNum(const void *v1, const void *v2) +{ + return ((*(Post_View **) v1)->Num - (*(Post_View **) v2)->Num); +} + +int fcmpPostViewAliasOf(const void *v1, const void *v2) +{ + return ((*(Post_View **) v1)->AliasOf - (*(Post_View **) v2)->AliasOf); +} + +int fcmpPostViewName(const void *v1, const void *v2) +{ + return strcmp((*(Post_View **) v1)->Name, (*(Post_View **) v2)->Name); +} + +int fcmpPostViewVisibility(const void *v1, const void *v2) +{ + return ((*(Post_View **) v2)->Visible - (*(Post_View **) v1)->Visible); +} + +Post_View *BeginView(int allocate) +{ + Post_View *v = (Post_View *)Malloc(sizeof(Post_View)); + static int UniqueNum = 0; + + if(!CTX.post.list) + CTX.post.list = List_Create(100, 100, sizeof(Post_View *)); + + // Important notes: + // - each view *must* have a unique number + // - the view list is assumned to be sorted with increasing nums + + if(!CTX.post.force_num) { + v->Num = ++UniqueNum; + List_Add(CTX.post.list, &v); + } + else { + v->Num = CTX.post.force_num; + List_Replace(CTX.post.list, &v, fcmpPostViewNum); + // FIXME: need to check here if the old view is used as a field in + // a background mesh (and if it is, remove that field). Until we + // do this, let's just invalidate all the lc fields + BGMReset(); + } + + int i = List_ISearch(CTX.post.list, &v, fcmpPostViewNum); + List_Read(CTX.post.list, i, &v); + + v->Index = i; + v->Dirty = 1; + v->TriVertexArray = NULL; + v->LinVertexArray = NULL; + v->NbTimeStep = 1; + v->TimeStepMin = NULL; + v->TimeStepMax = NULL; + v->NbSP = v->NbVP = v->NbTP = 0; + v->NbSL = v->NbVL = v->NbTL = v->NbSL2 = v->NbVL2 = v->NbTL2 = 0; + v->NbST = v->NbVT = v->NbTT = v->NbST2 = v->NbVT2 = v->NbTT2 = 0; + v->NbSQ = v->NbVQ = v->NbTQ = v->NbSQ2 = v->NbVQ2 = v->NbTQ2 = 0; + v->NbSS = v->NbVS = v->NbTS = v->NbSS2 = v->NbVS2 = v->NbTS2 = 0; + v->NbSH = v->NbVH = v->NbTH = v->NbSH2 = v->NbVH2 = v->NbTH2 = 0; + v->NbSI = v->NbVI = v->NbTI = v->NbSI2 = v->NbVI2 = v->NbTI2 = 0; + v->NbSY = v->NbVY = v->NbTY = v->NbSY2 = v->NbVY2 = v->NbTY2 = 0; + v->NbT2 = v->NbT3 = 0; + + if(allocate) { + v->DataSize = sizeof(double); + v->Grains = new std::map < int , List_T * > ; + v->DisplayListsOfGrains= new std::map < int , int > ; + +#define LCD List_Create(1, 1000, sizeof(double)) + v->Time = LCD; + v->SP = LCD; v->VP = LCD; v->TP = LCD; + v->SL = LCD; v->VL = LCD; v->TL = LCD; v->SL2 = LCD; v->VL2 = LCD; v->TL2 = LCD; + v->ST = LCD; v->VT = LCD; v->TT = LCD; v->ST2 = LCD; v->VT2 = LCD; v->TT2 = LCD; + v->SQ = LCD; v->VQ = LCD; v->TQ = LCD; v->SQ2 = LCD; v->VQ2 = LCD; v->TQ2 = LCD; + v->SS = LCD; v->VS = LCD; v->TS = LCD; v->SS2 = LCD; v->VS2 = LCD; v->TS2 = LCD; + v->SH = LCD; v->VH = LCD; v->TH = LCD; v->SH2 = LCD; v->VH2 = LCD; v->TH2 = LCD; + v->SI = LCD; v->VI = LCD; v->TI = LCD; v->SI2 = LCD; v->VI2 = LCD; v->TI2 = LCD; + v->SY = LCD; v->VY = LCD; v->TY = LCD; v->SY2 = LCD; v->VY2 = LCD; v->TY2 = LCD; +#undef LCD + + v->T2D = List_Create(1, 100, sizeof(double)); + v->T2C = List_Create(1, 100, sizeof(char)); + v->T3D = List_Create(1, 100, sizeof(double)); + v->T3C = List_Create(1, 100, sizeof(char)); + } + else { + v->Time = NULL; + v->Grains = 0; + v->DisplayListsOfGrains = 0; + v->SP = v->VP = v->TP = NULL; + v->SL = v->VL = v->TL = v->SL2 = v->VL2 = v->TL2 = NULL; + v->ST = v->VT = v->TT = v->ST2 = v->VT2 = v->TT2 = NULL; + v->SQ = v->VQ = v->TQ = v->SQ2 = v->VQ2 = v->TQ2 = NULL; + v->SS = v->VS = v->TS = v->SS2 = v->VS2 = v->TS2 = NULL; + v->SH = v->VH = v->TH = v->SH2 = v->VH2 = v->TH2 = NULL; + v->SI = v->VI = v->TI = v->SI2 = v->VI2 = v->TI2 = NULL; + v->SY = v->VY = v->TY = v->SY2 = v->VY2 = v->TY2 = NULL; + v->T2D = v->T2C = NULL; + v->T3D = v->T3C = NULL; + } + + // Copy all options from the reference view initialized in InitOptions() + CopyViewOptions(Post_ViewReference, v); + + v->Changed = 1; + v->Links = 0; + v->AliasOf = 0; + v->ScalarOnly = 1; + v->TextOnly = 1; + v->normals = new smooth_normals(v->AngleSmoothNormals); + v->Min = VAL_INF; + v->Max = -VAL_INF; + v->adaptive = 0; + for(i = 0; i < 3; i++) { + v->BBox[2 * i] = v->TmpBBox[2 * i] = VAL_INF; + v->BBox[2 * i + 1] = v->TmpBBox[2 * i + 1] = -VAL_INF; + } + for(i = 0; i < 3; i++) + v->GenRaise_f[i] = NULL; + + return v; +} + +void Post_View::reset_normals() +{ + if(normals) + delete normals; + normals = new smooth_normals(AngleSmoothNormals); +} + +double ComputeVonMises(double *V) +{ + static const double THIRD = 1.e0 / 3.e0; + double tr = (V[0] + V[4] + V[8]) * THIRD; + double v11 = V[0] - tr; + double v12 = V[1]; + double v13 = V[2]; + double v21 = V[3]; + double v22 = V[4] - tr; + double v23 = V[5]; + double v31 = V[6]; + double v32 = V[7]; + double v33 = V[8] - tr; + return sqrt(1.5 * (v11 * v11 + v12 * v12 + v13 * v13 + + v21 * v21 + v22 * v22 + v23 * v23 + + v31 * v31 + v32 * v32 + v33 * v33)); +} + +void Stat_Element(Post_View *v, int type, int nbnod, int N, + double *X, double *Y, double *Z, double *V) +{ + int i; + double l0; + + switch (type) { + + case 0: // scalar + if(v->Min == VAL_INF || v->Max == -VAL_INF) { + v->NbTimeStep = N / nbnod; + if(v->TimeStepMin) Free(v->TimeStepMin); + if(v->TimeStepMax) Free(v->TimeStepMax); + v->TimeStepMin = (double*)Malloc(v->NbTimeStep * sizeof(double)); + v->TimeStepMax = (double*)Malloc(v->NbTimeStep * sizeof(double)); + for(i = 0; i < v->NbTimeStep; i++){ + v->TimeStepMin[i] = VAL_INF; + v->TimeStepMax[i] = -VAL_INF; + } + } + else if(N / nbnod < v->NbTimeStep){ + // if some elts have less steps, reduce the total number! + v->NbTimeStep = N / nbnod; + } + + for(i = 0; i < N; i++) { + l0 = V[i]; + if(l0 < v->Min) + v->Min = l0; + if(l0 > v->Max) + v->Max = l0; + int ts = i / nbnod; + if(ts < v->NbTimeStep){ // security + if(l0 < v->TimeStepMin[ts]) + v->TimeStepMin[ts] = l0; + if(l0 > v->TimeStepMax[ts]) + v->TimeStepMax[ts] = l0; + } + } + break; + + case 1: // vector + if(v->Min == VAL_INF || v->Max == -VAL_INF) { + v->NbTimeStep = N / (3 * nbnod); + if(v->TimeStepMin) Free(v->TimeStepMin); + if(v->TimeStepMax) Free(v->TimeStepMax); + v->TimeStepMin = (double*)Malloc(v->NbTimeStep * sizeof(double)); + v->TimeStepMax = (double*)Malloc(v->NbTimeStep * sizeof(double)); + for(i = 0; i < v->NbTimeStep; i++){ + v->TimeStepMin[i] = VAL_INF; + v->TimeStepMax[i] = -VAL_INF; + } + } + else if(N / (3 * nbnod) < v->NbTimeStep){ + v->NbTimeStep = N / (3 * nbnod); + } + + for(i = 0; i < N; i += 3) { + l0 = sqrt(DSQR(V[i]) + DSQR(V[i + 1]) + DSQR(V[i + 2])); + if(l0 < v->Min) + v->Min = l0; + if(l0 > v->Max) + v->Max = l0; + int ts = i / (3 * nbnod); + if(ts < v->NbTimeStep){ // security + if(l0 < v->TimeStepMin[ts]) + v->TimeStepMin[ts] = l0; + if(l0 > v->TimeStepMax[ts]) + v->TimeStepMax[ts] = l0; + } + } + v->ScalarOnly = 0; + break; + + case 2: // tensor + if(v->Min == VAL_INF || v->Max == -VAL_INF) { + v->NbTimeStep = N / (9 * nbnod); + if(v->TimeStepMin) Free(v->TimeStepMin); + if(v->TimeStepMax) Free(v->TimeStepMax); + v->TimeStepMin = (double*)Malloc(v->NbTimeStep * sizeof(double)); + v->TimeStepMax = (double*)Malloc(v->NbTimeStep * sizeof(double)); + for(i = 0; i < v->NbTimeStep; i++){ + v->TimeStepMin[i] = VAL_INF; + v->TimeStepMax[i] = -VAL_INF; + } + } + else if(N / (9 * nbnod) < v->NbTimeStep){ + v->NbTimeStep = N / (9 * nbnod); + } + + for(i = 0; i < N; i += 9) { + // by lack of any current better solution, tensors are displayed + // as their Von Mises invariant (J2 invariant) + l0 = ComputeVonMises(V+i); + if(l0 < v->Min) + v->Min = l0; + if(l0 > v->Max) + v->Max = l0; + int ts = i / (9 * nbnod); + if(ts < v->NbTimeStep){ // security + if(l0 < v->TimeStepMin[ts]) + v->TimeStepMin[ts] = l0; + if(l0 > v->TimeStepMax[ts]) + v->TimeStepMax[ts] = l0; + } + } + v->ScalarOnly = 0; + break; + + } + + for(i = 0; i < nbnod; i++) { + if(X[i] < v->BBox[0]) v->BBox[0] = X[i]; + if(X[i] > v->BBox[1]) v->BBox[1] = X[i]; + if(Y[i] < v->BBox[2]) v->BBox[2] = Y[i]; + if(Y[i] > v->BBox[3]) v->BBox[3] = Y[i]; + if(Z[i] < v->BBox[4]) v->BBox[4] = Z[i]; + if(Z[i] > v->BBox[5]) v->BBox[5] = Z[i]; + } + + v->TextOnly = 0; +} + +void Stat_List(Post_View * v, List_T * listelm, int type, int nbelm, + int nbnod) +{ + int i, nb; + if(nbelm) { + nb = List_Nbr(listelm) / nbelm; + for(i = 0; i < List_Nbr(listelm); i += nb) + Stat_Element(v, type, nbnod, nb - 3 * nbnod, + (double *)List_Pointer_Fast(listelm, i), + (double *)List_Pointer_Fast(listelm, i + 1 * nbnod), + (double *)List_Pointer_Fast(listelm, i + 2 * nbnod), + (double *)List_Pointer_Fast(listelm, i + 3 * nbnod)); + } +} + +void Stat_Text(Post_View * v, List_T *D, List_T *C, int nb) +{ + for(int i = 0; i < List_Nbr(D); i += nb){ + double beg, end; + List_Read(D, i+nb-1, &beg); + if(i > List_Nbr(D) - 2*nb) + end = (double)List_Nbr(C); + else + List_Read(D, i+nb+nb-1, &end); + char *c = (char*)List_Pointer(C, (int)beg); + int nbtime = 0; + for(int j = 0; j < (int)(end-beg); j++) + if(c[j] == '\0') nbtime++; + if(nbtime > v->NbTimeStep) + v->NbTimeStep = nbtime; + } + + if(nb == 5){ + for(int i = 0; i < List_Nbr(D); i += nb){ + double x, y, z; + List_Read(D, i, &x); + List_Read(D, i+1, &y); + List_Read(D, i+2, &z); + if(x < v->BBox[0]) v->BBox[0] = x; + if(x > v->BBox[1]) v->BBox[1] = x; + if(y < v->BBox[2]) v->BBox[2] = y; + if(y > v->BBox[3]) v->BBox[3] = y; + if(z < v->BBox[4]) v->BBox[4] = z; + if(z > v->BBox[5]) v->BBox[5] = z; + } + } +} + +void EndView(Post_View * v, int add_in_gui, char *file_name, char *name) +{ + int i; + double d; + + // Stat text strings first, to get the max value of NbTimeStep for + // srings-only (strings are designed to degrade gracefully when some + // have fewer time steps than others). If there are any elements in + // the view, this value will be replaced by the minimum number of + // time steps common to all elements. + Stat_Text(v, v->T2D, v->T2C, 4); + Stat_Text(v, v->T3D, v->T3C, 5); + + // convert all curved (geometrically 2nd order) elements into linear + // elements *AND* free all the data associated with the curved + // elements + v->splitCurvedElements(); + + // Points + Stat_List(v, v->SP, 0, v->NbSP, 1); + Stat_List(v, v->VP, 1, v->NbVP, 1); + Stat_List(v, v->TP, 2, v->NbTP, 1); + + // Lines + Stat_List(v, v->SL, 0, v->NbSL, 2); + Stat_List(v, v->VL, 1, v->NbVL, 2); + Stat_List(v, v->TL, 2, v->NbTL, 2); + + // Triangles + Stat_List(v, v->ST, 0, v->NbST, 3); + Stat_List(v, v->VT, 1, v->NbVT, 3); + Stat_List(v, v->TT, 2, v->NbTT, 3); + + // Quadrangles + Stat_List(v, v->SQ, 0, v->NbSQ, 4); + Stat_List(v, v->VQ, 1, v->NbVQ, 4); + Stat_List(v, v->TQ, 2, v->NbTQ, 4); + + // Tetrahedra + Stat_List(v, v->SS, 0, v->NbSS, 4); + Stat_List(v, v->VS, 1, v->NbVS, 4); + Stat_List(v, v->TS, 2, v->NbTS, 4); + + // Hexahedra + Stat_List(v, v->SH, 0, v->NbSH, 8); + Stat_List(v, v->VH, 1, v->NbVH, 8); + Stat_List(v, v->TH, 2, v->NbTH, 8); + + // Prisms + Stat_List(v, v->SI, 0, v->NbSI, 6); + Stat_List(v, v->VI, 1, v->NbVI, 6); + Stat_List(v, v->TI, 2, v->NbTI, 6); + + // Pyramids + Stat_List(v, v->SY, 0, v->NbSY, 5); + Stat_List(v, v->VY, 1, v->NbVY, 5); + Stat_List(v, v->TY, 2, v->NbTY, 5); + + // Dummy time values if none (or too few) provided (e.g. using old + // parsed format) + if(v->Time && List_Nbr(v->Time) < v->NbTimeStep) { + for(i = List_Nbr(v->Time); i < v->NbTimeStep; i++) { + d = (double)i; + List_Add(v->Time, &d); + } + } + + opt_view_name(v->Index, GMSH_SET | GMSH_GUI, name); + opt_view_filename(v->Index, GMSH_SET | GMSH_GUI, file_name); + opt_view_nb_timestep(v->Index, GMSH_GUI, 0); + opt_view_timestep(v->Index, GMSH_SET | GMSH_GUI, v->TimeStep); + + if(CTX.post.smooth) + v->smooth(); + +#if defined(HAVE_FLTK) + if(add_in_gui) + UpdateViewsInGUI(); +#endif + + v->Dirty = 0; //the view is complete, we may draw it + + Msg(DEBUG, "Added View[%d]", v->Index); +} + +void AliasView(int index, int withoptions) +{ + if(index < 0 || index >= List_Nbr(CTX.post.list)) { + return; + } + + Post_View v, *pv, **ppv; + + Post_View *v1 = *(Post_View **) List_Pointer(CTX.post.list, index); + + Post_View *v2 = BeginView(0); + EndView(v2, 0, v1->FileName, v1->Name); + + if(!v1->AliasOf) { + v2->AliasOf = v1->Num; + v1->Links++; + } + else { + v.Num = v1->AliasOf; + pv = &v; + if(!(ppv = (Post_View **) List_PQuery(CTX.post.list, &pv, fcmpPostViewNum))) { + v2->AliasOf = v1->Num; + v1->Links++; + } + else { + v2->AliasOf = (*ppv)->Num; + (*ppv)->Links++; + } + } + + // When we create an alias we just point to a reference view: we + // DON'T allocate a new data set! + v2->Time = v1->Time; + v2->TimeStepMin = v1->TimeStepMin; + v2->TimeStepMax = v1->TimeStepMax; + + v2->NbSP = v1->NbSP; v2->SP = v1->SP; + v2->NbVP = v1->NbVP; v2->VP = v1->VP; + v2->NbTP = v1->NbTP; v2->TP = v1->TP; + + v2->NbSL = v1->NbSL; v2->SL = v1->SL; + v2->NbVL = v1->NbVL; v2->VL = v1->VL; + v2->NbTL = v1->NbTL; v2->TL = v1->TL; + + v2->NbST = v1->NbST; v2->ST = v1->ST; + v2->NbVT = v1->NbVT; v2->VT = v1->VT; + v2->NbTT = v1->NbTT; v2->TT = v1->TT; + + v2->NbSQ = v1->NbSQ; v2->SQ = v1->SQ; + v2->NbVQ = v1->NbVQ; v2->VQ = v1->VQ; + v2->NbTQ = v1->NbTQ; v2->TQ = v1->TQ; + + v2->NbSS = v1->NbSS; v2->SS = v1->SS; + v2->NbVS = v1->NbVS; v2->VS = v1->VS; + v2->NbTS = v1->NbTS; v2->TS = v1->TS; + + v2->NbSH = v1->NbSH; v2->SH = v1->SH; + v2->NbVH = v1->NbVH; v2->VH = v1->VH; + v2->NbTH = v1->NbTH; v2->TH = v1->TH; + + v2->NbSI = v1->NbSI; v2->SI = v1->SI; + v2->NbVI = v1->NbVI; v2->VI = v1->VI; + v2->NbTI = v1->NbTI; v2->TI = v1->TI; + + v2->NbSY = v1->NbSY; v2->SY = v1->SY; + v2->NbVY = v1->NbVY; v2->VY = v1->VY; + v2->NbTY = v1->NbTY; v2->TY = v1->TY; + + v2->NbT2 = v1->NbT2; v2->T2D = v1->T2D; v2->T2C = v1->T2C; + v2->NbT3 = v1->NbT3; v2->T3D = v1->T3D; v2->T3C = v1->T3C; + + v2->DataSize = v1->DataSize; + v2->ScalarOnly = v1->ScalarOnly; + v2->TextOnly = v1->TextOnly; + v2->Min = v1->Min; + v2->Max = v1->Max; + v2->NbTimeStep = v1->NbTimeStep; + for(int i=0 ; i<6 ; i++) + v2->BBox[i] = v1->BBox[i]; + + if(withoptions) + CopyViewOptions(v1, v2); + +#if defined(HAVE_FLTK) + UpdateViewsInGUI(); +#endif +} + +bool RemoveViewByIndex(int index) +{ + if(index < 0 || index >= List_Nbr(CTX.post.list)) { + return false; + } + + Post_View *v = *(Post_View **) List_Pointer(CTX.post.list, index); + FreeView(v); + List_PSuppress(CTX.post.list, index); + + // recalculate the indices + for(int i = 0; i < List_Nbr(CTX.post.list); i++){ + v = *(Post_View **) List_Pointer(CTX.post.list, i); + v->Index = i; + } + + Msg(DEBUG, "Removed View[%d] (%d views left)", index, List_Nbr(CTX.post.list)); + return true; +} + +bool RemoveViewByNumber(int num) +{ + Post_View v, *pv; + + v.Num = num; + pv = &v; + int i = List_ISearch(CTX.post.list, &pv, fcmpPostViewNum); + + return RemoveViewByIndex(i); +} + +void FreeView(Post_View * v) +{ + Post_View vv, *pvv, **ppvv; + int i, numdup, free = 1; + + if(v->AliasOf) { + vv.Num = v->AliasOf; + pvv = &vv; + Msg(DEBUG, "This view is a duplicata"); + if(!(ppvv = (Post_View **) List_PQuery(CTX.post.list, &pvv, fcmpPostViewNum))) { + Msg(DEBUG, " -the original view is gone"); + numdup = 0; + for(i = 0; i < List_Nbr(CTX.post.list); i++) + numdup += ((*(Post_View **) List_Pointer(CTX.post.list, i))->AliasOf + == v->AliasOf); + if(numdup == 1) { + Msg(DEBUG, " -there are no other duplicata, so I can free"); + free = 1; + } + else { + Msg(DEBUG, " -there are still duplicata, so I cannot free"); + free = 0; + } + } + else { + (*ppvv)->Links--; + free = 0; + Msg(DEBUG, " -the original still exists, so I cannot free"); + } + } + + if(free && !v->Links) { + Msg(DEBUG, "Freeing View!"); + List_Delete(v->Time); + Free(v->TimeStepMin); + Free(v->TimeStepMax); + List_Delete(v->SP); List_Delete(v->VP); List_Delete(v->TP); + List_Delete(v->SL); List_Delete(v->VL); List_Delete(v->TL); + List_Delete(v->ST); List_Delete(v->VT); List_Delete(v->TT); + List_Delete(v->SQ); List_Delete(v->VQ); List_Delete(v->TQ); + List_Delete(v->SS); List_Delete(v->VS); List_Delete(v->TS); + List_Delete(v->SH); List_Delete(v->VH); List_Delete(v->TH); + List_Delete(v->SI); List_Delete(v->VI); List_Delete(v->TI); + List_Delete(v->SY); List_Delete(v->VY); List_Delete(v->TY); + List_Delete(v->T2D); List_Delete(v->T2C); + List_Delete(v->T3D); List_Delete(v->T3C); + delete v->Grains; + delete v->DisplayListsOfGrains; + // Note: all the second order elements have already been freed in xxxx + if(v->normals) delete v->normals; + if(v->TriVertexArray) delete v->TriVertexArray; + if(v->LinVertexArray) delete v->LinVertexArray; + if(v->adaptive) delete v->adaptive; + FreeGeneralizedRaise(v); + Free(v); + } +} + +void CopyViewOptions(Post_View * src, Post_View * dest) +{ + dest->Type = src->Type; + dest->AutoPosition = src->AutoPosition; + dest->AxesAutoPosition = src->AxesAutoPosition; + dest->Position[0] = src->Position[0]; + dest->Position[1] = src->Position[1]; + dest->Size[0] = src->Size[0]; + dest->Size[1] = src->Size[1]; + for(int i = 0; i < 6; i++) dest->AxesPosition[i] = src->AxesPosition[i]; + for(int i = 0; i < 3; i++) dest->AxesTics[i] = src->AxesTics[i]; + strcpy(dest->Format, src->Format); + for(int i = 0; i < 3; i++) strcpy(dest->AxesFormat[i], src->AxesFormat[i]); + for(int i = 0; i < 3; i++) strcpy(dest->AxesLabel[i], src->AxesLabel[i]); + dest->CustomMin = src->CustomMin; + dest->CustomMax = src->CustomMax; + dest->Offset[0] = src->Offset[0]; + dest->Offset[1] = src->Offset[1]; + dest->Offset[2] = src->Offset[2]; + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) + dest->Transform[i][j] = src->Transform[i][j]; + dest->Raise[0] = src->Raise[0]; + dest->Raise[1] = src->Raise[1]; + dest->Raise[2] = src->Raise[2]; + dest->ArrowSize = src->ArrowSize; + dest->ArrowSizeProportional = src->ArrowSizeProportional; + dest->ArrowRelHeadRadius = src->ArrowRelHeadRadius; + dest->ArrowRelStemLength = src->ArrowRelStemLength; + dest->ArrowRelStemRadius = src->ArrowRelStemRadius; + dest->Normals = src->Normals; + dest->Tangents = src->Tangents; + dest->DisplacementFactor = src->DisplacementFactor; + dest->Explode = src->Explode; + dest->Visible = src->Visible; + dest->IntervalsType = src->IntervalsType; + dest->SaturateValues = src->SaturateValues; + dest->Boundary = src->Boundary; + dest->NbIso = src->NbIso; + dest->Light = src->Light; + dest->LightTwoSide = src->LightTwoSide; + dest->LightLines = src->LightLines; + dest->SmoothNormals = src->SmoothNormals; + dest->AngleSmoothNormals = src->AngleSmoothNormals; + dest->ShowElement = src->ShowElement; + dest->ShowTime = src->ShowTime; + dest->ShowScale = src->ShowScale; + dest->DrawPoints = src->DrawPoints; + dest->DrawLines = src->DrawLines; + dest->DrawTriangles = src->DrawTriangles; + dest->DrawQuadrangles = src->DrawQuadrangles; + dest->DrawTetrahedra = src->DrawTetrahedra; + dest->DrawHexahedra = src->DrawHexahedra; + dest->DrawPrisms = src->DrawPrisms; + dest->DrawPyramids = src->DrawPyramids; + dest->DrawScalars = src->DrawScalars; + dest->DrawVectors = src->DrawVectors; + dest->DrawTensors = src->DrawTensors; + dest->DrawStrings = src->DrawStrings; + dest->ScaleType = src->ScaleType; + dest->RangeType = src->RangeType; + dest->VectorType = src->VectorType; + dest->GlyphLocation = src->GlyphLocation; + dest->TensorType = src->TensorType; + dest->TimeStep = src->TimeStep; + dest->PointSize = src->PointSize; + dest->LineWidth = src->LineWidth; + dest->PointType = src->PointType; + dest->LineType = src->LineType; + dest->Axes = src->Axes; + dest->ExternalViewIndex = src->ExternalViewIndex; + dest->ViewIndexForGenRaise = src->ViewIndexForGenRaise; + dest->UseGenRaise = src->UseGenRaise; + dest->FakeTransparency = src->FakeTransparency; + dest->GenRaiseFactor = src->GenRaiseFactor; + strcpy(dest->GenRaiseX, src->GenRaiseX); + strcpy(dest->GenRaiseY, src->GenRaiseY); + strcpy(dest->GenRaiseZ, src->GenRaiseZ); + dest->UseStipple = src->UseStipple; + for(int i = 0; i < 10; i++){ + dest->Stipple[i][0] = src->Stipple[i][0]; + dest->Stipple[i][1] = src->Stipple[i][1]; + strcpy(dest->StippleString[i], src->StippleString[i]); + } + dest->color.point = src->color.point; + dest->color.line = src->color.line; + dest->color.triangle = src->color.triangle; + dest->color.quadrangle = src->color.quadrangle; + dest->color.tetrahedron = src->color.tetrahedron; + dest->color.hexahedron = src->color.hexahedron; + dest->color.prism = src->color.prism; + dest->color.pyramid = src->color.pyramid; + dest->color.tangents = src->color.tangents; + dest->color.normals = src->color.normals; + dest->color.text2d = src->color.text2d; + dest->color.text3d = src->color.text3d; + dest->color.axes = src->color.axes; + ColorTable_Copy(&src->CT); + ColorTable_Paste(&dest->CT); +} + +GmshColorTable *Get_ColorTable(int num) +{ + Post_View *v; + + if(!CTX.post.list){ + v = Post_ViewReference; + if(!v) return NULL; + } + else{ + Post_View **vv = (Post_View **) List_Pointer_Test(CTX.post.list, num); + if(!vv) return NULL; + v = *vv; + } + v->Changed = 1; // let's assume that if we get the ct we change it + return &v->CT; +} + +void Print_ColorTable(int num, int diff, char *prefix, FILE * file) +{ + char tmp[1024]; + Post_View *v; + + if(!CTX.post.list){ + v = Post_ViewReference; + if(!v) return; + } + else{ + Post_View **vv = (Post_View **) List_Pointer_Test(CTX.post.list, num); + if(!vv) return; + v = *vv; + } + + if(diff){ + // compare the current colormap with a vanilla colormap having the + // parameters + GmshColorTable ref; + ColorTable_InitParam(v->CT.ipar[COLORTABLE_NUMBER], &ref); + for(int i = 0; i < COLORTABLE_NBMAX_PARAM; i++){ + ref.ipar[i] = v->CT.ipar[i]; + ref.dpar[i] = v->CT.dpar[i]; + } + ColorTable_Recompute(&ref); + if(!ColorTable_Diff(&ref, &v->CT)) + return; + } + + sprintf(tmp, "%s = {", prefix); + if(file) + fprintf(file, "%s\n", tmp); + else + Msg(DIRECT, tmp); + ColorTable_Print(&v->CT, file); + sprintf(tmp, "};"); + if(file) + fprintf(file, "%s\n", tmp); + else + Msg(DIRECT, tmp); +} + +Post_View *Create2DGraph(char *xname, char *yname, + int nbdata, double *x, double *y) +{ + Post_View *v = BeginView(1); + for(int i = 0; i < nbdata; i++) { + double d; + if(x){ + List_Add(v->SP, &x[i]); + } + else{ + d = nbdata > 1 ? (double)i/(double)(nbdata - 1) : 0; + List_Add(v->SP, &d); + } + d = 0.; + List_Add(v->SP, &d); + List_Add(v->SP, &d); + List_Add(v->SP, &y[i]); + v->NbSP++; + } + char filename[1024]; + sprintf(filename, "%s.pos", yname); + EndView(v, 1, filename, yname); + v->Type = DRAW_POST_2D_SPACE; + v->Axes = 2; + strcpy(v->AxesLabel[0], xname); + return v; +} + +// Transform curved elements into linear ones and delete all the +// curved element data. This is a temporary solution, until we can use +// an Adaptive_Post_View on curved elements, too. + +void splitCurvedElement(List_T **in, int *nbin, List_T *out, int *nbout, + int nodin, int nodout, int nbcomp, int nbsplit, int split[][8], + int remove=1) +{ + if(*nbin){ + int nb = List_Nbr(*in) / *nbin; + int nbstep = (nb - 3 * nodin) / (nodin * nbcomp); // we don't know this yet for the view + for(int i = 0; i < List_Nbr(*in); i += nb) { + double *coord = (double *)List_Pointer_Fast(*in, i); + double *val = (double *)List_Pointer_Fast(*in, i + 3 * nodin); + for(int j = 0; j < nbsplit; j++){ + for(int k = 0; k < nodout; k++) + List_Add(out, &coord[split[j][k]]); + for(int k = 0; k < nodout; k++) + List_Add(out, &coord[nodin + split[j][k]]); + for(int k = 0; k < nodout; k++) + List_Add(out, &coord[2 * nodin + split[j][k]]); + for(int ts = 0; ts < nbstep; ts++){ + for(int k = 0; k < nodout; k++){ + for(int l = 0; l < nbcomp; l++){ + List_Add(out, &val[nodin * nbcomp * ts + nbcomp * split[j][k] + l]); + } + } + } + (*nbout)++; + } + } + } + + if(remove){ + *nbin = 0; + List_Delete(*in); + *in = NULL; + } +} + +void Post_View::splitCurvedElements() +{ + // we could keep track of the starting index in SL, VL, ..., so that + // we could draw the boundaries correctly + + int lin[2][8] = { // 2-split + {0,2}, {2,1} + }; + splitCurvedElement(&SL2, &NbSL2, SL, &NbSL, 3,2, 1, 2, lin); + splitCurvedElement(&VL2, &NbVL2, VL, &NbVL, 3,2, 3, 2, lin); + splitCurvedElement(&TL2, &NbTL2, TL, &NbTL, 3,2, 9, 2, lin); + + int tri[4][8] = { // 4-split + {0,3,5}, {1,4,3}, {2,5,4}, {3,4,5} + }; + splitCurvedElement(&ST2, &NbST2, ST, &NbST, 6,3, 1, 4, tri); + splitCurvedElement(&VT2, &NbVT2, VT, &NbVT, 6,3, 3, 4, tri); + splitCurvedElement(&TT2, &NbTT2, TT, &NbTT, 6,3, 9, 4, tri); + + int qua[4][8] = { // 4-split + {0,4,8,7}, {1,5,8,4}, {2,6,8,5}, {3,7,8,6} + }; + splitCurvedElement(&SQ2, &NbSQ2, SQ, &NbSQ, 9,4, 1, 4, qua); + splitCurvedElement(&VQ2, &NbVQ2, VQ, &NbVQ, 9,4, 3, 4, qua); + splitCurvedElement(&TQ2, &NbTQ2, TQ, &NbTQ, 9,4, 9, 4, qua); + + int tet[8][8] = { // 8-split + {0,4,6,7}, {1,5,4,9}, {2,6,5,8}, {3,9,7,8}, + {4,6,7,8}, {4,6,5,8}, {4,5,9,8}, {4,7,9,8} + }; + splitCurvedElement(&SS2, &NbSS2, SS, &NbSS, 10,4, 1, 8, tet); + splitCurvedElement(&VS2, &NbVS2, VS, &NbVS, 10,4, 3, 8, tet); + splitCurvedElement(&TS2, &NbTS2, TS, &NbTS, 10,4, 9, 8, tet); + + int hex[8][8] = { // 8-split + {0,8,20,9, 10,21,26,22}, {8,1,11,20, 21,12,23,26}, + {9,20,13,3, 22,26,24,15}, {20,11,2,13, 26,23,14,24}, + {10,21,26,22, 4,16,25,17}, {21,12,23,26, 16,5,18,25}, + {22,26,24,15, 17,25,19,7}, {26,23,14,24, 25,18,6,19} + }; + splitCurvedElement(&SH2, &NbSH2, SH, &NbSH, 27,8, 1, 8, hex); + splitCurvedElement(&VH2, &NbVH2, VH, &NbVH, 27,8, 3, 8, hex); + splitCurvedElement(&TH2, &NbTH2, TH, &NbTH, 27,8, 9, 8, hex); + + int pri[8][8] = { // 8-split + {0,6,7, 8,15,16}, {1,9,6, 10,17,15}, {2,7,9, 11,16,17}, {6,9,7, 15,17,16}, + {8,15,16, 3,12,13}, {10,17,15, 4,14,12}, {11,16,17, 5,13,14}, {15,17,16, 12,14,13} + }; + splitCurvedElement(&SI2, &NbSI2, SI, &NbSI, 18,6, 1, 8, pri); + splitCurvedElement(&VI2, &NbVI2, VI, &NbVI, 18,6, 3, 8, pri); + splitCurvedElement(&TI2, &NbTI2, TI, &NbTI, 18,6, 9, 8, pri); + + int pyr[6][8] = { // 6 pyramids + {0,5,13,6, 7}, {5,1,8,13, 9}, {6,13,10,3, 12}, {13,8,2,10, 11}, + {7,9,11,12, 4}, {7,12,11,9, 13} + }; + splitCurvedElement(&SY2, &NbSY2, SY, &NbSY, 14,5, 1, 6, pyr, 0); // don't remove yet + splitCurvedElement(&VY2, &NbVY2, VY, &NbVY, 14,5, 3, 6, pyr, 0); + splitCurvedElement(&TY2, &NbTY2, TY, &NbTY, 14,5, 9, 6, pyr, 0); + + int pyr2[4][8] = { // + 4 tets to fill the holes + {6,12,7,13}, {7,9,5,13}, {9,11,8,13}, {12,10,11,13} + }; + splitCurvedElement(&SY2, &NbSY2, SS, &NbSS, 14,4, 1, 4, pyr2); + splitCurvedElement(&VY2, &NbVY2, VS, &NbVS, 14,4, 3, 4, pyr2); + splitCurvedElement(&TY2, &NbTY2, TS, &NbTS, 14,4, 9, 4, pyr2); +} + +// Smoothing + +void generate_connectivities(List_T *list, int nbList, + int nbTimeStep, int nbVert, smooth_data &data) +{ + if(!nbList) return; + + double *vals = new double[nbTimeStep]; + int nb = List_Nbr(list) / nbList; + for(int i = 0; i < List_Nbr(list); i += nb) { + double *x = (double *)List_Pointer_Fast(list, i); + double *y = (double *)List_Pointer_Fast(list, i + nbVert); + double *z = (double *)List_Pointer_Fast(list, i + 2 * nbVert); + double *v = (double *)List_Pointer_Fast(list, i + 3 * nbVert); + for(int j = 0; j < nbVert; j++) { + for(int k = 0; k < nbTimeStep; k++) + vals[k] = v[j + k * nbVert]; + data.add(x[j], y[j], z[j], nbTimeStep, vals); + } + } + delete [] vals; +} + +void smooth_list(List_T *list, int nbList, + double *min, double *max, double *tsmin, double *tsmax, + int nbTimeStep, int nbVert, smooth_data &data) +{ + if(!nbList) + return; + + double *vals = new double[nbTimeStep]; + int nb = List_Nbr(list)/nbList; + for(int i = 0; i < List_Nbr(list); i += nb) { + double *x = (double *)List_Pointer_Fast(list, i); + double *y = (double *)List_Pointer_Fast(list, i + nbVert); + double *z = (double *)List_Pointer_Fast(list, i + 2 * nbVert); + double *v = (double *)List_Pointer_Fast(list, i + 3 * nbVert); + for(int j = 0; j < nbVert; j++) { + if(data.get(x[j], y[j], z[j], nbTimeStep, vals)){ + for(int k = 0; k < nbTimeStep; k++) { + double dd = vals[k]; + v[j + k * nbVert] = dd; + if(dd < *min) *min = dd; + if(dd > *max) *max = dd; + if(dd < tsmin[k]) tsmin[k] = dd; + if(dd > tsmax[k]) tsmax[k] = dd; + } + } + } + } + delete [] vals; +} + +void Post_View::smooth() +{ + double old_eps = xyzv::eps; + xyzv::eps = CTX.lc * 1.e-8; + + if(NbSL || NbST || NbSQ || NbSS || NbSH || NbSI || NbSY) { + Msg(INFO, "Smoothing scalar primitives in View[%d]", Index); + Min = VAL_INF; + Max = -VAL_INF; + for(int k = 0; k < NbTimeStep; k++) { + TimeStepMin[k] = VAL_INF; + TimeStepMax[k] = -VAL_INF; + } + smooth_data data; + generate_connectivities(SL, NbSL, NbTimeStep, 2, data); + generate_connectivities(ST, NbST, NbTimeStep, 3, data); + generate_connectivities(SQ, NbSQ, NbTimeStep, 4, data); + generate_connectivities(SS, NbSS, NbTimeStep, 4, data); + generate_connectivities(SH, NbSH, NbTimeStep, 8, data); + generate_connectivities(SI, NbSI, NbTimeStep, 6, data); + generate_connectivities(SY, NbSY, NbTimeStep, 5, data); + smooth_list(SL, NbSL, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 2, data); + smooth_list(ST, NbST, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 3, data); + smooth_list(SQ, NbSQ, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 4, data); + smooth_list(SS, NbSS, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 4, data); + smooth_list(SH, NbSH, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 8, data); + smooth_list(SI, NbSI, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 6, data); + smooth_list(SY, NbSY, &Min, &Max, TimeStepMin, TimeStepMax, NbTimeStep, 5, data); + Changed = 1; + } + + xyzv::eps = old_eps; +} + +// Combine views (merge elements or merge time steps) + +struct nameidx{ + char name[256]; + List_T *indices; +}; + +static int fcmp_name(const void *a, const void *b){ + char *name1 = ((struct nameidx*)a)->name; + char *name2 = ((struct nameidx*)b)->name; + return strcmp(name1, name2); +} + +static void combine(List_T * a, List_T * b) +{ + if(!a || !b) + return; + for(int i = 0; i < List_Nbr(a); i++) { + List_Add(b, List_Pointer(a, i)); + } +} + +static void combine_strings(Post_View *a, Post_View *b) +{ + for(int i = 0; i < List_Nbr(a->T2D); i+=4){ + List_Add(b->T2D, List_Pointer(a->T2D, i)); + List_Add(b->T2D, List_Pointer(a->T2D, i+1)); + List_Add(b->T2D, List_Pointer(a->T2D, i+2)); + double d = List_Nbr(b->T2C); + List_Add(b->T2D, &d); + double beg, end; + List_Read(a->T2D, i+3, &beg); + if(i > List_Nbr(a->T2D) - 8) + end = (double)List_Nbr(a->T2C); + else + List_Read(a->T2D, i+3+4, &end); + char *c = (char*)List_Pointer(a->T2C, (int)beg); + for(int j = 0; j < (int)(end-beg); j++) + List_Add(b->T2C, &c[j]); + b->NbT2++; + } + for(int i = 0; i < List_Nbr(a->T3D); i+=5){ + List_Add(b->T3D, List_Pointer(a->T3D, i)); + List_Add(b->T3D, List_Pointer(a->T3D, i+1)); + List_Add(b->T3D, List_Pointer(a->T3D, i+2)); + List_Add(b->T3D, List_Pointer(a->T3D, i+3)); + double d = List_Nbr(b->T3C); + List_Add(b->T3D, &d); + double beg, end; + List_Read(a->T3D, i+4, &beg); + if(i > List_Nbr(a->T3D) - 10) + end = (double)List_Nbr(a->T3C); + else + List_Read(a->T3D, i+4+5, &end); + char *c = (char*)List_Pointer(a->T3C, (int)beg); + for(int j = 0; j < (int)(end-beg); j++) + List_Add(b->T3C, &c[j]); + b->NbT3++; + } +} + +static void combine_space(struct nameidx *id, List_T *to_remove) +{ + int index; + + // sanity check + int nbt = 0; + for(int i = 0; i < List_Nbr(id->indices); i++) { + List_Read(id->indices, i, &index); + Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, index); + if(!i){ + nbt = v->NbTimeStep; + } + else{ + if(v->NbTimeStep != nbt){ + Msg(GERROR, "Cannot combine views having different number of time steps"); + return; + } + } + } + + Post_View *vm = BeginView(1); + for(int i = 0; i < List_Nbr(id->indices); i++) { + List_Read(id->indices, i, &index); + Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, index); + List_Insert(to_remove, &v->Num, fcmp_int); + combine(v->SP,vm->SP); vm->NbSP += v->NbSP; + combine(v->VP,vm->VP); vm->NbVP += v->NbVP; + combine(v->TP,vm->TP); vm->NbTP += v->NbTP; + combine(v->SL,vm->SL); vm->NbSL += v->NbSL; + combine(v->VL,vm->VL); vm->NbVL += v->NbVL; + combine(v->TL,vm->TL); vm->NbTL += v->NbTL; + combine(v->ST,vm->ST); vm->NbST += v->NbST; + combine(v->VT,vm->VT); vm->NbVT += v->NbVT; + combine(v->TT,vm->TT); vm->NbTT += v->NbTT; + combine(v->SQ,vm->SQ); vm->NbSQ += v->NbSQ; + combine(v->VQ,vm->VQ); vm->NbVQ += v->NbVQ; + combine(v->TQ,vm->TQ); vm->NbTQ += v->NbTQ; + combine(v->SS,vm->SS); vm->NbSS += v->NbSS; + combine(v->VS,vm->VS); vm->NbVS += v->NbVS; + combine(v->TS,vm->TS); vm->NbTS += v->NbTS; + combine(v->SH,vm->SH); vm->NbSH += v->NbSH; + combine(v->VH,vm->VH); vm->NbVH += v->NbVH; + combine(v->TH,vm->TH); vm->NbTH += v->NbTH; + combine(v->SI,vm->SI); vm->NbSI += v->NbSI; + combine(v->VI,vm->VI); vm->NbVI += v->NbVI; + combine(v->TI,vm->TI); vm->NbTI += v->NbTI; + combine(v->SY,vm->SY); vm->NbSY += v->NbSY; + combine(v->VY,vm->VY); vm->NbVY += v->NbVY; + combine(v->TY,vm->TY); vm->NbTY += v->NbTY; + combine_strings(v,vm); + } + +#if 0 + // debug strings: + for(int i=0; i<List_Nbr(vm->T2D); i++) + printf("%g ", *(double*)List_Pointer(vm->T2D, i)); + printf("\n"); + for(int i=0; i<List_Nbr(vm->T2C); i++) + printf("%c ", *(char*)List_Pointer(vm->T2C, i)); + printf("\n"); +#endif + + // finalize + char name[256], filename[256], tmp[256]; + if(!strcmp(id->name, "__all__")) + strcpy(tmp, "all"); + else if(!strcmp(id->name, "__vis__")) + strcpy(tmp, "visible"); + else + strcpy(tmp, id->name); + sprintf(name, "%s_Combine", tmp); + sprintf(filename, "%s_Combine.pos", tmp); + EndView(vm, 0, filename, name); +} + +static void combine_time(struct nameidx *id, List_T *to_remove) +{ + int index, *nbe=0, *nbe2=0, nbn, nbn2, nbc, nbc2; + List_T *list=0, *list2=0; + + if(List_Nbr(id->indices) < 2){ + return; // nothing to do + } + + Post_View *vm = BeginView(1); + + // use the first view as the reference + List_Read(id->indices, 0, &index); + Post_View *v = *(Post_View **)List_Pointer(CTX.post.list, index); + for(int i = 0; i < VIEW_NB_ELEMENT_TYPES; i++){ + vm->get_raw_data(i, &list, &nbe, &nbc, &nbn); + v->get_raw_data(i, &list2, &nbe2, &nbc2, &nbn2); + *nbe = *nbe2; + } + vm->NbT2 = v->NbT2; + vm->NbT3 = v->NbT3; + + // merge values for all element types + for(int i = 0; i < VIEW_NB_ELEMENT_TYPES; i++){ + vm->get_raw_data(i, &list, &nbe, &nbc, &nbn); + for(int j = 0; j < *nbe; j++){ + for(int k = 0; k < List_Nbr(id->indices); k++){ + List_Read(id->indices, k, &index); + v = *(Post_View **)List_Pointer(CTX.post.list, index); + v->get_raw_data(i, &list2, &nbe2, &nbc2, &nbn2); + if(*nbe && *nbe == *nbe2){ + List_Insert(to_remove, &v->Num, fcmp_int); + int nb2 = List_Nbr(list2) / *nbe2; + if(!k){ + // copy coordinates of elm j (we are always here as + // expected, since the ref view is the first one!) + for(int l = 0; l < 3*nbn2; l++){ + List_Add(list, List_Pointer(list2, j*nb2+l)); + } + } + // copy values of elm j + for(int l = 0; l < v->NbTimeStep*nbc2*nbn2; l++){ + List_Add(list, List_Pointer(list2, j*nb2+3*nbn2+l)); + } + } + } + } + } + + // and a bit of spaghetti code for you now: + + // merge 2d strings + for(int j = 0; j < vm->NbT2; j++){ + for(int k = 0; k < List_Nbr(id->indices); k++){ + List_Read(id->indices, k, &index); + v = *(Post_View **)List_Pointer(CTX.post.list, index); + if(vm->NbT2 == v->NbT2){ + List_Insert(to_remove, &v->Num, fcmp_int); + if(!k){ + // copy coordinates + List_Add(vm->T2D, List_Pointer(v->T2D, j*4)); + List_Add(vm->T2D, List_Pointer(v->T2D, j*4+1)); + List_Add(vm->T2D, List_Pointer(v->T2D, j*4+2)); + // index + double d = List_Nbr(vm->T2C); + List_Add(vm->T2D, &d); + } + // copy char values + double beg, end; + List_Read(v->T2D, j*4+3, &beg); + if(j == vm->NbT2 - 1) + end = (double)List_Nbr(v->T2C); + else + List_Read(v->T2D, j*4+4+3, &end); + char *c = (char*)List_Pointer(v->T2C, (int)beg); + for(int l = 0; l < (int)(end-beg); l++) + List_Add(vm->T2C, &c[l]); + } + } + } + + // merge 3d strings + for(int j = 0; j < vm->NbT3; j++){ + for(int k = 0; k < List_Nbr(id->indices); k++){ + List_Read(id->indices, k, &index); + v = *(Post_View **)List_Pointer(CTX.post.list, index); + if(vm->NbT3 == v->NbT3){ + List_Insert(to_remove, &v->Num, fcmp_int); + if(!k){ + // copy coordinates + List_Add(vm->T3D, List_Pointer(v->T3D, j*5)); + List_Add(vm->T3D, List_Pointer(v->T3D, j*5+1)); + List_Add(vm->T3D, List_Pointer(v->T3D, j*5+2)); + List_Add(vm->T3D, List_Pointer(v->T3D, j*5+3)); + // index + double d = List_Nbr(vm->T3C); + List_Add(vm->T3D, &d); + } + // copy char values + double beg, end; + List_Read(v->T3D, j*5+4, &beg); + if(j == vm->NbT3 - 1) + end = (double)List_Nbr(v->T3C); + else + List_Read(v->T3D, j*5+5+4, &end); + char *c = (char*)List_Pointer(v->T3C, (int)beg); + for(int l = 0; l < (int)(end-beg); l++) + List_Add(vm->T3C, &c[l]); + } + } + } + + // create the time data + for(int i = 0; i < List_Nbr(id->indices); i++){ + List_Read(id->indices, i, &index); + v = *(Post_View **)List_Pointer(CTX.post.list, index); + for(int j = 0; j < List_Nbr(v->Time); j++){ + List_Add(vm->Time, List_Pointer(v->Time, j)); + } + } + + // if all the time values are the same, it probably means that the + // original views didn't have any time data: let's put some indices, + // then + double time0 = 0.0; + if(List_Nbr(vm->Time)) List_Read(vm->Time, 0, &time0); + int nbtime = List_Nbr(vm->Time), ok = 0; + for(int i = 1; i < nbtime; i++){ + if(time0 != *(double*)List_Pointer(vm->Time, i)){ + ok = 1; + break; + } + } + if(!ok){ + List_Reset(vm->Time); + for(int i = 0; i < nbtime; i++){ + double time = i; + List_Add(vm->Time, &time); + } + } + + // finalize + char name[256], filename[256], tmp[256]; + if(!strcmp(id->name, "__all__")) + strcpy(tmp, "all"); + else if(!strcmp(id->name, "__vis__")) + strcpy(tmp, "visible"); + else + strcpy(tmp, id->name); + sprintf(name, "%s_Combine", tmp); + sprintf(filename, "%s_Combine.pos", tmp); + EndView(vm, 0, filename, name); +} + +void CombineViews(int time, int how, int remove) +{ + // time==0: combine the elements + // time==1: combine the timesteps + + // how==0: try to combine all visible views + // how==1: try to combine all views + // how==2: try to combine all views having identical names + + List_T *ids = List_Create(10, 10, sizeof(nameidx)); + List_T *to_remove = List_Create(10, 10, sizeof(int)); + struct nameidx *pid; + + for(int i = 0; i < List_Nbr(CTX.post.list); i++) { + Post_View *v = *(Post_View **) List_Pointer(CTX.post.list, i); + if(how || v->Visible) { + nameidx id; + // this might potentially lead to unwanted results if there are + // views named "__all__" or "__vis__", but what the heck... + if(how == 2) + strcpy(id.name, v->Name); + else if(how == 1) + strcpy(id.name, "__all__"); + else + strcpy(id.name, "__vis__"); + if((pid = (struct nameidx*)List_PQuery(ids, &id, fcmp_name))){ + List_Add(pid->indices, &i); + } + else{ + id.indices = List_Create(10, 10, sizeof(int)); + List_Add(id.indices, &i); + List_Add(ids, &id); + } + } + } + + for(int i = 0; i < List_Nbr(ids); i++){ + pid = (struct nameidx*)List_Pointer(ids, i); + if(time) + combine_time(pid, to_remove); + else + combine_space(pid, to_remove); + List_Delete(pid->indices); + } + List_Delete(ids); + + // remove original view? + if(remove){ + for(int i = 0; i < List_Nbr(to_remove); i++){ + int num; + List_Read(to_remove, i, &num); + RemoveViewByNumber(num); + } + } + List_Delete(to_remove); + +#if defined(HAVE_FLTK) + UpdateViewsInGUI(); +#endif +} + +// generic access functions + +int Post_View::empty(){ + if(NbSP || NbVP || NbTP || + NbSL || NbVL || NbTL || + NbST || NbVT || NbTT || + NbSQ || NbVQ || NbTQ || + NbSS || NbVS || NbTS || + NbSH || NbVH || NbTH || + NbSI || NbVI || NbTI || + NbSY || NbVY || NbTY || + NbT2 || NbT3) + return 0; + else + return 1; +} + +void Post_View::get_raw_data(int type, List_T **list, int **nbe, int *nbc, int *nbn){ + switch(type){ + case 0 : *list = SP; *nbe = &NbSP; *nbc = 1; *nbn = 1; break; + case 1 : *list = VP; *nbe = &NbVP; *nbc = 3; *nbn = 1; break; + case 2 : *list = TP; *nbe = &NbTP; *nbc = 9; *nbn = 1; break; + case 3 : *list = SL; *nbe = &NbSL; *nbc = 1; *nbn = 2; break; + case 4 : *list = VL; *nbe = &NbVL; *nbc = 3; *nbn = 2; break; + case 5 : *list = TL; *nbe = &NbTL; *nbc = 9; *nbn = 2; break; + case 6 : *list = ST; *nbe = &NbST; *nbc = 1; *nbn = 3; break; + case 7 : *list = VT; *nbe = &NbVT; *nbc = 3; *nbn = 3; break; + case 8 : *list = TT; *nbe = &NbTT; *nbc = 9; *nbn = 3; break; + case 9 : *list = SQ; *nbe = &NbSQ; *nbc = 1; *nbn = 4; break; + case 10: *list = VQ; *nbe = &NbVQ; *nbc = 3; *nbn = 4; break; + case 11: *list = TQ; *nbe = &NbTQ; *nbc = 9; *nbn = 4; break; + case 12: *list = SS; *nbe = &NbSS; *nbc = 1; *nbn = 4; break; + case 13: *list = VS; *nbe = &NbVS; *nbc = 3; *nbn = 4; break; + case 14: *list = TS; *nbe = &NbTS; *nbc = 9; *nbn = 4; break; + case 15: *list = SH; *nbe = &NbSH; *nbc = 1; *nbn = 8; break; + case 16: *list = VH; *nbe = &NbVH; *nbc = 3; *nbn = 8; break; + case 17: *list = TH; *nbe = &NbTH; *nbc = 9; *nbn = 8; break; + case 18: *list = SI; *nbe = &NbSI; *nbc = 1; *nbn = 6; break; + case 19: *list = VI; *nbe = &NbVI; *nbc = 3; *nbn = 6; break; + case 20: *list = TI; *nbe = &NbTI; *nbc = 9; *nbn = 6; break; + case 21: *list = SY; *nbe = &NbSY; *nbc = 1; *nbn = 5; break; + case 22: *list = VY; *nbe = &NbVY; *nbc = 3; *nbn = 5; break; + case 23: *list = TY; *nbe = &NbTY; *nbc = 9; *nbn = 5; break; + default: Msg(GERROR, "Wrong type in Post_View::get_raw_data"); break; + } +} + +// Generalized raise + +void InitGeneralizedRaise(Post_View *v) +{ + FreeGeneralizedRaise(v); + + char *expr[3] = { v->GenRaiseX, v->GenRaiseY, v->GenRaiseZ }; +#if defined(HAVE_MATH_EVAL) + for(int i = 0; i < 3; i++) { + if(strlen(expr[i])) { + if(!(v->GenRaise_f[i] = evaluator_create(expr[i]))) + Msg(GERROR, "Invalid expression '%s'", expr[i]); + } + } +#else + for(int i = 0; i < 3; i++) { + if(!strcmp(expr[i], "v0")) v->GenRaise_f[i] = (void*)0; + else if(!strcmp(expr[i], "v1")) v->GenRaise_f[i] = (void*)1; + else if(!strcmp(expr[i], "v2")) v->GenRaise_f[i] = (void*)2; + else if(!strcmp(expr[i], "v3")) v->GenRaise_f[i] = (void*)3; + else if(!strcmp(expr[i], "v4")) v->GenRaise_f[i] = (void*)4; + else if(!strcmp(expr[i], "v5")) v->GenRaise_f[i] = (void*)5; + else if(!strcmp(expr[i], "v6")) v->GenRaise_f[i] = (void*)6; + else if(!strcmp(expr[i], "v7")) v->GenRaise_f[i] = (void*)7; + else if(!strcmp(expr[i], "v8")) v->GenRaise_f[i] = (void*)8; + else if(strlen(expr[i])) { + Msg(GERROR, "Invalid expression '%s'", expr[i]); + return; + } + } +#endif +} + +void FreeGeneralizedRaise(Post_View *v) +{ + for(int i = 0; i < 3; i++){ +#if defined(HAVE_MATH_EVAL) + if(v->GenRaise_f[i]) + evaluator_destroy(v->GenRaise_f[i]); + v->GenRaise_f[i] = NULL; +#else + v->GenRaise_f[i] = (void*)-1; +#endif + } +} + +void ApplyGeneralizedRaise(Post_View * v, int numNodes, int numComp, double *vals, + double *x, double *y, double *z) +{ + double *coords[3] = { x, y, z }; + + for(int k = 0; k < numNodes; k++) { + double d[9] = {0., 0., 0., 0., 0., 0., 0., 0., 0.}; + for(int l = 0; l < numComp; l++) + d[l] = vals[numComp * k + l]; +#if defined(HAVE_MATH_EVAL) + char *names[] = { "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8" , + "x", "y", "z" }; + double values[] = { d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], + x[k], y[k], z[k] }; + for(int i = 0; i < 3; i++) { + if(v->GenRaise_f[i]) + coords[i][k] += + evaluator_evaluate(v->GenRaise_f[i], sizeof(names) / + sizeof(names[0]), names, values) * v->GenRaiseFactor; + } +#else + for(int i = 0; i < 3; i++){ + int comp = (int)v->GenRaise_f[i]; + if(comp >= 0) + coords[i][k] += d[comp] * v->GenRaiseFactor; + } +#endif + } +} diff --git a/Common/Views.h b/Common/Views.h new file mode 100644 index 0000000000000000000000000000000000000000..3ba4b108997e317dbcd5857126ad7df4d5125bbd --- /dev/null +++ b/Common/Views.h @@ -0,0 +1,231 @@ +#ifndef _VIEWS_H_ +#define _VIEWS_H_ + +// 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 <map> +#include "ColorTable.h" +#include "List.h" +#include "VertexArray.h" +#include "SmoothData.h" +#include "AdaptiveViews.h" + +#define VIEW_NB_ELEMENT_TYPES (8*3) +#define VAL_INF 1.e200 + +#define POST_POINT 0 +#define POST_LINE 1 +#define POST_TRIANGLE 2 +#define POST_QUADRANGLE 3 +#define POST_TETRAHEDRON 4 +#define POST_HEXAHEDRON 5 +#define POST_PRISM 6 +#define POST_PYRAMID 7 + +class Post_View{ + public : + // intrinsic to a view + int Num, Index, Changed, AliasOf, Links, Dirty; + char FileName[256], Name[256]; + + // the data + int DataSize; // size(double) or sizeof(float) + int NbTimeStep, ScalarOnly, TextOnly; + double Min, Max, BBox[6], *TimeStepMin, *TimeStepMax; + List_T *Time; + int NbSP, NbVP, NbTP; + List_T *SP, *VP, *TP; // points + int NbSL, NbVL, NbTL, NbSL2, NbVL2, NbTL2; + List_T *SL, *VL, *TL, *SL2, *VL2, *TL2; // lines + int NbST, NbVT, NbTT, NbST2, NbVT2, NbTT2; + List_T *ST, *VT, *TT, *ST2, *VT2, *TT2; // triangles + int NbSQ, NbVQ, NbTQ, NbSQ2, NbVQ2, NbTQ2; + List_T *SQ, *VQ, *TQ, *SQ2, *VQ2, *TQ2; // quadrangles + int NbSS, NbVS, NbTS, NbSS2, NbVS2, NbTS2; + List_T *SS, *VS, *TS, *SS2, *VS2, *TS2; // tetrahedra + int NbSH, NbVH, NbTH, NbSH2, NbVH2, NbTH2; + List_T *SH, *VH, *TH, *SH2, *VH2, *TH2; // hexahedra + int NbSI, NbVI, NbTI, NbSI2, NbVI2, NbTI2; + List_T *SI, *VI, *TI, *SI2, *VI2, *TI2; // prisms + int NbSY, NbVY, NbTY, NbSY2, NbVY2, NbTY2; + List_T *SY, *VY, *TY, *SY2, *VY2, *TY2; // pyramids + int NbT2, NbT3; + List_T *T2D, *T2C, *T3D, *T3C; // 2D and 3D text strings + std::map < int , List_T * > *Grains; // For LMGC90, grains shapes + std::map < int , int > *DisplayListsOfGrains; // For LMGC90, grains shapes + + + // vertex arrays to draw triangles and lines efficiently + VertexArray *TriVertexArray, *LinVertexArray; + + // options + int Type; + int Position[2], Size[2], AutoPosition; + char Format[256]; + int Axes, AxesAutoPosition, AxesTics[3]; + char AxesFormat[3][256], AxesLabel[3][256]; + double AxesPosition[6]; + double CustomMin, CustomMax; + double Offset[3], Raise[3], Transform[3][3], DisplacementFactor, Explode; + double ArrowSize, ArrowRelHeadRadius, ArrowRelStemRadius, ArrowRelStemLength; + double Normals, Tangents; + int Visible, IntervalsType, NbIso, ArrowSizeProportional; + int Light, LightTwoSide, LightLines, SmoothNormals; + double AngleSmoothNormals; + int SaturateValues, FakeTransparency; + int ShowElement, ShowTime, ShowScale; + int ScaleType, RangeType; + int VectorType, TensorType, GlyphLocation; + int TimeStep; + int DrawStrings; + int DrawPoints, DrawLines, DrawTriangles, DrawQuadrangles; + int DrawTetrahedra, DrawHexahedra, DrawPrisms, DrawPyramids; + int DrawScalars, DrawVectors, DrawTensors; + int Boundary, PointType, LineType; + double PointSize, LineWidth; + GmshColorTable CT; + int UseStipple, Stipple[10][2]; + char StippleString[10][32]; + int ExternalViewIndex, ViewIndexForGenRaise; + int UseGenRaise; + double GenRaiseFactor; + char GenRaiseX[256], GenRaiseY[256], GenRaiseZ[256]; + void *GenRaise_f[3]; + + // color options + struct{ + unsigned int point, line, triangle, quadrangle; + unsigned int tetrahedron, hexahedron, prism, pyramid; + unsigned int tangents, normals; + unsigned int text2d, text3d, axes; + } color; + + // dynamic + double (*GVFI)(double min, double max, int nb, int index); + int (*GIFV)(double min, double max, int nb, double value); + int ExternalElementIndex; + double ExternalMin, ExternalMax; + double TmpBBox[6]; // dynamically computed during drawing + + // smooth the view + void smooth(); + // smooth normals + smooth_normals *normals; + void reset_normals(); + + // some generic access functions + int empty(); + void get_raw_data(int type, List_T **list, int **nbe, int *nbc, int *nbn); + + // transforms curved elements into linear ones + void splitCurvedElements(); + + // If the view is high order, coeffs are interpreated as + // coefficients of a high order interpolation. So, a pre-pro + // is done at the end of the view that sets the view to the + // minimal resolution. Then, we can interactively modify the + // resolution. + Adaptive_Post_View *adaptive; + void setGlobalResolutionLevel(int level) + { + if (adaptive) + adaptive->setGlobalResolutionLevel(this, level); + } + void setAdaptiveResolutionLevel (int level, GMSH_Post_Plugin *plug = 0) + { + if (adaptive) + adaptive->setAdaptiveResolutionLevel(this, level, plug); + } + +}; + +// Type +#define DRAW_POST_3D 1 +#define DRAW_POST_2D_SPACE 2 +#define DRAW_POST_2D_TIME 3 + +// IntervalsType +#define DRAW_POST_ISO 1 +#define DRAW_POST_CONTINUOUS 2 +#define DRAW_POST_DISCRETE 3 +#define DRAW_POST_NUMERIC 4 + +// VectorType +#define DRAW_POST_SEGMENT 1 +#define DRAW_POST_ARROW 2 +#define DRAW_POST_PYRAMID 3 +#define DRAW_POST_ARROW3D 4 +#define DRAW_POST_DISPLACEMENT 5 + +// GlyphLocation +#define DRAW_POST_LOCATE_COG 1 +#define DRAW_POST_LOCATE_VERTEX 2 + +// TensorType +#define DRAW_POST_VONMISES 1 +#define DRAW_POST_LMGC90 2 +#define DRAW_POST_LMGC90_TYPE 3 +#define DRAW_POST_LMGC90_COORD 4 +#define DRAW_POST_LMGC90_PRES 5 +#define DRAW_POST_LMGC90_SN 6 +#define DRAW_POST_LMGC90_DEPX 7 +#define DRAW_POST_LMGC90_DEPY 8 +#define DRAW_POST_LMGC90_DEPZ 9 +#define DRAW_POST_LMGC90_DEPAV 10 +#define DRAW_POST_LMGC90_DEPNORM 11 +// RangeType +#define DRAW_POST_RANGE_DEFAULT 1 +#define DRAW_POST_RANGE_CUSTOM 2 +#define DRAW_POST_RANGE_PER_STEP 3 + +// ScaleType +#define DRAW_POST_LINEAR 1 +#define DRAW_POST_LOGARITHMIC 2 +#define DRAW_POST_DOUBLELOGARITHMIC 3 // for vorticity e.g. + +// Public functions + +int fcmpPostViewNum(const void *v1, const void *v2); +int fcmpPostViewAliasOf(const void *v1, const void *v2); + +Post_View *BeginView(int alloc); +void EndView(Post_View *v, int AddInUI, char *FileName, char *Name); +void AliasView(int num, int withoptions); +void FreeView(Post_View *v); +bool RemoveViewByIndex(int index); +bool RemoveViewByNumber(int num); +int ReadView(char *filename); +void WriteView(Post_View *v, char *filename, int format, int append); +void CopyViewOptions(Post_View *src, Post_View *dest); +void CombineViews(int time, int how, int remove); + +Post_View *Create2DGraph(char *xname, char *yname, int nbdata, double *x, double *y); + +GmshColorTable *Get_ColorTable(int num); +void Print_ColorTable(int num, int diff, char *prefix, FILE *file); + +double ComputeVonMises(double* val); + +void InitGeneralizedRaise(Post_View *v); +void FreeGeneralizedRaise(Post_View *v); +void ApplyGeneralizedRaise(Post_View * v, int numNodes, int numComp, double *vals, + double *x, double *y, double *z); + +#endif diff --git a/Common/ViewsIO.cpp b/Common/ViewsIO.cpp new file mode 100644 index 0000000000000000000000000000000000000000..860e6e7ae3cf27ee0187e0a638e7c221d817364a --- /dev/null +++ b/Common/ViewsIO.cpp @@ -0,0 +1,839 @@ +// $Id: ViewsIO.cpp,v 1.9 2006-11-27 22:22:08 geuzaine 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 <set> +#include "Gmsh.h" +#include "Numeric.h" +#include "Views.h" +#include "Context.h" + +extern Context_T CTX; + +#if defined(HAVE_FLTK) +void UpdateViewsInGUI(); +#endif + +// Read view from file + +int ReadView(char *filename) +{ + FILE *fp = fopen(filename, "rb"); + if(!fp){ + Msg(GERROR, "Unable to open file '%s'", filename); + return 0; + } + + char str[256], name[256]; + int i, nb, format, size, testone, swap, t2l, t3l; + double version; + Post_View *v; + + while(1) { + + do { + if(!fgets(str, 256, fp) || feof(fp)) + break; + } while(str[0] != '$'); + + if(feof(fp)) + break; + + if(!strncmp(&str[1], "PostFormat", 10)) { + if(!fscanf(fp, "%lf %d %d\n", &version, &format, &size)){ + Msg(GERROR, "Read error"); + return 0; + } + if(version < 1.0) { + Msg(GERROR, "This post-processing file is too old (version %g < 1.0)", + version); + return 0; + } + if(size == sizeof(double)) + Msg(DEBUG, "Data is in double precision format (size==%d)", size); + else if(size == sizeof(float)) + Msg(DEBUG, "Data is in single precision format (size==%d)", size); + else { + Msg(GERROR, "Unknown data size (%d) in post-processing file", size); + return 0; + } + if(format == 0) + format = LIST_FORMAT_ASCII; + else if(format == 1) + format = LIST_FORMAT_BINARY; + else { + Msg(GERROR, "Unknown format for view"); + return 0; + } + } + + if(!strncmp(&str[1], "View", 4)) { + v = BeginView(0); + if(version <= 1.0) { + Msg(DEBUG, "Detected post-processing view format <= 1.0"); + if(!fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + name, &v->NbTimeStep, + &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL, &v->NbVL, &v->NbTL, + &v->NbST, &v->NbVT, &v->NbTT, &v->NbSS, &v->NbVS, &v->NbTS)){ + Msg(GERROR, "Read error"); + return 0; + } + v->NbT2 = t2l = v->NbT3 = t3l = 0; + } + else if(version == 1.1) { + Msg(DEBUG, "Detected post-processing view format 1.1"); + if(!fscanf(fp, + "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + name, &v->NbTimeStep, &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL, + &v->NbVL, &v->NbTL, &v->NbST, &v->NbVT, &v->NbTT, &v->NbSS, + &v->NbVS, &v->NbTS, &v->NbT2, &t2l, &v->NbT3, &t3l)){ + Msg(GERROR, "Read error"); + return 0; + } + } + else if(version == 1.2 || version == 1.3) { + Msg(DEBUG, "Detected post-processing view format %g", version); + if(!fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d %d %d %d %d\n", + name, &v->NbTimeStep, + &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL, &v->NbVL, &v->NbTL, + &v->NbST, &v->NbVT, &v->NbTT, &v->NbSQ, &v->NbVQ, &v->NbTQ, + &v->NbSS, &v->NbVS, &v->NbTS, &v->NbSH, &v->NbVH, &v->NbTH, + &v->NbSI, &v->NbVI, &v->NbTI, &v->NbSY, &v->NbVY, &v->NbTY, + &v->NbT2, &t2l, &v->NbT3, &t3l)){ + Msg(GERROR, "Read error"); + return 0; + } + } + else if(version == 1.4) { + Msg(DEBUG, "Detected post-processing view format 1.4"); + if(!fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + name, &v->NbTimeStep, + &v->NbSP, &v->NbVP, &v->NbTP, &v->NbSL, &v->NbVL, &v->NbTL, + &v->NbST, &v->NbVT, &v->NbTT, &v->NbSQ, &v->NbVQ, &v->NbTQ, + &v->NbSS, &v->NbVS, &v->NbTS, &v->NbSH, &v->NbVH, &v->NbTH, + &v->NbSI, &v->NbVI, &v->NbTI, &v->NbSY, &v->NbVY, &v->NbTY, + &v->NbSL2, &v->NbVL2, &v->NbTL2, &v->NbST2, &v->NbVT2, &v->NbTT2, + &v->NbSQ2, &v->NbVQ2, &v->NbTQ2, &v->NbSS2, &v->NbVS2, &v->NbTS2, + &v->NbSH2, &v->NbVH2, &v->NbTH2, &v->NbSI2, &v->NbVI2, &v->NbTI2, + &v->NbSY2, &v->NbVY2, &v->NbTY2, &v->NbT2, &t2l, &v->NbT3, &t3l)){ + Msg(GERROR, "Read error"); + return 0; + } + } + else { + Msg(GERROR, "Unknown post-processing file format (version %g)", + version); + return 0; + } + + for(i = 0; i < (int)strlen(name); i++) + if(name[i] == '^') + name[i] = ' '; + + swap = 0; + if(format == LIST_FORMAT_BINARY) { + if(!fread(&testone, sizeof(int), 1, fp)){ + Msg(GERROR, "Read error"); + return 0; + } + if(testone != 1) { + Msg(INFO, "Swapping bytes from binary file"); + swap = 1; + } + } + + v->DataSize = size; + + // Time values + v->Time = List_CreateFromFile(v->NbTimeStep, 100, size, fp, format, swap); + + // Note: if nb==0, we still allocates the lists (so that they + // are ready to be filled later, e.g. in plugins) + +#define LCD List_CreateFromFile(nb, 1000, size, fp, format, swap) + + // Points + nb = v->NbSP ? v->NbSP * (v->NbTimeStep * 1 + 3) : 0; v->SP = LCD; + nb = v->NbVP ? v->NbVP * (v->NbTimeStep * 3 + 3) : 0; v->VP = LCD; + nb = v->NbTP ? v->NbTP * (v->NbTimeStep * 9 + 3) : 0; v->TP = LCD; + + // Lines + nb = v->NbSL ? v->NbSL * (v->NbTimeStep * 2 * 1 + 6) : 0; v->SL = LCD; + nb = v->NbVL ? v->NbVL * (v->NbTimeStep * 2 * 3 + 6) : 0; v->VL = LCD; + nb = v->NbTL ? v->NbTL * (v->NbTimeStep * 2 * 9 + 6) : 0; v->TL = LCD; + + // Triangles + nb = v->NbST ? v->NbST * (v->NbTimeStep * 3 * 1 + 9) : 0; v->ST = LCD; + nb = v->NbVT ? v->NbVT * (v->NbTimeStep * 3 * 3 + 9) : 0; v->VT = LCD; + nb = v->NbTT ? v->NbTT * (v->NbTimeStep * 3 * 9 + 9) : 0; v->TT = LCD; + + // Quadrangles + nb = v->NbSQ ? v->NbSQ * (v->NbTimeStep * 4 * 1 + 12) : 0; v->SQ = LCD; + nb = v->NbVQ ? v->NbVQ * (v->NbTimeStep * 4 * 3 + 12) : 0; v->VQ = LCD; + nb = v->NbTQ ? v->NbTQ * (v->NbTimeStep * 4 * 9 + 12) : 0; v->TQ = LCD; + + // Tetrahedra + nb = v->NbSS ? v->NbSS * (v->NbTimeStep * 4 * 1 + 12) : 0; v->SS = LCD; + nb = v->NbVS ? v->NbVS * (v->NbTimeStep * 4 * 3 + 12) : 0; v->VS = LCD; + nb = v->NbTS ? v->NbTS * (v->NbTimeStep * 4 * 9 + 12) : 0; v->TS = LCD; + + // Hexahedra + nb = v->NbSH ? v->NbSH * (v->NbTimeStep * 8 * 1 + 24) : 0; v->SH = LCD; + nb = v->NbVH ? v->NbVH * (v->NbTimeStep * 8 * 3 + 24) : 0; v->VH = LCD; + nb = v->NbTH ? v->NbTH * (v->NbTimeStep * 8 * 9 + 24) : 0; v->TH = LCD; + + // Prisms + nb = v->NbSI ? v->NbSI * (v->NbTimeStep * 6 * 1 + 18) : 0; v->SI = LCD; + nb = v->NbVI ? v->NbVI * (v->NbTimeStep * 6 * 3 + 18) : 0; v->VI = LCD; + nb = v->NbTI ? v->NbTI * (v->NbTimeStep * 6 * 9 + 18) : 0; v->TI = LCD; + + // Pyramids + nb = v->NbSY ? v->NbSY * (v->NbTimeStep * 5 * 1 + 15) : 0; v->SY = LCD; + nb = v->NbVY ? v->NbVY * (v->NbTimeStep * 5 * 3 + 15) : 0; v->VY = LCD; + nb = v->NbTY ? v->NbTY * (v->NbTimeStep * 5 * 9 + 15) : 0; v->TY = LCD; + + // 2nd order Lines + nb = v->NbSL2 ? v->NbSL2 * (v->NbTimeStep * 3 * 1 + 9) : 0; v->SL2 = LCD; + nb = v->NbVL2 ? v->NbVL2 * (v->NbTimeStep * 3 * 3 + 9) : 0; v->VL2 = LCD; + nb = v->NbTL2 ? v->NbTL2 * (v->NbTimeStep * 3 * 9 + 9) : 0; v->TL2 = LCD; + + // 2nd order Triangles + nb = v->NbST2 ? v->NbST2 * (v->NbTimeStep * 6 * 1 + 18) : 0; v->ST2 = LCD; + nb = v->NbVT2 ? v->NbVT2 * (v->NbTimeStep * 6 * 3 + 18) : 0; v->VT2 = LCD; + nb = v->NbTT2 ? v->NbTT2 * (v->NbTimeStep * 6 * 9 + 18) : 0; v->TT2 = LCD; + + // 2nd order Quadrangles + nb = v->NbSQ2 ? v->NbSQ2 * (v->NbTimeStep * 9 * 1 + 27) : 0; v->SQ2 = LCD; + nb = v->NbVQ2 ? v->NbVQ2 * (v->NbTimeStep * 9 * 3 + 27) : 0; v->VQ2 = LCD; + nb = v->NbTQ2 ? v->NbTQ2 * (v->NbTimeStep * 9 * 9 + 27) : 0; v->TQ2 = LCD; + + // 2nd order Tetrahedra + nb = v->NbSS2 ? v->NbSS2 * (v->NbTimeStep * 10 * 1 + 30) : 0; v->SS2 = LCD; + nb = v->NbVS2 ? v->NbVS2 * (v->NbTimeStep * 10 * 3 + 30) : 0; v->VS2 = LCD; + nb = v->NbTS2 ? v->NbTS2 * (v->NbTimeStep * 10 * 9 + 30) : 0; v->TS2 = LCD; + + // 2nd order Hexahedra + nb = v->NbSH2 ? v->NbSH2 * (v->NbTimeStep * 27 * 1 + 81) : 0; v->SH2 = LCD; + nb = v->NbVH2 ? v->NbVH2 * (v->NbTimeStep * 27 * 3 + 81) : 0; v->VH2 = LCD; + nb = v->NbTH2 ? v->NbTH2 * (v->NbTimeStep * 27 * 9 + 81) : 0; v->TH2 = LCD; + + // 2nd order Prisms + nb = v->NbSI2 ? v->NbSI2 * (v->NbTimeStep * 18 * 1 + 54) : 0; v->SI2 = LCD; + nb = v->NbVI2 ? v->NbVI2 * (v->NbTimeStep * 18 * 3 + 54) : 0; v->VI2 = LCD; + nb = v->NbTI2 ? v->NbTI2 * (v->NbTimeStep * 18 * 9 + 54) : 0; v->TI2 = LCD; + + // 2nd order Pyramids + nb = v->NbSY2 ? v->NbSY2 * (v->NbTimeStep * 14 * 1 + 42) : 0; v->SY2 = LCD; + nb = v->NbVY2 ? v->NbVY2 * (v->NbTimeStep * 14 * 3 + 42) : 0; v->VY2 = LCD; + nb = v->NbTY2 ? v->NbTY2 * (v->NbTimeStep * 14 * 9 + 42) : 0; v->TY2 = LCD; + +#undef LCD + + // 2D strings + nb = v->NbT2 ? v->NbT2 * 4 : 0; + v->T2D = List_CreateFromFile(nb, 100, size, fp, format, swap); + if(version <= 1.2) + v->T2C = List_CreateFromFileOld(t2l, 100, sizeof(char), fp, format, swap); + else + v->T2C = List_CreateFromFile(t2l, 100, sizeof(char), fp, format, swap); + + // 3D strings + nb = v->NbT3 ? v->NbT3 * 5 : 0; + v->T3D = List_CreateFromFile(nb, 100, size, fp, format, swap); + if(version <= 1.2) + v->T3C = List_CreateFromFileOld(t3l, 100, sizeof(char), fp, format, swap); + else + v->T3C = List_CreateFromFile(t3l, 100, sizeof(char), fp, format, swap); + + Msg(DEBUG, + "Read View '%s' (%d TimeSteps): " + "SP(%d/%d) VP(%d/%d) TP(%d/%d) " + "SL(%d/%d) VL(%d/%d) TL(%d/%d) " + "ST(%d/%d) VT(%d/%d) TT(%d/%d) " + "SQ(%d/%d) VQ(%d/%d) TQ(%d/%d) " + "SS(%d/%d) VS(%d/%d) TS(%d/%d) " + "SH(%d/%d) VH(%d/%d) TH(%d/%d) " + "SI(%d/%d) VI(%d/%d) TI(%d/%d) " + "SY(%d/%d) VY(%d/%d) TY(%d/%d) " + "SL2(%d/%d) VL2(%d/%d) TL2(%d/%d) " + "ST2(%d/%d) VT2(%d/%d) TT2(%d/%d) " + "SQ2(%d/%d) VQ2(%d/%d) TQ2(%d/%d) " + "SS2(%d/%d) VS2(%d/%d) TS2(%d/%d) " + "SH2(%d/%d) VH2(%d/%d) TH2(%d/%d) " + "SI2(%d/%d) VI2(%d/%d) TI2(%d/%d) " + "SY2(%d/%d) VY2(%d/%d) TY2(%d/%d) " + "T2(%d/%d/%d) T3(%d/%d/%d) ", + name, v->NbTimeStep, + v->NbSP, List_Nbr(v->SP), v->NbVP, List_Nbr(v->VP), v->NbTP, List_Nbr(v->TP), + v->NbSL, List_Nbr(v->SL), v->NbVL, List_Nbr(v->VL), v->NbTL, List_Nbr(v->TL), + v->NbST, List_Nbr(v->ST), v->NbVT, List_Nbr(v->VT), v->NbTT, List_Nbr(v->TT), + v->NbSQ, List_Nbr(v->SQ), v->NbVQ, List_Nbr(v->VQ), v->NbTQ, List_Nbr(v->TQ), + v->NbSS, List_Nbr(v->SS), v->NbVS, List_Nbr(v->VS), v->NbTS, List_Nbr(v->TS), + v->NbSH, List_Nbr(v->SH), v->NbVH, List_Nbr(v->VH), v->NbTH, List_Nbr(v->TH), + v->NbSI, List_Nbr(v->SI), v->NbVI, List_Nbr(v->VI), v->NbTI, List_Nbr(v->TI), + v->NbSY, List_Nbr(v->SY), v->NbVY, List_Nbr(v->VY), v->NbTY, List_Nbr(v->TY), + v->NbSL2, List_Nbr(v->SL2), v->NbVL2, List_Nbr(v->VL2), v->NbTL2, List_Nbr(v->TL2), + v->NbST2, List_Nbr(v->ST2), v->NbVT2, List_Nbr(v->VT2), v->NbTT2, List_Nbr(v->TT2), + v->NbSQ2, List_Nbr(v->SQ2), v->NbVQ2, List_Nbr(v->VQ2), v->NbTQ2, List_Nbr(v->TQ2), + v->NbSS2, List_Nbr(v->SS2), v->NbVS2, List_Nbr(v->VS2), v->NbTS2, List_Nbr(v->TS2), + v->NbSH2, List_Nbr(v->SH2), v->NbVH2, List_Nbr(v->VH2), v->NbTH2, List_Nbr(v->TH2), + v->NbSI2, List_Nbr(v->SI2), v->NbVI2, List_Nbr(v->VI2), v->NbTI2, List_Nbr(v->TI2), + v->NbSY2, List_Nbr(v->SY2), v->NbVY2, List_Nbr(v->VY2), v->NbTY2, List_Nbr(v->TY2), + v->NbT2, List_Nbr(v->T2D), List_Nbr(v->T2C), + v->NbT3, List_Nbr(v->T3D), List_Nbr(v->T3C)); + + // don't update the ui after each view, but only at the end + EndView(v, 0, filename, name); + } + + do { + if(!fgets(str, 256, fp) || feof(fp)) + Msg(GERROR, "Prematured end of file"); + } while(str[0] != '$'); + + } + +#if defined(HAVE_FLTK) + UpdateViewsInGUI(); +#endif + + return 1; +} + +// Write view to file in Parsed, ASCII or Binary format + +static void write_parsed_time(List_T *list, FILE *fp) +{ + if(List_Nbr(list) > 1) { + fprintf(fp, "TIME{"); + for(int i = 0; i < List_Nbr(list); i ++) { + if(i) fprintf(fp, ","); + fprintf(fp, "%.16g", *(double *)List_Pointer(list, i)); + } + fprintf(fp, "};\n"); + } +} + +static void write_parsed_elements(char *str, int nbnod, int nb, List_T *list, FILE *fp) +{ + if(nb) { + int n = List_Nbr(list) / nb; + for(int i = 0; i < List_Nbr(list); i += n) { + double *x = (double *)List_Pointer(list, i); + double *y = (double *)List_Pointer(list, i + nbnod); + double *z = (double *)List_Pointer(list, i + 2 * nbnod); + fprintf(fp, "%s(", str); + for(int j = 0; j < nbnod; j++) { + if(j) fprintf(fp, ","); + fprintf(fp, "%.16g,%.16g,%.16g", x[j], y[j], z[j]); + } + fprintf(fp, "){"); + for(int j = 3 * nbnod; j < n; j++) { + if(j - 3 * nbnod) fprintf(fp, ","); + fprintf(fp, "%.16g", *(double *)List_Pointer(list, i + j)); + } + fprintf(fp, "};\n"); + } + } +} + +static void write_parsed_strings(int nbc, int nb, List_T *TD, List_T *TC, FILE *fp) +{ + if(!nb || (nbc != 4 && nbc != 5)) return; + for(int j = 0; j < List_Nbr(TD); j += nbc){ + double x, y, z, style, start, end; + List_Read(TD, j, &x); + List_Read(TD, j+1, &y); + if(nbc == 5) + List_Read(TD, j+2, &z); + List_Read(TD, j+nbc-2, &style); + if(nbc == 4) + fprintf(fp, "T2(%g,%g,%g){", x, y, style); + else + fprintf(fp, "T3(%g,%g,%g,%g){", x, y, z, style); + List_Read(TD, j+nbc-1, &start); + if(j+nbc*2-1 < List_Nbr(TD)) + List_Read(TD, j+nbc*2-1, &end); + else + end = List_Nbr(TC); + int l = 0; + while(l < end-start){ + char *str = (char*)List_Pointer(TC, (int)start + l); + if(l) fprintf(fp, ","); + fprintf(fp, "\"%s\"", str); + l += strlen(str)+1; + } + fprintf(fp, "};\n"); + } +} + +void WriteViewPOS(Post_View *v, FILE *file, int binary=0, int parsed=1, int append=0) +{ + char name[256]; + int f, One = 1; + + if(!parsed && !append){ + fprintf(file, "$PostFormat /* Gmsh 1.3, %s */\n", + binary ? "binary" : "ascii"); + fprintf(file, "1.3 %d %d\n", binary, (int)sizeof(double)); + fprintf(file, "$EndPostFormat\n"); + } + + strcpy(name, v->Name); + for(int i = 0; i < (int)strlen(name); i++) + if(name[i] == ' ') name[i] = '^'; + + if(!parsed){ + fprintf(file, "$View /* %s */\n", v->Name); + fprintf(file, "%s ", name); + fprintf(file, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d " + "%d %d %d %d %d %d %d %d %d %d %d %d\n", + List_Nbr(v->Time), + v->NbSP, v->NbVP, v->NbTP, v->NbSL, v->NbVL, v->NbTL, + v->NbST, v->NbVT, v->NbTT, v->NbSQ, v->NbVQ, v->NbTQ, + v->NbSS, v->NbVS, v->NbTS, v->NbSH, v->NbVH, v->NbTH, + v->NbSI, v->NbVI, v->NbTI, v->NbSY, v->NbVY, v->NbTY, + v->NbT2, List_Nbr(v->T2C), v->NbT3, List_Nbr(v->T3C)); + if(binary) { + f = LIST_FORMAT_BINARY; + if(!fwrite(&One, sizeof(int), 1, file)){ + Msg(GERROR, "Write error"); + return; + } + } + else + f = LIST_FORMAT_ASCII; + List_WriteToFile(v->Time, file, f); + List_WriteToFile(v->SP, file, f); + List_WriteToFile(v->VP, file, f); + List_WriteToFile(v->TP, file, f); + List_WriteToFile(v->SL, file, f); + List_WriteToFile(v->VL, file, f); + List_WriteToFile(v->TL, file, f); + List_WriteToFile(v->ST, file, f); + List_WriteToFile(v->VT, file, f); + List_WriteToFile(v->TT, file, f); + List_WriteToFile(v->SQ, file, f); + List_WriteToFile(v->VQ, file, f); + List_WriteToFile(v->TQ, file, f); + List_WriteToFile(v->SS, file, f); + List_WriteToFile(v->VS, file, f); + List_WriteToFile(v->TS, file, f); + List_WriteToFile(v->SH, file, f); + List_WriteToFile(v->VH, file, f); + List_WriteToFile(v->TH, file, f); + List_WriteToFile(v->SI, file, f); + List_WriteToFile(v->VI, file, f); + List_WriteToFile(v->TI, file, f); + List_WriteToFile(v->SY, file, f); + List_WriteToFile(v->VY, file, f); + List_WriteToFile(v->TY, file, f); + List_WriteToFile(v->T2D, file, f); + List_WriteToFile(v->T2C, file, f); + List_WriteToFile(v->T3D, file, f); + List_WriteToFile(v->T3C, file, f); + fprintf(file, "\n"); + fprintf(file, "$EndView\n"); + } + else{ + fprintf(file, "View \"%s\" {\n", v->Name); + write_parsed_time(v->Time, file); + write_parsed_elements("SP", 1, v->NbSP, v->SP, file); + write_parsed_elements("VP", 1, v->NbVP, v->VP, file); + write_parsed_elements("TP", 1, v->NbTP, v->TP, file); + write_parsed_elements("SL", 2, v->NbSL, v->SL, file); + write_parsed_elements("VL", 2, v->NbVL, v->VL, file); + write_parsed_elements("TL", 2, v->NbTL, v->TL, file); + write_parsed_elements("ST", 3, v->NbST, v->ST, file); + write_parsed_elements("VT", 3, v->NbVT, v->VT, file); + write_parsed_elements("TT", 3, v->NbTT, v->TT, file); + write_parsed_elements("SQ", 4, v->NbSQ, v->SQ, file); + write_parsed_elements("VQ", 4, v->NbVQ, v->VQ, file); + write_parsed_elements("TQ", 4, v->NbTQ, v->TQ, file); + write_parsed_elements("SS", 4, v->NbSS, v->SS, file); + write_parsed_elements("VS", 4, v->NbVS, v->VS, file); + write_parsed_elements("TS", 4, v->NbTS, v->TS, file); + write_parsed_elements("SH", 8, v->NbSH, v->SH, file); + write_parsed_elements("VH", 8, v->NbVH, v->VH, file); + write_parsed_elements("TH", 8, v->NbTH, v->TH, file); + write_parsed_elements("SI", 6, v->NbSI, v->SI, file); + write_parsed_elements("VI", 6, v->NbVI, v->VI, file); + write_parsed_elements("TI", 6, v->NbTI, v->TI, file); + write_parsed_elements("SY", 5, v->NbSY, v->SY, file); + write_parsed_elements("VY", 5, v->NbVY, v->VY, file); + write_parsed_elements("TY", 5, v->NbTY, v->TY, file); + write_parsed_strings(4, v->NbT2, v->T2D, v->T2C, file); + write_parsed_strings(5, v->NbT3, v->T3D, v->T3C, file); + fprintf(file, "};\n"); + } +} + +// Write view to file in STL format + +static void write_stl(FILE *file, int nbelm, List_T *list, int nbnod) +{ + if(nbelm){ + int nb = List_Nbr(list) / nbelm; + for(int i = 0; i < List_Nbr(list); i+=nb){ + double *x = (double*)List_Pointer(list, i); + double n[3]; + normal3points(x[0], x[3], x[6], + x[1], x[4], x[7], + x[2], x[5], x[8], n); + if(nbnod == 3){ + fprintf(file, "facet normal %g %g %g\n", n[0], n[1], n[2]); + fprintf(file, " outer loop\n"); + fprintf(file, " vertex %g %g %g\n", x[0], x[3], x[6]); + fprintf(file, " vertex %g %g %g\n", x[1], x[4], x[7]); + fprintf(file, " vertex %g %g %g\n", x[2], x[5], x[8]); + fprintf(file, " endloop\n"); + fprintf(file, "endfacet\n"); + } + else{ + fprintf(file, "facet normal %g %g %g\n", n[0], n[1], n[2]); + fprintf(file, " outer loop\n"); + fprintf(file, " vertex %g %g %g\n", x[0], x[4], x[8]); + fprintf(file, " vertex %g %g %g\n", x[1], x[5], x[9]); + fprintf(file, " vertex %g %g %g\n", x[2], x[6], x[10]); + fprintf(file, " endloop\n"); + fprintf(file, "endfacet\n"); + fprintf(file, "facet normal %g %g %g\n", n[0], n[1], n[2]); + fprintf(file, " outer loop\n"); + fprintf(file, " vertex %g %g %g\n", x[0], x[4], x[8]); + fprintf(file, " vertex %g %g %g\n", x[2], x[6], x[10]); + fprintf(file, " vertex %g %g %g\n", x[3], x[7], x[11]); + fprintf(file, " endloop\n"); + fprintf(file, "endfacet\n"); + } + } + } +} + +void WriteViewSTL(Post_View *v, FILE *file) +{ + if(!v->NbST && !v->NbVT && !v->NbTT && + !v->NbSQ && !v->NbVQ && !v->NbTQ){ + Msg(GERROR, "No surface elements to save"); + return; + } + + fprintf(file, "solid Created by Gmsh\n"); + write_stl(file, v->NbST, v->ST, 3); + write_stl(file, v->NbVT, v->VT, 3); + write_stl(file, v->NbTT, v->TT, 3); + write_stl(file, v->NbSQ, v->SQ, 4); + write_stl(file, v->NbVQ, v->VQ, 4); + write_stl(file, v->NbTQ, v->TQ, 4); + fprintf(file, "endsolid Created by Gmsh\n"); +} + +// Write view to file in Text format (should change this to have 2 +// choices: "Tabular (By Element)" and "Tabular (By Time Step)") + +static void write_txt(FILE *file, int nbelm, List_T *list, + int nbnod, int nbcomp, int nbtime) +{ + if(nbelm){ + int nb = List_Nbr(list) / nbelm; + for(int i = 0; i < List_Nbr(list); i+=nb){ + double *x = (double*)List_Pointer(list, i); + for(int j = 0; j < nbnod*(3+nbcomp*nbtime); j++) + fprintf(file, "%.16g ", x[j]); + fprintf(file, "\n"); + } + fprintf(file, "\n"); + } +} + +void WriteViewTXT(Post_View *v, FILE *file) +{ + write_txt(file, v->NbSP, v->SP, 1, 1, v->NbTimeStep); + write_txt(file, v->NbVP, v->VP, 1, 3, v->NbTimeStep); + write_txt(file, v->NbTP, v->TP, 1, 9, v->NbTimeStep); + write_txt(file, v->NbSL, v->SL, 2, 1, v->NbTimeStep); + write_txt(file, v->NbVL, v->VL, 2, 3, v->NbTimeStep); + write_txt(file, v->NbTL, v->TL, 2, 9, v->NbTimeStep); + write_txt(file, v->NbST, v->ST, 3, 1, v->NbTimeStep); + write_txt(file, v->NbVT, v->VT, 3, 3, v->NbTimeStep); + write_txt(file, v->NbTT, v->TT, 3, 9, v->NbTimeStep); + write_txt(file, v->NbSQ, v->SQ, 4, 1, v->NbTimeStep); + write_txt(file, v->NbVQ, v->VQ, 4, 3, v->NbTimeStep); + write_txt(file, v->NbTQ, v->TQ, 4, 9, v->NbTimeStep); + write_txt(file, v->NbSS, v->SS, 4, 1, v->NbTimeStep); + write_txt(file, v->NbVS, v->VS, 4, 3, v->NbTimeStep); + write_txt(file, v->NbTS, v->TS, 4, 9, v->NbTimeStep); + write_txt(file, v->NbSH, v->SH, 8, 1, v->NbTimeStep); + write_txt(file, v->NbVH, v->VH, 8, 3, v->NbTimeStep); + write_txt(file, v->NbTH, v->TH, 8, 9, v->NbTimeStep); + write_txt(file, v->NbSI, v->SI, 6, 1, v->NbTimeStep); + write_txt(file, v->NbVI, v->VI, 6, 3, v->NbTimeStep); + write_txt(file, v->NbTI, v->TI, 6, 9, v->NbTimeStep); + write_txt(file, v->NbSY, v->SY, 5, 1, v->NbTimeStep); + write_txt(file, v->NbVY, v->VY, 5, 3, v->NbTimeStep); + write_txt(file, v->NbTY, v->TY, 5, 9, v->NbTimeStep); +} + +// Write view to file in MSH format + +class Nod{ + public: + int Num; + double X, Y, Z; + Nod() : Num(0), X(0.), Y(0.), Z(0.) {} + Nod(double x, double y, double z) : Num(0), X(x), Y(y), Z(z) {} +}; + +class NodCompPos{ + public: + bool operator()(const Nod ent1, const Nod ent2) const + { + double tol = CTX.lc * 1.e-10 ; + if(ent1.X - ent2.X > tol) return true; + if(ent1.X - ent2.X < -tol) return false; + if(ent1.Y - ent2.Y > tol) return true; + if(ent1.Y - ent2.Y < -tol) return false; + if(ent1.Z - ent2.Z > tol) return true; + return false; + } +}; + +static void get_nod(int nbelm, List_T *list, int nbnod, int nbcomp, + std::set<Nod, NodCompPos> *nodes, + int *numelm) +{ + if(nbelm){ + int nb = List_Nbr(list) / nbelm; + for(int i = 0; i < List_Nbr(list); i+=nb){ + double *x = (double *)List_Pointer_Fast(list, i); + double *y = (double *)List_Pointer_Fast(list, i + nbnod); + double *z = (double *)List_Pointer_Fast(list, i + 2 * nbnod); + for(int j = 0; j < nbnod; j++) { + Nod n(x[j], y[j], z[j]); + std::set<Nod, NodCompPos>::iterator it = nodes->find(n); + if(it == nodes->end()){ + n.Num = nodes->size() + 1; + nodes->insert(n); + } + } + (*numelm)++; + } + } +} + +static void print_elm(FILE *file, int num, int nbnod, Nod nod[8], + int nbcomp, double *vals, int dim) +{ + // compute average value in elm + double d = 0.; + for(int k = 0; k < nbnod; k++) { + double *v = &vals[nbcomp * k]; + switch(nbcomp) { + case 1: // scalar + d += v[0]; + break; + case 3 : // vector + d += sqrt(DSQR(v[0]) + DSQR(v[1]) + DSQR(v[2])); + break; + case 9 : // tensor + d += ComputeVonMises(v); + break; + } + } + d /= (double)nbnod; + + // assign val as elementary region number + int ele = (int)fabs(d), phys = 1; + + switch(dim){ + case 0: + fprintf(file, "%d 15 %d %d 1 %d\n", num, phys, ele, nod[0].Num); + break; + case 1: + fprintf(file, "%d 1 %d %d 2 %d %d\n", num, phys, ele, nod[0].Num, nod[1].Num); + break; + case 2: + if(nbnod == 3) + fprintf(file, "%d 2 %d %d 3 %d %d %d\n", num, phys, ele, + nod[0].Num, nod[1].Num, nod[2].Num); + else + fprintf(file, "%d 3 %d %d 4 %d %d %d %d\n", num, phys, ele, + nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num); + break; + case 3: + default: + if(nbnod == 4) + fprintf(file, "%d 4 %d %d 4 %d %d %d %d\n", num, phys, ele, + nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num); + else if(nbnod == 5) + fprintf(file, "%d 7 %d %d 5 %d %d %d %d %d\n", num, phys, ele, + nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num); + else if(nbnod == 6) + fprintf(file, "%d 6 %d %d 6 %d %d %d %d %d %d\n", num, phys, ele, + nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num, + nod[5].Num); + else + fprintf(file, "%d 5 %d %d 8 %d %d %d %d %d %d %d %d\n", num, phys, ele, + nod[0].Num, nod[1].Num, nod[2].Num, nod[3].Num, nod[4].Num, + nod[5].Num, nod[6].Num, nod[7].Num); + break; + } +} + +static void print_elms(FILE *file, int nbelm, List_T *list, + int nbnod, int nbcomp, int dim, + std::set<Nod, NodCompPos> *nodes, + int *numelm) +{ + Nod nod[8]; + + if(nbelm){ + int nb = List_Nbr(list) / nbelm; + for(int i = 0; i < List_Nbr(list); i+=nb){ + double *x = (double *)List_Pointer_Fast(list, i); + double *y = (double *)List_Pointer_Fast(list, i + nbnod); + double *z = (double *)List_Pointer_Fast(list, i + 2 * nbnod); + double *v = (double *)List_Pointer_Fast(list, i + 3 * nbnod); + for(int j = 0; j < nbnod; j++) { + Nod n(x[j], y[j], z[j]); + std::set<Nod, NodCompPos>::iterator it = nodes->find(n); + if(it == nodes->end()){ + Msg(GERROR, "Unknown node in element"); + return; + } + else{ + nod[j] = (Nod)(*it); + } + } + (*numelm)++; + print_elm(file, *numelm, nbnod, nod, nbcomp, v, dim); + } + } +} + +void WriteViewMSH(Post_View *v, FILE *file) +{ + std::set<Nod, NodCompPos> nodes; + int numelm = 0; + get_nod(v->NbSP, v->SP, 1, 1, &nodes, &numelm); + get_nod(v->NbVP, v->VP, 1, 3, &nodes, &numelm); + get_nod(v->NbTP, v->TP, 1, 9, &nodes, &numelm); + get_nod(v->NbSL, v->SL, 2, 1, &nodes, &numelm); + get_nod(v->NbVL, v->VL, 2, 3, &nodes, &numelm); + get_nod(v->NbTL, v->TL, 2, 9, &nodes, &numelm); + get_nod(v->NbST, v->ST, 3, 1, &nodes, &numelm); + get_nod(v->NbVT, v->VT, 3, 3, &nodes, &numelm); + get_nod(v->NbTT, v->TT, 3, 9, &nodes, &numelm); + get_nod(v->NbSQ, v->SQ, 4, 1, &nodes, &numelm); + get_nod(v->NbVQ, v->VQ, 4, 3, &nodes, &numelm); + get_nod(v->NbTQ, v->TQ, 4, 9, &nodes, &numelm); + get_nod(v->NbSS, v->SS, 4, 1, &nodes, &numelm); + get_nod(v->NbVS, v->VS, 4, 3, &nodes, &numelm); + get_nod(v->NbTS, v->TS, 4, 9, &nodes, &numelm); + get_nod(v->NbSH, v->SH, 8, 1, &nodes, &numelm); + get_nod(v->NbVH, v->VH, 8, 3, &nodes, &numelm); + get_nod(v->NbTH, v->TH, 8, 9, &nodes, &numelm); + get_nod(v->NbSI, v->SI, 6, 1, &nodes, &numelm); + get_nod(v->NbVI, v->VI, 6, 3, &nodes, &numelm); + get_nod(v->NbTI, v->TI, 6, 9, &nodes, &numelm); + get_nod(v->NbSY, v->SY, 5, 1, &nodes, &numelm); + get_nod(v->NbVY, v->VY, 5, 3, &nodes, &numelm); + get_nod(v->NbTY, v->TY, 5, 9, &nodes, &numelm); + + fprintf(file, "$NOD\n"); + fprintf(file, "%d\n", (int)nodes.size()); + std::set<Nod, NodCompPos>::const_iterator it = nodes.begin(); + std::set<Nod, NodCompPos>::const_iterator ite = nodes.end(); + for(; it != ite; ++it){ + Nod n = (Nod)(*it); + fprintf(file, "%d %.16g %.16g %.16g\n", n.Num, n.X, n.Y, n.Z); + } + fprintf(file, "$ENDNOD\n"); + + fprintf(file, "$ELM\n"); + fprintf(file, "%d\n", numelm); + numelm = 0; + print_elms(file, v->NbSP, v->SP, 1, 1, 0, &nodes, &numelm); + print_elms(file, v->NbVP, v->VP, 1, 3, 0, &nodes, &numelm); + print_elms(file, v->NbTP, v->TP, 1, 9, 0, &nodes, &numelm); + print_elms(file, v->NbSL, v->SL, 2, 1, 1, &nodes, &numelm); + print_elms(file, v->NbVL, v->VL, 2, 3, 1, &nodes, &numelm); + print_elms(file, v->NbTL, v->TL, 2, 9, 1, &nodes, &numelm); + print_elms(file, v->NbST, v->ST, 3, 1, 2, &nodes, &numelm); + print_elms(file, v->NbVT, v->VT, 3, 3, 2, &nodes, &numelm); + print_elms(file, v->NbTT, v->TT, 3, 9, 2, &nodes, &numelm); + print_elms(file, v->NbSQ, v->SQ, 4, 1, 2, &nodes, &numelm); + print_elms(file, v->NbVQ, v->VQ, 4, 3, 2, &nodes, &numelm); + print_elms(file, v->NbTQ, v->TQ, 4, 9, 2, &nodes, &numelm); + print_elms(file, v->NbSS, v->SS, 4, 1, 3, &nodes, &numelm); + print_elms(file, v->NbVS, v->VS, 4, 3, 3, &nodes, &numelm); + print_elms(file, v->NbTS, v->TS, 4, 9, 3, &nodes, &numelm); + print_elms(file, v->NbSH, v->SH, 8, 1, 3, &nodes, &numelm); + print_elms(file, v->NbVH, v->VH, 8, 3, 3, &nodes, &numelm); + print_elms(file, v->NbTH, v->TH, 8, 9, 3, &nodes, &numelm); + print_elms(file, v->NbSI, v->SI, 6, 1, 3, &nodes, &numelm); + print_elms(file, v->NbVI, v->VI, 6, 3, 3, &nodes, &numelm); + print_elms(file, v->NbTI, v->TI, 6, 9, 3, &nodes, &numelm); + print_elms(file, v->NbSY, v->SY, 5, 1, 3, &nodes, &numelm); + print_elms(file, v->NbVY, v->VY, 5, 3, 3, &nodes, &numelm); + print_elms(file, v->NbTY, v->TY, 5, 9, 3, &nodes, &numelm); + fprintf(file, "$ENDELM\n"); +} + +// Write view to file + +void WriteView(Post_View *v, char *filename, int format, int append) +{ + FILE *file; + int binary = (format == 1) ? 1 : 0; + int parsed = (format == 2); + int stl = (format == 3); + int txt = (format == 4); + int msh = (format == 5); + + if(filename) { + file = fopen(filename, append ? (binary ? "ab" : "a") : (binary ? "wb" : "w")); + if(!file) { + Msg(GERROR, "Unable to open file '%s'", filename); + return; + } + if(!append) + Msg(STATUS2, "Writing '%s'", filename); + } + else + file = stdout; + + if(stl) + WriteViewSTL(v, file); + else if(txt) + WriteViewTXT(v, file); + else if(msh) + WriteViewMSH(v, file); + else + WriteViewPOS(v, file, binary, parsed, append); + + if(filename) { + fclose(file); + Msg(STATUS2, "Wrote '%s'", filename); + } + +} diff --git a/Fltk/Bitmaps.h b/Fltk/Bitmaps.h new file mode 100644 index 0000000000000000000000000000000000000000..b959cb2bc70a4e0a0cf0724111821de18b140e3b --- /dev/null +++ b/Fltk/Bitmaps.h @@ -0,0 +1,92 @@ +#ifndef _BITMAPS_H_ +#define _BITMAPS_H_ + +// 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>. + +// Standard Gmsh Unix icon + +#if !defined(WIN32) && !defined(__APPLE__) +#define gmsh32x32_width 32 +#define gmsh32x32_height 32 +static char gmsh32x32_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x03, 0x00, + 0x00, 0x40, 0x03, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, 0x20, 0x07, 0x00, + 0x00, 0x10, 0x0f, 0x00, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x08, 0x1f, 0x00, + 0x00, 0x08, 0x1f, 0x00, 0x00, 0x04, 0x3f, 0x00, 0x00, 0x04, 0x3f, 0x00, + 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x01, 0xff, 0x00, + 0x00, 0x01, 0xff, 0x00, 0x80, 0x00, 0xff, 0x01, 0x80, 0x00, 0xff, 0x01, + 0x40, 0x00, 0xff, 0x03, 0x40, 0x00, 0xff, 0x03, 0x20, 0x00, 0xff, 0x07, + 0x20, 0x00, 0xff, 0x07, 0x10, 0x00, 0xff, 0x0f, 0x10, 0x00, 0xff, 0x0f, + 0x08, 0x00, 0xff, 0x1f, 0x08, 0x00, 0xff, 0x1f, 0x04, 0x40, 0xfd, 0x3f, + 0x04, 0xa8, 0xea, 0x3f, 0x02, 0x55, 0x55, 0x7f, 0xa2, 0xaa, 0xaa, 0x7a, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; +#endif + +// 'Abort' bitmap +// disabled until the mesh thread is back +/* +#define abort_width 13 +#define abort_height 13 +static char abort_bits[] = { + 0x00,0xe0,0x40,0xe0,0x40,0xe0,0x50,0xe1,0x48,0xe2,0x44,0xe4,0x44,0xe4,0x44, + 0xe4,0x04,0xe4,0x04,0xe4,0x08,0xe2,0xf0,0xe1,0x00,0xe0}; +*/ + +// 'Play button' bitmap + +#define start_width 9 +#define start_height 13 +static char start_bits[] = { + 0x00,0xfe,0x06,0xfe,0x0a,0xfe,0x12,0xfe,0x22,0xfe,0x42,0xfe,0x82,0xfe,0x42, + 0xfe,0x22,0xfe,0x12,0xfe,0x0a,0xfe,0x06,0xfe,0x00,0xfe}; + +// 'Pause button' bitmap + +#define stop_width 9 +#define stop_height 13 +static char stop_bits[] = { + 0x00,0xfe,0xee,0xfe,0xaa,0xfe,0xaa,0xfe,0xaa,0xfe,0xaa,0xfe,0xaa,0xfe,0xaa, + 0xfe,0xaa,0xfe,0xaa,0xfe,0xaa,0xfe,0xee,0xfe,0x00,0xfe}; + +// 'Rewind button' bitmap + +#define rewind_width 12 +#define rewind_height 13 +static char rewind_bits[] = { + 0x00,0xf0,0x0e,0xf6,0x0a,0xf5,0x8a,0xf4,0x4a,0xf4,0x2a,0xf4,0x1a,0xf4,0x2a, + 0xf4,0x4a,0xf4,0x8a,0xf4,0x0a,0xf5,0x0e,0xf6,0x00,0xf0}; + +// 'Orthographic projection' bitmap +#define ortho_width 13 +#define ortho_height 13 +static unsigned char ortho_bits[] = { + 0x00, 0x00, 0xf0, 0x0f, 0x18, 0x0c, 0x14, 0x0a, 0xfe, 0x09, 0x12, 0x09, + 0x12, 0x09, 0x12, 0x09, 0xf2, 0x0f, 0x0a, 0x05, 0x06, 0x03, 0xfe, 0x01, + 0x00, 0x00 }; + +// '90 degrees rotation' bitmap +#define rotate_width 12 +#define rotate_height 13 +static unsigned char rotate_bits[] = { + 0x00, 0x00, 0xf0, 0x00, 0x08, 0x01, 0x04, 0x02, 0x02, 0x04, 0x02, 0x04, + 0x02, 0x04, 0x02, 0x00, 0x24, 0x00, 0x68, 0x00, 0xf0, 0x00, 0x60, 0x00, + 0x20, 0x00 }; + +#endif diff --git a/Geo/fourierFace.h b/Geo/fourierFace.h new file mode 100644 index 0000000000000000000000000000000000000000..0c56386f0ad299ffda90145982ab1524b7eff8d3 --- /dev/null +++ b/Geo/fourierFace.h @@ -0,0 +1,95 @@ +#ifndef _FOURIER_MODEL_H_ +#define _FOURIER_MODEL_H_ + +#include "GModel.h" + +#if defined(HAVE_FOURIER_MODEL) + +#include "GVertex.h" +#include "GEdge.h" +#include "GFace.h" +#include "Range.h" + +class fourierVertex : public GVertex { + private: + MVertex *_v; + public: + fourierVertex(GModel *m, MVertex *v) : GVertex(m, v->getNum()), _v(v) + { + mesh_vertices.push_back(v); + } + virtual ~fourierVertex() {} + virtual GPoint point() const { return GPoint(_v->x(), _v->y(), _v->z(), this); } + virtual double x() const { return _v->x(); } + virtual double y() const { return _v->y(); } + virtual double z() const { return _v->z(); } + virtual double prescribedMeshSizeAtVertex() const { return 0.1; } + ModelType getNativeType() const { return FourierModel; } +}; + +class fourierEdge : public GEdge { + public: + fourierEdge(GModel *m, int num, GVertex *v1, GVertex *v2); + virtual ~fourierEdge() {} + double period() const { throw ; } + virtual bool periodic(int dim=0) const { return false; } + virtual Range<double> parBounds(int i) const { throw; } + virtual GeomType geomType() const { throw; } + virtual bool degenerate(int) const { return false; } + virtual bool continuous(int dim) const { return true; } + virtual GPoint point(double p) const { throw; } + virtual GPoint closestPoint(const SPoint3 & queryPoint) { throw; } + virtual int containsPoint(const SPoint3 &pt) const { throw; } + virtual int containsParam(double pt) const { throw; } + virtual SVector3 firstDer(double par) const { throw; } + virtual SPoint2 reparamOnFace(GFace * face, double epar, int dir) const { throw; } + virtual double parFromPoint(const SPoint3 &pt) const { throw; } + virtual int minimumMeshSegments () const { throw; } + virtual int minimumDrawSegments () const { throw; } + ModelType getNativeType() const { return FourierModel; } +}; + +class fourierFace : public GFace { + private: + // flag to know if is the face is already meshed + int _discrete; + // floag to know if the face is just a plane + int _plane; + // vertices and edges purely local to the face (not shared with the model) + GVertex *_v[4]; + GEdge *_e[4]; + public: + fourierFace(GModel *m, int num); + fourierFace(GFace *f, std::vector<MVertex*> &loop, std::vector<MVertex*> &hole); + virtual ~fourierFace(); + + void meshBoundary(); + + Range<double> parBounds(int i) const; + virtual int paramDegeneracies(int dir, double *par) { return 0; } + + virtual GPoint point(double par1, double par2) const; + virtual GPoint closestPoint(const SPoint3 & queryPoint) const ; + + virtual int containsPoint(const SPoint3 &pt) const; + virtual int containsParam(const SPoint2 &pt) const; + + virtual SVector3 normal(const SPoint2 ¶m) const; + virtual Pair<SVector3,SVector3> firstDer(const SPoint2 ¶m) const {throw;} + + virtual GEntity::GeomType geomType() const; + virtual int geomDirection() const { return 1; } + + virtual bool continuous(int dim) const { return true; } + virtual bool periodic(int dim) const { return false; } + virtual bool degenerate(int dim) const { return false; } + virtual double period(int dir) const {throw;} + ModelType getNativeType() const { return FourierModel; } + void * getNativePtr() const {throw;} + virtual bool surfPeriodic(int dim) const {throw;} + virtual SPoint2 parFromPoint(const SPoint3 &) const; +}; + +#endif + +#endif diff --git a/Plugin/DecomposeInSimplex.cpp b/Plugin/DecomposeInSimplex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e6f5e9a69cfeb674c4a56f3fdf8859a989b913e --- /dev/null +++ b/Plugin/DecomposeInSimplex.cpp @@ -0,0 +1,253 @@ +// $Id: DecomposeInSimplex.cpp,v 1.22 2007-05-04 10:45:08 geuzaine 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 "Plugin.h" +#include "DecomposeInSimplex.h" +#include "List.h" +#include "Tree.h" +#include "Views.h" +#include "Context.h" +#include "Malloc.h" +#include "Numeric.h" + +extern Context_T CTX; + +StringXNumber DecomposeInSimplexOptions_Number[] = { + {GMSH_FULLRC, "iView", NULL, -1.} +}; + +extern "C" +{ + GMSH_Plugin *GMSH_RegisterDecomposeInSimplexPlugin() + { + return new GMSH_DecomposeInSimplexPlugin(); + } +} + +GMSH_DecomposeInSimplexPlugin::GMSH_DecomposeInSimplexPlugin() +{ + ; +} + +void GMSH_DecomposeInSimplexPlugin::getName(char *name) const +{ + strcpy(name, "Decompose in Simplex"); +} + +void GMSH_DecomposeInSimplexPlugin::getInfos(char *author, char *copyright, + char *help_text) const +{ + strcpy(author, "C. Geuzaine"); + strcpy(copyright, "DGR (www.multiphysics.com)"); + strcpy(help_text, + "Plugin(DecomposeInSimplex) decomposes all\n" + "non-simplectic elements (quadrangles, prisms,\n" + "hexahedra, pyramids) in the view `iView' into\n" + "simplices (triangles, tetrahedra). If `iView' < 0,\n" + "the plugin is run on the current view.\n" + "\n" + "Plugin(DecomposeInSimplex) is executed\n" + "in-place.\n"); +} + +int GMSH_DecomposeInSimplexPlugin::getNbOptions() const +{ + return sizeof(DecomposeInSimplexOptions_Number) / sizeof(StringXNumber); +} + +StringXNumber *GMSH_DecomposeInSimplexPlugin::getOption(int iopt) +{ + return &DecomposeInSimplexOptions_Number[iopt]; +} + +void GMSH_DecomposeInSimplexPlugin::catchErrorMessage(char *errorMessage) const +{ + strcpy(errorMessage, "DecomposeInSimplex failed..."); +} + +static void decomposeList(Post_View *v, int nbNod, int nbComp, + List_T **listIn, int *nbIn, List_T *listOut, int *nbOut) +{ + double xNew[4], yNew[4], zNew[4]; + double *valNew = new double[v->NbTimeStep * nbComp * nbNod]; + DecomposeInSimplex dec(nbNod, nbComp, v->NbTimeStep); + + if(!(*nbIn)) + return; + + v->Changed = 1; + + int nb = List_Nbr(*listIn) / (*nbIn); + for(int i = 0; i < List_Nbr(*listIn); i += nb){ + double *x = (double *)List_Pointer(*listIn, i); + double *y = (double *)List_Pointer(*listIn, i + nbNod); + double *z = (double *)List_Pointer(*listIn, i + 2 * nbNod); + double *val = (double *)List_Pointer(*listIn, i + 3 * nbNod); + for(int j = 0; j < dec.numSimplices(); j++){ + dec.decompose(j, x, y, z, val, xNew, yNew, zNew, valNew); + for(int k = 0; k < dec.numSimplexNodes(); k++) + List_Add(listOut, &xNew[k]); + for(int k = 0; k < dec.numSimplexNodes(); k++) + List_Add(listOut, &yNew[k]); + for(int k = 0; k < dec.numSimplexNodes(); k++) + List_Add(listOut, &zNew[k]); + for(int k = 0; k < dec.numSimplexNodes()*v->NbTimeStep*nbComp; k++) + List_Add(listOut, &valNew[k]); + (*nbOut)++; + } + } + + delete [] valNew; + + List_Reset(*listIn); + *nbIn = 0; +} + +Post_View *GMSH_DecomposeInSimplexPlugin::execute(Post_View * v) +{ + int iView = (int)DecomposeInSimplexOptions_Number[0].def; + + if(iView < 0) + iView = v ? v->Index : 0; + + if(!List_Pointer_Test(CTX.post.list, iView)) { + Msg(GERROR, "View[%d] does not exist", iView); + return v; + } + + Post_View *v1 = *(Post_View **)List_Pointer(CTX.post.list, iView); + + // Bail out if the view is an alias or if other views duplicate it + if(v1->AliasOf || v1->Links) { + Msg(GERROR, "DecomposeInSimplex cannot be applied to an aliased view"); + return 0; + } + + // quads + decomposeList(v1, 4, 1, &v1->SQ, &v1->NbSQ, v1->ST, &v1->NbST); + decomposeList(v1, 4, 3, &v1->VQ, &v1->NbVQ, v1->VT, &v1->NbVT); + decomposeList(v1, 4, 9, &v1->TQ, &v1->NbTQ, v1->TT, &v1->NbTT); + + // hexas + decomposeList(v1, 8, 1, &v1->SH, &v1->NbSH, v1->SS, &v1->NbSS); + decomposeList(v1, 8, 3, &v1->VH, &v1->NbVH, v1->VS, &v1->NbVS); + decomposeList(v1, 8, 9, &v1->TH, &v1->NbTH, v1->TS, &v1->NbTS); + + // prisms + decomposeList(v1, 6, 1, &v1->SI, &v1->NbSI, v1->SS, &v1->NbSS); + decomposeList(v1, 6, 3, &v1->VI, &v1->NbVI, v1->VS, &v1->NbVS); + decomposeList(v1, 6, 9, &v1->TI, &v1->NbTI, v1->TS, &v1->NbTS); + + // pyramids + decomposeList(v1, 5, 1, &v1->SY, &v1->NbSY, v1->SS, &v1->NbSS); + decomposeList(v1, 5, 3, &v1->VY, &v1->NbVY, v1->VS, &v1->NbVS); + decomposeList(v1, 5, 9, &v1->TY, &v1->NbTY, v1->TS, &v1->NbTS); + + return v1; +} + +// Utility class + +DecomposeInSimplex::DecomposeInSimplex(int numNodes, int numComponents, int numTimeSteps) + : _numNodes(numNodes), _numComponents(numComponents), _numTimeSteps(numTimeSteps) +{ + ; +} + +int DecomposeInSimplex::numSimplices() +{ + switch(_numNodes) { + case 4: return 2; // quad -> 2 tris + case 5: return 2; // pyramid -> 2 tets + case 6: return 3; // prism -> 3 tets + case 8: return 6; // hexa -> 6 tets + } + return 0; +} + +int DecomposeInSimplex::numSimplexNodes() +{ + if(_numNodes == 4) + return 3; // quad -> tris + else + return 4; // all others -> tets +} + +void DecomposeInSimplex::reorder(int map[4], int n, + double *x, double *y, double *z, double *val, + double *xn, double *yn, double *zn, double *valn) +{ + for(int i = 0; i < n; i++) { + xn[i] = x[map[i]]; + yn[i] = y[map[i]]; + zn[i] = z[map[i]]; + } + + int map2[4] = {map[0], map[1], map[2], map[3]}; +#if 0 + // make sure to create tets with positive volume? + if(n == 4){ // tets + double mat[3][3]; + mat[0][0] = xn[1] - xn[0]; mat[0][1] = xn[2] - xn[0]; mat[0][2] = xn[3] - xn[0]; + mat[1][0] = yn[1] - yn[0]; mat[1][1] = yn[2] - yn[0]; mat[1][2] = yn[3] - yn[0]; + mat[2][0] = zn[1] - zn[0]; mat[2][1] = zn[2] - zn[0]; mat[2][2] = zn[3] - zn[0]; + if(det3x3(mat) < 0.){ + map2[0] = map[1]; + map2[1] = map[0]; + xn[0] = x[map2[0]]; + yn[0] = y[map2[0]]; + zn[0] = z[map2[0]]; + xn[1] = x[map2[1]]; + yn[1] = y[map2[1]]; + zn[1] = z[map2[1]]; + } + } +#endif + + for(int ts = 0; ts < _numTimeSteps; ts++) + for(int i = 0; i < n; i++) { + for(int j = 0; j < _numComponents; j++) + valn[ts*n*_numComponents + i*_numComponents + j] = + val[ts*_numNodes*_numComponents + map2[i]*_numComponents + j]; + } +} + +void DecomposeInSimplex::decompose(int num, + double *x, double *y, double *z, double *val, + double *xn, double *yn, double *zn, double *valn) +{ + int quadTri[2][4] = {{0,1,2,-1}, {0,2,3,-1}}; + int hexaTet[6][4] = {{0,1,3,7}, {0,4,1,7}, {1,4,5,7}, {1,2,3,7}, {1,6,2,7}, {1,5,6,7}}; + int prisTet[3][4] = {{0,1,2,4}, {0,2,4,5}, {0,3,4,5}}; + int pyraTet[2][4] = {{0,1,3,4}, {1,2,3,4}}; + + if(num < 0 || num > numSimplices()-1) { + Msg(GERROR, "Invalid decomposition"); + num = 0; + } + + switch(_numNodes) { + case 4: reorder(quadTri[num], 3, x, y, z, val, xn, yn, zn, valn); break ; + case 8: reorder(hexaTet[num], 4, x, y, z, val, xn, yn, zn, valn); break ; + case 6: reorder(prisTet[num], 4, x, y, z, val, xn, yn, zn, valn); break ; + case 5: reorder(pyraTet[num], 4, x, y, z, val, xn, yn, zn, valn); break ; + } +} diff --git a/Plugin/DecomposeInSimplex.h b/Plugin/DecomposeInSimplex.h new file mode 100644 index 0000000000000000000000000000000000000000..881024d2f50fced1ca9835cb9dd35cf31244bfa6 --- /dev/null +++ b/Plugin/DecomposeInSimplex.h @@ -0,0 +1,67 @@ +#ifndef _DECOMPOSE_IN_SIMPLEX_H_ +#define _DECOMPOSE_IN_SIMPLEX_H_ + +// 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 "Plugin.h" + +extern "C" +{ + GMSH_Plugin *GMSH_RegisterDecomposeInSimplexPlugin(); +} + +class GMSH_DecomposeInSimplexPlugin : public GMSH_Post_Plugin +{ +public: + GMSH_DecomposeInSimplexPlugin(); + void getName(char *name) const; + void getInfos(char *author, char *copyright, char *help_text) const; + void catchErrorMessage(char *errorMessage) const; + int getNbOptions() const; + StringXNumber* getOption(int iopt); + Post_View *execute(Post_View *); +}; + +class DecomposeInSimplex{ + private: + // how many nodes in the element to decompose + int _numNodes; + // how many field components + int _numComponents; + // how many time steps + int _numTimeSteps; + // create a simplex + void reorder(int map[4], int n, + double *x, double *y, double *z, double *val, + double *xn, double *yn, double *zn, double *valn); + public: + // default constructor + DecomposeInSimplex(int numNodes, int numComponents, int numTimeSteps=1); + // the number of simplices into which the element is decomposed + int numSimplices(); + // the number of nodes of the simplex + int numSimplexNodes(); + // returns the i-th simplex in the decomposition + void decompose(int num, + double *x, double *y, double *z, double *val, + double *xn, double *yn, double *zn, double *valn); +}; + +#endif diff --git a/benchmarks/bugs/geom8eu_needs_rand_1e-9.geo b/benchmarks/bugs/geom8eu_needs_rand_1e-9.geo new file mode 100644 index 0000000000000000000000000000000000000000..3ab453faff7bf4eda3a8b6609a6d5f0810537d62 --- /dev/null +++ b/benchmarks/bugs/geom8eu_needs_rand_1e-9.geo @@ -0,0 +1,487 @@ +Point(101) = {0, 0, -6, 20}; +Point(102) = {100, 0, -6, 20}; +Point(103) = {-100, 0, -6, 20}; +Point(104) = {0, 100, -6, 20}; +Point(105) = {0, -100, -6, 20}; +Point(106) = {0, 0, 194, 20}; +Point(107) = {0, 0, -206, 20}; +Point(201) = {-1, -1, -7, 0.3}; +Point(202) = {-1, -1, -5, 0.3}; +Point(203) = {-1, 1, -7, 0.3}; +Point(204) = {-1, 1, -5, 0.3}; +Point(205) = {1, -1, -7, 0.3}; +Point(206) = {1, -1, -5, 0.3}; +Point(207) = {1, 1, -7, 0.3}; +Point(208) = {1, 1, -5, 0.3}; +Point(301) = {0, -1, -4, 0.4}; +Point(302) = {0, -1, 6, 0.4}; +Point(303) = {0, 1, -4, 0.4}; +Point(304) = {0, 1, 6, 0.4}; +Point(305) = {-0.2, -1, -4, 0.4}; +Point(306) = {-0.2, -1, 6, 0.4}; +Point(307) = {-0.2, 1, -4, 0.4}; +Point(308) = {-0.2, 1, 6, 0.4}; +Point(401) = {0, -1, -8, 0.6}; +Point(402) = {0, -1, -18, 0.6}; +Point(403) = {0, 1, -8, 0.6}; +Point(404) = {0, 1, -18, 0.6}; +Point(405) = {-0.2, -1, -8, 0.6}; +Point(406) = {-0.2, -1, -18, 0.6}; +Point(407) = {-0.2, 1, -8, 0.6}; +Point(408) = {-0.2, 1, -18, 0.6}; +Point(1001) = {0, -0.01, 0.9995000000000001, 0.0007}; +Point(1002) = {0, -0.01, 1.0005, 0.0007}; +Point(1003) = {0, 0.01, 0.9995000000000001, 0.0007}; +Point(1004) = {0, 0.01, 1.0005, 0.0007}; +Point(1005) = {0, -0.02, 0.997, 0.00175}; +Point(1006) = {0, -0.02, 1.003, 0.00175}; +Point(1007) = {0, 0.02, 0.997, 0.00175}; +Point(1008) = {0, 0.02, 1.003, 0.00175}; +Point(1009) = {0.005590169943749475, -0.02, 0.997, 0.002625}; +Point(1010) = {0.005590169943749475, -0.02, 1.003, 0.002625}; +Point(1011) = {0.005590169943749475, 0.02, 0.997, 0.002625}; +Point(1012) = {0.005590169943749475, 0.02, 1.003, 0.002625}; +Point(1013) = {0, -0.04, 0.991, 0.004375}; +Point(1014) = {0, -0.04, 1.009, 0.004375}; +Point(1015) = {0, 0.04, 0.991, 0.004375}; +Point(1016) = {0, 0.04, 1.009, 0.004375}; +Point(1017) = {0.01397542485937369, -0.04, 0.991, 0.006562500000000001}; +Point(1018) = {0.01397542485937369, -0.04, 1.009, 0.006562500000000001}; +Point(1019) = {0.01397542485937369, 0.04, 0.991, 0.006562500000000001}; +Point(1020) = {0.01397542485937369, 0.04, 1.009, 0.006562500000000001}; +Point(1021) = {0, -0.08, 0.973, 0.0109375}; +Point(1022) = {0, -0.08, 1.027, 0.0109375}; +Point(1023) = {0, 0.08, 0.973, 0.0109375}; +Point(1024) = {0, 0.08, 1.027, 0.0109375}; +Point(1025) = {0.03493856214843422, -0.08, 0.973, 0.01640625}; +Point(1026) = {0.03493856214843422, -0.08, 1.027, 0.01640625}; +Point(1027) = {0.03493856214843422, 0.08, 0.973, 0.01640625}; +Point(1028) = {0.03493856214843422, 0.08, 1.027, 0.01640625}; +Point(1029) = {0, -0.16, 0.919, 0.02734375}; +Point(1030) = {0, -0.16, 1.081, 0.02734375}; +Point(1031) = {0, 0.16, 0.919, 0.02734375}; +Point(1032) = {0, 0.16, 1.081, 0.02734375}; +Point(1033) = {0.08734640537108554, -0.16, 0.919, 0.04101562500000001}; +Point(1034) = {0.08734640537108554, -0.16, 1.081, 0.04101562500000001}; +Point(1035) = {0.08734640537108554, 0.16, 0.919, 0.04101562500000001}; +Point(1036) = {0.08734640537108554, 0.16, 1.081, 0.04101562500000001}; +Point(1037) = {0, -0.32, 0.7569999999999999, 0.06835937500000001}; +Point(1038) = {0, -0.32, 1.243, 0.06835937500000001}; +Point(1039) = {0, 0.32, 0.7569999999999999, 0.06835937500000001}; +Point(1040) = {0, 0.32, 1.243, 0.06835937500000001}; +Point(1041) = {0.2183660134277138, -0.32, 0.7569999999999999, 0.1025390625}; +Point(1042) = {0.2183660134277138, -0.32, 1.243, 0.1025390625}; +Point(1043) = {0.2183660134277138, 0.32, 0.7569999999999999, 0.1025390625}; +Point(1044) = {0.2183660134277138, 0.32, 1.243, 0.1025390625}; +Point(1045) = {0, -0.64, 0.2709999999999999, 0.1708984375}; +Point(1046) = {0, -0.64, 1.729, 0.1708984375}; +Point(1047) = {0, 0.64, 0.2709999999999999, 0.1708984375}; +Point(1048) = {0, 0.64, 1.729, 0.1708984375}; +Point(1049) = {0.5459150335692846, -0.64, 0.2709999999999999, 0.2563476562500001}; +Point(1050) = {0.5459150335692846, -0.64, 1.729, 0.2563476562500001}; +Point(1051) = {0.5459150335692846, 0.64, 0.2709999999999999, 0.2563476562500001}; +Point(1052) = {0.5459150335692846, 0.64, 1.729, 0.2563476562500001}; +Point(1053) = {-2.5, -2.5, -24, 0.75}; +Point(1054) = {-2.5, -2.5, 12, 0.75}; +Point(1055) = {-2.5, 2.5, -24, 0.75}; +Point(1056) = {-2.5, 2.5, 12, 0.75}; +Point(1057) = {2.5, -2.5, -24, 0.75}; +Point(1058) = {2.5, -2.5, 12, 0.75}; +Point(1059) = {2.5, 2.5, -24, 0.75}; +Point(1060) = {2.5, 2.5, 12, 0.75}; +Point(1061) = {-6.25, -6.25, -33, 1.875}; +Point(1062) = {-6.25, -6.25, 21, 1.875}; +Point(1063) = {-6.25, 6.25, -33, 1.875}; +Point(1064) = {-6.25, 6.25, 21, 1.875}; +Point(1065) = {6.25, -6.25, -33, 1.875}; +Point(1066) = {6.25, -6.25, 21, 1.875}; +Point(1067) = {6.25, 6.25, -33, 1.875}; +Point(1068) = {6.25, 6.25, 21, 1.875}; +Point(1069) = {-15.625, -15.625, -46.5, 4.6875}; +Point(1070) = {-15.625, -15.625, 34.5, 4.6875}; +Point(1071) = {-15.625, 15.625, -46.5, 4.6875}; +Point(1072) = {-15.625, 15.625, 34.5, 4.6875}; +Point(1073) = {15.625, -15.625, -46.5, 4.6875}; +Point(1074) = {15.625, -15.625, 34.5, 4.6875}; +Point(1075) = {15.625, 15.625, -46.5, 4.6875}; +Point(1076) = {15.625, 15.625, 34.5, 4.6875}; +Point(1077) = {-39.0625, -39.0625, -66.75, 11.71875}; +Point(1078) = {-39.0625, -39.0625, 54.75, 11.71875}; +Point(1079) = {-39.0625, 39.0625, -66.75, 11.71875}; +Point(1080) = {-39.0625, 39.0625, 54.75, 11.71875}; +Point(1081) = {39.0625, -39.0625, -66.75, 11.71875}; +Point(1082) = {39.0625, -39.0625, 54.75, 11.71875}; +Point(1083) = {39.0625, 39.0625, -66.75, 11.71875}; +Point(1084) = {39.0625, 39.0625, 54.75, 11.71875}; +Ellipse (1) = {103, 101, 103, 104} Plane{0, 0, 1}; +Ellipse (2) = {106, 101, 104, 104} Plane{0, 0, 1}; +Ellipse (3) = {102, 101, 104, 104} Plane{0, 0, 1}; +Ellipse (4) = {107, 101, 104, 104} Plane{0, 0, 1}; +Ellipse (5) = {105, 101, 106, 106} Plane{0, 0, 1}; +Ellipse (6) = {105, 101, 103, 103} Plane{0, 0, 1}; +Ellipse (7) = {105, 101, 107, 107} Plane{0, 0, 1}; +Ellipse (8) = {105, 101, 102, 102} Plane{0, 0, 1}; +Ellipse (9) = {103, 101, 106, 106} Plane{0, 0, 1}; +Ellipse (10) = {106, 101, 102, 102} Plane{0, 0, 1}; +Ellipse (11) = {102, 101, 107, 107} Plane{0, 0, 1}; +Ellipse (12) = {107, 101, 103, 103} Plane{0, 0, 1}; +Line (10031) = {201, 202}; +Line (10032) = {203, 204}; +Line (10033) = {207, 208}; +Line (10034) = {205, 206}; +Line (10035) = {205, 201}; +Line (10036) = {206, 202}; +Line (10037) = {208, 204}; +Line (10038) = {207, 203}; +Line (10039) = {203, 201}; +Line (10040) = {204, 202}; +Line (10041) = {208, 206}; +Line (10042) = {207, 205}; +Line (20057) = {304, 308}; +Line (20058) = {302, 306}; +Line (20059) = {301, 305}; +Line (20060) = {303, 307}; +Line (20061) = {303, 301}; +Line (20062) = {307, 305}; +Line (20063) = {304, 302}; +Line (20064) = {308, 306}; +Line (20065) = {304, 303}; +Line (20066) = {308, 307}; +Line (20067) = {302, 301}; +Line (20068) = {306, 305}; +Line (30057) = {404, 408}; +Line (30058) = {402, 406}; +Line (30059) = {401, 405}; +Line (30060) = {403, 407}; +Line (30061) = {403, 401}; +Line (30062) = {407, 405}; +Line (30063) = {404, 402}; +Line (30064) = {408, 406}; +Line (30065) = {404, 403}; +Line (30066) = {408, 407}; +Line (30067) = {402, 401}; +Line (30068) = {406, 405}; +Line (30082) = {1004, 1003}; +Line (30083) = {1002, 1001}; +Line (30084) = {1004, 1002}; +Line (30085) = {1003, 1001}; +Line (30088) = {1005, 1006}; +Line (30089) = {1007, 1008}; +Line (30090) = {1009, 1010}; +Line (30091) = {1011, 1012}; +Line (30092) = {1005, 1007}; +Line (30093) = {1006, 1008}; +Line (30094) = {1009, 1011}; +Line (30095) = {1010, 1012}; +Line (30096) = {1005, 1009}; +Line (30097) = {1006, 1010}; +Line (30098) = {1007, 1011}; +Line (30099) = {1008, 1012}; +Line (30114) = {1013, 1014}; +Line (30115) = {1015, 1016}; +Line (30116) = {1017, 1018}; +Line (30117) = {1019, 1020}; +Line (30118) = {1013, 1015}; +Line (30119) = {1014, 1016}; +Line (30120) = {1017, 1019}; +Line (30121) = {1018, 1020}; +Line (30122) = {1013, 1017}; +Line (30123) = {1014, 1018}; +Line (30124) = {1015, 1019}; +Line (30125) = {1016, 1020}; +Line (30140) = {1021, 1022}; +Line (30141) = {1023, 1024}; +Line (30142) = {1025, 1026}; +Line (30143) = {1027, 1028}; +Line (30144) = {1021, 1023}; +Line (30145) = {1022, 1024}; +Line (30146) = {1025, 1027}; +Line (30147) = {1026, 1028}; +Line (30148) = {1021, 1025}; +Line (30149) = {1022, 1026}; +Line (30150) = {1023, 1027}; +Line (30151) = {1024, 1028}; +Line (30166) = {1029, 1030}; +Line (30167) = {1031, 1032}; +Line (30168) = {1033, 1034}; +Line (30169) = {1035, 1036}; +Line (30170) = {1029, 1031}; +Line (30171) = {1030, 1032}; +Line (30172) = {1033, 1035}; +Line (30173) = {1034, 1036}; +Line (30174) = {1029, 1033}; +Line (30175) = {1030, 1034}; +Line (30176) = {1031, 1035}; +Line (30177) = {1032, 1036}; +Line (30192) = {1037, 1038}; +Line (30193) = {1039, 1040}; +Line (30194) = {1041, 1042}; +Line (30195) = {1043, 1044}; +Line (30196) = {1037, 1039}; +Line (30197) = {1038, 1040}; +Line (30198) = {1041, 1043}; +Line (30199) = {1042, 1044}; +Line (30200) = {1037, 1041}; +Line (30201) = {1038, 1042}; +Line (30202) = {1039, 1043}; +Line (30203) = {1040, 1044}; +Line (30218) = {1045, 1046}; +Line (30219) = {1047, 1048}; +Line (30220) = {1049, 1050}; +Line (30221) = {1051, 1052}; +Line (30222) = {1045, 1047}; +Line (30223) = {1046, 1048}; +Line (30224) = {1049, 1051}; +Line (30225) = {1050, 1052}; +Line (30226) = {1045, 1049}; +Line (30227) = {1046, 1050}; +Line (30228) = {1047, 1051}; +Line (30229) = {1048, 1052}; +Line (30244) = {1053, 1054}; +Line (30245) = {1055, 1056}; +Line (30246) = {1057, 1058}; +Line (30247) = {1059, 1060}; +Line (30248) = {1053, 1055}; +Line (30249) = {1054, 1056}; +Line (30250) = {1057, 1059}; +Line (30251) = {1058, 1060}; +Line (30252) = {1053, 1057}; +Line (30253) = {1054, 1058}; +Line (30254) = {1055, 1059}; +Line (30255) = {1056, 1060}; +Line (30269) = {1061, 1062}; +Line (30270) = {1063, 1064}; +Line (30271) = {1065, 1066}; +Line (30272) = {1067, 1068}; +Line (30273) = {1061, 1063}; +Line (30274) = {1062, 1064}; +Line (30275) = {1065, 1067}; +Line (30276) = {1066, 1068}; +Line (30277) = {1061, 1065}; +Line (30278) = {1062, 1066}; +Line (30279) = {1063, 1067}; +Line (30280) = {1064, 1068}; +Line (30294) = {1069, 1070}; +Line (30295) = {1071, 1072}; +Line (30296) = {1073, 1074}; +Line (30297) = {1075, 1076}; +Line (30298) = {1069, 1071}; +Line (30299) = {1070, 1072}; +Line (30300) = {1073, 1075}; +Line (30301) = {1074, 1076}; +Line (30302) = {1069, 1073}; +Line (30303) = {1070, 1074}; +Line (30304) = {1071, 1075}; +Line (30305) = {1072, 1076}; +Line (30319) = {1077, 1078}; +Line (30320) = {1079, 1080}; +Line (30321) = {1081, 1082}; +Line (30322) = {1083, 1084}; +Line (30323) = {1077, 1079}; +Line (30324) = {1078, 1080}; +Line (30325) = {1081, 1083}; +Line (30326) = {1082, 1084}; +Line (30327) = {1077, 1081}; +Line (30328) = {1078, 1082}; +Line (30329) = {1079, 1083}; +Line (30330) = {1080, 1084}; +Line Loop (1000014) = {2, -1, 9}; +Ruled Surface (14) = {1000014}; +Line Loop (1000016) = {4, -1, -12}; +Ruled Surface (16) = {1000016}; +Line Loop (1000018) = {2, -3, -10}; +Ruled Surface (18) = {1000018}; +Line Loop (1000020) = {3, -4, -11}; +Ruled Surface (20) = {1000020}; +Line Loop (1000022) = {5, -9, -6}; +Ruled Surface (22) = {1000022}; +Line Loop (1000024) = {7, 12, -6}; +Ruled Surface (24) = {1000024}; +Line Loop (1000026) = {7, -11, -8}; +Ruled Surface (26) = {1000026}; +Line Loop (1000028) = {8, -10, -5}; +Ruled Surface (28) = {1000028}; +Line Loop (1010044) = {10031, -10040, -10032, 10039}; +Plane Surface (10044) = {1010044}; +Line Loop (1010046) = {10042, 10034, -10041, -10033}; +Plane Surface (10046) = {1010046}; +Line Loop (1010048) = {10035, -10039, -10038, 10042}; +Plane Surface (10048) = {1010048}; +Line Loop (1010050) = {10036, -10040, -10037, 10041}; +Plane Surface (10050) = {1010050}; +Line Loop (1010052) = {10034, 10036, -10031, -10035}; +Plane Surface (10052) = {1010052}; +Line Loop (1010054) = {10032, -10037, -10033, 10038}; +Plane Surface (10054) = {1010054}; +Line Loop (1020070) = {20063, 20058, -20064, -20057}; +Plane Surface (20070) = {1020070}; +Line Loop (1020072) = {20061, 20059, -20062, -20060}; +Plane Surface (20072) = {1020072}; +Line Loop (1020074) = {20065, 20060, -20066, -20057}; +Plane Surface (20074) = {1020074}; +Line Loop (1020076) = {20067, 20059, -20068, -20058}; +Plane Surface (20076) = {1020076}; +Line Loop (1020078) = {20064, 20068, -20062, -20066}; +Plane Surface (20078) = {1020078}; +Line Loop (1030070) = {30063, 30058, -30064, -30057}; +Plane Surface (30070) = {1030070}; +Line Loop (1030072) = {30061, 30059, -30062, -30060}; +Plane Surface (30072) = {1030072}; +Line Loop (1030074) = {30065, 30060, -30066, -30057}; +Plane Surface (30074) = {1030074}; +Line Loop (1030076) = {30067, 30059, -30068, -30058}; +Plane Surface (30076) = {1030076}; +Line Loop (1030078) = {30064, 30068, -30062, -30066}; +Plane Surface (30078) = {1030078}; +Line Loop (1030080) = {30063, 30067, -30061, -30065}; +Plane Surface (30080) = {1030080}; +Line Loop (1030087) = {30084, 30083, -30085, -30082}; +Plane Surface (30087) = {1030087}; +Line Loop (1030090) = {20063, 20067, -20061, -20065, 30222, 30219, -30223, -30218}; +Plane Surface (30090) = {1030090}; +Line Loop (1030106) = {30088, 30093, -30089, -30092, 30082, 30085, -30083, -30084}; +Plane Surface (30106) = {1030106}; +Line Loop (1030107) = {-30090, 30094, 30091, -30095}; +Plane Surface (30107) = {1030107}; +Line Loop (1030108) = {-30088, 30096, 30090, -30097}; +Plane Surface (30108) = {1030108}; +Line Loop (1030109) = {30089, 30099, -30091, -30098}; +Plane Surface (30109) = {1030109}; +Line Loop (1030110) = {30092, 30098, -30094, -30096}; +Plane Surface (30110) = {1030110}; +Line Loop (1030111) = {-30093, 30097, 30095, -30099}; +Plane Surface (30111) = {1030111}; +Line Loop (1030132) = {30114, 30119, -30115, -30118, 30092, 30089, -30093, -30088}; +Plane Surface (30132) = {1030132}; +Line Loop (1030133) = {-30116, 30120, 30117, -30121}; +Plane Surface (30133) = {1030133}; +Line Loop (1030134) = {-30114, 30122, 30116, -30123}; +Plane Surface (30134) = {1030134}; +Line Loop (1030135) = {30115, 30125, -30117, -30124}; +Plane Surface (30135) = {1030135}; +Line Loop (1030136) = {30118, 30124, -30120, -30122}; +Plane Surface (30136) = {1030136}; +Line Loop (1030137) = {-30119, 30123, 30121, -30125}; +Plane Surface (30137) = {1030137}; +Line Loop (1030158) = {30140, 30145, -30141, -30144, 30118, 30115, -30119, -30114}; +Plane Surface (30158) = {1030158}; +Line Loop (1030159) = {-30142, 30146, 30143, -30147}; +Plane Surface (30159) = {1030159}; +Line Loop (1030160) = {-30140, 30148, 30142, -30149}; +Plane Surface (30160) = {1030160}; +Line Loop (1030161) = {30141, 30151, -30143, -30150}; +Plane Surface (30161) = {1030161}; +Line Loop (1030162) = {30144, 30150, -30146, -30148}; +Plane Surface (30162) = {1030162}; +Line Loop (1030163) = {-30145, 30149, 30147, -30151}; +Plane Surface (30163) = {1030163}; +Line Loop (1030184) = {30166, 30171, -30167, -30170, 30144, 30141, -30145, -30140}; +Plane Surface (30184) = {1030184}; +Line Loop (1030185) = {-30168, 30172, 30169, -30173}; +Plane Surface (30185) = {1030185}; +Line Loop (1030186) = {-30166, 30174, 30168, -30175}; +Plane Surface (30186) = {1030186}; +Line Loop (1030187) = {30167, 30177, -30169, -30176}; +Plane Surface (30187) = {1030187}; +Line Loop (1030188) = {30170, 30176, -30172, -30174}; +Plane Surface (30188) = {1030188}; +Line Loop (1030189) = {-30171, 30175, 30173, -30177}; +Plane Surface (30189) = {1030189}; +Line Loop (1030210) = {30192, 30197, -30193, -30196, 30170, 30167, -30171, -30166}; +Plane Surface (30210) = {1030210}; +Line Loop (1030211) = {-30194, 30198, 30195, -30199}; +Plane Surface (30211) = {1030211}; +Line Loop (1030212) = {-30192, 30200, 30194, -30201}; +Plane Surface (30212) = {1030212}; +Line Loop (1030213) = {30193, 30203, -30195, -30202}; +Plane Surface (30213) = {1030213}; +Line Loop (1030214) = {30196, 30202, -30198, -30200}; +Plane Surface (30214) = {1030214}; +Line Loop (1030215) = {-30197, 30201, 30199, -30203}; +Plane Surface (30215) = {1030215}; +Line Loop (1030236) = {30218, 30223, -30219, -30222, 30196, 30193, -30197, -30192}; +Plane Surface (30236) = {1030236}; +Line Loop (1030237) = {-30220, 30224, 30221, -30225}; +Plane Surface (30237) = {1030237}; +Line Loop (1030238) = {-30218, 30226, 30220, -30227}; +Plane Surface (30238) = {1030238}; +Line Loop (1030239) = {30219, 30229, -30221, -30228}; +Plane Surface (30239) = {1030239}; +Line Loop (1030240) = {30222, 30228, -30224, -30226}; +Plane Surface (30240) = {1030240}; +Line Loop (1030241) = {-30223, 30227, 30225, -30229}; +Plane Surface (30241) = {1030241}; +Line Loop (1030257) = {30244, 30249, -30245, -30248}; +Plane Surface (30257) = {1030257}; +Line Loop (1030259) = {-30246, 30250, 30247, -30251}; +Plane Surface (30259) = {1030259}; +Line Loop (1030261) = {-30244, 30252, 30246, -30253}; +Plane Surface (30261) = {1030261}; +Line Loop (1030263) = {30245, 30255, -30247, -30254}; +Plane Surface (30263) = {1030263}; +Line Loop (1030265) = {30248, 30254, -30250, -30252}; +Plane Surface (30265) = {1030265}; +Line Loop (1030267) = {-30249, 30253, 30251, -30255}; +Plane Surface (30267) = {1030267}; +Line Loop (1030282) = {30269, 30274, -30270, -30273}; +Plane Surface (30282) = {1030282}; +Line Loop (1030284) = {-30271, 30275, 30272, -30276}; +Plane Surface (30284) = {1030284}; +Line Loop (1030286) = {-30269, 30277, 30271, -30278}; +Plane Surface (30286) = {1030286}; +Line Loop (1030288) = {30270, 30280, -30272, -30279}; +Plane Surface (30288) = {1030288}; +Line Loop (1030290) = {30273, 30279, -30275, -30277}; +Plane Surface (30290) = {1030290}; +Line Loop (1030292) = {-30274, 30278, 30276, -30280}; +Plane Surface (30292) = {1030292}; +Line Loop (1030307) = {30294, 30299, -30295, -30298}; +Plane Surface (30307) = {1030307}; +Line Loop (1030309) = {-30296, 30300, 30297, -30301}; +Plane Surface (30309) = {1030309}; +Line Loop (1030311) = {-30294, 30302, 30296, -30303}; +Plane Surface (30311) = {1030311}; +Line Loop (1030313) = {30295, 30305, -30297, -30304}; +Plane Surface (30313) = {1030313}; +Line Loop (1030315) = {30298, 30304, -30300, -30302}; +Plane Surface (30315) = {1030315}; +Line Loop (1030317) = {-30299, 30303, 30301, -30305}; +Plane Surface (30317) = {1030317}; +Line Loop (1030332) = {30319, 30324, -30320, -30323}; +Plane Surface (30332) = {1030332}; +Line Loop (1030334) = {-30321, 30325, 30322, -30326}; +Plane Surface (30334) = {1030334}; +Line Loop (1030336) = {-30319, 30327, 30321, -30328}; +Plane Surface (30336) = {1030336}; +Line Loop (1030338) = {30320, 30330, -30322, -30329}; +Plane Surface (30338) = {1030338}; +Line Loop (1030340) = {30323, 30329, -30325, -30327}; +Plane Surface (30340) = {1030340}; +Line Loop (1030342) = {-30324, 30328, 30326, -30330}; +Plane Surface (30342) = {1030342}; +Surface Loop (1000001) = {30282, 30284, 30286, 30288, 30290, 30292, 30257, 30259, 30261, 30263, 30265, 30267}; +Volume (1) = {1000001}; +Surface Loop (1000002) = {30307, 30309, 30311, 30313, 30315, 30317, 30282, 30284, 30286, 30288, 30290, 30292}; +Volume (2) = {1000002}; +Surface Loop (1000003) = {30332, 30334, 30336, 30338, 30340, 30342, 30307, 30309, 30311, 30313, 30315, 30317}; +Volume (3) = {1000003}; +Surface Loop (1000004) = {22, 28, 26, 24, 16, 20, 18, 14, 30332, 30334, 30336, 30338, 30340, 30342}; +Volume (4) = {1000004}; +Surface Loop (1001000) = {30257, 30259, 30261, 30263, 30265, 30267, 10052, 10046, 10048, 10044, 10050, 10054, 30090, 30237, 30238, 30239, 30240, 30241, 20070, 20076, 20072, 20078, 20074, 30080, 30070, 30076, 30072, 30078, 30074}; +Volume (1000) = {1001000}; +Surface Loop (1030113) = {30106, 30107, 30108, 30109, 30110, 30111, 30087}; +Volume (30113) = {1030113}; +Surface Loop (1030139) = {30132, 30133, 30134, 30135, 30136, 30137, 30107, 30108, 30109, 30110, 30111}; +Volume (30139) = {1030139}; +Surface Loop (1030165) = {30158, 30159, 30160, 30161, 30162, 30163, 30133, 30134, 30135, 30136, 30137}; +Volume (30165) = {1030165}; +Surface Loop (1030191) = {30184, 30185, 30186, 30187, 30188, 30189, 30159, 30160, 30161, 30162, 30163}; +Volume (30191) = {1030191}; +Surface Loop (1030217) = {30210, 30211, 30212, 30213, 30214, 30215, 30185, 30186, 30187, 30188, 30189}; +Volume (30217) = {1030217}; +Surface Loop (1030243) = {30236, 30237, 30238, 30239, 30240, 30241, 30211, 30212, 30213, 30214, 30215}; +Volume (30243) = {1030243}; +Physical Surface (1) = {14, 16, 18, 20, 22, 24, 26, 28}; +Physical Surface (2) = {10044, 10046, 10048, 10050, 10052, 10054}; +Physical Surface (3) = {30087}; +Physical Surface (5) = {30070, 30072, 30074, 30076, 30078, 30080}; diff --git a/examples/cube.geo b/examples/cube.geo deleted file mode 100644 index decdd4a696bb42dae6ae5bda42e91f3bb5b099e1..0000000000000000000000000000000000000000 --- a/examples/cube.geo +++ /dev/null @@ -1,83 +0,0 @@ -lcar1 = .0275; - -length = 0.25; -height = 1.0; -depth = 0.25; - -Point(newp) = {length/2,height/2,depth,lcar1}; /* Point 1 */ -Point(newp) = {length/2,height/2,0,lcar1}; /* Point 2 */ -Point(newp) = {-length/2,height/2,depth,lcar1}; /* Point 3 */ -Point(newp) = {-length/2,-height/2,depth,lcar1}; /* Point 4 */ -Point(newp) = {length/2,-height/2,depth,lcar1}; /* Point 5 */ -Point(newp) = {length/2,-height/2,0,lcar1}; /* Point 6 */ -Point(newp) = {-length/2,height/2,0,lcar1}; /* Point 7 */ -Point(newp) = {-length/2,-height/2,0,lcar1}; /* Point 8 */ -Line(1) = {3,1}; -Line(2) = {3,7}; -Line(3) = {7,2}; -Line(4) = {2,1}; -Line(5) = {1,5}; -Line(6) = {5,4}; -Line(7) = {4,8}; -Line(8) = {8,6}; -Line(9) = {6,5}; -Line(10) = {6,2}; -Line(11) = {3,4}; -Line(12) = {8,7}; -Line Loop(13) = {-6,-5,-1,11}; -Plane Surface(14) = {13}; -Line Loop(15) = {4,5,-9,10}; -Plane Surface(16) = {15}; -Line Loop(17) = {-3,-12,8,10}; -Plane Surface(18) = {17}; -Line Loop(19) = {7,12,-2,11}; -Plane Surface(20) = {19}; -Line Loop(21) = {-4,-3,-2,1}; -Plane Surface(22) = {21}; -Line Loop(23) = {8,9,6,7}; -Plane Surface(24) = {23}; - -Surface Loop(25) = {14,24,-18,22,16,-20}; -Complex Volume(26) = {25}; - -n = 21; - -/* -sizex = 4; -sizey = 6; -sizez = 4; -*/ -sizex = n*length; -sizey = n*height; -sizez = n*depth; - -sizex = 9; -sizey = 33; -sizez = 9; - - -Transfinite Line {2,4,9,7} = sizez; -Transfinite Line {11,5,10,12} = sizey; -Transfinite Line {3,1,6,8} = sizex; - -Transfinite Surface {14} = {5,4,3,1}; -Transfinite Surface {16} = {6,2,1,5}; -Transfinite Surface {18} = {6,2,7,8}; -Transfinite Surface {20} = {3,7,8,4}; -Transfinite Surface {22} = {3,7,2,1}; -Transfinite Surface {24} = {4,8,6,5}; - -Recombine Surface {14,16,18,20,22,24}; - -Transfinite Volume {26} = {3,7,2,1,4,8,6,5}; - -Physical Surface(200) = {14,16,18,20,24}; - -Physical Volume(100) = {26}; -/* -Mesh.use_cut_plane = 1; -Mesh.cut_planea = 0; -Mesh.cut_planeb = 0; -Mesh.cut_planec = 1; -Mesh.cut_planed = -0.125; -*/ \ No newline at end of file