// $Id: x22c.c 12176 2012-02-24 20:33:39Z andrewross $
//
// Simple vector plot example
// Copyright (C) 2004 Andrew Ross
// Copyright (C) 2004 Rafael Laboissiere
//
//
// This file is part of PLplot.
//
// PLplot is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License as published
// by the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// PLplot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with PLplot; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//
#include "plcdemos.h"
void circulation( void );
void constriction( void );
void potential( void );
void f2mnmx( PLFLT **f, PLINT nx, PLINT ny, PLFLT *fnmin, PLFLT *fnmax );
// Pairs of points making the line segments used to plot the user defined arrow
static PLFLT arrow_x[6] = { -0.5, 0.5, 0.3, 0.5, 0.3, 0.5 };
static PLFLT arrow_y[6] = { 0.0, 0.0, 0.2, 0.0, -0.2, 0.0 };
static PLFLT arrow2_x[6] = { -0.5, 0.3, 0.3, 0.5, 0.3, 0.3 };
static PLFLT arrow2_y[6] = { 0.0, 0.0, 0.2, 0.0, -0.2, 0.0 };
//--------------------------------------------------------------------------
// main
//
// Generates several simple vector plots.
//--------------------------------------------------------------------------
//
// Vector plot of the circulation about the origin
//
void
circulation( void )
{
int i, j;
PLFLT dx, dy, x, y;
PLcGrid2 cgrid2;
PLFLT **u, **v;
const int nx = 20;
const int ny = 20;
PLFLT xmin, xmax, ymin, ymax;
dx = 1.0;
dy = 1.0;
xmin = -nx / 2 * dx;
xmax = nx / 2 * dx;
ymin = -ny / 2 * dy;
ymax = ny / 2 * dy;
plAlloc2dGrid( &cgrid2.xg, nx, ny );
plAlloc2dGrid( &cgrid2.yg, nx, ny );
plAlloc2dGrid( &u, nx, ny );
plAlloc2dGrid( &v, nx, ny );
cgrid2.nx = nx;
cgrid2.ny = ny;
// Create data - circulation around the origin.
for ( i = 0; i < nx; i++ )
{
x = ( i - nx / 2 + 0.5 ) * dx;
for ( j = 0; j < ny; j++ )
{
y = ( j - ny / 2 + 0.5 ) * dy;
cgrid2.xg[i][j] = x;
cgrid2.yg[i][j] = y;
u[i][j] = y;
v[i][j] = -x;
}
}
// Plot vectors with default arrows
plenv( xmin, xmax, ymin, ymax, 0, 0 );
pllab( "(x)", "(y)", "#frPLplot Example 22 - circulation" );
plcol0( 2 );
plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nx, ny, 0.0, pltr2, (void *) &cgrid2 );
plcol0( 1 );
plFree2dGrid( cgrid2.xg, nx, ny );
plFree2dGrid( cgrid2.yg, nx, ny );
plFree2dGrid( u, nx, ny );
plFree2dGrid( v, nx, ny );
}
//
// Vector plot of flow through a constricted pipe
//
void
constriction( void )
{
int i, j;
PLFLT dx, dy, x, y;
PLFLT xmin, xmax, ymin, ymax;
PLFLT Q, b, dbdx;
PLcGrid2 cgrid2;
PLFLT **u, **v;
const int nx = 20;
const int ny = 20;
dx = 1.0;
dy = 1.0;
xmin = -nx / 2 * dx;
xmax = nx / 2 * dx;
ymin = -ny / 2 * dy;
ymax = ny / 2 * dy;
plAlloc2dGrid( &cgrid2.xg, nx, ny );
plAlloc2dGrid( &cgrid2.yg, nx, ny );
plAlloc2dGrid( &u, nx, ny );
plAlloc2dGrid( &v, nx, ny );
cgrid2.nx = nx;
cgrid2.ny = ny;
Q = 2.0;
for ( i = 0; i < nx; i++ )
{
x = ( i - nx / 2 + 0.5 ) * dx;
for ( j = 0; j < ny; j++ )
{
y = ( j - ny / 2 + 0.5 ) * dy;
cgrid2.xg[i][j] = x;
cgrid2.yg[i][j] = y;
b = ymax / 4.0 * ( 3 - cos( M_PI * x / xmax ) );
if ( fabs( y ) < b )
{
dbdx = ymax / 4.0 * sin( M_PI * x / xmax ) *
y / b;
u[i][j] = Q * ymax / b;
v[i][j] = dbdx * u[i][j];
}
else
{
u[i][j] = 0.0;
v[i][j] = 0.0;
}
}
}
plenv( xmin, xmax, ymin, ymax, 0, 0 );
pllab( "(x)", "(y)", "#frPLplot Example 22 - constriction" );
plcol0( 2 );
plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nx, ny, -0.5, pltr2, (void *) &cgrid2 );
plcol0( 1 );
plFree2dGrid( cgrid2.xg, nx, ny );
plFree2dGrid( cgrid2.yg, nx, ny );
plFree2dGrid( u, nx, ny );
plFree2dGrid( v, nx, ny );
}
void
f2mnmx( PLFLT **f, PLINT nx, PLINT ny, PLFLT *fnmin, PLFLT *fnmax )
{
int i, j;
*fnmax = f[0][0];
*fnmin = *fnmax;
for ( i = 0; i < nx; i++ )
{
for ( j = 0; j < ny; j++ )
{
*fnmax = MAX( *fnmax, f[i][j] );
*fnmin = MIN( *fnmin, f[i][j] );
}
}
}
//
// Vector plot of the gradient of a shielded potential (see example 9)
//
void
potential( void )
{
#if !defined ( WIN32 )
const int nper = 100;
const int nlevel = 10;
const int nr = 20;
const int ntheta = 20;
#else
#define nper 100
#define nlevel 10
#define nr 20
#define ntheta 20
#endif
int i, j;
PLFLT eps, q1, d1, q1i, d1i, q2, d2, q2i, d2i;
PLFLT div1, div1i, div2, div2i;
PLFLT **u, **v, **z, r, theta, x, y, dz;
PLFLT xmin, xmax, ymin, ymax, rmax, zmax, zmin;
PLFLT px[nper], py[nper], clevel[nlevel];
PLcGrid2 cgrid2;
// Create data to be plotted
plAlloc2dGrid( &cgrid2.xg, nr, ntheta );
plAlloc2dGrid( &cgrid2.yg, nr, ntheta );
plAlloc2dGrid( &u, nr, ntheta );
plAlloc2dGrid( &v, nr, ntheta );
plAlloc2dGrid( &z, nr, ntheta );
cgrid2.nx = nr;
cgrid2.ny = ntheta;
// Potential inside a conducting cylinder (or sphere) by method of images.
// Charge 1 is placed at (d1, d1), with image charge at (d2, d2).
// Charge 2 is placed at (d1, -d1), with image charge at (d2, -d2).
// Also put in smoothing term at small distances.
//
rmax = (double) nr;
eps = 2.;
q1 = 1.;
d1 = rmax / 4.;
q1i = -q1 * rmax / d1;
d1i = pow( rmax, 2. ) / d1;
q2 = -1.;
d2 = rmax / 4.;
q2i = -q2 * rmax / d2;
d2i = pow( rmax, 2. ) / d2;
for ( i = 0; i < nr; i++ )
{
r = 0.5 + (double) i;
for ( j = 0; j < ntheta; j++ )
{
theta = 2. * M_PI / ( ntheta - 1 ) * ( 0.5 + (double) j );
x = r * cos( theta );
y = r * sin( theta );
cgrid2.xg[i][j] = x;
cgrid2.yg[i][j] = y;
div1 = sqrt( pow( x - d1, 2. ) + pow( y - d1, 2. ) + pow( eps, 2. ) );
div1i = sqrt( pow( x - d1i, 2. ) + pow( y - d1i, 2. ) + pow( eps, 2. ) );
div2 = sqrt( pow( x - d2, 2. ) + pow( y + d2, 2. ) + pow( eps, 2. ) );
div2i = sqrt( pow( x - d2i, 2. ) + pow( y + d2i, 2. ) + pow( eps, 2. ) );
z[i][j] = q1 / div1 + q1i / div1i + q2 / div2 + q2i / div2i;
u[i][j] = -q1 * ( x - d1 ) / pow( div1, 3. ) - q1i * ( x - d1i ) / pow( div1i, 3.0 )
- q2 * ( x - d2 ) / pow( div2, 3. ) - q2i * ( x - d2i ) / pow( div2i, 3. );
v[i][j] = -q1 * ( y - d1 ) / pow( div1, 3. ) - q1i * ( y - d1i ) / pow( div1i, 3.0 )
- q2 * ( y + d2 ) / pow( div2, 3. ) - q2i * ( y + d2i ) / pow( div2i, 3. );
}
}
f2mnmx( cgrid2.xg, nr, ntheta, &xmin, &xmax );
f2mnmx( cgrid2.yg, nr, ntheta, &ymin, &ymax );
f2mnmx( z, nr, ntheta, &zmin, &zmax );
plenv( xmin, xmax, ymin, ymax, 0, 0 );
pllab( "(x)", "(y)", "#frPLplot Example 22 - potential gradient vector plot" );
// Plot contours of the potential
dz = ( zmax - zmin ) / (double) nlevel;
for ( i = 0; i < nlevel; i++ )
{
clevel[i] = zmin + ( (double) i + 0.5 ) * dz;
}
plcol0( 3 );
pllsty( 2 );
plcont( (const PLFLT * const *) z, nr, ntheta, 1, nr, 1, ntheta, clevel, nlevel, pltr2, (void *) &cgrid2 );
pllsty( 1 );
plcol0( 1 );
// Plot the vectors of the gradient of the potential
plcol0( 2 );
plvect( (const PLFLT * const *) u, (const PLFLT * const *) v, nr, ntheta, 25.0, pltr2, (void *) &cgrid2 );
plcol0( 1 );
// Plot the perimeter of the cylinder
for ( i = 0; i < nper; i++ )
{
theta = ( 2. * M_PI / ( nper - 1 ) ) * (double) i;
px[i] = rmax * cos( theta );
py[i] = rmax * sin( theta );
}
plline( nper, px, py );
plFree2dGrid( z, nr, ntheta );
plFree2dGrid( cgrid2.xg, nr, ntheta );
plFree2dGrid( cgrid2.yg, nr, ntheta );
plFree2dGrid( u, nr, ntheta );
plFree2dGrid( v, nr, ntheta );
}
int
main( int argc, const char *argv[] )
{
PLINT narr, fill;
// Parse and process command line arguments
plparseopts( &argc, argv, PL_PARSE_FULL );
// Initialize plplot
plinit();
circulation();
narr = 6;
fill = 0;
// Set arrow style using arrow_x and arrow_y then
// plot using these arrows.
plsvect( arrow_x, arrow_y, narr, fill );
constriction();
// Set arrow style using arrow2_x and arrow2_y then
// plot using these filled arrows.
fill = 1;
plsvect( arrow2_x, arrow2_y, narr, fill );
constriction();
potential();
plend();
exit( 0 );
}