/****************************************************************************
 * Function definitions
 ****************************************************************************/
void BoundaryConditionsAndTreatments(const int tn, Space *space, const Model *model)
{
    /*
     * Internal boundary treatment
     *
     * Should be performed first to ensure stencils for diffusive flux
     * discretization are treated correctly, especially for collapsed
     * dimensions.
     */
    ImmersedBoundaryTreatment(tn, space, model);
    /*
     * External boundary treatment
     *
     * When no mixed derivatives are discretized, only cross-type stencils
     * are needed. Then, the corner ghost nodes do not need treatment.
     * However, corner ghost nodes are necessary for the computation of 
     * mixed derivatives as in viscous fluxes, or for transfer operators
     * within multigrid. To treat the entire ghost region, the boundary
     * treatment should be performed one box layer by one box layer from
     * inside to outside.
     */
    const Partition *restrict part = &(space->part);
    int box[DIMS][LIMIT] = {{0}}; /* range box of regions */
    for (int r = 0; r <= part->ng; ++r) { /* process layer by layer */
        for (int p = PWB; p < PWG; ++p) {
            const IntVec N = {part->N[p][X], part->N[p][Y], part->N[p][Z]};
            for (int s = 0; s < DIMS; ++s) { /* compute range box of each layer */
                box[s][MIN] = part->ns[p][s][MIN] + r * (N[s] - !N[s]);
                box[s][MAX] = part->ns[p][s][MAX] + r * (N[s] + !N[s]);
            }
            ApplyBoundaryConditions(p, r, box, tn, space, model);
        }
    }
    return;
}
예제 #2
0
/* This program takes up to three arguments. The first is the Peclet number to
 * use in the calculation. The second is the number of elements to use when
 * solving the problem, and the third (optional) argument is the filename to
 * save the solution to. */
int main(int argc, char *argv[])
{
    double Pe, h;
    double left = 0;
    double right = 1;
    //double right = PI/2;
    int n;
    matrix *J, *F, *u, *Jinv, *mesh, *x;

    /* Parse arguments */
    if(argc < 2) {
        fprintf(stderr, "Too few arguments: exiting.\n");
        return 1;
    }
    Pe = atof(argv[1]);

    n = atoi(argv[2]);

    /* Create a uniform mesh */
    mesh = GenerateUniformMesh(left, right, n);

    /* Use a mesh with these node spacings */
    //mesh = ParseMatrix("[.75;.15;.0125;.0125;.0125;.0125;.0125;.0125;.0125;.0125]");

    x = MeshXCoords(mesh, left, right);

    /* All the nodes are equally spaced. */
    h = val(mesh, 0, 0);

    J = AssembleJ(&CreateElementMatrix, mesh, Pe);
    //J = AssembleJMesh(&testelem, mesh, Pe);

    F = AssembleF(&CreateElementLoad, mesh, Pe);
    //F = AssembleFMesh(&testload, mesh, Pe);

    ApplyBoundaryConditions(J, F, 0, 1);
    //ApplyBoundaryConditions(J, F, 2, 1);

    /* Invert the coefficient matrix and premultiply the load vector by it. */
    Jinv = CalcInv(J);
    u = mtxmul(Jinv, F);

    /* Print out the result */
    if(argc == 4) {
        mtxprntfile(u, argv[3]);
    } else {
        mtxprnt(x);
        puts("");
        mtxprnt(u);
    }

    /* Clean up the allocated memory */
    DestroyMatrix(J);
    DestroyMatrix(F);
    DestroyMatrix(u);
    DestroyMatrix(Jinv);
    DestroyMatrix(mesh);

    return 0;
}
예제 #3
0
void FluidBase::SolvePoissonPressureEquation(unsigned int pressureID, 
                                             unsigned int divergenceID,
                                             int numIterations, 
                                             bool obstacles,
                                             unsigned int pressureOffsetID /* = 0 */)
{
    static unsigned int lastPressure = 0;
    static unsigned int lastDivergence = 0;
    static unsigned int lastOffset = 0;
    
    if (lastPressure != pressureID)
    {
        _poissonSolver.SetOutputTexture(pressureID, _iWidth, _iHeight);
        _poissonSolver.SetTextureParameter("x", pressureID);
        _arbitraryPressureBC.SetTextureParameter("p", pressureID);        
        _arbitraryPressureBC.SetOutputTexture(pressureID, _iWidth, _iHeight);
        lastPressure = pressureID;
    }

    if (lastDivergence != divergenceID)
    {
        _poissonSolver.SetTextureParameter("b", divergenceID);
        lastDivergence = divergenceID;
    }

    if (obstacles && lastOffset != pressureOffsetID)
    {
        _arbitraryPressureBC.SetTextureParameter("offsets", pressureOffsetID);
        lastOffset = pressureOffsetID;
    }

    float step = 1.0f / (float)numIterations;
    float z = 1 - step;

    for (int i = 0; i < numIterations; ++i)
    {
        // Apply pure neumann boundary conditions
        ApplyBoundaryConditions(pressureID, 1);
        
        // Apply pure neumann boundary conditions to arbitrary 
        // interior boundaries if they are enabled.
        if (obstacles)
        {
            _arbitraryPressureBC.Compute();
        }

        // for the zcull optimization
        _poissonSolver.SetStreamRect(1.0f / (float)_iWidth, 
                                      1.0f / (float)_iHeight, 
                                      1 - 1.0f / (float)_iWidth, 
                                      1 - 1.0f / (float)_iHeight,
                                      z);
		//*?* this might be something we want to change
		//_poissonSolver.SetStreamRect(1, 1, _iWidth - 1, _iHeight - 1, z);
        z -= step;
        
        _poissonSolver.Compute(); // perform one Jacobi iteration      
    }
}
예제 #4
0
void FluidBase::ComputeVorticityConfinement(unsigned int velocityID, 
                                            unsigned int vorticityID, 
                                            float timestep,
                                            float scale)
{
    static unsigned int lastVelocity  = 0;
    static unsigned int lastVorticity = 0;
    static float        lastScale     = 0;
    static float        lastTimestep  = 0;

    if (lastTimestep != timestep)
    {
        _vorticityForce.SetFragmentParameter1f("timestep", timestep);
        lastTimestep = timestep;
    }

    if (lastVelocity != velocityID)
    {
        _vorticityForce.SetTextureParameter("u", velocityID);
        _vorticityForce.SetOutputTexture(velocityID, _iWidth, _iHeight);
        lastVelocity = velocityID;
    }

    if (lastVorticity != vorticityID)
    {
        _vorticityForce.SetTextureParameter("vort", vorticityID);
        lastVorticity = vorticityID;
    }

    if (lastScale != scale)
    {
        _vorticityForce.SetFragmentParameter2f("dxscale", 
                                               scale * _dx, scale * _dx);
        lastScale = scale;
    }

    ApplyBoundaryConditions(velocityID, -1);
    _vorticityForce.Compute();
}