Plot more points only in specific region of plot

Unfortunately the recursion algorithm fails to increase points near the Dirac points (actually, with a narrow band gap). It seems that it is because $\partial f(x,y)/\partial x,\ \partial f(x,y)/\partial y \ll 1$. However you can scale your function, scale back with a post-processing and obtain a nice plot!

scale = 1000;
postProcess[g_] := 
  g /. GraphicsComplex[pts_, opts___] :> 
     GraphicsComplex[(pts\[Transpose]/{1, 1, scale})\[Transpose], 
      opts] /. (VertexNormals -> 
      n_) :> (VertexNormals -> (n\[Transpose] {1, 1, 
          scale})\[Transpose]);
Timing[With[{plotopts = {Mesh -> None, PlotStyle -> Opacity[0.7], 
     Ticks -> {{-Pi, 0, Pi}, {-Pi, 0, Pi}, Automatic}, 
     PlotPoints -> 10, MaxRecursion -> 4, 
     ViewPoint -> {1.43, -2.84, 1.13}, 
     ViewVertical -> {0., 0., 1.}}},
  plot1 = 
   Plot3D[(wp[qx, qy, r][[1]]) scale, {qx, -Pi, Pi}, {qy, -Pi, Pi}, 
     plotopts] // postProcess;
  plot2 = 
   Plot3D[(wp[qx, qy, r][[2]]) scale, {qx, -Pi, Pi}, {qy, -Pi, Pi}, 
     plotopts] // postProcess;]]
plot = Show[plot1, plot2, PlotRange -> {0.96, 1.04}, 
  Ticks -> {{-Pi, 0, Pi}, {-Pi, 0, Pi}}, LabelStyle -> Medium, 
  BoxRatios -> {2, 2, 3}, BoxStyle -> Opacity[0.4]]

enter image description here

You can see a fine mesh near the Dirac points:

enter image description here

Now you can obtain a considerable speedup by tuning PlotPloits and MaxRecursion.


It looks like the plotting may be slow because you're trying to resolve a small feature and upping the number of points you use in the entire plot.

If you instead try upping the number of points only in the region between 0.99 and 1.01, where you know the sharp features are, you cut down on the amount of time spent searching:


Timing[With[{plotopts = {Mesh -> None, PlotStyle -> Opacity[0.7], 
     Ticks -> {{-Pi, 0, Pi}, {-Pi, 0, Pi}, Automatic}, 
     ViewPoint -> {1.43, -2.84, 1.13}, 
     ViewVertical -> {0., 0., 1.}}},
  plot1 = 
   Plot3D[wp[qx, qy, r][[1]], {qx, -Pi, Pi}, {qy, -Pi, Pi}, plotopts, 
    PlotRange -> {{-π, π}, {-π, π}, {1.00, 1.01}}, 
    PlotPoints -> 40, ClippingStyle -> None, BoundaryStyle -> None];
  plot2 = 
   Plot3D[wp[qx, qy, r][[2]], {qx, -Pi, Pi}, {qy, -Pi, Pi}, plotopts, 
    PlotRange -> {{-π, π}, {-π, π}, {0.99, 1.00}}, 
    PlotPoints -> 40, ClippingStyle -> None, BoundaryStyle -> None];
  plot3 = 
   Plot3D[wp[qx, qy, r][[1]], {qx, -Pi, Pi}, {qy, -Pi, Pi}, plotopts, 
    PlotRange -> {{-π, π}, {-π, π}, {1.01, 1.04}}, 
    PlotPoints -> 20, ClippingStyle -> None, BoundaryStyle -> None];
  plot4 = 
   Plot3D[wp[qx, qy, r][[2]], {qx, -Pi, Pi}, {qy, -Pi, Pi}, plotopts, 
    PlotRange -> {{-π, π}, {-π, π}, {0.96, 0.99}}, 
    PlotPoints -> 20, ClippingStyle -> None, BoundaryStyle -> None];
  plot = Show[{plot1, plot2, plot3, plot4}, PlotRange -> {0.96, 1.04},
     Ticks -> {{-Pi, 0, Pi}, {-Pi, 0, Pi}}, LabelStyle -> Medium, 
    BoxRatios -> {2, 2, 3}, BoxStyle -> Opacity[0.4]]

  ]
 ]

When I run this it looks the same as the plot you've posted but only takes about 4 seconds to plot.enter image description here


One can use FEM's ToElementMesh, MeshRefinementFunction, and ElementMeshPlot3D to refine the plot. ElementMeshPlot3D does not work like Plot3D. In particular VertexNormals are not computed, so I borrowed the utility function addnormals[] from How to improve this plot? Also there is no PlotStyle option, so some other method needs to be used; it does have a ColorFunction option.

Needs["NDSolve`FEM`"];
emesh = ToElementMesh[FullRegion[2], {{-Pi, Pi}, {-Pi, Pi}},
   MeshRefinementFunction -> 
    Function[{vertices, area}, 
     Abs[Mean[wp[##, r][[1]] & @@@ vertices] - wp[##, r][[1]] & @@ 
        Mean[vertices]] > 0.0001]
   ];
Show[emesh["Wireframe"], Frame -> True]

Mathematica graphics

Needs["NDSolve`FEM`"];
ClearAll[plotwp];

plotwp[wpr_, opts : OptionsPattern[ElementMeshPlot3D]] := 
 Module[{mins, wp1C, wp2C, vals1, eIF1, vals2, eIF2, emesh},
  wp1C = Compile[{qx, qy}, Evaluate[wpr[qx, qy][[1]] /. Sqrt[s_] :> Sqrt@Abs[s]]];
  wp2C = Compile[{qx, qy}, Evaluate[wpr[qx, qy][[2]] /. Sqrt[s_] :> Sqrt@Abs[s]]]; 
  emesh = ToElementMesh[FullRegion[2], {{-Pi, Pi}, {-Pi, Pi}},
    MeshRefinementFunction -> 
     Function[{vertices, area}, 
      Abs[Mean[wp1C @@@ vertices] - wp1C @@ Mean[vertices]] > 0.0001]
    ];
  vals1 = wp1C @@@ emesh["Coordinates"];
  eIF1 = ElementMeshInterpolation[{emesh}, vals1];
  vals2 = wp2C @@@ emesh["Coordinates"];
  eIF2 = ElementMeshInterpolation[{emesh}, vals2];
  Show[
   addnormals[eIF1][ElementMeshPlot3D[eIF1, BoxRatios -> {1, 1, 0.6}, opts]], 
   addnormals[eIF2][ElementMeshPlot3D[eIF2, BoxRatios -> {1, 1, 0.6}, opts]],
   PlotRange -> All, Options[plot]]
  ]


pl = plotwp[wp[##, r] &, ColorFunction -> None]; // AbsoluteTiming // First
pl = DeleteCases[pl, HoldPattern[VertexColors -> _], Infinity] /. 
 GraphicsComplex[p_, g_, r___] :> 
  GraphicsComplex[
   p, {First@Charting`getPlotStyles[
       "DefaultPlotStyle" /. (Method /. 
          Charting`ResolvePlotTheme[$PlotTheme, Plot3D])][1, Opacity[0.7]],
    g}, r]
(* 0.529355  <-- timing  *)

Mathematica graphics

Utility:

(*add VertexNormals to plot assumed to be the plot of the function u*)
addnormals[u_][plot_Graphics3D /; ! FreeQ[plot, GraphicsComplex]] := 
 plot /. GraphicsComplex[p_, rest___] :> 
   GraphicsComplex[p, rest, 
    VertexNormals -> 
     With[{dx = Derivative[1, 0][u], dy = Derivative[0, 1][u], 
       xy = p[[All, {1, 2}]]}, 
      Transpose@{-dx @@@ xy, -dy @@@ xy, ConstantArray[1., Length@p]}]
    ]

Tags:

Plotting