DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦61a4eeb00⟧ TextFile

    Length: 7577 (0x1d99)
    Types: TextFile
    Names: »dynamics.c«

Derivation

└─⟦276d19d6e⟧ Bits:30007243 EUUGD5_I: X11R5
    └─⟦af7d3f39a⟧ »./mit-2/mit-2.00« 
        └─⟦0abaffd9e⟧ 
            └─⟦this⟧ »mit/demos/xgas/dynamics.c« 

TextFile

/*
 * dynamics.c
 *   xgas: Copyright 1990 Larry Medwin: @(#)dynamics.c	1.5 2/9/90
 *   Larry Medwin -- Dec. 15, 1989
 *   fixed: lm 3-24-91
 */

#include "xgas.h"
static void inertia();
static void collide();
static double hit();
static double hitHole();

/* DYNAMICS */
void dynamics( mol, data )
    Molecule *mol;
    LabData *data;
{
    /* Move molecule */
    while( mol->collisionTime <= data->timestepSize) {
	collide( mol, data );
	findNextCollision( mol, data);
    }
    inertia( mol, data );
}

/* INERTIA() */
static void inertia( mol, data)
    Molecule *mol;
    LabData *data;
{
    /* Solve equations of motion */
    mol->pos.x = mol->xCoeff[0] += mol->xCoeff[1] * data->timestepSize;
    mol->pos.y = mol->yCoeff[0] += mol->yCoeff[1] * data->timestepSize;
    mol->collisionTime -= data->timestepSize;
}

/*
 * COLLIDE()
 * bounce a molecule off a wall with given temperature
 *   recompute its new velocity,
 *   including next collision info.
 */
static void collide( mol, data)
    Molecule *mol;
    LabData *data;
{
    float vMagnitude, hypot;
    float x, y;
    float theta, thetaRand;
    WallType *wallParams;
    int corner;


    /* Find out about the wall we're about to hit */
    wallParams = &WallParam[ mol->collisionWall->type ];

    /*
     * Are we colliding with a corner?
     */
    if ((corner = whichCorner( mol->collisionPos.x, mol->collisionPos.y,
		mol->thisBox, data)) != 0)
	wallParams = &WallParam[ corner ];

    /* Reflect the trajectory */
    mol->xCoeff[1] *= wallParams->wallReflect.x;
    mol->yCoeff[1] *= wallParams->wallReflect.y;

    /* Rotate the trajectory into the canonical orientation */
    x = mol->xCoeff[1] * wallParams->toRotate[0][0] +
	mol->yCoeff[1] * wallParams->toRotate[0][1];
    y = mol->xCoeff[1] * wallParams->toRotate[1][0] +
	mol->yCoeff[1] * wallParams->toRotate[1][1];

    /* Find reflection angle theta */
    if ( fabs ( x ) > SMALL ) theta = atan ( y / x );
    else if ( y > 0.0 ) theta = M_PI_2;
    else theta = -M_PI_2;

    /* Randomize angle by the weight "randomBounce" */
    if (corner) thetaRand = frand( 0.0, M_PI_2);
    else thetaRand = frand( -M_PI_2, M_PI_2);

    theta = (1.0 - data->randomBounce) * theta
		+ data->randomBounce * thetaRand;

    /* Molecule approaches equilibrium according to weight "equilibrium" */
    mol->temperature = (1.0 - data->equilibrium) * mol->temperature
	+ data->equilibrium * data->chamber[mol->thisBox].temperature;

    /* Find velocity vector magnitude */
    vMagnitude = vEquilibrium( mol->temperature);

    /* ... and components */
    x = vMagnitude * cos( theta );
    y = vMagnitude * sin( theta );

    /* Rotate the trajectory back to its original orientation */
    mol->xCoeff[1] = x * wallParams->fromRotate[0][0] +
			y * wallParams->fromRotate[0][1];
    mol->yCoeff[1] = x * wallParams->fromRotate[1][0] +
			y * wallParams->fromRotate[1][1];
}

/*
 * FIND TIME AND POSITION OF NEXT COLLISION
 *   given the equations of motion for the molecule
 */
