Okay, I have two potential solutions for you.
The first adds a new version of the slopefield function that works for slopefields specified as (dx/dt, dy/dt) rather than dy/dx.
import slopefield;
picture slopefield(pair dir(real,real), pair a, pair b,
int nx=nmesh, int ny=nx,
real tickfactor=0.5, pen p=currentpen, arrowbar arrow=None)
{
picture pic;
real dx=(b.x-a.x)/nx;
real dy=(b.y-a.y)/ny;
real step=0.5*tickfactor*min(dx,dy);
for(int i=0; i <= nx; ++i) {
real x=a.x+i*dx;
for(int j=0; j <= ny; ++j) {
pair cp=(x,a.y+j*dy);
pair direction=unit(dir(cp.x,cp.y));
draw(pic,(cp-step*direction)--(cp+step*direction),p,arrow);
}
}
clip(pic,box(a,b));
return pic;
}
Here's the code in context, and the result. (Note that I've used the asypictureB package because it gives better debug output, but the asymptote package would still work.)
\documentclass{article}
\usepackage{asypictureB}
\begin{asyheader}
import slopefield;
picture slopefield(pair dir(real,real), pair a, pair b,
int nx=nmesh, int ny=nx,
real tickfactor=0.5, pen p=currentpen, arrowbar arrow=None)
{
picture pic;
real dx=(b.x-a.x)/nx;
real dy=(b.y-a.y)/ny;
real step=0.5*tickfactor*min(dx,dy);
for(int i=0; i <= nx; ++i) {
real x=a.x+i*dx;
for(int j=0; j <= ny; ++j) {
pair cp=(x,a.y+j*dy);
pair direction=unit(dir(cp.x,cp.y));
draw(pic,(cp-step*direction)--(cp+step*direction),p,arrow);
}
}
clip(pic,box(a,b));
return pic;
}
\end{asyheader}
\begin{document}
\begin{figure}
\centering
\begin{asypicture}{}
settings.outformat = "pdf";
import graph;
size(200);
//
// Callable function (dx/dt, dy/dt)=f(x,y)
//
pair direction(real x, real y) {
return (y, -(x + y));
}
//
real xmin=-1, xmax=1;
real ymin=-1, ymax=1;
pair pmin=(xmin,ymin);
pair pmax=(xmax,ymax);
add(slopefield(direction,pmin,pmax,20,deepgreen+0.4bp,Arrow));
xaxis(YEquals(ymin),xmin,xmax,LeftTicks());
xaxis(YEquals(ymax),xmin,xmax);
yaxis(XEquals(xmin),ymin,ymax,RightTicks());
yaxis(XEquals(xmax),ymin,ymax);
\end{asypicture}
\caption{$\left(\frac{dx}{dt}, \frac{dy}{dt}\right)=(y, -(x+y))$}
\end{figure}
\end{document}

The result is very nice, but it also allows right-to-left arrows. This is much more natural for the graph in question, but I was also interested to see if I could do something that was aimed at the dy/dx = case. Here's what I came up with:

