#include #include #include #include #include // #include #include #include namespace netgen { VisualSceneSolution & GetVSSolution() { static VisualSceneSolution vssolution; return vssolution; } // extern shared_ptr mesh; extern VisualSceneMesh vsmesh; VisualSceneSolution :: SolData :: SolData () : data (0), solclass(0) { ; } VisualSceneSolution :: SolData :: ~SolData () { // delete [] name; delete data; delete solclass; } VisualSceneSolution :: VisualSceneSolution () : VisualScene() { // cout << "init VisualSceneSolution" << endl; surfellist = 0; linelist = 0; element1dlist = 0; clipplanelist_scal = 0; clipplanelist_vec = 0; isolinelist = 0; clipplane_isolinelist = 0; surface_vector_list = 0; isosurface_list = 0; numtexturecols = 8; fieldlineslist = 0; pointcurvelist = 0; num_fieldlineslists = 0; surfeltimestamp = GetTimeStamp(); surfellinetimestamp = GetTimeStamp(); clipplanetimestamp = GetTimeStamp(); solutiontimestamp = GetTimeStamp(); fieldlinestimestamp = GetTimeStamp(); pointcurve_timestamp = GetTimeStamp(); surface_vector_timestamp = GetTimeStamp(); isosurface_timestamp = GetTimeStamp(); timetimestamp = GetTimeStamp(); // AddVisualizationScene ("solution", &vssolution); } VisualSceneSolution :: ~VisualSceneSolution () { // cout << "exit VisualSceneSolution" << endl; ClearSolutionData(); } /* void VisualSceneSolution :: SetMesh (shared_ptr amesh) { wp_mesh = amesh; } */ void VisualSceneSolution :: AddSolutionData (SolData * sd) { shared_ptr mesh = GetMesh(); NgLock meshlock1 (mesh->MajorMutex(), 1); int funcnr = -1; for (int i = 0; i < soldata.Size(); i++) { // if (strcmp (soldata[i]->name, sd->name) == 0) if (soldata[i]->name == sd->name) { delete soldata[i]; soldata[i] = sd; funcnr = i; break; } } if (funcnr == -1) { soldata.Append (sd); funcnr = soldata.Size()-1; } SolData * nsd = soldata[funcnr]; nsd->size = 0; if (mesh) { switch (nsd->soltype) { case SOL_NODAL: nsd->size = mesh->GetNV(); break; case SOL_ELEMENT: nsd->size = mesh->GetNE(); break; case SOL_SURFACE_ELEMENT: nsd->size = mesh->GetNSE(); break; case SOL_NONCONTINUOUS: { switch (nsd->order) { case 0: nsd->size = mesh->GetNE(); break; case 1: nsd->size = 6 * mesh->GetNE(); break; case 2: nsd->size = 18 * mesh->GetNE(); break; } break; } case SOL_SURFACE_NONCONTINUOUS: { switch (nsd->order) { case 0: nsd->size = mesh->GetNSE(); break; case 1: nsd->size = 4 * mesh->GetNSE(); break; case 2: nsd->size = 9 * mesh->GetNSE(); break; } break; } default: nsd->size = 0; } solutiontimestamp = NextTimeStamp(); } } void VisualSceneSolution :: ClearSolutionData () { for (int i = 0; i < soldata.Size(); i++) delete soldata[i]; soldata.SetSize (0); } void VisualSceneSolution :: UpdateSolutionTimeStamp () { solutiontimestamp = NextTimeStamp(); } VisualSceneSolution::SolData * VisualSceneSolution :: GetSolData (int i) { if (i >= 0 && i < soldata.Size()) return soldata[i]; else return NULL; } void VisualSceneSolution :: SaveSolutionData (const char * filename) { shared_ptr mesh = GetMesh(); PrintMessage (1, "Write solution data to file ", filename); if (strcmp (&filename[strlen(filename)-3], "sol") == 0) { ofstream ost(filename); for (int i = 0; i < soldata.Size(); i++) { const SolData & sol = *soldata[i]; ost << "solution " << sol.name << " -size=" << sol.size << " -components=" << sol.components << " -order=" << sol.order; if (sol.iscomplex) ost << " -complex"; switch (sol.soltype) { case SOL_NODAL: ost << " -type=nodal"; break; case SOL_ELEMENT: ost << " -type=element"; break; case SOL_SURFACE_ELEMENT: ost << " -type=surfaceelement"; break; case SOL_NONCONTINUOUS: ost << " -type=noncontinuous"; break; case SOL_SURFACE_NONCONTINUOUS: ost << " -type=surfacenoncontinuous"; break; default: cerr << "save solution data, case not handled" << endl; } ost << endl; for (int j = 0; j < sol.size; j++) { for (int k = 0; k < sol.components; k++) ost << sol.data[j*sol.dist+k] << " "; ost << "\n"; } } } if (strcmp (&filename[strlen(filename)-3], "vtk") == 0) { string surf_fn = filename; surf_fn.erase (strlen(filename)-4); surf_fn += "_surf.vtk"; cout << "surface mesh = " << surf_fn << endl; ofstream surf_ost(surf_fn.c_str()); surf_ost << "# vtk DataFile Version 1.0\n" << "NGSolve surface mesh\n" << "ASCII\n" << "DATASET UNSTRUCTURED_GRID\n\n"; surf_ost << "POINTS " << mesh->GetNP() << " float\n"; for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) { const MeshPoint & mp = (*mesh)[pi]; surf_ost << mp(0) << " " << mp(1) << " " << mp(2) << "\n"; } int cntverts = 0; for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) cntverts += 1 + (*mesh)[sei].GetNP(); surf_ost << "\nCELLS " << mesh->GetNSE() << " " << cntverts << "\n"; for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) { const Element2d & el = (*mesh)[sei]; surf_ost << el.GetNP(); for (int j = 0; j < el.GetNP(); j++) surf_ost << " " << el[j] - PointIndex::BASE; surf_ost << "\n"; } surf_ost << "\nCELL_TYPES " << mesh->GetNSE() << "\n"; for (SurfaceElementIndex sei = 0; sei < mesh->GetNSE(); sei++) { const Element2d & el = (*mesh)[sei]; switch (el.GetType()) { case QUAD: surf_ost << 9; break; case TRIG: surf_ost << 5; break; default: cerr << "not implemented 2378" << endl; } surf_ost << "\n"; } ofstream ost(filename); ost << "# vtk DataFile Version 1.0\n" << "NGSolve solution\n" << "ASCII\n" << "DATASET UNSTRUCTURED_GRID\n\n"; ost << "POINTS " << mesh->GetNP() << " float\n"; for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) { const MeshPoint & mp = (*mesh)[pi]; ost << mp(0) << " " << mp(1) << " " << mp(2) << "\n"; } cntverts = 0; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) cntverts += 1 + (*mesh)[ei].GetNP(); ost << "\nCELLS " << mesh->GetNE() << " " << cntverts << "\n"; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; ost << el.GetNP(); for (int j = 0; j < el.GetNP(); j++) ost << " " << el[j] - PointIndex::BASE; ost << "\n"; } ost << "\nCELL_TYPES " << mesh->GetNE() << "\n"; for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; switch (el.GetType()) { case TET: ost << 10; break; default: cerr << "not implemented 67324" << endl; } ost << "\n"; } ost << "CELL_DATA " << mesh->GetNE() << "\n"; for (int i = 0; i < soldata.Size(); i++) { ost << "VECTORS bfield float\n"; SolutionData & sol = *(soldata[i] -> solclass); double values[3]; for (int elnr = 0; elnr < mesh->GetNE(); elnr++) { sol.GetValue (elnr, 0.25, 0.25, 0.25, values); ost << values[0] << " " << values[1] << " " << values[2] << "\n"; } } /* ost << "POINT_DATA " << mesh->GetNP() << "\n"; for (int i = 0; i < soldata.Size(); i++) { ost << "VECTORS bfield float\n"; SolutionData & sol = *(soldata[i] -> solclass); for (PointIndex pi = PointIndex::BASE; pi < mesh->GetNP()+PointIndex::BASE; pi++) { double values[3], sumvalues[3] = { 0, 0, 0 }; NgFlatArray els = mesh->GetTopology().GetVertexElements(pi); for (int j = 0; j < els.Size(); j++) { sol.GetValue (els[j]-1, 0.25, 0.25, 0.25, values); for (int k = 0; k < 3; k++) sumvalues[k] += values[k]; } for (int k = 0; k < 3; k++) sumvalues[k] /= els.Size(); ost << sumvalues[0] << " " << sumvalues[1] << " " << sumvalues[2] << "\n"; } } */ } } void VisualSceneSolution :: DrawScene () { try { shared_ptr mesh = GetMesh(); if (!mesh) { VisualScene::DrawScene(); return; } // static NgLock mem_lock(mem_mutex); // mem_lock.Lock(); NgLock meshlock1 (mesh->MajorMutex(), true); NgLock meshlock (mesh->Mutex(), true); BuildScene(); CreateTexture (GetVSSolution().numtexturecols, lineartexture, 0.5, GL_MODULATE); glClearColor(backcolor, backcolor, backcolor, 1); // glClearColor(backcolor, backcolor, backcolor, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetLight(); glPushMatrix(); glMultMatrixd (transformationmat); glMatrixMode (GL_MODELVIEW); glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPolygonOffset (1, 1); glEnable (GL_POLYGON_OFFSET_FILL); glEnable (GL_COLOR_MATERIAL); if (usetexture) { SetTextureMode (usetexture); glMatrixMode (GL_TEXTURE); glLoadIdentity(); if (usetexture == 1) { double hmax = maxval; double hmin = minval; if (invcolor) Swap (hmax, hmin); if (fabs (hmax - hmin) > 1e-30) glScaled (1.0 / (hmin - hmax), 0, 0); else glScaled (1e30, 0, 0); glTranslatef (-hmax, 0, 0); } else { glTranslatef (0.5, 0, 0); glRotatef(360 * netgen::GetVSSolution().time, 0, 0, -1); if (fabs (maxval) > 1e-10) glScalef(0.5/maxval, 0.5/maxval, 0.5/maxval); else glScalef (1e10, 1e10, 1e10); } glMatrixMode (GL_MODELVIEW); } if (vispar.drawfilledtrigs || vispar.drawtetsdomain > 0 || vispar.drawdomainsurf > 0) { // Change for Martin: // orig: SetClippingPlane (); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // glEnable(GL_BLEND); glDisable(GL_BLEND); glCallList (surfellist); #ifdef USE_BUFFERS // static int timer = NgProfiler::CreateTimer ("Solution::drawing - DrawSurfaceElements VBO"); // NgProfiler::StartTimer(timer); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // NgProfiler::StopTimer(timer); #endif glDisable(GL_BLEND); /* // transparent test ... glColor4f (1, 0, 0, 0.1); glEnable (GL_COLOR_MATERIAL); glDepthFunc(GL_GREATER); glDepthMask(GL_FALSE); // glBlendFunc(GL_ONE_MINUS_DST_ALPHA,GL_DST_ALPHA); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA); glCallList (surfellist); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); glDepthMask(GL_TRUE); glCallList (surfellist); // end test ... */ glCallList (surface_vector_list); glDisable(GL_CLIP_PLANE0); } if (showclipsolution) { if (clipsolution == 1) { // Martin // orig: glCallList (clipplanelist_scal); // transparent experiments // see http://wiki.delphigl.com/index.php/Blenden /* glColor4f (1, 1, 1, 0.5); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_COLOR); glDepthFunc(GL_GREATER); glDepthMask(GL_FALSE); glCallList (clipplanelist_scal); glDepthFunc(GL_LEQUAL); glDepthMask(GL_TRUE); glCallList (clipplanelist_scal); glDisable(GL_BLEND); */ /* // latest transparent version ... glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_DEPTH_TEST); // CreateTexture (numtexturecols, lineartexture, 0.25, GL_MODULATE); // glCallList (clipplanelist_scal); glEnable(GL_BLEND); // glDisable(GL_DEPTH_TEST); // CreateTexture (numtexturecols, lineartexture, 0.25, GL_MODULATE); glCallList (clipplanelist_scal); // glDepthFunc(GL_LEQUAL); // glDepthMask(GL_TRUE); // glCallList (clipplanelist_scal); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); */ // end test } if (clipsolution == 2) { // glDisable(GL_DEPTH_TEST); glCallList (clipplanelist_vec); // glEnable(GL_DEPTH_TEST); } } if (draw_fieldlines) { SetClippingPlane(); if (num_fieldlineslists <= 1) glCallList (fieldlineslist); else { // animated int start = int (time / 10 * num_fieldlineslists); for (int ln = 0; ln < 10; ln++) { int nr = fieldlineslist + (start + ln) % num_fieldlineslists; glCallList (nr); } } glDisable(GL_CLIP_PLANE0); } if(drawpointcurves) { glCallList(pointcurvelist); } glMatrixMode (GL_TEXTURE); glLoadIdentity(); glMatrixMode (GL_MODELVIEW); glDisable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_2D); glDisable (GL_POLYGON_OFFSET_FILL); glDisable (GL_COLOR_MATERIAL); if (draw_isosurface) glCallList (isosurface_list); GLfloat matcol0[] = { 0, 0, 0, 1 }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, matcol0); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matcol0); glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); glLineWidth (1.0f); glColor3f (0.0f, 0.0f, 0.0f); glDisable (GL_LINE_SMOOTH); if (vispar.drawedges) { glCallList (element1dlist); } if (vispar.drawoutline && !numisolines) { SetClippingPlane (); glDepthMask(GL_FALSE); glCallList (linelist); glDepthMask(GL_TRUE); glDisable(GL_CLIP_PLANE0); } if (numisolines) { SetClippingPlane (); glCallList (isolinelist); glDisable(GL_CLIP_PLANE0); glCallList (clipplane_isolinelist); } // user visualization for (int i = 0; i < user_vis.Size(); i++) user_vis[i] -> Draw(); DrawMarker(); glPopMatrix(); glDisable(GL_CLIP_PLANE0); DrawColorBar (minval, maxval, logscale, lineartexture, number_format, unit); DrawTitle (title); if (vispar.drawcoordinatecross) DrawCoordinateCross (); DrawNetgenLogo (); glFinish(); // delete lock; // mem_lock.UnLock(); } catch (bad_weak_ptr e) { // cout << "don't have a mesh to visualize" << endl; VisualScene::DrawScene(); } } /* void VisualSceneSolution :: RealVec3d (const double * values, Vec3d & v, bool iscomplex, bool imag) { if (!iscomplex) { v.X() = values[0]; v.Y() = values[1]; v.Z() = values[2]; } else { if (!imag) { v.X() = values[0]; v.Y() = values[2]; v.Z() = values[4]; } else { v.X() = values[1]; v.Y() = values[3]; v.Z() = values[5]; } } } */ Vec<3> VisualSceneSolution :: RealVec3d (const double * values, bool iscomplex, bool imag) { Vec<3> v; if (!iscomplex) { for (int j = 0; j < 3; j++) v(j) = values[j]; } else { if (!imag) { for (int j = 0; j < 3; j++) v(j) = values[2*j]; } else { for (int j = 0; j < 3; j++) v(j) = values[2*j+1]; } } return v; } void VisualSceneSolution :: RealVec3d (const double * values, Vec3d & v, bool iscomplex, double phaser, double phasei) { if (!iscomplex) { v.X() = values[0]; v.Y() = values[1]; v.Z() = values[2]; } else { for (int i = 0; i < 3; i++) v.X(i+1) = phaser * values[2*i] + phasei * values[2*i+1]; } } void VisualSceneSolution :: BuildScene (int zoomall) { try { shared_ptr mesh = GetMesh(); if (!mesh) { VisualScene::BuildScene (zoomall); return; } /* if (!cone_list) { cone_list = glGenLists (1); glNewList (cone_list, GL_COMPILE); DrawCone (Point<3> (0,0,0), Point<3> (0,0,1), 0.4); glEndList(); } */ // vispar.colormeshsize = 1; // recalc clipping plane SetClippingPlane (); glDisable(GL_CLIP_PLANE0); SolData * sol = NULL; SolData * vsol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; if (vecfunction != -1) vsol = soldata[vecfunction]; if (mesh->GetTimeStamp () > solutiontimestamp) { sol = NULL; vsol = NULL; } if (sol && sol->solclass) sol->solclass->SetMultiDimComponent (multidimcomponent); if (vsol && vsol->solclass) vsol->solclass->SetMultiDimComponent (multidimcomponent); if (!autoscale || (!sol && !vsol) ) { minval = mminval; maxval = mmaxval; } else { if (mesh->GetTimeStamp () > surfeltimestamp || vispar.clipping.timestamp > clipplanetimestamp || solutiontimestamp > surfeltimestamp) { GetMinMax (scalfunction, scalcomp, minval, maxval); } } if (mesh->GetTimeStamp() > surfeltimestamp || solutiontimestamp > surfeltimestamp || zoomall) { if (mesh->GetTimeStamp() > surfeltimestamp || zoomall) { // mesh has changed vsmesh.SelectCenter(zoomall); } DrawSurfaceElements(); surfeltimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp()); } if (mesh->GetTimeStamp() > surfellinetimestamp || subdivision_timestamp > surfellinetimestamp || (solutiontimestamp > surfellinetimestamp) || zoomall) { DrawSurfaceElementLines(); surfellinetimestamp = max2 (solutiontimestamp, mesh->GetTimeStamp()); } if (vispar.drawedges) Draw1DElements(); if (mesh->GetTimeStamp() > surface_vector_timestamp || solutiontimestamp > surface_vector_timestamp || zoomall) { if (surface_vector_list) glDeleteLists (surface_vector_list, 1); surface_vector_list = glGenLists (1); glNewList (surface_vector_list, GL_COMPILE); glEnable (GL_NORMALIZE); DrawSurfaceVectors(); glEndList (); surface_vector_timestamp = max2 (mesh->GetTimeStamp(), solutiontimestamp); } if (clipplanetimestamp < vispar.clipping.timestamp || clipplanetimestamp < solutiontimestamp) { // cout << "clipsolution = " << clipsolution << endl; if (vispar.clipping.enable && clipsolution == 2) { mesh->Mutex().unlock(); mesh->BuildElementSearchTree(); mesh->Mutex().lock(); } if (vispar.clipping.enable && clipsolution == 1 && sol) DrawClipPlaneTrigs (); if (clipplanelist_vec) glDeleteLists (clipplanelist_vec, 1); clipplanelist_vec = glGenLists (1); glNewList (clipplanelist_vec, GL_COMPILE); if (vispar.clipping.enable && clipsolution == 2 && vsol) { SetTextureMode (usetexture); if (autoscale) GetMinMax (vecfunction, 0, minval, maxval); NgArray cpp; GetClippingPlaneGrid (cpp); for (int i = 0; i < cpp.Size(); i++) { const ClipPlanePoint & p = cpp[i]; double values[6]; Vec3d v; bool drawelem = GetValues (vsol, p.elnr, p.lami(0), p.lami(1), p.lami(2), values); // RealVec3d (values, v, vsol->iscomplex, imag_part); v = RealVec3d (values, vsol->iscomplex, imag_part); double val = v.Length(); if (drawelem && val > 1e-10 * maxval) { v *= (rad / val / gridsize * 0.5); SetOpenGlColor (val); DrawCone (p.p, p.p+v, rad / gridsize * 0.2); } } } glEndList (); } if (mesh->GetTimeStamp() > isosurface_timestamp || solutiontimestamp > isosurface_timestamp || zoomall) { if (isosurface_list) glDeleteLists (isosurface_list, 1); isosurface_list = glGenLists (1); glNewList (isosurface_list, GL_COMPILE); glEnable (GL_NORMALIZE); DrawIsoSurface(sol, vsol, scalcomp); glEndList (); isosurface_timestamp = max2 (mesh->GetTimeStamp(), solutiontimestamp); } if(mesh->GetTimeStamp() > pointcurve_timestamp || solutiontimestamp > pointcurve_timestamp) { if(pointcurvelist) glDeleteLists(pointcurvelist,1); if(mesh->GetNumPointCurves() > 0) { pointcurvelist = glGenLists(1); glNewList(pointcurvelist,GL_COMPILE); //glColor3f (1.0f, 0.f, 0.f); for(int i=0; iGetNumPointCurves(); i++) { Box3d box; box.SetPoint(mesh->GetPointCurvePoint(i,0)); for(int j=1; jGetNumPointsOfPointCurve(i); j++) box.AddPoint(mesh->GetPointCurvePoint(i,j)); double diam = box.CalcDiam(); double thick = min2(0.1*diam, 0.001*rad); double red,green,blue; mesh->GetPointCurveColor(i,red,green,blue); glColor3f (red, green, blue); for(int j=0; jGetNumPointsOfPointCurve(i)-1; j++) { DrawCylinder(mesh->GetPointCurvePoint(i,j), mesh->GetPointCurvePoint(i,j+1), thick); } } glEndList(); } } if ( numisolines && (clipplanetimestamp < vispar.clipping.timestamp || clipplanetimestamp < solutiontimestamp) ) { if (isolinelist) glDeleteLists (isolinelist, 1); isolinelist = glGenLists (1); glNewList (isolinelist, GL_COMPILE); Point<3> points[1100]; double values[1100]; int nse = mesh->GetNSE(); CurvedElements & curv = mesh->GetCurvedElements(); if (sol) { glBegin (GL_LINES); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; bool curved = curv.IsHighOrder(); // && curv.IsSurfaceElementCurved(sei); if (el.GetType() == TRIG || el.GetType() == TRIG6) { Point<3> lp1, lp2, lp3; if (!curved) { GetPointDeformation (el[0]-1, lp1); GetPointDeformation (el[1]-1, lp2); GetPointDeformation (el[2]-1, lp3); } int n = 1 << subdivisions; int ii = 0; int ix, iy; for (iy = 0; iy <= n; iy++) for (ix = 0; ix <= n-iy; ix++) { double x = double(ix) / n; double y = double(iy) / n; // TODO: consider return value (bool: draw/don't draw element) GetSurfValue (sol, sei, -1, x, y, scalcomp, values[ii]); Point<2> xref(x,y); if (curved) mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, points[ii]); else points[ii] = lp3 + x * (lp1-lp3) + y * (lp2-lp3); if (deform) { points[ii] += GetSurfDeformation (sei, -1, x, y); } ii++; } ii = 0; for (iy = 0; iy < n; iy++, ii++) for (ix = 0; ix < n-iy; ix++, ii++) { int index[] = { ii, ii+1, ii+n-iy+1, ii+1, ii+n-iy+2, ii+n-iy+1 }; DrawIsoLines (points[index[0]], points[index[1]], points[index[2]], values[index[0]], values[index[1]], values[index[2]]); if (ix < n-iy-1) DrawIsoLines (points[index[3]], points[index[4]], points[index[5]], values[index[3]], values[index[4]], values[index[5]]); } } if (el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 ) { Point<3> lpi[4]; Vec<3> vx = 0.0, vy = 0.0, vtwist = 0.0, def; if (!curved) { for (int j = 0; j < 4; j++) GetPointDeformation (el[j]-1, lpi[j]); vx = lpi[1]-lpi[0]; vy = lpi[3]-lpi[0]; vtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]); } int n = 1 << subdivisions; int ix, iy, ii = 0; for (iy = 0; iy <= n; iy++) for (ix = 0; ix <= n; ix++, ii++) { double x = double(ix) / n; double y = double(iy) / n; // TODO: consider return value (bool: draw/don't draw element) GetSurfValue (sol, sei, -1, x, y, scalcomp, values[ii]); Point<2> xref(x,y); if (curved) mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, points[ii]); else points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist; if (deform) points[ii] += GetSurfDeformation (sei, -1, x, y); } ii = 0; for (iy = 0; iy < n; iy++, ii++) for (ix = 0; ix < n; ix++, ii++) { DrawIsoLines (points[ii], points[ii+1], points[ii+n+1], values[ii], values[ii+1], values[ii+n+1]); DrawIsoLines (points[ii+1], points[ii+n+2], points[ii+n+1], values[ii+1], values[ii+n+2], values[ii+n+1]); } } } glEnd(); } glEndList (); if (clipplane_isolinelist) glDeleteLists (clipplane_isolinelist, 1); if (vispar.clipping.enable && clipsolution == 1 && sol) { clipplane_isolinelist = glGenLists (1); glNewList (clipplane_isolinelist, GL_COMPILE); NgArray cpt; NgArray pts; GetClippingPlaneTrigs (sol, cpt, pts); bool drawelem; glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); glBegin (GL_LINES); if (numisolines) for (int i = 0; i < cpt.Size(); i++) { const ClipPlaneTrig & trig = cpt[i]; double vali[3]; for (int j = 0; j < 3; j++) { Point<3> lami = pts[trig.points[j].pnr].lami; drawelem = GetValue (sol, trig.elnr, lami(0), lami(1), lami(2), scalcomp, vali[j]); } if ( drawelem ) DrawIsoLines (pts[trig.points[0].pnr].p, pts[trig.points[1].pnr].p, pts[trig.points[2].pnr].p, vali[0], vali[1], vali[2]); } glEnd(); glEndList (); } } clipplanetimestamp = max2 (vispar.clipping.timestamp, solutiontimestamp); } catch (bad_weak_ptr e) { PrintMessage (3, "vssolution::buildscene: don't have a mesh to visualize"); VisualScene::BuildScene (zoomall); } } void VisualSceneSolution :: Draw1DElements () { shared_ptr mesh = GetMesh(); if (element1dlist) glDeleteLists (element1dlist, 1); element1dlist = glGenLists (1); glNewList (element1dlist, GL_COMPILE); int npt = (1 << subdivisions) + 1; NgArray pref(npt), values(npt); NgArray > points(npt); const SolData * sol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; const SolData * vsol = NULL; if (deform && vecfunction != -1) vsol = soldata[vecfunction]; int ncomp = 0; if (sol) ncomp = sol->components; if (vsol) ncomp = vsol->components; NgArray mvalues(ncomp); for (int i = 0; i < npt; i++) pref[i] = double(i) / (npt-1); int meshdim = mesh->GetDimension(); for (SegmentIndex i = 0; i < mesh -> GetNSeg(); i++) { // mesh->GetCurvedElements(). // CalcMultiPointSegmentTransformation (&pref, i, &points, NULL); // const Segment & seg = mesh -> LineSegment(i); for (int j = 0; j < npt; j++) mesh->GetCurvedElements(). CalcSegmentTransformation (pref[j], i, points[j]); if (vsol) { for (int j = 0; j < npt; j++) { vsol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]); // values[j] = ExtractValue (sol, scalcomp, &mvalues[0]); for (int k = 0; k < min(ncomp, 3); k++) points[j](k) += scaledeform * mvalues[k]; // points[j](0) += scaledeform * mvalues[0]; // points[j](1) += scaledeform * mvalues[1]; } } else if (sol) { for (int j = 0; j < npt; j++) { sol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]); values[j] = ExtractValue (sol, scalcomp, &mvalues[0]); if (meshdim <= 2) points[j](meshdim) += scaledeform * values[j]; } } glBegin (GL_LINE_STRIP); for (int i = 0; i < npt; i++) glVertex3dv (points[i]); glEnd(); } glEndList (); } void VisualSceneSolution :: DrawSurfaceElements () { shared_ptr mesh = GetMesh(); static int timer = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements"); /* static int timerstart = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements start"); static int timerloops = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements loops"); static int timerlist = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements list"); static int timerbuffer = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements buffer"); static int timer1 = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1"); static int timer1a = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1a"); static int timer1b = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1b"); static int timer1c = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 1c"); static int timer2 = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2"); static int timer2a = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2a"); static int timer2b = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2b"); */ NgProfiler::RegionTimer reg (timer); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); par_surfellists.SetSize (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("solsurfellist"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_surfellists[dest], dest, MPI_TAG_VIS); if (surfellist) glDeleteLists (surfellist, 1); surfellist = glGenLists (1); glNewList (surfellist, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_surfellists[dest]); glEndList(); return; } #endif // NgProfiler::StartTimer(timerstart); if (surfellist) glDeleteLists (surfellist, 1); surfellist = glGenLists (1); glNewList (surfellist, GL_COMPILE); const SolData * sol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; if (mesh->GetTimeStamp () > solutiontimestamp) sol = NULL; if (sol && sol->solclass) sol->solclass->SetMultiDimComponent (multidimcomponent); glLineWidth (1.0f); GLfloat col_grey[] = { 0.6f, 0.6f, 0.6f, 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col_grey); int nse = mesh->GetNSE(); SetTextureMode (usetexture); CurvedElements & curv = mesh->GetCurvedElements(); int n = 1 << subdivisions; int npt = sqr(n+1); NgArray > pref (npt); NgArray > points (npt); NgArray > dxdxis (npt); NgArray > nvs(npt); NgArray values(npt); NgArray mvalues(npt); int sol_comp = (sol && sol->draw_surface) ? sol->components : 0; NgArray> > simd_pref ( (npt+SIMD::Size()-1)/SIMD::Size() ); NgArray> > simd_points ( (npt+SIMD::Size()-1)/SIMD::Size() ); NgArray> > simd_dxdxis ( (npt+SIMD::Size()-1)/SIMD::Size() ); NgArray> > simd_nvs( (npt+SIMD::Size()-1)/SIMD::Size() ); NgArray> simd_values( (npt+SIMD::Size()-1)/SIMD::Size() * sol_comp); // NgArray> glob_pnts; // NgArray> glob_nvs; // NgArray glob_values; if (sol && sol->draw_surface) mvalues.SetSize (npt * sol->components); NgArray > valuesc(npt); #ifdef USE_BUFFERS if (has_surfel_vbo) glDeleteBuffers (4, &surfel_vbo[0]); glGenBuffers (4, &surfel_vbo[0]); has_surfel_vbo = true; glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[0]); glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(Point<3,double>), NULL, GL_STATIC_DRAW); glVertexPointer(3, GL_DOUBLE, 0, 0); // glEnableClientState(GL_VERTEX_ARRAY); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[1]); glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(Vec<3,double>), NULL, GL_STATIC_DRAW); // glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_DOUBLE, 0, 0); // glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[2]); glBufferData (GL_ARRAY_BUFFER, nse*npt*sizeof(double), NULL, GL_STATIC_DRAW); glTexCoordPointer(1, GL_DOUBLE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, nse*npt*6*sizeof(int), NULL, GL_STATIC_DRAW); surfel_vbo_size = 0; #endif // NgProfiler::StopTimer(timerstart); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; if(!SurfaceElementActive(sol, *mesh, el)) continue; if ( el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 ) { bool curved = curv.IsSurfaceElementCurved (sei); for (int iy = 0, ii = 0; iy <= n; iy++) for (int ix = 0; ix <= n; ix++, ii++) pref[ii] = Point<2> (double(ix)/n, double(iy)/n); int npt = (n+1)*(n+1); if (curved) { for (int ii = 0; ii < npt; ii++) { Point<2> xref = pref[ii]; mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, points[ii], dxdxis[ii]); nvs[ii] = Cross (dxdxis[ii].Col(0), dxdxis[ii].Col(1)); nvs[ii].Normalize(); } } else { Point<3> lpi[4]; Vec<3> vx, vy, vtwist; for (int k = 0; k < 4; k++) GetPointDeformation (el[k]-1, lpi[k]); vx = lpi[1]-lpi[0]; vy = lpi[3]-lpi[0]; vtwist = (lpi[0]-lpi[1]) + (lpi[2]-lpi[3]); for (int ii = 0; ii < npt; ii++) { double x = pref[ii](0); double y = pref[ii](1); points[ii] = lpi[0] + x * vx + y * vy + x*y * vtwist; for (int j = 0; j < 3; j++) { dxdxis[ii](j,0) = vx(j) + y*vtwist(j); dxdxis[ii](j,1) = vy(j) + x*vtwist(j); } } Vec<3> nv = Cross (vx, vy); nv.Normalize(); for (int ii = 0; ii < npt; ii++) nvs[ii] = nv; } bool drawelem = false; /* if (sol && sol->draw_surface) { if (usetexture == 2) for (int ii = 0; ii < npt; ii++) drawelem = GetSurfValueComplex (sol, sei, -1, pref[ii](0), pref[ii](1), scalcomp, valuesc[ii]); else for (int ii = 0; ii < npt; ii++) drawelem = GetSurfValue (sol, sei, -1, pref[ii](0), pref[ii](1), scalcomp, values[ii]); } */ if (sol && sol->draw_surface) { drawelem = GetMultiSurfValues (sol, sei, -1, npt, &pref[0](0), &pref[1](0)-&pref[0](0), &points[0](0), &points[1](0)-&points[0](0), &dxdxis[0](0), &dxdxis[1](0)-&dxdxis[0](0), &mvalues[0], sol->components); if (usetexture == 2) for (int ii = 0; ii < npt; ii++) valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < npt; ii++) values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); } if (deform) for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); int save_usetexture = usetexture; if (!drawelem) { usetexture = 0; SetTextureMode (0); } int ii = 0; glBegin (GL_QUADS); for (int iy = 0; iy < n; iy++, ii++) for (int ix = 0; ix < n; ix++, ii++) { int index[] = { ii, ii+1, ii+n+2, ii+n+1 }; for (int j = 0; j < 4; j++) { if (drawelem) { if (usetexture != 2) SetOpenGlColor (values[index[j]]); else glTexCoord2f ( valuesc[index[j]].real(), valuesc[index[j]].imag() ); } else glColor4fv (col_grey); glNormal3dv (nvs[index[j]]); glVertex3dv (points[index[j]]); } } glEnd(); if (!drawelem && (usetexture != save_usetexture)) { usetexture = save_usetexture; SetTextureMode (usetexture); } } } n = 1 << subdivisions; double invn = 1.0 / n; npt = (n+1)*(n+2)/2; // NgProfiler::StartTimer(timerloops); size_t base_pi = 0; for (int iy = 0, ii = 0; iy <= n; iy++) for (int ix = 0; ix <= n-iy; ix++, ii++) pref[ii] = Point<2> (ix*invn, iy*invn); constexpr size_t simd_size = SIMD::Size(); size_t simd_npt = (npt+simd_size-1)/simd_size; for (size_t i = 0; i < simd_npt; i++) { simd_pref[i](0) = [&] (size_t j) { size_t ii = i*simd_size+j; return (ii < npt) ? pref[ii](0) : 0; }; simd_pref[i](1) = [&] (size_t j) { size_t ii = i*simd_size+j; return (ii < npt) ? pref[ii](1) : 0; }; } NgArray ind_reftrig; for (int iy = 0, ii = 0; iy < n; iy++,ii++) for (int ix = 0; ix < n-iy; ix++, ii++) { int nv = (ix+iy+1 < n) ? 6 : 3; int ind[] = { ii, ii+1, ii+n-iy+1, ii+n-iy+1, ii+1, ii+n-iy+2 }; for (int j = 0; j < nv; j++) ind_reftrig.Append (ind[j]); } NgArray glob_ind; glob_ind.SetSize(ind_reftrig.Size()); for(SurfaceElementIndex sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; // if (el.GetIndex() <= 1) continue; if(!SurfaceElementActive(sol, *mesh, el)) continue; if ( el.GetType() == TRIG || el.GetType() == TRIG6 ) { // NgProfiler::StartTimer(timer1); #ifdef __AVX_try_it_out__ // NgProfiler::StartTimer(timer1a); bool curved = curv.IsSurfaceElementCurved(sei); if (curved) { mesh->GetCurvedElements(). CalcMultiPointSurfaceTransformation<3> (sei, simd_npt, &simd_pref[0](0), 2, &simd_points[0](0), 3, &simd_dxdxis[0](0,0), 6); for (size_t ii = 0; ii < simd_npt; ii++) simd_nvs[ii] = Cross (simd_dxdxis[ii].Col(0), simd_dxdxis[ii].Col(1)).Normalize(); } else { Point<3,SIMD> p1 = mesh->Point (el[0]); Point<3,SIMD> p2 = mesh->Point (el[1]); Point<3,SIMD> p3 = mesh->Point (el[2]); Vec<3,SIMD> vx = p1-p3; Vec<3,SIMD> vy = p2-p3; for (size_t ii = 0; ii < simd_npt; ii++) { simd_points[ii] = p3 + simd_pref[ii](0) * vx + simd_pref[ii](1) * vy; for (size_t j = 0; j < 3; j++) { simd_dxdxis[ii](j,0) = vx(j); simd_dxdxis[ii](j,1) = vy(j); } } Vec<3,SIMD> nv = Cross (vx, vy).Normalize(); for (size_t ii = 0; ii < simd_npt; ii++) simd_nvs[ii] = nv; } bool drawelem = false; if (sol && sol->draw_surface) { // NgProfiler::StopTimer(timer1a); // NgProfiler::StartTimer(timer1b); drawelem = sol->solclass->GetMultiSurfValue (sei, -1, simd_npt, &simd_pref[0](0).Data(), &simd_points[0](0).Data(), &simd_dxdxis[0](0).Data(), &simd_values[0].Data()); // NgProfiler::StopTimer(timer1b); // NgProfiler::StartTimer(timer1c); for (size_t j = 0; j < sol->components; j++) for (size_t i = 0; i < npt; i++) mvalues[i*sol->components+j] = ((double*)&simd_values[j*simd_npt])[i]; if (usetexture == 2) for (int ii = 0; ii < npt; ii++) valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < npt; ii++) values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); } for (size_t i = 0; i < npt; i++) { size_t ii = i/4; size_t r = i%4; for (int j = 0; j < 2; j++) pref[i](j) = simd_pref[ii](j)[r]; for (int j = 0; j < 3; j++) points[i](j) = simd_points[ii](j)[r]; for (int j = 0; j < 3; j++) nvs[i](j) = simd_nvs[ii](j)[r]; } if (deform) for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); // NgProfiler::StopTimer(timer1c); #else bool curved = (*mesh)[sei].IsCurved(); for (int iy = 0, ii = 0; iy <= n; iy++) for (int ix = 0; ix <= n-iy; ix++, ii++) pref[ii] = Point<2> (ix*invn, iy*invn); if (curved) { mesh->GetCurvedElements(). CalcMultiPointSurfaceTransformation (&pref, sei, &points, &dxdxis); for (int ii = 0; ii < npt; ii++) nvs[ii] = Cross (dxdxis[ii].Col(0), dxdxis[ii].Col(1)).Normalize(); } else { Point<3> p1 = mesh->Point (el[0]); Point<3> p2 = mesh->Point (el[1]); Point<3> p3 = mesh->Point (el[2]); Vec<3> vx = p1-p3; Vec<3> vy = p2-p3; for (int ii = 0; ii < npt; ii++) { points[ii] = p3 + pref[ii](0) * vx + pref[ii](1) * vy; for (int j = 0; j < 3; j++) { dxdxis[ii](j,0) = vx(j); dxdxis[ii](j,1) = vy(j); } } Vec<3> nv = Cross (vx, vy).Normalize(); for (int ii = 0; ii < npt; ii++) nvs[ii] = nv; } bool drawelem = false; if (sol && sol->draw_surface) { drawelem = GetMultiSurfValues (sol, sei, -1, npt, &pref[0](0), &pref[1](0)-&pref[0](0), &points[0](0), &points[1](0)-&points[0](0), &dxdxis[0](0), &dxdxis[1](0)-&dxdxis[0](0), &mvalues[0], sol->components); if (usetexture == 2) for (int ii = 0; ii < npt; ii++) valuesc[ii] = ExtractValueComplex(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < npt; ii++) values[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); } if (deform) for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); #endif // NgProfiler::StopTimer(timer1); int save_usetexture = usetexture; if (!drawelem) { usetexture = 0; SetTextureMode (usetexture); } // NgProfiler::StartTimer(timer2); #ifdef USE_BUFFERS if (drawelem && usetexture == 1 && !logscale) { glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[0]); glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(Point<3,double>), npt*sizeof(Point<3,double>), &points[0][0]); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[1]); glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(Vec<3,double>), npt*sizeof(Vec<3,double>), &nvs[0][0]); glBindBuffer (GL_ARRAY_BUFFER, surfel_vbo[2]); glBufferSubData (GL_ARRAY_BUFFER, base_pi*sizeof(double), npt*sizeof(double), &values[0]); for (size_t i = 0; i < ind_reftrig.Size(); i++) glob_ind[i] = base_pi+ind_reftrig[i]; glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); glBufferSubData (GL_ELEMENT_ARRAY_BUFFER, surfel_vbo_size*sizeof(int), ind_reftrig.Size()*sizeof(int), &glob_ind[0]); surfel_vbo_size += ind_reftrig.Size(); base_pi += npt; } else #endif for (int iy = 0, ii = 0; iy < n; iy++) { glBegin (GL_TRIANGLE_STRIP); for (int ix = 0; ix <= n-iy; ix++, ii++) for (int k = 0; k < 2; k++) { if (ix+iy+k > n) continue; int hi = (k == 0) ? ii : ii+n-iy+1; if (drawelem) { if (usetexture != 2) SetOpenGlColor (values[hi]); else glTexCoord2f ( valuesc[hi].real(), valuesc[hi].imag() ); } else glColor4fv (col_grey); glNormal3dv (nvs[hi]); glVertex3dv (points[hi]); } glEnd(); } // NgProfiler::StopTimer(timer2); if (!drawelem && (usetexture != save_usetexture)) { usetexture = save_usetexture; SetTextureMode (usetexture); } } } // NgProfiler::StopTimer(timerloops); // NgProfiler::StartTimer(timerbuffer); // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); // glBufferData(GL_ELEMENT_ARRAY_BUFFER, glob_ind.Size()*sizeof(int), &glob_ind[0], GL_STATIC_DRAW); // surfel_vbo_size = glob_ind.Size(); // NgProfiler::StopTimer(timerbuffer); // glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0); // glDrawElements(GL_TRIANGLES, glob_ind.Size(), GL_UNSIGNED_INT, &glob_ind[0]); // glDisableClientState(GL_VERTEX_ARRAY); // glDisableClientState(GL_NORMAL_ARRAY); // glDisableClientState(GL_TEXTURE_COORD_ARRAY); // glDeleteBuffers (1, &IndexVBOID); // glDeleteBuffers (4, &vboId[0]); // NgProfiler::StartTimer(timerlist); glEndList (); // NgProfiler::StopTimer(timerlist); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (surfellist, 0, MPI_TAG_VIS); #endif } void VisualSceneSolution :: DrawSurfaceElementLines () { shared_ptr mesh = GetMesh(); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); par_surfellists.SetSize (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("solsurfellinelist"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (par_surfellists[dest], dest, MPI_TAG_VIS); if (linelist) glDeleteLists (linelist, 1); linelist = glGenLists (1); glNewList (linelist, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (par_surfellists[dest]); glEndList(); return; } #endif if (linelist) glDeleteLists (linelist, 1); linelist = glGenLists (1); glNewList (linelist, GL_COMPILE); glLineWidth (1.0f); int nse = mesh->GetNSE(); CurvedElements & curv = mesh->GetCurvedElements(); int n = 1 << subdivisions; NgArrayMem, 65> ptsloc(n+1); NgArrayMem, 65> ptsglob(n+1); double trigpts[3][2] = { { 0, 0 }, { 0, 1 }, { 1, 0} }; double trigvecs[3][2] = { { 1, 0 }, { 0, -1 }, { -1, 1} }; double quadpts[4][2] = { { 0, 0 }, { 1, 1 }, { 0, 1}, { 1, 0 } }; double quadvecs[4][2] = { { 1, 0 }, { -1, 0}, { 0, -1}, { 0, 1 } }; for (SurfaceElementIndex sei = 0; sei < nse; sei++) { Element2d & el = (*mesh)[sei]; if(scalfunction != -1) if(!SurfaceElementActive(soldata[scalfunction], *mesh, el)) continue; int nv = (el.GetType() == TRIG || el.GetType() == TRIG6) ? 3 : 4; for (int k = 0; k < nv; k++) { Point<2> p0; Vec<2> vtau; if (nv == 3) { p0 = Point<2>(trigpts[k][0], trigpts[k][1]); vtau = Vec<2>(trigvecs[k][0], trigvecs[k][1]); } else { p0 = Point<2>(quadpts[k][0], quadpts[k][1]); vtau = Vec<2>(quadvecs[k][0], quadvecs[k][1]); } glBegin (GL_LINE_STRIP); for (int ix = 0; ix <= n; ix++) ptsloc[ix] = p0 + (double(ix) / n) * vtau; curv.CalcMultiPointSurfaceTransformation (&ptsloc, sei, &ptsglob, 0); for (int ix = 0; ix <= n; ix++) { if (deform) ptsglob[ix] += GetSurfDeformation (sei, k, ptsloc[ix](0), ptsloc[ix](1)); glVertex3dv (ptsglob[ix]); } glEnd (); } } glEndList (); #ifdef PARALLELGL glFinish(); if (id > 0) MyMPI_Send (linelist, 0, MPI_TAG_VIS); #endif } void VisualSceneSolution :: DrawIsoSurface(const SolData * sol, const SolData * vsol, int comp) { shared_ptr mesh = GetMesh(); if (!draw_isosurface) return; if (!sol) return; SetTextureMode (0); glColor3d (1.0, 0, 0); glEnable (GL_COLOR_MATERIAL); glBegin (GL_TRIANGLES); int ne = mesh->GetNE(); const int edgei[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; double edgelam[6]; Point<3> edgep[6]; Vec<3> normp[6]; double nodevali[4]; int cntce; int cpe1 = 0, cpe2 = 0, cpe3 = 0; int n = 1 << subdivisions; int n3 = (n+1)*(n+1)*(n+1); NgArray > grid(n3); NgArray > locgrid(n3); NgArray > trans(n3); NgArray val1(n3*sol->components); NgArray > grads1(n3); NgArray compress(n3); MatrixFixWidth<3> pointmat(8); grads1 = Vec<3> (0.0); for (ElementIndex ei = 0; ei < ne; ei++) { // if(vispar.clipdomain > 0 && vispar.clipdomain != (*mesh)[ei].GetIndex()) continue; // if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue; const Element & el = (*mesh)[ei]; if(!VolumeElementActive(sol, *mesh, el)) continue; ELEMENT_TYPE type = el.GetType(); if (type == HEX || type == PRISM || type == TET || type == PYRAMID) { int ii = 0; int cnt_valid = 0; for (int ix = 0; ix <= n; ix++) for (int iy = 0; iy <= n; iy++) for (int iz = 0; iz <= n; iz++, ii++) { Point<3> ploc; compress[ii] = ii; switch (type) { case PRISM: if (ix+iy <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); compress[ii] = cnt_valid; cnt_valid++; } else compress[ii] = -1; break; case TET: if (ix+iy+iz <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); compress[ii] = cnt_valid; cnt_valid++; } else compress[ii] = -1; break; case HEX: ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); break; case PYRAMID: ploc = Point<3> (double(ix) / n * (1-double(iz)/n), double(iy) / n * (1-double(iz)/n), double(iz)/n); break; default: cerr << "case not implemented 878234" << endl; ploc = 0.0; } if (compress[ii] != -1) locgrid[compress[ii]] = ploc; } if (type != TET && type != PRISM) cnt_valid = n3; if (mesh->GetCurvedElements().IsHighOrder() || 1) { mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locgrid, ei, &grid, &trans); } else { Vector shape(el.GetNP()); for (int k = 0; k < el.GetNP(); k++) for (int j = 0; j < 3; j++) pointmat(k,j) = (*mesh)[el[k]](j); for (int i = 0; i < cnt_valid; i++) { el.GetShapeNew (locgrid[i], shape); Point<3> pglob; for (int j = 0; j < 3; j++) { pglob(j) = 0; for (int k = 0; k < el.GetNP(); k++) pglob(j) += shape(k) * pointmat(k,j); } grid[i] = pglob; } } bool has_pos = 0, has_neg = 0; GetMultiValues( sol, ei, -1, n3, &locgrid[0](0), &locgrid[1](0)-&locgrid[0](0), &grid[0](0), &grid[1](0)-&grid[0](0), &trans[0](0), &trans[1](0)-&trans[0](0), &val1[0], sol->components); for (int i = 0; i < cnt_valid; i++) { // GetValue (sol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), comp, val[i]); // val[i] -= minval; val1[sol->components*i+comp-1] -= minval; // if (vsol) // GetValues (vsol, ei, &locgrid[i](0), &grid[i](0), &trans[i](0), &grads[i](0)); // grads[i] *= -1; if (val1[i*sol->components+comp-1] > 0) has_pos = 1; else has_neg = 1; // if (val[i] > 0) // has_pos = 1; // else // has_neg = 1; } if (!has_pos || !has_neg) continue; if (vsol) { GetMultiValues(vsol, ei, -1, n3, &locgrid[0](0), &locgrid[1](0)-&locgrid[0](0), &grid[0](0), &grid[1](0)-&grid[0](0), &trans[0](0), &trans[1](0)-&trans[0](0), &grads1[0](0), vsol->components); // for (int i = 0; i < cnt_valid; i++) // grads1[i*sol->components+comp-1] *= -1; for (int i = 0; i < cnt_valid; i++) grads1[i] *= -1; } for (int ix = 0; ix < n; ix++) for (int iy = 0; iy < n; iy++) for (int iz = 0; iz < n; iz++) { int base = iz + (n+1)*iy + (n+1)*(n+1)*ix; int pi[8] = { base, base+(n+1)*(n+1), base+(n+1)*(n+1)+(n+1), base+(n+1), base+1, base+(n+1)*(n+1)+1, base+(n+1)*(n+1)+(n+1)+1, base+(n+1)+1 }; for (int j = 0; j < 8; j++) pi[j] = compress[pi[j]]; int tets[6][4] = { { 1, 2, 4, 5 }, { 4, 5, 2, 8 }, { 2, 8, 5, 6 }, { 2, 3, 4, 8 }, { 2, 3, 8, 6 }, { 3, 8, 6, 7 } }; for (int ii = 0; ii < 6; ii++) { int teti[4]; for (int k = 0; k < 4; k++) teti[k] = pi[tets[ii][k]-1]; bool is_valid = 1; for (int j = 0; j < 4; j++) if (teti[j] == -1) is_valid = 0; if (!is_valid) continue; // for (int j = 0; j < 4; j++) // nodevali[j] = val[teti[j]]; for (int j = 0; j < 4; j++) nodevali[j] = val1[sol->components*teti[j]+comp-1]; cntce = 0; for (int j = 0; j < 6; j++) { int lpi1 = edgei[j][0]; int lpi2 = edgei[j][1]; if ( (nodevali[lpi1] > 0) != (nodevali[lpi2] > 0) ) { Point<3> p1 = grid[teti[lpi1]]; Point<3> p2 = grid[teti[lpi2]]; edgelam[j] = nodevali[lpi2] / (nodevali[lpi2] - nodevali[lpi1]); edgep[j] = grid[teti[lpi1]] + (1-edgelam[j]) * (grid[teti[lpi2]]-grid[teti[lpi1]]); // normp[j] = grads[teti[lpi1]] + (1-edgelam[j]) * (grads[teti[lpi2]]-grads[teti[lpi1]]); normp[j] = grads1[teti[lpi1]] + (1-edgelam[j]) * (grads1[teti[lpi2]]-grads1[teti[lpi1]]); // normp[j] = grads1[sol->components*teti[lpi1]+comp-1] + (1-edgelam[j]) * (grads1[sol->components*teti[lpi2]+comp-1]-grads1[sol->components*teti[lpi1]+comp-1]); cntce++; cpe3 = cpe2; cpe2 = cpe1; cpe1 = j; if (cntce >= 3) { if (!vsol) { Point<3> points[3]; points[0] = edgep[cpe1]; points[1] = edgep[cpe2]; points[2] = edgep[cpe3]; Vec<3> normal = Cross (points[2]-points[0], points[1]-points[0]); if ( ( (normal * (p2-p1)) > 0 ) == ( nodevali[lpi1] < 0) ) normal *= -1; glNormal3dv (normal); glVertex3dv (points[0]); glVertex3dv (points[1]); glVertex3dv (points[2]); } else { glNormal3dv (normp[cpe1]); glVertex3dv (edgep[cpe1]); glNormal3dv (normp[cpe2]); glVertex3dv (edgep[cpe2]); glNormal3dv (normp[cpe3]); glVertex3dv (edgep[cpe3]); } } } } } } } } glEnd(); } void VisualSceneSolution :: DrawTrigSurfaceVectors(const NgArray< Point<3> > & lp, const Point<3> & pmin, const Point<3> & pmax, const int sei, const SolData * vsol, bool swap_lam) { shared_ptr mesh = GetMesh(); int dir,dir1,dir2; double s,t; Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]); Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2))); if (na(0) > na(1) && na(0) > na(2)) dir = 1; else if (na(1) > na(2)) dir = 2; else dir = 3; dir1 = (dir % 3) + 1; dir2 = (dir1 % 3) + 1; Point<2> p2d[3]; int k; for (k = 0; k < 3; k++) { p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad), (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad)); } double minx2d, maxx2d, miny2d, maxy2d; minx2d = maxx2d = p2d[0](0); miny2d = maxy2d = p2d[0](1); for (k = 1; k < 3; k++) { minx2d = min2 (minx2d, p2d[k](0)); maxx2d = max2 (maxx2d, p2d[k](0)); miny2d = min2 (miny2d, p2d[k](1)); maxy2d = max2 (maxy2d, p2d[k](1)); } double mat11 = p2d[1](0) - p2d[0](0); double mat21 = p2d[1](1) - p2d[0](1); double mat12 = p2d[2](0) - p2d[0](0); double mat22 = p2d[2](1) - p2d[0](1); double det = mat11*mat22-mat21*mat12; double inv11 = mat22/det; double inv21 = -mat21/det; double inv12 = -mat12/det; double inv22 = mat11/det; // cout << "drawsurfacevectors. xoffset = " << xoffset << ", yoffset = "; // cout << yoffset << endl; for (s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize) if (s >= minx2d && s <= maxx2d) for (t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize) if (t >= miny2d && t <= maxy2d) { double lam1 = inv11 * (s - p2d[0](0)) + inv12 * (t-p2d[0](1)); double lam2 = inv21 * (s - p2d[0](0)) + inv22 * (t-p2d[0](1)); if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1) { if(swap_lam) { Swap(lam1, lam2); lam1 = 1.0-lam1; lam2 = 1.0-lam2; } Point<3> cp; for (k = 0; k < 3; k++) cp(k) = lp[0](k) + lam1 * (lp[1](k)-lp[0](k)) + lam2 * (lp[2](k)-lp[0](k)); Point<2> xref(lam1, lam2); if (mesh->GetCurvedElements().IsHighOrder()) mesh->GetCurvedElements(). CalcSurfaceTransformation (xref, sei, cp); Vec<3> v; double values[6]; bool drawelem = GetSurfValues (vsol, sei, -1, lam1, lam2, values); if (!vsol->iscomplex) for (k = 0; k < 3; k++) v(k) = values[k]; else { if (!imag_part) for (k = 0; k < 3; k++) v(k) = values[2*k]; else for (k = 0; k < 3; k++) v(k) = values[2*k+1]; } if (mesh->GetDimension() == 2) if ( (!vsol->iscomplex && vsol->components != 3) || (vsol->iscomplex && vsol->components != 6) ) v(2) = 0; double val = v.Length(); SetOpenGlColor (val); // (val, minval, maxval, logscale); // change JS if (val > 1e-10 * maxval) v *= (rad / val / gridsize * 0.5); else drawelem = 0; if ( drawelem ) DrawCone (cp, cp+4*v, 0.8*rad / gridsize); } } } void VisualSceneSolution :: DrawSurfaceVectors () { shared_ptr mesh = GetMesh(); SurfaceElementIndex sei; const SolData * vsol = NULL; // bool drawelem; if (vecfunction != -1) vsol = soldata[vecfunction]; if (mesh->GetTimeStamp () > solutiontimestamp) vsol = NULL; if (!vsol) return; Point<3> pmin = center - Vec3d (rad, rad, rad); Point<3> pmax = center - Vec3d (rad, rad, rad); // glColor3d (1.0, 1.0, 1.0); // glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); if (vsol->draw_surface && showsurfacesolution) { int nse = mesh->GetNSE(); for (sei = 0; sei < nse; sei++) { const Element2d & el = (*mesh)[sei]; if (el.GetType() == TRIG || el.GetType() == TRIG6) { NgArray< Point<3> > lp(3); lp[0] = mesh->Point(el[2]); lp[1] = mesh->Point(el[0]); lp[2] = mesh->Point(el[1]); DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol); /* Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]); Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2))); if (na(0) > na(1) && na(0) > na(2)) dir = 1; else if (na(1) > na(2)) dir = 2; else dir = 3; dir1 = (dir % 3) + 1; dir2 = (dir1 % 3) + 1; for (k = 0; k < 3; k++) { p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad), (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad)); } double minx2d, maxx2d, miny2d, maxy2d; minx2d = maxx2d = p2d[0](0); miny2d = maxy2d = p2d[0](1); for (k = 1; k < 3; k++) { minx2d = min2 (minx2d, p2d[k](0)); maxx2d = max2 (maxx2d, p2d[k](0)); miny2d = min2 (miny2d, p2d[k](1)); maxy2d = max2 (maxy2d, p2d[k](1)); } double mat11 = p2d[1](0) - p2d[0](0); double mat21 = p2d[1](1) - p2d[0](1); double mat12 = p2d[2](0) - p2d[0](0); double mat22 = p2d[2](1) - p2d[0](1); double det = mat11*mat22-mat21*mat12; double inv11 = mat22/det; double inv21 = -mat21/det; double inv12 = -mat12/det; double inv22 = mat11/det; // cout << "drawsurfacevectors. xoffset = " << xoffset << ", yoffset = "; // cout << yoffset << endl; for (s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize) if (s >= minx2d && s <= maxx2d) for (t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize) if (t >= miny2d && t <= maxy2d) { double lam1 = inv11 * (s - p2d[0](0)) + inv12 * (t-p2d[0](1)); double lam2 = inv21 * (s - p2d[0](0)) + inv22 * (t-p2d[0](1)); if (lam1 >= 0 && lam2 >= 0 && lam1+lam2 <= 1) { Point<3> cp; for (k = 0; k < 3; k++) cp(k) = lp[0](k) + lam1 * (lp[1](k)-lp[0](k)) + lam2 * (lp[2](k)-lp[0](k)); Vec<3> v; double values[6]; drawelem = GetSurfValues (vsol, sei, lam1, lam2, values); if (!vsol->iscomplex) for (k = 0; k < 3; k++) v(k) = values[k]; else { if (!imag_part) for (k = 0; k < 3; k++) v(k) = values[2*k]; else for (k = 0; k < 3; k++) v(k) = values[2*k+1]; } if (mesh->GetDimension() == 2) if ( (!vsol->iscomplex && vsol->components != 3) || (vsol->iscomplex && vsol->components != 6) ) v(2) = 0; double val = v.Length(); SetOpenGlColor (val, minval, maxval, logscale); if (val > 1e-10 * maxval) v *= (rad / val / gridsize * 0.5); else drawelem = 0; // "drawelem": added 07.04.2004 (FB) if ( drawelem ) DrawCone (cp, cp+4*v, 0.8*rad / gridsize); } } */ } else if (el.GetType() == QUAD) { NgArray < Point<3> > lp(3); lp[0] = mesh->Point(el[0]); lp[1] = mesh->Point(el[1]); lp[2] = mesh->Point(el[3]); DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol); lp[0] = mesh->Point(el[2]); lp[1] = mesh->Point(el[1]); lp[2] = mesh->Point(el[3]); DrawTrigSurfaceVectors(lp,pmin,pmax,sei,vsol, true); /* Point<3> lp[4]; Point<2> p2d[4]; for (int k = 0; k < 4; k++) lp[k] = mesh->Point (el[k]); Vec<3> n = Cross (lp[1]-lp[0], lp[2]-lp[0]); Vec<3> na (fabs (n(0)), fabs(n(1)), fabs(n(2))); int dir, dir1, dir2; if (na(0) > na(1) && na(0) > na(2)) dir = 1; else if (na(1) > na(2)) dir = 2; else dir = 3; dir1 = (dir % 3) + 1; dir2 = (dir1 % 3) + 1; for (int k = 0; k < 4; k++) { p2d[k] = Point<2> ((lp[k](dir1-1) - pmin(dir1-1)) / (2*rad), (lp[k](dir2-1) - pmin(dir2-1)) / (2*rad)); } double minx2d, maxx2d, miny2d, maxy2d; minx2d = maxx2d = p2d[0](0); miny2d = maxy2d = p2d[0](1); for (int k = 1; k < 4; k++) { minx2d = min2 (minx2d, p2d[k](0)); maxx2d = max2 (maxx2d, p2d[k](0)); miny2d = min2 (miny2d, p2d[k](1)); maxy2d = max2 (maxy2d, p2d[k](1)); } for (double s = xoffset/gridsize; s <= 1+xoffset/gridsize; s += 1.0 / gridsize) if (s >= minx2d && s <= maxx2d) for (double t = yoffset/gridsize; t <= 1+yoffset/gridsize; t += 1.0 / gridsize) if (t >= miny2d && t <= maxy2d) { double lami[3]; Point3d p3d(2*rad*s+pmin(0), 2*rad*t+pmin(1),0); if (mesh->PointContainedIn2DElement (p3d, lami, sei+1)) { Point<3> cp = p3d; double lam1 = lami[0]; double lam2 = lami[1]; //for (k = 0; k < 3; k++) //cp(k) = lp[0](k) + //lam1 * (lp[1](k)-lp[0](k)) + //lam2 * (lp[2](k)-lp[0](k)); Vec<3> v; double values[6]; bool drawelem = GetSurfValues (vsol, sei, -1, lam1, lam2, values); (*testout) << "sei " << sei << " lam1 " << lam1 << " lam2 " << lam2 << " drawelem " << drawelem << endl; if (!vsol->iscomplex) for (int k = 0; k < 3; k++) v(k) = values[k]; else { if (!imag_part) for (int k = 0; k < 3; k++) v(k) = values[2*k]; else for (int k = 0; k < 3; k++) v(k) = values[2*k+1]; } if (mesh->GetDimension() == 2) if ( (!vsol->iscomplex && vsol->components != 3) || (vsol->iscomplex && vsol->components != 6) ) v(2) = 0; double val = v.Length(); SetOpenGlColor (val); // , minval, maxval, logscale); july 09 (*testout) << "v " << v << endl; if (val > 1e-10 * maxval) v *= (rad / val / gridsize * 0.5); (*testout) << "v " << v << endl; if ( drawelem ) { DrawCone (cp, cp+4*v, 0.8*rad / gridsize); (*testout) << "cp " << cp << " rad " << rad << " gridsize " << gridsize << endl; } } } */ } } } } void VisualSceneSolution :: DrawIsoLines (const Point<3> & p1, const Point<3> & p2, const Point<3> & p3, double val1, double val2, double val3) { DrawIsoLines2 (p1, p2, p1, p3, val1, val2, val1, val3); // , minval, maxval, n); DrawIsoLines2 (p2, p1, p2, p3, val2, val1, val2, val3); // , minval, maxval, n); DrawIsoLines2 (p3, p1, p3, p2, val3, val1, val3, val2); // , minval, maxval, n); } void VisualSceneSolution :: DrawIsoLines2 (const Point<3> & hp1, const Point<3> & hp2, const Point<3> & hp3, const Point<3> & hp4, double val1, double val2, double val3, double val4) { int n = numisolines; Point<3> p1, p2, p3, p4; if (val1 < val2) { p1 = hp1; p2 = hp2; } else { p1 = hp2; p2 = hp1; swap (val1, val2); } if (val3 < val4) { p3 = hp3; p4 = hp4; } else { p3 = hp4; p4 = hp3; swap (val3, val4); } val2 += 1e-10; val4 += 1e-10; double fac = (maxval-minval) / n; double idelta1 = 1.0 / (val2 - val1); double idelta2 = 1.0 / (val4 - val3); int mini = int ((max2 (val1, val3) - minval) / fac); int maxi = int ((min2 (val2, val4) - minval) / fac); if (mini < 0) mini = 0; if (maxi > n-1) maxi = n-1; for (int i = mini; i <= maxi; i++) { double val = minval + i * fac; double lam1 = (val - val1) * idelta1; double lam2 = (val - val3) * idelta2; if (lam1 >= 0 && lam1 <= 1 && lam2 >= 0 && lam2 <= 1) { Point<3> lp1 = p1 + lam1 * (p2-p1); Point<3> lp2 = p3 + lam2 * (p4-p3); glVertex3dv (lp1 ); glVertex3dv (lp2 ); // glVertex3dv (lp2 ); // better ? // glVertex3dv (lp1 ); } } } void VisualSceneSolution :: GetMinMax (int funcnr, int comp, double & minv, double & maxv) const { shared_ptr mesh = GetMesh(); // static int timer1 = NgProfiler::CreateTimer ("getminmax, vol"); // static int timer2 = NgProfiler::CreateTimer ("getminmax, surf"); #ifdef PARALLELGL auto comm = mesh->GetCommunicator(); if (comm.Size() > 1) { if (id == 0) { MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("getminmax"); } MyMPI_Bcast (funcnr, mesh->GetCommunicator()); MyMPI_Bcast (comp, mesh->GetCommunicator()); } #endif // double val; // bool considerElem; bool hasit = false; #ifdef max #undef max #endif minv = numeric_limits::max(); maxv = -numeric_limits::max(); if ((ntasks == 1) || (id > 0)) if (funcnr != -1) { const SolData * sol = soldata[funcnr]; if (sol->draw_volume) { // NgProfiler::RegionTimer reg1 (timer1); int ne = mesh->GetNE(); mutex min_mutex; mutex max_mutex; ParallelFor(0, ne, [&] (int first, int next) { double minv_local = numeric_limits::max(); double maxv_local = -numeric_limits::max(); for (int i=first; i maxv_local) maxv_local = val; if (val < minv_local) minv_local = val; hasit = true; } } if(minv_local < minv) { lock_guard guard(min_mutex); if(minv_local < minv) minv = minv_local; } if(maxv_local > maxv) { lock_guard guard(max_mutex); if(maxv_local > maxv) maxv = maxv_local; } }); } if (sol->draw_surface) { // NgProfiler::RegionTimer reg2 (timer2); // int nse = mesh->GetNSE(); // for (int i = 0; i < nse; i++) for (SurfaceElementIndex i : mesh->SurfaceElements().Range()) { ELEMENT_TYPE type = (*mesh)[i].GetType(); double val; bool considerElem = (type == QUAD) ? GetSurfValue (sol, i, -1, 0.5, 0.5, comp, val) : GetSurfValue (sol, i, -1, 0.3333333, 0.3333333, comp, val); if (considerElem) { if (val > maxv) maxv = val; if (val < minv) minv = val; hasit = true; } } } } if (minv == maxv) maxv = minv+1e-6; if (!hasit) { minv = 0; maxv = 1; } #ifdef PARALLEL if ((ntasks > 1) && (id == 0)) { minv = 1e99; maxv = -1e99; } if (ntasks > 1) { double hmin, hmax; MPI_Reduce (&minv, &hmin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); MPI_Reduce (&maxv, &hmax, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); minv = hmin; maxv = hmax; } #endif } bool VisualSceneSolution :: GetValues (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); break; } default: { for (int i = 0; i < data->components; i++) ok = GetValue (data, elnr, lam1, lam2, lam3, i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetValues (const SolData * data, ElementIndex elnr, const double xref[], const double x[], const double dxdxref[], double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetValue (elnr, xref, x, dxdxref, values); break; } default: { for (int i = 0; i < data->components; i++) ok = GetValue (data, elnr, xref[0], xref[1], xref[2], i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetValue (const SolData * data, ElementIndex elnr, const double xref[], const double x[], const double dxdxref[], int comp, double & val) const { shared_ptr mesh = GetMesh(); double lam1 = xref[0]; double lam2 = xref[1]; double lam3 = xref[2]; val = 0; bool ok = 0; if (comp == 0) { NgArrayMem values(data->components); ok = GetValues (data, elnr, xref, x, dxdxref, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { double values[20]; ok = data->solclass->GetValue (elnr, xref, x, dxdxref, values); val = values[comp-1]; return ok; } case SOL_NODAL: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } default: cerr << "case not implemented 23523" << endl; } for (int i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { val = data->data[elnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_ELEMENT: return 0; case SOL_NONCONTINUOUS: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } case PYRAMID: case PYRAMID13: { if (lam3 > 1-1e-5) { lami[0] = lami[1] = lami[2] = lami[3] = 0; lami[4] = 1; } else { double x0 = lam1 / (1-lam3); double y0 = lam2 / (1-lam3); lami[0] = (1-x0) * (1-y0) * (1-lam3); lami[1] = ( x0) * (1-y0) * (1-lam3); lami[2] = ( x0) * ( y0) * (1-lam3); lami[3] = (1-x0) * ( y0) * (1-lam3); lami[4] = lam3; np = 5; } break; } default: np = 0; } int base; if (data->order == 1) base = 6 * elnr; else base = 10 * elnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { val = (*mesh)[elnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { val = (*mesh)[elnr].GetOrder(); return 1; } default: cerr << "case not handled 7234" << endl; } return 0; } bool VisualSceneSolution :: GetValue (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, int comp, double & val) const { shared_ptr mesh = GetMesh(); val = 0; bool ok = 0; if (comp == 0) { NgArrayMem values(data->components); ok = GetValues (data, elnr, lam1, lam2, lam3, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { val = 0.0; double values[20]; ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); val = values[comp-1]; return ok; } case SOL_NODAL: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } default: cerr << "case not implemented 234324" << endl; } for (int i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { val = data->data[elnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_ELEMENT: return 0; case SOL_NONCONTINUOUS: { const Element & el = (*mesh)[elnr]; double lami[8] = { 0.0 }; int np = 0; switch (el.GetType()) { case TET: case TET10: { lami[1] = lam1; lami[2] = lam2; lami[3] = lam3; lami[0] = 1-lam1-lam2-lam3; np = 4; break; } case PRISM: case PRISM12: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; lami[2] = (1-lam3) * lam2; lami[3] = (lam3) * (1-lam1-lam2); lami[4] = (lam3) * lam1; lami[5] = (lam3) * lam2; np = 6; break; } case PYRAMID: { if (lam3 > 1-1e-5) { lami[0] = lami[1] = lami[2] = lami[3] = 0; lami[4] = 1; } else { double x0 = lam1 / (1-lam3); double y0 = lam2 / (1-lam3); lami[0] = (1-x0) * (1-y0) * (1-lam3); lami[1] = ( x0) * (1-y0) * (1-lam3); lami[2] = ( x0) * ( y0) * (1-lam3); lami[3] = (1-x0) * ( y0) * (1-lam3); lami[4] = lam3; np = 5; } break; } default: np = 0; } int base; if (data->order == 1) base = 6 * elnr; else base = 10 * elnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { val = (*mesh)[elnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { val = (*mesh)[elnr].GetOrder(); return 1; } default: cerr << "case not implemented 234234" << endl; } return 0; } bool VisualSceneSolution :: GetValueComplex (const SolData * data, ElementIndex elnr, double lam1, double lam2, double lam3, int comp, complex & val) const { shared_ptr mesh = GetMesh(); val = 0.0; bool ok = 0; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { double values[20]; ok = data->solclass->GetValue (elnr, lam1, lam2, lam3, values); val = complex (values[comp-1], values[comp]); return ok; } default: cerr << "case not handled 234234" << endl; } return 0; } bool VisualSceneSolution :: GetMultiValues (const SolData * data, ElementIndex elnr, int facetnr, int npt, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * val, int sval) const { bool drawelem = false; if (data->soltype == SOL_VIRTUALFUNCTION) drawelem = data->solclass->GetMultiValue(elnr, facetnr, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval); else for (int i = 0; i < npt; i++) drawelem = GetValues (data, elnr, xref+i*sxref, x+i*sx, dxdxref+i*sdxdxref, val+i*sval); return drawelem; } bool VisualSceneSolution :: GetSurfValues (const SolData * data, SurfaceElementIndex selnr, int facetnr, double lam1, double lam2, double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, values); // ok = 1; // values[0] = 1.0; break; } default: { for (int i = 0; i < data->components; i++) ok = GetSurfValue (data, selnr, facetnr, lam1, lam2, i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetSurfValues (const SolData * data, SurfaceElementIndex selnr, int facetnr, const double xref[], const double x[], const double dxdxref[], double * values) const { bool ok = false; switch (data->soltype) { case SOL_VIRTUALFUNCTION: { ok = data->solclass->GetSurfValue (selnr, facetnr, xref, x, dxdxref, values); break; } default: { for (int i = 0; i < data->components; i++) ok = GetSurfValue (data, selnr, facetnr, xref[0], xref[1], i+1, values[i]); } } return ok; } bool VisualSceneSolution :: GetMultiSurfValues (const SolData * data, SurfaceElementIndex elnr, int facetnr, int npt, const double * xref, int sxref, const double * x, int sx, const double * dxdxref, int sdxdxref, double * val, int sval) const { bool drawelem = false; if (data->soltype == SOL_VIRTUALFUNCTION) drawelem = data->solclass->GetMultiSurfValue(elnr, facetnr, npt, xref, sxref, x, sx, dxdxref, sdxdxref, val, sval); else for (int i = 0; i < npt; i++) drawelem = GetSurfValues (data, elnr, facetnr, xref+i*sxref, x+i*sx, dxdxref+i*sdxdxref, val+i*sval); return drawelem; } double VisualSceneSolution :: ExtractValue (const SolData * data, int comp, double * values) const { double val = 0; if (comp == 0) { switch (evalfunc) { case FUNC_ABS: { for (int ci = 0; ci < data->components; ci++) val += sqr (values[ci]); val = sqrt (val); break; } case FUNC_ABS_TENSOR: { int d = 0; switch (data->components) { case 1: d = 1; break; case 3: d = 2; break; case 6: d = 3; break; } for (int ci = 0; ci < d; ci++) val += sqr (values[ci]); for (int ci = d; ci < data->components; ci++) val += 2*sqr (values[ci]); val = sqrt (val); break; } case FUNC_MISES: { int d = 0; switch(data->components) { case 1: d = 1; break; case 3: d = 2; break; case 6: d = 3; break; } int ci; double trace = 0.; for (ci = 0; ci < d; ci++) trace += 1./3.*(values[ci]); for (ci = 0; ci < d; ci++) val += sqr (values[ci]-trace); for (ci = d; ci < data->components; ci++) val += 2.*sqr (values[ci]); val = sqrt (val); break; } case FUNC_MAIN: { int d = 0; switch(data->components) { case 1: d = 1; break; case 3: d = 2; break; case 6: d = 3; break; } Mat<3,3> m ; Vec<3> ev; int ci; for (ci = 0; ci < d; ci++) m(ci,ci) = (values[ci]); m(0,1) = m(1,0) = values[3]; m(0,2) = m(2,0) = values[4]; m(1,2) = m(2,1) = values[5]; EigenValues (m, ev); double help; for (int i=0; i abs(ev(j-1)) ) { help = ev(j); ev(j) = ev(j-1); ev(j-1) = help; } } } val = (ev(0)); break; } } return val; } return values[comp-1]; } complex VisualSceneSolution :: ExtractValueComplex (const SolData * data, int comp, double * values) const { if (!data->iscomplex) return values[comp-1]; else return complex (values[comp-1], values[comp]); } bool VisualSceneSolution :: GetSurfValueComplex (const SolData * data, SurfaceElementIndex selnr, int facetnr, double lam1, double lam2, int comp, complex & val) const { switch (data->soltype) { case SOL_VIRTUALFUNCTION: { NgArrayMem values(data->components); bool ok; ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, &values[0]); if (ok) { if (!data->iscomplex) val = values[comp-1]; else val = complex (values[comp-1], values[comp]); } return ok; } default: cerr << "case not implemented 6565" << endl; } return 0; } bool VisualSceneSolution :: GetSurfValue (const SolData * data, SurfaceElementIndex selnr, int facetnr, double lam1, double lam2, int comp, double & val) const { bool ok; if (comp == 0) { val = 0; NgArrayMem values(data->components); ok = GetSurfValues (data, selnr, facetnr, lam1, lam2, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { NgArrayMem values(data->components); bool ok; ok = data->solclass->GetSurfValue (selnr, facetnr, lam1, lam2, &values[0]); if (ok) { if (!data->iscomplex) val = values[comp-1]; else { // cout << "time = " << time << ", cos = " << cos(time) << endl; // old version: val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); // SZ: Sept 06 if(comp%2==0) val = values[comp-1]*cos(3*time) - values[comp-2]*sin(3*time); else val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); } } return ok; } case SOL_NODAL: { shared_ptr mesh = GetMesh(); const Element2d & el = (*mesh)[selnr]; double lami[8]; int np, i; val = 0; double lam3 = 1-lam1-lam2; switch (el.GetType()) { case TRIG: /* lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; */ lami[0] = lam1; lami[1] = lam2; lami[2] = lam3; np = 3; break; case TRIG6: /* lami[0] = lam3*(2*lam3-1); lami[1] = lam1*(2*lam1-1); lami[2] = lam2*(2*lam2-1); */ // hierarchical basis: lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; case QUAD: case QUAD6: case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; lami[3] = (1-lam1) * lam2; np = 4; break; default: np = 0; } for (i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { shared_ptr mesh = GetMesh(); int el1, el2; mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2); el1--; val = data->data[el1 * data->dist+comp-1]; return 1; } case SOL_NONCONTINUOUS: { val = 0; // ????? return 0; } case SOL_SURFACE_ELEMENT: { val = data->data[selnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_NONCONTINUOUS: { shared_ptr mesh = GetMesh(); const Element2d & el = (*mesh)[selnr]; double lami[8]; int np = 0; val = 0; int order = data->order; switch (order) { case 0: return data->data[selnr * data->dist + comp-1]; case 1: { switch (el.GetType()) { case TRIG: case TRIG6: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } default: cerr << "case not implemented 2342" << endl; } break; } case 2: { switch (el.GetType()) { case TRIG: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } case TRIG6: { double lam3 = 1-lam1-lam2; lami[1] = 2*lam1 * (lam1-0.5); lami[2] = 2*lam2 * (lam2-0.5); lami[0] = 2*lam3 * (lam3-0.5); lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; } default: cerr << "case not implemented 8712" << endl; } break; } } int base; if (order == 1) base = 4 * selnr; else base = 9 * selnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { shared_ptr mesh = GetMesh(); val = (*mesh)[selnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { shared_ptr mesh = GetMesh(); val = (*mesh)[selnr].GetOrder(); return 1; } } return 0; } bool VisualSceneSolution :: GetSurfValue (const SolData * data, SurfaceElementIndex selnr, int facetnr, const double xref[], const double x[], const double dxdxref[], int comp, double & val) const { shared_ptr mesh = GetMesh(); double lam1 = xref[0], lam2 = xref[1]; bool ok; if (comp == 0) { val = 0; NgArrayMem values(data->components); ok = GetSurfValues (data, selnr, facetnr, xref, x, dxdxref, &values[0]); val = ExtractValue (data, 0, &values[0]); return ok; } switch (data->soltype) { case SOL_VIRTUALFUNCTION: { NgArrayMem values(data->components); bool ok; // ok = data->solclass->GetSurfValue (selnr, lam1, lam2, &values[0]); // cout << "data->solclass = " << flush << data->solclass << endl; ok = data->solclass->GetSurfValue (selnr, facetnr, xref, x, dxdxref, &values[0]); // ok = 1; // values[0] = 1.0; if (ok) { if (!data->iscomplex) val = values[comp-1]; else { // cout << "time = " << time << ", cos = " << cos(time) << endl; // old version: val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); // SZ: Sept 06 if(comp%2==0) val = values[comp-1]*cos(3*time) - values[comp-2]*sin(3*time); else val = values[comp-1]*cos(3*time) + values[comp]*sin(3*time); } } return ok; } case SOL_NODAL: { const Element2d & el = (*mesh)[selnr]; double lami[8]; int np, i; val = 0; double lam3 = 1-lam1-lam2; switch (el.GetType()) { case TRIG: /* lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; */ lami[0] = lam1; lami[1] = lam2; lami[2] = lam3; np = 3; break; case TRIG6: /* lami[0] = lam3*(2*lam3-1); lami[1] = lam1*(2*lam1-1); lami[2] = lam2*(2*lam2-1); */ // hierarchical basis: lami[0] = lam3; lami[1] = lam1; lami[2] = lam2; lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; case QUAD: case QUAD6: case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; lami[3] = (1-lam1) * lam2; np = 4; break; default: np = 0; } for (i = 0; i < np; i++) val += lami[i] * data->data[(el[i]-1) * data->dist + comp-1]; return 1; } case SOL_ELEMENT: { int el1, el2; mesh->GetTopology().GetSurface2VolumeElement (selnr+1, el1, el2); el1--; val = data->data[el1 * data->dist+comp-1]; return 1; } case SOL_NONCONTINUOUS: { val = 0; // ????? return 0; } case SOL_SURFACE_ELEMENT: { val = data->data[selnr * data->dist + comp-1]; return 1; } case SOL_SURFACE_NONCONTINUOUS: { const Element2d & el = (*mesh)[selnr]; double lami[8] = { 0.0 }; int np = 0; val = 0; int order = data->order; switch (order) { case 0: return data->data[selnr * data->dist + comp-1]; case 1: { switch (el.GetType()) { case TRIG: case TRIG6: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } default: cerr << "case not impl 234234" << endl; } break; } case 2: { switch (el.GetType()) { case TRIG: { lami[1] = lam1; lami[2] = lam2; lami[0] = 1-lam1-lam2; np = 3; break; } case TRIG6: { double lam3 = 1-lam1-lam2; lami[1] = 2*lam1 * (lam1-0.5); lami[2] = 2*lam2 * (lam2-0.5); lami[0] = 2*lam3 * (lam3-0.5); lami[3] = 4*lam1*lam2; lami[4] = 4*lam2*lam3; lami[5] = 4*lam1*lam3; np = 6; break; } default: cerr << "case not implemented 3234" << endl; } break; } } int base; if (order == 1) base = 4 * selnr; else base = 9 * selnr; for (int i = 0; i < np; i++) val += lami[i] * data->data[(base+i) * data->dist + comp-1]; return 1; } case SOL_MARKED_ELEMENTS: { val = (*mesh)[selnr].TestRefinementFlag(); return 1; } case SOL_ELEMENT_ORDER: { val = (*mesh)[selnr].GetOrder(); return 1; } } return 0; } Vec<3> VisualSceneSolution :: GetDeformation (ElementIndex elnr, const Point<3> & p) const { Vec<3> def; if (deform && vecfunction != -1) { GetValues (soldata[vecfunction], elnr, p(0), p(1), p(2), &def(0)); def *= scaledeform; if (soldata[vecfunction]->components == 2) def(2) = 0; } else def = 0; return def; } Vec<3> VisualSceneSolution :: GetSurfDeformation (SurfaceElementIndex elnr, int facetnr, double lam1, double lam2) const { shared_ptr mesh = GetMesh(); Vec<3> def; if (deform && vecfunction != -1) { // GetSurfValues (soldata[vecfunction], elnr, facetnr, lam1, lam2, &def(0)); double values[6]; GetSurfValues (soldata[vecfunction], elnr, facetnr, lam1, lam2, values); def = RealVec3d (values, soldata[vecfunction]->iscomplex, imag_part); def *= scaledeform; if (soldata[vecfunction]->components == 2) def(2) = 0; } else if (deform && scalfunction != -1 && mesh->GetDimension()==2) { // he: allow for 3d plots of 2d surfaces: usage: turn deformation on def = 0; GetSurfValue (soldata[scalfunction], elnr, facetnr, lam1, lam2, scalcomp, def(2)); def *= scaledeform; } else def = 0; return def; } void VisualSceneSolution :: GetPointDeformation (int pnum, Point<3> & p, SurfaceElementIndex elnr) const { shared_ptr mesh = GetMesh(); p = mesh->Point (pnum+1); if (deform && vecfunction != -1) { const SolData * vsol = soldata[vecfunction]; Vec<3> v(0,0,0); if (vsol->soltype == SOL_NODAL) { v = Vec3d(vsol->data[pnum * vsol->dist], vsol->data[pnum * vsol->dist+1], vsol->data[pnum * vsol->dist+2]); } else if (vsol->soltype == SOL_SURFACE_NONCONTINUOUS) { const Element2d & el = (*mesh)[elnr]; for (int j = 0; j < el.GetNP(); j++) if (el[j] == pnum+1) { int base = (4*elnr+j-1) * vsol->dist; v = Vec3d(vsol->data[base], vsol->data[base+1], vsol->data[base+2]); } } if (vsol->dist == 2) v(2) = 0; v *= scaledeform; p += v; } } void VisualSceneSolution :: GetClippingPlaneTrigs (SolData * sol, NgArray & trigs, NgArray & pts) { shared_ptr mesh = GetMesh(); // static int timer_vals = NgProfiler::CreateTimer ("ClipPlaneTrigs - vertex values"); static int timer1 = NgProfiler::CreateTimer ("ClipPlaneTrigs1"); // static int timer1a = NgProfiler::CreateTimer ("ClipPlaneTrigs1a"); // static int timer2 = NgProfiler::CreateTimer ("ClipPlaneTrigs2"); // static int timer3 = NgProfiler::CreateTimer ("ClipPlaneTrigs3"); // static int timer4 = NgProfiler::CreateTimer ("ClipPlaneTrigs4"); // static int timer4b = NgProfiler::CreateTimer ("ClipPlaneTrigs4b"); NgProfiler::RegionTimer reg1 (timer1); int ne = mesh->GetNE(); const int edgei[6][2] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 } }; double edgelam[6]; // Point<3> edgep[6]; double nodevali[4]; int cntce; int cpe1 = 0, cpe2 = 0, cpe3 = 0; // NgArray loctets; // NgArray loctetsloc; // NgArray > pointsloc; int n = 1 << subdivisions; int n3 = (n+1)*(n+1)*(n+1); NgArray > grid(n3); NgArray > locgrid(n3); NgArray > trans(n3); NgArray val(n3); NgArray locposval(n3); NgArray compress(n3); // NgProfiler::StartTimer (timer_vals); NgArray vertval(mesh->GetNP()); NgArray posval(mesh->GetNP()); // for (PointIndex pi = vertval.Begin(); pi < vertval.End(); pi++) for (PointIndex pi : vertval.Range()) { Point<3> vert = (*mesh)[pi]; vertval[pi] = vert(0) * clipplane[0] + vert(1) * clipplane[1] + vert(2) * clipplane[2] + clipplane[3]; posval[pi] = vertval[pi] > 0; } // NgProfiler::StopTimer (timer_vals); INDEX_2_CLOSED_HASHTABLE edges(8*n3); // point nr of edge for (ElementIndex ei = 0; ei < ne; ei++) { // NgProfiler::RegionTimer reg1a (timer1a); const Element & el = (*mesh)[ei]; if(!VolumeElementActive(sol, *mesh, el)) continue; int first_point_of_element = pts.Size(); locgrid.SetSize(n3); if(vispar.clipdomain > 0 && vispar.clipdomain != (*mesh)[ei].GetIndex()) continue; if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue; ELEMENT_TYPE type = (*mesh)[ei].GetType(); if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID || type == PYRAMID13 || type == PRISM15 || type == HEX20 || type == HEX7) { int ii = 0; int cnt_valid = 0; // NgProfiler::StartTimer (timer2); if (!mesh->GetCurvedElements().IsElementHighOrder(ei)) { bool has_pos = 0, has_neg = 0; for (int i = 0; i < el.GetNP(); i++) if (posval[el[i]]) has_pos = 1; else has_neg = 1; if (!has_pos || !has_neg) { // NgProfiler::StopTimer (timer2); continue; } } if (type == TET || type == TET10) { for (int ix = 0; ix <= n; ix++) for (int iy = 0; iy <= n; iy++) for (int iz = 0; iz <= n; iz++, ii++) { if (ix+iy+iz <= n) { compress[ii] = cnt_valid; locgrid[cnt_valid] = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); cnt_valid++; } else compress[ii] = -1; } } else for (int ix = 0; ix <= n; ix++) for (int iy = 0; iy <= n; iy++) for (int iz = 0; iz <= n; iz++, ii++) { double x = double(ix)/n; double y = double(iy)/n; double z = double(iz)/n; Point<3> ploc; compress[ii] = ii; switch (type) { case PRISM: case PRISM12: case PRISM15: if (ix+iy <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); compress[ii] = cnt_valid; cnt_valid++; } else compress[ii] = -1; break; case HEX: case HEX20: ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); break; case PYRAMID: case PYRAMID13: ploc = Point<3> (double(ix) / n * (1-double(iz)/n), double(iy) / n * (1-double(iz)/n), double(iz)/n); if (iz == n) ploc = Point<3> (0,0,1-1e-8); break; case HEX7: { if (iz == n && iy==n) { y -= 1e-7, z -= 1e-7; } ploc = Point<3> (x * (1-y*z), y, z); // if (iz == n && iy==n) ploc = Point<3> (0,1-1e-8,1-1e-8); break; } default: cerr << "clip plane trigs not implemented" << endl; ploc = Point<3> (0,0,0); } if (compress[ii] != -1) locgrid[compress[ii]] = ploc; } if (type != TET && type != TET10 && type != PRISM && type != PRISM12 && type != PRISM15) cnt_valid = n3; locgrid.SetSize(cnt_valid); // NgProfiler::StopTimer (timer2); // NgProfiler::RegionTimer reg4(timer4); if (mesh->GetCurvedElements().IsHighOrder()) { // NgProfiler::RegionTimer reg4(timer4); mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locgrid, ei, &grid, 0); } else { // NgProfiler::RegionTimer reg4(timer4b); Vector shape(el.GetNP()); MatrixFixWidth<3> pointmat(el.GetNP()); for (int k = 0; k < el.GetNP(); k++) for (int j = 0; j < 3; j++) pointmat(k,j) = (*mesh)[el[k]](j); for (int i = 0; i < cnt_valid; i++) { el.GetShapeNew (locgrid[i], shape); Point<3> pglob; for (int j = 0; j < 3; j++) { pglob(j) = 0; for (int k = 0; k < el.GetNP(); k++) pglob(j) += shape(k) * pointmat(k,j); } grid[i] = pglob; } } // NgProfiler::RegionTimer reg3(timer3); bool has_pos = false, all_pos = true; for (int i = 0; i < cnt_valid; i++) { val[i] = grid[i](0) * clipplane[0] + grid[i](1) * clipplane[1] + grid[i](2) * clipplane[2] + clipplane[3]; locposval[i] = val[i] > 0; has_pos |= locposval[i]; all_pos &= locposval[i]; // if (val[i] > 0) has_pos = 1; else has_neg = 1; } // if (!has_pos || !has_neg) continue; if (!has_pos || all_pos) continue; edges.DeleteData(); for (int ix = 0; ix < n; ix++) for (int iy = 0; iy < n; iy++) for (int iz = 0; iz < n; iz++) { int base = iz + (n+1)*iy + (n+1)*(n+1)*ix; int pi[8] = { base, base+(n+1)*(n+1), base+(n+1)*(n+1)+(n+1), base+(n+1), base+1, base+(n+1)*(n+1)+1, base+(n+1)*(n+1)+(n+1)+1, base+(n+1)+1 }; for (int j = 0; j < 8; j++) pi[j] = compress[pi[j]]; bool has_pos = false, all_pos = true; for (int j = 0; j < 8; j++) if (pi[j] != -1) { has_pos |= locposval[pi[j]]; all_pos &= locposval[pi[j]]; } if (!has_pos || all_pos) continue; const int tets[6][4] = { { 1, 2, 4, 5 }, { 4, 5, 2, 8 }, { 2, 8, 5, 6 }, { 2, 3, 4, 8 }, { 2, 3, 8, 6 }, { 3, 8, 6, 7 } }; for (int ii = 0; ii < 6; ii++) { int teti[4]; for (int k = 0; k < 4; k++) teti[k] = pi[tets[ii][k]-1]; bool is_valid = true; for (int j = 0; j < 4; j++) is_valid &= (teti[j] != -1); if (!is_valid) continue; bool has_pos = false, all_pos = true; for (int j = 0; j < 4; j++) { has_pos |= locposval[teti[j]]; all_pos &= locposval[teti[j]]; } if (!has_pos || all_pos) continue; for (int j = 0; j < 4; j++) nodevali[j] = val[teti[j]]; cntce = 0; for (int j = 0; j < 6; j++) { int lpi1 = edgei[j][0]; int lpi2 = edgei[j][1]; if ( (nodevali[lpi1] > 0) != (nodevali[lpi2] > 0) ) { cntce++; cpe3 = cpe2; cpe2 = cpe1; cpe1 = j; if (cntce >= 3) { ClipPlaneTrig cpt; cpt.elnr = ei; for (int k = 0; k < 3; k++) { int ednr; switch (k) { case 0: ednr = cpe1; break; case 1: ednr = cpe2; break; case 2: ednr = cpe3; break; } int pi1 = edgei[ednr][0]; int pi2 = edgei[ednr][1]; int pnr = -1; INDEX_2 pair (teti[pi1], teti[pi2]); pair.Sort(); if (edges.Used(pair)) pnr = edges.Get(pair); else { ClipPlanePoint cppt; cppt.elnr = ei; edgelam[ednr] = nodevali[pi2] / (nodevali[pi2] - nodevali[pi1]); Point<3> gp1 = grid[teti[pi1]]; Point<3> gp2 = grid[teti[pi2]]; cppt.p = gp2 + edgelam[ednr] * (gp1-gp2); Point<3> p1 = locgrid[teti[pi1]]; Point<3> p2 = locgrid[teti[pi2]]; cppt.lami = p2 + edgelam[ednr] * (p1-p2); pts.Append (cppt); pnr = pts.Size()-1; edges.Set (pair, pnr); } cpt.points[k].pnr = pnr; cpt.points[k].locpnr = pnr-first_point_of_element; } trigs.Append (cpt); } } } } } } else { // other elements not supported (JS, June 2007) continue; // return; } } } void VisualSceneSolution :: GetClippingPlaneGrid (NgArray & pts) { shared_ptr mesh = GetMesh(); Vec3d n(clipplane[0], clipplane[1], clipplane[2]); double mu = -clipplane[3] / n.Length2(); Point3d p(mu*n.X(), mu * n.Y(), mu * n.Z()); // n /= n.Length(); n.Normalize(); Vec3d t1, t2; n.GetNormal (t1); t2 = Cross (n, t1); double xi1, xi2; double xi1mid = (center - p) * t1; double xi2mid = (center - p) * t2; pts.SetSize(0); for (xi1 = xi1mid-rad+xoffset/gridsize; xi1 <= xi1mid+rad+xoffset/gridsize; xi1 += rad / gridsize) for (xi2 = xi2mid-rad+yoffset/gridsize; xi2 <= xi2mid+rad+yoffset/gridsize; xi2 += rad / gridsize) { Point3d hp = p + xi1 * t1 + xi2 * t2; int cindex(-1); bool allowindex(true); if(vispar.clipdomain > 0) { cindex = vispar.clipdomain; } else if(vispar.donotclipdomain > 0) { allowindex = false; cindex = vispar.donotclipdomain; } double lami[3]; int elnr = mesh->GetElementOfPoint (hp, lami,0,cindex,allowindex)-1; if (elnr != -1) { ClipPlanePoint cpp; cpp.p = hp; cpp.elnr = elnr; cpp.lami(0) = lami[0]; cpp.lami(1) = lami[1]; cpp.lami(2) = lami[2]; pts.Append (cpp); } } }; void VisualSceneSolution :: DrawClipPlaneTrigs () { shared_ptr mesh = GetMesh(); #ifdef PARALLELGL if (id == 0 && ntasks > 1) { InitParallelGL(); NgArray parlists (ntasks); MyMPI_SendCmd ("redraw"); MyMPI_SendCmd ("clipplanetrigs"); for ( int dest = 1; dest < ntasks; dest++ ) MyMPI_Recv (parlists[dest], dest, MPI_TAG_VIS); if (clipplanelist_scal) glDeleteLists (clipplanelist_scal, 1); clipplanelist_scal = glGenLists (1); glNewList (clipplanelist_scal, GL_COMPILE); for ( int dest = 1; dest < ntasks; dest++ ) glCallList (parlists[dest]); glEndList(); return; } #endif if (clipplanelist_scal) glDeleteLists (clipplanelist_scal, 1); clipplanelist_scal = glGenLists (1); glNewList (clipplanelist_scal, GL_COMPILE); NgArray trigs; NgArray points; glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); glColor3d (1.0, 1.0, 1.0); SetTextureMode (usetexture); SolData * sol = NULL; if (scalfunction != -1) sol = soldata[scalfunction]; GetClippingPlaneTrigs (sol, trigs, points); if (sol -> draw_volume) { glBegin (GL_TRIANGLES); int maxlpnr = 0; for (int i = 0; i < trigs.Size(); i++) for (int j = 0; j < 3; j++) maxlpnr = max2 (maxlpnr, trigs[i].points[j].locpnr); NgArray vals(maxlpnr+1); NgArray > valsc(maxlpnr+1); NgArray elnrs(maxlpnr+1); NgArray trigok(maxlpnr+1); NgArray > locpoints(maxlpnr+1); NgArray > globpoints(maxlpnr+1); NgArray > jacobi(maxlpnr+1); NgArray mvalues( (maxlpnr+1) * sol->components); trigok = false; elnrs = -1; Point<3> p[3]; // double val[3]; // complex valc[3]; int lastelnr = -1; int nlp = -1; bool ok = false; for (int i = 0; i < trigs.Size(); i++) { const ClipPlaneTrig & trig = trigs[i]; if (trig.elnr != lastelnr) { lastelnr = trig.elnr; nlp = -1; for (int ii = i; ii < trigs.Size(); ii++) { if (trigs[ii].elnr != trig.elnr) break; for (int j = 0; j < 3; j++) nlp = max (nlp, trigs[ii].points[j].locpnr); } nlp++; locpoints.SetSize (nlp); for (int ii = i; ii < trigs.Size(); ii++) { if (trigs[ii].elnr != trig.elnr) break; for (int j = 0; j < 3; j++) locpoints[trigs[ii].points[j].locpnr] = points[trigs[ii].points[j].pnr].lami; } mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locpoints, trig.elnr, &globpoints, &jacobi); bool drawelem = GetMultiValues (sol, trig.elnr, -1, nlp, &locpoints[0](0), &locpoints[1](0)-&locpoints[0](0), &globpoints[0](0), &globpoints[1](0)-&globpoints[0](0), &jacobi[0](0), &jacobi[1](0)-&jacobi[0](0), &mvalues[0], sol->components); // cout << "have multivalues, comps = " << sol->components << endl; // if (!drawelem) ok = false; ok = drawelem; if (usetexture != 2 || !sol->iscomplex) for (int ii = 0; ii < nlp; ii++) vals[ii] = ExtractValue(sol, scalcomp, &mvalues[ii*sol->components]); else for (int ii = 0; ii < nlp; ii++) valsc[ii] = complex (mvalues[ii*sol->components + scalcomp-1], mvalues[ii*sol->components + scalcomp]); } if(ok) for(int j=0; j<3; j++) { if (usetexture != 2 || !sol->iscomplex) SetOpenGlColor (vals[trig.points[j].locpnr]); else glTexCoord2f ( valsc[trig.points[j].locpnr].real(), valsc[trig.points[j].locpnr].imag() ); p[j] = points[trig.points[j].pnr].p; if (deform) { Point<3> ploc = points[trig.points[j].pnr].lami; p[j] += GetDeformation (trig.elnr, ploc); } glVertex3dv (p[j]); } } glEnd(); } glEndList (); #ifdef PARALLELGLGL glFinish(); if (id > 0) MyMPI_Send (clipplanelist_scal, 0, MPI_TAG_VIS); #endif } void VisualSceneSolution :: SetOpenGlColor(double val) { if (usetexture == 1 && !logscale) { glTexCoord1f ( val ); return; } double valmin = minval; double valmax = maxval; double value; if (!logscale) value = (val - valmin) / (valmax - valmin); else { if (valmax <= 0) valmax = 1; if (valmin <= 0) valmin = 1e-4 * valmax; value = (log(fabs(val)) - log(valmin)) / (log(valmax) - log(valmin)); } if (!invcolor) value = 1 - value; if (value > 1) value = 1; if (value < 0) value = 0; value *= 4; static const double colp[][3] = { { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 0, 1 }, { 1, 0, 1 }, { 1, 0, 0 }, }; int i = int(value); double r = value - i; GLdouble col[3]; for (int j = 0; j < 3; j++) col[j] = (1-r) * colp[i][j] + r * colp[i+1][j]; glColor3dv (col); } void VisualSceneSolution :: SetTextureMode (int texturemode) const { switch (texturemode) { case 0: glDisable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_2D); break; case 1: glEnable (GL_TEXTURE_1D); glDisable (GL_TEXTURE_2D); glColor3d (1.0, 1.0, 1.0); break; case 2: glDisable (GL_TEXTURE_1D); glEnable (GL_TEXTURE_2D); glColor3d (1.0, 1.0, 1.0); break; } } void VisualSceneSolution :: DrawCone (const Point<3> & p1, const Point<3> & p2, double r) { int n = 10, i; Vec<3> p1p2 = p2 - p1; p1p2.Normalize(); Vec<3> p2p1 = -p1p2; Vec<3> t1 = p1p2.GetNormal(); Vec<3> t2 = Cross (p1p2, t1); Point<3> oldp = p1 + r * t1; Vec<3> oldn = t1; Point<3> p; Vec<3> normal; Mat<2> rotmat; Vec<2> cs, newcs; cs(0) = 1; cs(1) = 0; rotmat(0,0) = rotmat(1,1) = cos(2*M_PI/n); rotmat(1,0) = sin(2*M_PI/n); rotmat(0,1) = -rotmat(1,0); glBegin (GL_TRIANGLES); for (i = 1; i <= n; i++) { /* phi = 2 * M_PI * i / n; normal = cos(phi) * t1 + sin(phi) * t2; */ newcs = rotmat * cs; cs = newcs; normal = cs(0) * t1 + cs(1) * t2; p = p1 + r * normal; // cone glNormal3dv (normal); glVertex3dv (p); glVertex3dv (p2); glNormal3dv (oldn); glVertex3dv (oldp); // base-circle glNormal3dv (p2p1); glVertex3dv (p); glVertex3dv (p1); glVertex3dv (oldp); oldp = p; oldn = normal; } glEnd (); } void VisualSceneSolution :: DrawCylinder (const Point<3> & p1, const Point<3> & p2, double r) { int n = 10, i; Vec<3> p1p2 = p2 - p1; p1p2.Normalize(); // Vec<3> p2p1 = -p1p2; Vec<3> t1 = p1p2.GetNormal(); Vec<3> t2 = Cross (p1p2, t1); Point<3> oldhp1 = p1 + r * t1; Point<3> oldhp2 = p2 + r * t1; Vec<3> oldn = t1; Point<3> hp1, hp2; Vec<3> normal; Mat<2> rotmat; Vec<2> cs, newcs; cs(0) = 1; cs(1) = 0; rotmat(0,0) = rotmat(1,1) = cos(2*M_PI/n); rotmat(1,0) = sin(2*M_PI/n); rotmat(0,1) = -rotmat(1,0); glBegin (GL_QUADS); for (i = 1; i <= n; i++) { newcs = rotmat * cs; cs = newcs; normal = cs(0) * t1 + cs(1) * t2; hp1 = p1 + r * normal; hp2 = p2 + r * normal; // cylinder glNormal3dv (normal); glVertex3dv (hp1); glVertex3dv (hp2); glVertex3dv (oldhp2); glVertex3dv (oldhp1); oldhp1 = hp1; oldhp2 = hp2; oldn = normal; } glEnd (); } bool VisualSceneSolution :: SurfaceElementActive(const SolData *data, const Mesh & mesh, const Element2d & el) { if(data == nullptr) return true; bool is_active = data->draw_surface; if (vispar.drawdomainsurf > 0) { if (mesh.GetDimension() == 3) { if (vispar.drawdomainsurf != mesh.GetFaceDescriptor(el.GetIndex()).DomainIn() && vispar.drawdomainsurf != mesh.GetFaceDescriptor(el.GetIndex()).DomainOut()) is_active = false; } else { if (el.GetIndex() != vispar.drawdomainsurf) is_active = false; } } if(data->draw_surfaces) is_active = is_active && (*data->draw_surfaces)[el.GetIndex()-1]; return is_active; } bool VisualSceneSolution :: VolumeElementActive(const SolData *data, const Mesh & mesh, const Element & el) { bool is_active = true; if(data->draw_volumes) is_active = is_active && (*data->draw_volumes)[el.GetIndex()-1]; return is_active; } void VisualSceneSolution :: MouseDblClick (int px, int py) { auto mesh = GetMesh(); // auto dim = mesh->GetDimension(); marker = nullopt; auto formatComplex = [](double real, double imag) { return ToString(real) + (imag < 0 ? "" : "+") + ToString(imag) + "j"; }; auto printScalValue = [&formatComplex] (SolData & sol, int comp, double value, double imag=0., bool iscomplex=false) { cout << '\t'; if(sol.components>1) { if(comp==0) cout << "func(" << sol.name << ")"; else cout << sol.name << "["+ToString(comp)+"]"; } else cout << sol.name; cout << " = " << (iscomplex ? formatComplex(value, imag) : ToString(value)) << endl; }; auto printVecValue = [&formatComplex] (SolData & sol, FlatArray values) { if(sol.iscomplex) { cout << sol.name << " = ( " << formatComplex(values[0], values[1]); for(int i = 2; i < values.Size(); i+=2) cout << ", " << formatComplex(values[i], values[i+1]); cout << " )" << endl; } else { cout << sol.name << " = ( " << values[0]; for(int i = 1; i < values.Size(); i++) cout << ", " << values[i]; cout << " )" << endl; } }; Point<3> p; bool found_point = vsmesh.SelectSurfaceElement(px, py, p, showclipsolution && clipsolution); if(!found_point) return; // marker = p; // found point on clipping plane if(selelement==0) { GLint viewport[4]; GLdouble projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, &projection[0]); glGetIntegerv(GL_VIEWPORT, &viewport[0]); Point<3> eye; gluUnProject( (viewport[2]-viewport[0])/2 , (viewport[3]-viewport[1])/2, 0.0, transformationmat, projection, viewport, &eye[0], &eye[1], &eye[2]); Vec<3> n{vispar.clipping.normal}; n.Normalize(); Vec<3> view = p-eye; // check if we look at the clipping plane from the right direction if(n*view > 1e-8) { double lam = vispar.clipping.dist - Vec<3>{eye}*n; lam /= n*view; p = eye + lam*view; double lami[3]; if(auto el3d = mesh->GetElementOfPoint( p, lami )) { cout << endl << "Selected point " << p << " on clipping plane" << endl; // marker = p; bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_volume; // bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_volume; if(have_scal_func) { auto & sol = *soldata[scalfunction]; double val; double imag = 0; int rcomponent = scalcomp; int comp = scalcomp; if(sol.iscomplex && rcomponent != 0) { rcomponent = 2 * ((rcomponent-1)/2) + 1; GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent+1, imag); comp = (scalcomp-1)/2 + 1; } GetValue(&sol, el3d-1, lami[0], lami[1], lami[2], rcomponent, val); printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0); } if(vecfunction!=-1 && soldata[vecfunction]->draw_volume) { auto & sol = *soldata[vecfunction]; ArrayMem values(sol.components); GetValues(&sol, el3d-1, lami[0], lami[1], lami[2], &values[0]); printVecValue(sol, values); } return; } } } double lami[3] = {0.0, 0.0, 0.0}; // Check if unprojected Point is close to surface element (eps of 1e-3 due to z-Buffer accuracy) bool found_2del = false; if(selelement>0 && mesh->PointContainedIn2DElement(p, lami, selelement, false && fabs(lami[2])<1e-3)) { // Found it, use coordinates of point projected to surface element mesh->GetCurvedElements().CalcSurfaceTransformation({1.0-lami[0]-lami[1], lami[0]}, selelement-1, p); found_2del = true; } cout << endl << "Selected point " << p << " on surface" << endl; if(!found_2del) return; bool have_scal_func = scalfunction!=-1 && soldata[scalfunction]->draw_surface; bool have_vec_func = vecfunction!=-1 && soldata[vecfunction]->draw_surface; if(have_scal_func) { auto & sol = *soldata[scalfunction]; double val; double imag = 0; int rcomponent = scalcomp; int comp = scalcomp; if(sol.iscomplex && rcomponent != 0) { rcomponent = 2 * ((rcomponent-1)/2) + 1; GetSurfValue(&sol, selelement-1, -1, 1.0-lami[0]-lami[1], lami[0], rcomponent+1, imag); comp = (scalcomp-1)/2 + 1; } GetSurfValue(&sol, selelement-1, -1, 1.0-lami[0]-lami[1], lami[0], rcomponent, val); printScalValue(sol, comp, val, imag, sol.iscomplex && comp > 0); } if(have_vec_func) { auto & sol = *soldata[vecfunction]; ArrayMem values(sol.components); GetSurfValues(&sol, selelement-1, -1, 1.0-lami[0]-lami[1], lami[0], &values[0]); printVecValue(sol, values); } } #ifdef PARALLELGL void VisualSceneSolution :: Broadcast () { MPI_Datatype type; int blocklen[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1 }; MPI_Aint displ[] = { (char*)&usetexture - (char*)this, (char*)&clipsolution - (char*)this, (char*)&scalfunction - (char*)this, (char*)&scalcomp - (char*)this, (char*)&vecfunction - (char*)this, (char*)&gridsize - (char*)this, (char*)&autoscale - (char*)this, (char*)&logscale - (char*)this, (char*)&minval - (char*)this, (char*)&maxval - (char*)this, (char*)&numisolines - (char*)this, (char*)&subdivisions - (char*)this, (char*)&evalfunc - (char*)this, (char*)&clipplane[0] - (char*)this, (char*)&multidimcomponent - (char*)this, (char*)&deform - (char*)this, (char*)&scaledeform - (char*)this }; MPI_Datatype types[] = { MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_DOUBLE }; MPI_Type_create_struct (17, blocklen, displ, types, &type); MPI_Type_commit ( &type ); MPI_Bcast (this, 1, type, 0, MPI_COMM_WORLD); MPI_Type_free (&type); } #endif } #include "../include/nginterface.h" void Impl_Ng_ClearSolutionData () { #ifdef OPENGL // if (nodisplay) return; // netgen::vssolution.ClearSolutionData(); netgen::GetVSSolution().ClearSolutionData(); #endif } void Impl_Ng_InitSolutionData (Ng_SolutionData * soldata) { // soldata -> name = NULL; soldata -> data = NULL; soldata -> components = 1; soldata -> dist = 1; soldata -> order = 1; soldata -> iscomplex = 0; soldata -> draw_surface = 1; soldata -> draw_volume = 1; soldata -> draw_surfaces = nullptr; soldata -> draw_volumes = nullptr; soldata -> soltype = NG_SOLUTION_NODAL; soldata -> solclass = 0; } void Impl_Ng_SetSolutionData (Ng_SolutionData * soldata) { #ifdef OPENGL // if (nodisplay) return; // vssolution.ClearSolutionData (); netgen::VisualSceneSolution::SolData * vss = new netgen::VisualSceneSolution::SolData; // vss->name = new char[strlen (soldata->name)+1]; // strcpy (vss->name, soldata->name); vss->name = soldata->name; vss->title = soldata->title; vss->number_format = soldata->number_format; vss->unit = soldata->unit; vss->data = soldata->data; vss->components = soldata->components; vss->dist = soldata->dist; vss->order = soldata->order; vss->iscomplex = bool(soldata->iscomplex); vss->draw_surface = soldata->draw_surface; vss->draw_volume = soldata->draw_volume; vss->draw_surfaces = soldata->draw_surfaces; vss->draw_volumes = soldata->draw_volumes; vss->soltype = netgen::VisualSceneSolution::SolType (soldata->soltype); vss->solclass = soldata->solclass; // netgen::vssolution.AddSolutionData (vss); netgen::GetVSSolution().AddSolutionData (vss); #endif } void Impl_Ng_Redraw (bool blocking) { #ifdef OPENGL //netgen::vssolution.UpdateSolutionTimeStamp(); netgen::GetVSSolution().UpdateSolutionTimeStamp(); netgen::Render(blocking); #endif } #ifdef OPENGL #ifdef WIN32 void (*glBindBuffer) (GLenum a, GLuint b); void (*glDeleteBuffers) (GLsizei a, const GLuint *b); void (*glGenBuffers) (GLsizei a, GLuint *b); void (*glBufferData) (GLenum a, GLsizeiptr b, const GLvoid *c, GLenum d); void (*glBufferSubData) (GLenum a, GLintptr b, GLsizeiptr c, const GLvoid *d); GLenum (*glCheckFramebufferStatus) (GLenum target); void (*glBindFramebuffer) (GLenum target, GLuint framebuffer); void (*glBindRenderbuffer) (GLenum target, GLuint renderbuffer); void (*glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers); void (*glDeleteRenderbuffers) (GLsizei n, const GLuint *renderbuffers); void (*glGenFramebuffers) (GLsizei n, GLuint *framebuffers); void (*glGenRenderbuffers) (GLsizei n, GLuint *renderbuffers); void (*glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); void (*glFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); NGGUI_API void LoadOpenGLFunctionPointers() { #ifdef USE_BUFFERS glBindBuffer = (decltype(glBindBuffer)) wglGetProcAddress("glBindBuffer"); glBufferSubData = (decltype(glBufferSubData)) wglGetProcAddress("glBufferSubData"); glBufferData = (decltype(glBufferData)) wglGetProcAddress("glBufferData"); glDeleteBuffers = (decltype(glDeleteBuffers)) wglGetProcAddress("glDeleteBuffers"); glGenBuffers = (decltype(glGenBuffers)) wglGetProcAddress("glGenBuffers"); if(!glBindBuffer) throw std::runtime_error("Could not load OpenGL functions!"); #endif glCheckFramebufferStatus = (decltype(glCheckFramebufferStatus )) wglGetProcAddress("glCheckFramebufferStatus"); glBindFramebuffer = (decltype(glBindFramebuffer )) wglGetProcAddress("glBindFramebuffer"); glBindRenderbuffer = (decltype(glBindRenderbuffer )) wglGetProcAddress("glBindRenderbuffer"); glDeleteFramebuffers = (decltype(glDeleteFramebuffers )) wglGetProcAddress("glDeleteFramebuffers"); glDeleteRenderbuffers = (decltype(glDeleteRenderbuffers )) wglGetProcAddress("glDeleteRenderbuffers"); glGenFramebuffers = (decltype(glGenFramebuffers )) wglGetProcAddress("glGenFramebuffers"); glGenRenderbuffers = (decltype(glGenRenderbuffers )) wglGetProcAddress("glGenRenderbuffers"); glRenderbufferStorage = (decltype(glRenderbufferStorage )) wglGetProcAddress("glRenderbufferStorage"); glFramebufferRenderbuffer = (decltype(glFramebufferRenderbuffer )) wglGetProcAddress("glFramebufferRenderbuffer"); } #else // WIN32 NGGUI_API void LoadOpenGLFunctionPointers() { } #endif // WIN32 #endif // OPENGL // set function pointers static bool dummy_init = [](){ Ptr_Ng_ClearSolutionData = Impl_Ng_ClearSolutionData; Ptr_Ng_InitSolutionData = Impl_Ng_InitSolutionData; Ptr_Ng_SetSolutionData = Impl_Ng_SetSolutionData; Ptr_Ng_Redraw = Impl_Ng_Redraw; return true; }();