void findNextCollision( mol, data)
    Molecule *mol;
    LabData *data;
{
    int i;
    int box;
    double deltaT;
    Coord lastCollision;

    /* Save position of last collision */
    lastCollision.x = mol->collisionPos.x;
    lastCollision.y = mol->collisionPos.y;

    box = mol->thisBox;

    /* Do we go through the hole? (walls[0]) */
    if( hitHole( mol, &data->chamber[box].walls[0], data) > 0.0) {

        /* Move into the other box */
        box = 1 - box;
    }

    /*
     * Now check for collisions with the walls
     * Update collisionPos in hit()
     */
    for( i=1; i<NWALLS ; i++ ) {
	if((mol->collisionWall != &data->chamber[box].walls[i])
	  && (( deltaT = hit( mol, &data->chamber[box].walls[i]))
		 > 0.0)) {
	  break;
	}
    }

    if( deltaT == -1) {
	error("In findNextCollision(): couldn't find a wall to hit.",
	    data->time);
    }

    /* Correct the equations of motion for the particle */
    mol->xCoeff[1]
	= (mol->collisionPos.x - lastCollision.x) / deltaT;
    mol->yCoeff[1]
	= (mol->collisionPos.y - lastCollision.y) / deltaT;
    mol->xCoeff[0] = lastCollision.x;
    mol->yCoeff[0] = lastCollision.y;

    /* Update collision info */
    mol->collisionTime = deltaT;
    mol->collisionWall = &data->chamber[box].walls[i];
    mol->thisBox = box;
}

/*
 * HIT
 * Return collision time if the molecule will hit this wall
 *   otherwise -1.0
 */
static double hit( mol, wall)
    Molecule *mol;
    Wall *wall;
{
    double deltaT;
    int xPos, yPos;

    /* Find intersection of trajectory and wall */

    /* Horizontal wall */
    if( wall->type == TOP || wall->type == BOTTOM) {

        if( fabs( mol->yCoeff[1]) >= SMALL) {
	    deltaT = (wall->end[0].y-mol->collisionPos.y) / mol->yCoeff[1];

	    /* Are we headed in that direction? */
	    if( deltaT < 0.0)
		return -1.0;

	    xPos = mol->collisionPos.x + mol->xCoeff[1] * deltaT;

	    /* Hits wall between endpoints */
	    if( xPos >= wall->end[0].x && xPos <= wall->end[1].x) {
		mol->collisionPos.x = xPos;
		mol->collisionPos.y = wall->end[0].y;
		return deltaT;
	    }
	    else return -1.0;
	}
	else return -1.0;
    }

    /* Vertical wall */
    else if ( wall->type == LEFT || wall->type == RIGHT) {
        if( fabs( mol->xCoeff[1]) >= SMALL) {
	    deltaT = (wall->end[0].x - mol->collisionPos.x) / mol->xCoeff[1];

	    /* Are we headed in that direction? */
	    if( deltaT < 0.0)
		return -1.0;

	    yPos = mol->collisionPos.y + mol->yCoeff[1] * deltaT;

	    /* Hits wall between endpoints */
	    if( yPos >= wall->end[0].y && yPos <= wall->end[1].y) {
		mol->collisionPos.x = wall->end[0].x;
		mol->collisionPos.y = yPos;
		return deltaT;
	    }
	    else return -1.0;
	}
	else return -1.0;
    }
    else {
	error(" In hit, illegal wall type.", 0);
	return -1.0;
    }
}

/*
 * HITHOLE
 * Return collision time if the molecule will go through hole
 *   otherwise -1.0
 */
static double hitHole( mol, wall, data)
    Molecule *mol;
    Wall *wall;
    LabData *data;
{
    double deltaT;
    int xPos, yPos;

    /* Find intersection of trajectory and hole */

    /* OK to divide? */
    if( fabs( mol->xCoeff[1]) < SMALL)
	return -1.0;

    deltaT = (wall->end[0].x - mol->collisionPos.x) / mol->xCoeff[1];

    /* Are we headed in that direction? */
    /* ... or already on wall or corner? use <=, not <   lm 4/4/91 */
    if( deltaT <= 0.0)
	return -1.0;

    /* FInd intersection with barrier wall */
    yPos = mol->collisionPos.y + mol->yCoeff[1] * deltaT;

    /* Does it go through hole between endpoints? */
    if( !( yPos > wall->end[0].y && yPos < wall->end[1].y))
	return -1.0;

    /*
     * Check that x-intersection with horizontal wall will not
     *   be truncated to corner position.   This happens once
     *   every 10^7 collisions.
     */

    /* This isn't a problem for molecules moving in -x direction */
    if( mol->xCoeff[1] < 0.0)
	return deltaT;

    /* OK to divide? */
    if( fabs( mol->yCoeff[1]) < SMALL)
	return -1.0;

    /* Moving in +y or -y direction? */
    if( mol->yCoeff[1] > 0.0)
	deltaT = (data->heightMM - mol->collisionPos.y) / mol->yCoeff[1];
    else
	deltaT = (0 - mol->collisionPos.y) / mol->yCoeff[1];

    /* Where do we hit the horizontal wall? */
    xPos = mol->collisionPos.x + mol->xCoeff[1] * deltaT;

    /*
     *  If xPos truncated so that it lies at the x-position of the corner,
     *    then the molecule really doesn't go through the hole.
     */
    if( xPos == data->chamber[0].walls[0].end[0].x)
	return -1.0;

    /* It went through! */
    return deltaT;
}