The idea is the following.
- First, a "quiet divide" function is added that, when division by zero is attempted, returns a non-finite value rather than throwing an error. The function is rewritten to use this
quietdivide function rather than /.
- Second, the relevant
slopefield function is rewritten (with helper functions) to take the following actions if it encounters a non-finite dy/dx value:
- Attempt to compute the "limiting direction" by averaging the directions at
a number of randomly chosen points near the problematic point. If the chosen
points all give similar directions, this is considered to have succeeded.
- Try the same thing again, but in such a way that the positive and negative
vertical directions have no distance between them. If this succeeds, draw a
line in the specified direction, but with no directional arrow.
- If neither of the two preceding limit approximations succeeds, just draw a
directionless point.
The code:
import graph;
import slopefield;
import stats;
size(200);
real quietdivide(real s, real t) { return (abs(t) >= 1e-6) ? s / t : inf; }
real epsilon = 1e-3;
real maxstdev = 5e-2;
private real limitdirection_helper(pair[] datapoints) {
real[] xdata, ydata;
for (pair datapoint : datapoints) {
xdata.push(datapoint.x);
ydata.push(datapoint.y);
}
real xstdev = stdev(xdata), ystdev = stdev(ydata);
real[] toreturn;
if (xstdev < maxstdev && ystdev < maxstdev) {
pair limitdirection = (mean(xdata), mean(ydata));
return angle(limitdirection);
} else {
return inf;
}
}
// If returnedarray[0] exists and is finite, then it specifies the (approximate) limit direction in radians.
// If returnedarray[1] exists and is finite, then it specifies the limit direction mod reflection in radians on the interval (-pi/2, pi/2]. This is useful primarily because it is defined when the limit slope is vertical but the limit direction (up vs down) is not defined.
// If neither of the two preceeding conditions holds, then no limit was found.
real[] limitdirection(pair f(real x, real y), real x, real y) {
pair[] datapoints;
int maxiter = 100, numdatapoints = 20;
for (int i = 0; i < maxiter && datapoints.length < numdatapoints; ++i) {
pair delta = epsilon * Gaussrandpair();
pair possibledirection = f(x + delta.x, y + delta.y);
if (finite(possibledirection)) datapoints.push(unit(possibledirection));
}
if (datapoints.length < numdatapoints) return new real[0]; // could not find enough nearby finite points to compute limit
real[] toreturn;
toreturn.push(limitdirection_helper(datapoints));
pair[] datapointsmod2 = map(new pair(pair datapoint) {
real angle = angle(datapoint);
return expi(2*angle);
}, datapoints);
toreturn.push(limitdirection_helper(datapointsmod2) / 2);
return toreturn;
}
picture slopefield(real f(real,real), pair a, pair b,
int nx=nmesh, int ny=nx,
real tickfactor=0.5, pen p=currentpen, arrowbar arrow=None)
{
picture pic;
real dx=(b.x-a.x)/nx;
real dy=(b.y-a.y)/ny;
real step=0.5*tickfactor*min(dx,dy);
for(int i=0; i <= nx; ++i) {
real x=a.x+i*dx;
for(int j=0; j <= ny; ++j) {
pair cp=(x,a.y+j*dy);
real slope=f(cp.x,cp.y);
if (finite(slope)) {
real mp=step/sqrt(1+slope^2);
draw(pic,(cp.x-mp,cp.y-mp*slope)--(cp.x+mp,cp.y+mp*slope),p,arrow);
} else {
real[] limitdirection = limitdirection(new pair(real x, real y) {
return (1, f(x,y));
}, cp.x, cp.y);
if (alias(limitdirection, null)
|| limitdirection.length == 0
|| (limitdirection.length == 1 && !finite(limitdirection[0]))
|| (!finite(limitdirection[0]) && !finite(limitdirection[1]))) {
draw(pic, cp, p); // just a small dot
} else if (finite(limitdirection[0])) {
pair direction = expi(limitdirection[0]);
draw(pic,(cp-step*direction)--(cp+step*direction),p,arrow);
} else { // finite(limitdirection[1])
pair direction = expi(limitdirection[1]);
draw(pic,(cp-step*direction)--(cp+step*direction),p); // line with no arrow
}
}
}
}
clip(pic,box(a,b));
return pic;
}
// Callable function dy/dx=f(x,y)
real dy(real x, real y) { return -(quietdivide(x,y) + 1); }
//
real xmin=-1, xmax=1;
real ymin=-1, ymax=1;
pair pmin=(xmin,ymin);
pair pmax=(xmax,ymax);
add(slopefield(dy,pmin,pmax,20,deepgreen+0.4bp,Arrow));
xaxis(YEquals(ymin),xmin,xmax,LeftTicks());
xaxis(YEquals(ymax),xmin,xmax);
yaxis(XEquals(xmin),ymin,ymax,RightTicks());
yaxis(XEquals(xmax),ymin,ymax);