Asíntota: La superficie paramétrica no funciona con la interpolación Spline

Asíntota: La superficie paramétrica no funciona con la interpolación Spline

Tengo una superficie paramétrica que se define en términos deFunción de Lambert Wy que quiero mostrar con Asíntota. Para eso, se implementó la función Lambert W utilizando el método de Newton y la superficie original (cerrada) tuvo que dividirse en dos superficies abiertas para evitar problemas de división por cero. Aquí está el MWE:

settings.render=8;
settings.prc=false;
settings.outformat="pdf";
import graph3;

size(200);

currentprojection=orthographic(40,10,10);

// contour value
real c = 0.006;

// parameter ranges
real umin = asin(1.5*exp(1)*sqrt(c*(sqrt(2*pi))));
real umax = pi-asin(1.5*exp(1)*sqrt(c*(sqrt(2*pi))));
real vmin = 0;
real vmax = 1;

// Lambert W function
real w1(real w, real z, int i){return z<-1/exp(1) - 0.00001 ? 1/0 : z<-1/exp(1) ? -1 : i>0 && abs((w*exp(w)-z)/(exp(w)+w*exp(w))) > 1e-7 ? w1(w-(w*exp(w)-z)/(exp(w)+w*exp(w)),z,i-1) : w-(w*exp(w)-z)/(exp(w)+w*exp(w));};

// auxiliary functions
real y5(real h, real p){return (1/4.)*sqrt(15./pi) * sin(2*p) * sin(h)**2;};

real r1(real y){return -6*w1(-2,-sqrt(c*9*sqrt(30)/abs(y))/4,200);};
real r2(real y){return -6*w1(1,-sqrt(c*9*sqrt(30)/abs(y))/4,200);};

// x, y, and z coordinates of the surfaces
real x11(real u, real v){return r1(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*cos(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real y11(real u, real v){return r1(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*sin(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real z11(real u, real v){return r1(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)) ))*cos(u);};

real x12(real u, real v){return r2(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*cos(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real y12(real u, real v){return r2(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2))))*sin(u)*sin(v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)));};
real z12(real u, real v){return r2(y5(u,v*pi/2+(0.5-v)*asin(exp(1)**2*9.*c*sqrt(2.*pi)/(4.*sin(u)**2)) ))*cos(u);};

triple f11(pair p){return (x11(p.x,p.y),y11(p.x,p.y),z11(p.x,p.y));};
triple f12(pair p){return (x12(p.x,p.y),y12(p.x,p.y),z12(p.x,p.y));};

surface s11 = surface(f=f11,a=(umin, vmin),b=(umax,vmax));  // this works
surface s12 = surface(f=f12,a=(umin, vmin),b=(umax,vmax));  // this works

// surface s11 = surface(f=f11,a=(umin, vmin),b=(umax,vmax),Spline);  // this doesn't work
// surface s12 = surface(f=f12,a=(umin, vmin),b=(umax,vmax),Spline);  // this doesn't work

draw(s11, red+opacity(0.5));
draw(s12, red+opacity(0.5));  

ingrese la descripción de la imagen aquí

Si agrego la Splinedirectiva para hacer que la superficie se vea suave, Asymptote falla con el error some path/graph_splinetype.asy: 89.10: function values are not periodic. Intenté entender qué salió mal graph_splinetype.asyy graph3.asy, lamentablemente, no soy lo suficientemente competente para lograrlo. Entonces mi pregunta es:¿Existe la posibilidad de empezar Splinea trabajar con esta superficie paramétrica o tal vez otra forma de hacer que parezca suave?

Lo que lo hace aún más desconcertante es que Splinefunciona bien para una superficie paramétrica similar (aunque esta tiene simetría rotacional alrededor del eje z, lo cual podría ser importante), concretamente esta:

settings.render=8;
settings.prc=false;
settings.outformat="pdf";
import graph3;

size(200);

currentprojection=orthographic(40,10,10);

// contour value
real c = 0.006;

// parameter ranges
real umin = 0;
real umax = acos(2*exp(1)*c*sqrt(2*pi))-0.0000001;
real vmin = 0;
real vmax = 2*pi;

// Lambert W function
real w1(real w, real z, int i){return z<-1/exp(1) - 0.00001 ? 1/0 : z<-1/exp(1) ? -1 : i>0 && abs((w*exp(w)-z)/(exp(w)+w*exp(w))) > 1e-7 ? w1(w-(w*exp(w)-z)/(exp(w)+w*exp(w)),z,i-1) : w-(w*exp(w)-z)/(exp(w)+w*exp(w));};

// auxiliary functions
real y1(real h){return sqrt(3./pi)/2.*cos(h);};

real r1(real y){return -2*w1(-2,-c*sqrt(6)/abs(y),200);};
real r2(real y){return -2*w1(1,-c*sqrt(6)/abs(y),200);};

// x, y, and z coordinates of the surfaces
real x11(real u, real v){return r1(y1(u))*sin(u)*cos(v);};
real y11(real u, real v){return r1(y1(u))*sin(u)*sin(v);};
real z11(real u, real v){return r1(y1(u))*cos(u);};

real x12(real u, real v){return r2(y1(u))*sin(u)*cos(v);};
real y12(real u, real v){return r2(y1(u))*sin(u)*sin(v);};
real z12(real u, real v){return r2(y1(u))*cos(u);};

triple f11(pair p){return (x11(p.x,p.y),y11(p.x,p.y),z11(p.x,p.y));};
triple f12(pair p){return (x12(p.x,p.y),y12(p.x,p.y),z12(p.x,p.y));};

surface s11 = surface(f11,(umin,vmin),(umax,vmax),50,Spline);
surface s12 = surface(f12,(umin,vmin),(umax,vmax),50,Spline);

draw(s11, red+opacity(0.5));
draw(s12, red+opacity(0.5));

ingrese la descripción de la imagen aquí

Respuesta1

¿Podrías precisar tu sistema y la versión de asíntota? En mi computadora (Linux 64 bits, Sid, Asymptote svn) no tengo problemas y su código produce una superficie suave.

Dado que la elección entre spline periódico o not_a_knot se implementa en la rutina de superficie, parece que es menos restrictiva que la rutina de spline paramétrica final (escribí hace mucho tiempo una parte de esta rutina de superficie suave). Es posible forzar una elección "no es un nudo" con el siguiente código

splinetype[] Notaknot={notaknot,notaknot,notaknot};
surface s11 = surface(f=f11,a=(umin,vmin),b=(umax,vmax),8,16,Notaknot,Notaknot);  
surface s12 = surface(f=f12,a=(umin,vmin),b=(umax,vmax),8,16,Notaknot,Notaknot);

Espero que funcione en su sistema.

OG

información relacionada