A First Vfs Program

As an example of a simple VfsTools application the following program computes the deflection of two truss elements under a load. The resulting deflections are printed to standard output.

C

A First Program - C Version

#include <stdio.h>
#include <math.h>
#include "sam/vfs/vfs.h"

/* Stiffnesses (Lower Triangle) for Two Trusses */
static Vdouble kt[2][10] = {
{100., 0., 0., -100., 0., 100., 0., 0., 0., 0.},
{0., 0., 100., 0., 0., 0., 0., -100., 0., 100.},
};
/* Connectivity for Two Trusses */
static Vint ix[2][2] = {{1, 2}, {2, 3}};

/* Generic Truss Dof Map */
static Vint loc[4] = {1, 1, 2, 2};
static Vint tag[4] = {SYS_DOF_TX, SYS_DOF_TY, SYS_DOF_TX, SYS_DOF_TY};

/*
                _ 10. load at 45 degrees
                /|
               /
     1 -/\/\- 2
    pin       |
              /
              \
              |
              3
             pin
*/

/*----------------------------------------------------------------------
                      Solve for Displacement of Two Trusses.
----------------------------------------------------------------------*/
int
main()
{
    vfs_SysMatrix* sysmatrix;
    vfs_SysVector *load, *soln;
    vfs_DofTab* doftab;
    Vint numnp, numel;
    Vint nix, nndofs, nedofs;
    Vint eid, nid;
    Vint restag[2];
    Vint neq, nre;
    Vint lodtag[2];
    Vdouble lodval[2];
    Vint lm[4];
    Vint soltag[2];
    Vdouble solval[2];

    /* Set number of nodes, elements */
    numnp = 3;
    numel = 2;
    /* Set number of nodes per element */
    nix = 2;
    /* Set dof per node, dof per element */
    nndofs = 2;
    nedofs = nix * nndofs;

    /* Create degree of freedom table */
    doftab = vfs_DofTabBegin();
    vfs_DofTabDef(doftab, numnp, numel);

    /* Loop over elements to set degree of freedom use */
    vfs_DofTabSetMap(doftab, nedofs, loc, tag);
    for (eid = 1; eid <= numel; eid++) {
        vfs_DofTabElemUse(doftab, eid, nix, ix[eid - 1]);
    }

    /* Suppress all translations at nodes 1 and 3 */
    restag[0] = SYS_DOF_TX;
    restag[1] = SYS_DOF_TY;
    nid = 1;
    vfs_DofTabNodePerm(doftab, nid, nndofs, restag);
    nid = 3;
    vfs_DofTabNodePerm(doftab, nid, nndofs, restag);

    /* Process dof table, count equations and reactions */
    vfs_DofTabProcess(doftab, &neq, &nre);

    /* Create system stiffness matrix */
    sysmatrix = vfs_SysMatrixBegin();
    vfs_SysMatrixDef(sysmatrix, SYSMATRIX_SYMM_SPARSE, neq);
    vfs_SysMatrixSetObject(sysmatrix, VFS_DOFTAB, (Vobject*)doftab);

    /* Initialize */
    vfs_SysMatrixPreProcess(sysmatrix);
    vfs_SysMatrixInit(sysmatrix, 0.);
    /* Assemble actual stiffness */
    for (eid = 1; eid <= numel; eid++) {
        vfs_DofTabElemDof(doftab, eid, nix, ix[eid - 1], &nedofs, lm);
        vfs_SysMatrixAssem(sysmatrix, nedofs, lm, kt[eid - 1]);
    }

    /* Factorize matrix */
    vfs_SysMatrixProcess(sysmatrix);
    vfs_SysMatrixFactor(sysmatrix);

    /* Create system vector for assembled load */
    load = vfs_SysVectorBegin();
    vfs_SysVectorDef(load, neq);

    /* Define load at node 2 */
    nid = 2;
    lodtag[0] = SYS_DOF_TX;
    lodtag[1] = SYS_DOF_TY;
    vfs_DofTabNodeDof(doftab, nid, nndofs, lodtag, lm);
    lodval[0] = .5 * sqrt(2.) * 10.;
    lodval[1] = .5 * sqrt(2.) * 10.;
    vfs_SysVectorAssem(load, nndofs, lm, lodval);

    /* Create system vector for solution */
    soln = vfs_SysVectorBegin();
    vfs_SysVectorDef(soln, neq);

    /* Backsubstitution for solution */
    vfs_SysMatrixSolve(sysmatrix, load, soln);

    /* Gather and print solution */
    printf("Displacements\n");
    soltag[0] = SYS_DOF_TX;
    soltag[1] = SYS_DOF_TY;
    for (nid = 1; nid <= numnp; nid++) {
        vfs_DofTabNodeDof(doftab, nid, nndofs, soltag, lm);
        solval[0] = 0.;
        solval[1] = 0.;
        vfs_SysVectorGather(soln, nndofs, lm, solval);
        printf(" nid= %d  ux= %10f  uy= %10f\n", nid, solval[0], solval[1]);
    }

    /* Delete objects */
    vfs_DofTabEnd(doftab);
    vfs_SysVectorEnd(load);
    vfs_SysVectorEnd(soln);
    vfs_SysMatrixEnd(sysmatrix);
    return 0;
}
C++

A First Program - C++ Version

The following program is a listing of the C++ version of the same “A First Program” listed above which used C language bindings.

#include <stdio.h>
#include <math.h>
#include "sam/base/base.h"
#include "sam/vfs/vfs.h"

/* Stiffnesses (Lower Triangle) for Two Trusses */
static Vdouble kt[2][10] = {
{100., 0., 0., -100., 0., 100., 0., 0., 0., 0.},
{0., 0., 100., 0., 0., 0., 0., -100., 0., 100.},
};
/* Connectivity for Two Trusses */
static Vint ix[2][2] = {{1, 2}, {2, 3}};

/* Generic Truss Dof Map */
static Vint loc[4] = {1, 1, 2, 2};
static Vint tag[4] = {SYS_DOF_TX, SYS_DOF_TY, SYS_DOF_TX, SYS_DOF_TY};

/*
                _ 10. load at 45 degrees
                /|
               /
     1 -/\/\- 2
    pin       |
              /
              \
              |
              3
             pin
*/

/*----------------------------------------------------------------------
                      Solve for Displacement of Two Trusses.
----------------------------------------------------------------------*/
int
main()
{
    vfs_SysMatrix* sysmatrix;
    vfs_SysVector *load, *soln;
    vfs_DofTab* doftab;
    Vint numnp, numel;
    Vint nix, nndofs, nedofs;
    Vint eid, nid;
    Vint restag[2];
    Vint neq, nre;
    Vint lodtag[2];
    Vdouble lodval[2];
    Vint lm[4];
    Vint soltag[2];
    Vdouble solval[2];

    /* Set number of nodes, elements */
    numnp = 3;
    numel = 2;
    /* Set number of nodes per element */
    nix = 2;
    /* Set dof per node, dof per element */
    nndofs = 2;
    nedofs = nix * nndofs;

    /* Create degree of freedom table */
    doftab = new vfs_DofTab;
    doftab->Def(numnp, numel);

    /* Loop over elements to set degree of freedom use */
    doftab->SetMap(nedofs, loc, tag);
    for (eid = 1; eid <= numel; eid++) {
        doftab->ElemUse(eid, nix, ix[eid - 1]);
    }

    /* Suppress all translations at nodes 1 and 3 */
    restag[0] = SYS_DOF_TX;
    restag[1] = SYS_DOF_TY;
    nid = 1;
    doftab->NodePerm(nid, nndofs, restag);
    nid = 3;
    doftab->NodePerm(nid, nndofs, restag);

    /* Process dof table, count equations and reactions */
    doftab->Process(&neq, &nre);

    /* Create system stiffness matrix */
    sysmatrix = new vfs_SysMatrix;
    sysmatrix->Def(SYSMATRIX_SYMM_SPARSE, neq);
    sysmatrix->SetObject(VFS_DOFTAB, (Vobject*)doftab);

    /* Initialize */
    sysmatrix->PreProcess();
    sysmatrix->Init(0.);

    /* Assemble actual stiffness */
    for (eid = 1; eid <= numel; eid++) {
        doftab->ElemDof(eid, nix, ix[eid - 1], &nedofs, lm);
        sysmatrix->Assem(nedofs, lm, kt[eid - 1]);
    }

    /* Factorize matrix */
    sysmatrix->Process();
    sysmatrix->Factor();

    /* Create system vector for assembled load */
    load = new vfs_SysVector;
    load->Def(neq);

    /* Define load at node 2 */
    nid = 2;
    lodtag[0] = SYS_DOF_TX;
    lodtag[1] = SYS_DOF_TY;
    doftab->NodeDof(nid, nndofs, lodtag, lm);
    lodval[0] = .5 * sqrt(2.) * 10.;
    lodval[1] = .5 * sqrt(2.) * 10.;
    load->Assem(nndofs, lm, lodval);

    /* Create system vector for solution */
    soln = new vfs_SysVector;
    soln->Def(neq);

    /* Backsubstitution for solution */
    sysmatrix->Solve(load, soln);

    /* Gather and print solution */
    printf("Displacements\n");
    soltag[0] = SYS_DOF_TX;
    soltag[1] = SYS_DOF_TY;
    for (nid = 1; nid <= numnp; nid++) {
        doftab->NodeDof(nid, nndofs, soltag, lm);
        solval[0] = 0.;
        solval[1] = 0.;
        soln->Gather(nndofs, lm, solval);
        printf(" nid= %d  ux= %10f  uy= %10f\n", nid, solval[0], solval[1]);
    }

    /* Delete objects */
    delete doftab;
    delete load;
    delete soln;
    delete sysmatrix;
    return 0;
}
FORTRAN

A First Program - FORTRAN Version

The following program is a listing of the FORTRAN version of the same “A First Program” listed above which used C language bindings. Although the FORTRAN language does not distinguish between upper and lower case characters, the example retains the conventions employed in the C version for clarity. Note that the prefix vfs_ is replaced by vfsf_.

C 
C               _ 10. load at 45 degrees
C               /|
C              /
C    1 -/\/\- 2
C   pin       |
C             /
C             \
C             |
C             3
C            pin
C 

C-----------------------------------------------------------------------
C                   Solve for Displacement of Two Trusses.
C-----------------------------------------------------------------------
      program main
      include 'base/fortran/base.inc'
      include 'vfs/fortran/vfs.inc'
C                  Stiffnesses (Lower Triangle) for Two Trusses
      double precision kt(10,2)
      data kt /
     &  100.,
     &    0.,   0.,
     & -100., 0., 100.,
     &    0.,   0.,   0.,   0.,
     &    0.,
     &    0., 100.,
     &    0.,   0.,   0.,
     &    0.,-100.,   0., 100. /
C                  Connectivity for Two Trusses
      integer ix(2,2)
      data ix / 1,2, 2,3 /
C                  Generic Truss Dof Map
      integer loc(4)
      data loc / 1,1, 2,2 /
      integer tag(4)
      data tag / SYS_DOF_TX, SYS_DOF_TY, SYS_DOF_TX, SYS_DOF_TY /

      double precision sysmatrix
      double precision load, soln
      double precision doftab
      integer numnp, numel
      integer nix, nndofs, nedofs
      integer eid, nid
      integer restag(2)
      integer neq, nre
      integer lodtag(2)
      double precision lodval(2)
      integer lm(4)
      integer soltag(2)
      double precision solval(2)

C                  Set number of nodes, elements
      numnp = 3
      numel = 2
C                  Set number of nodes per element
      nix = 2
C                  Set dof per node, dof per element
      nndofs = 2
      nedofs = nix * nndofs

C                  Create degree of freedom table
      call vfsf_DofTabBegin (doftab)
      call vfsf_DofTabDef (doftab,numnp,numel)

C                  Loop over elements to set degree of freedom use
      call vfsf_DofTabSetMap (doftab,nedofs,loc,tag)
      do eid = 1,numel
         call vfsf_DofTabElemUse (doftab,eid,nix,ix(1,eid))
      enddo

C                  Suppress all translations at nodes 1 and 3
      restag(1) = SYS_DOF_TX
      restag(2) = SYS_DOF_TY
      nid = 1
      call vfsf_DofTabNodePerm (doftab,nid,nndofs,restag)
      nid = 3
      call vfsf_DofTabNodePerm (doftab,nid,nndofs,restag)

C                  Process dof table, count equations and reactions
      call vfsf_DofTabProcess (doftab,neq,nre)

C                  Create system stiffness matrix
      call vfsf_SysMatrixBegin (sysmatrix)
      call vfsf_SysMatrixDef (sysmatrix,SYSMATRIX_SYMM_SPARSE,neq)

C                  Preprocess stiffness matrix
      call vfsf_SysMatrixSetObject (sysmatrix,VFS_DOFTAB,doftab)
      call vfsf_SysMatrixPreProcess (sysmatrix)

C                  Initialize
      call vfsf_SysMatrixInit (sysmatrix,0.)

C                  Assemble actual stiffness
      do eid = 1,numel
         call vfsf_DofTabElemDof (doftab,eid,nix,ix(1,eid),nedofs,lm)
         call vfsf_SysMatrixAssem (sysmatrix,nedofs,lm,kt(1,eid))
      enddo

C                  Factorize matrix
      call vfsf_SysMatrixProcess (sysmatrix)
      call vfsf_SysMatrixFactor (sysmatrix)

C                  Create system vector for assembled load
      call vfsf_SysVectorBegin (load)
      call vfsf_SysVectorDef (load,neq)

C                  Define load at node 2
      nid = 2
      lodtag(1) = SYS_DOF_TX
      lodtag(2) = SYS_DOF_TY
      call vfsf_DofTabNodeDof (doftab,nid,nndofs,lodtag,lm)
      lodval(1) = .5*sqrt(2.)*10.
      lodval(2) = .5*sqrt(2.)*10.
      call vfsf_SysVectorAssem (load,nndofs,lm,lodval)

C                  Create system vector for solution
      call vfsf_SysVectorBegin (soln)
      call vfsf_SysVectorDef (soln,neq)

C                  Backsubstitution for solution
      call vfsf_SysMatrixSolve (sysmatrix,load,soln)

C                  Gather and print solution
      write(6,*) "Displacements"
      soltag(1) = SYS_DOF_TX
      soltag(2) = SYS_DOF_TY
      do nid = 1,numnp
         call vfsf_DofTabNodeDof (doftab,nid,nndofs,soltag,lm)
         solval(1) = 0.
         solval(2) = 0.
         call vfsf_SysVectorGather (soln,nndofs,lm,solval)
         write(6,1000) nid,solval(1),solval(2)
      enddo
   
C                  Delete objects
      call vfsf_DofTabEnd (doftab)
      call vfsf_SysVectorEnd (load)
      call vfsf_SysVectorEnd (soln)
      call vfsf_SysMatrixEnd (sysmatrix)
1000  format(' nid= ',i2,'  ux= ',f11.6,'  uy= ',f11.6)
      stop
      end
C#

A First Program - C# Version

The following program is a listing of the C# version of the same “A First Program” listed above which used C language bindings. Note that the prefix vfs_ is replaced by vfs..

using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Text;
using DevTools;

public class Intro1
{

    /* Stiffnesses (Lower Triangle) for Two Trusses */
    public static double[][] kt = {
      new double[] { 100.0,
                     0.0,   0.0,
                    -100.0, 0.0, 100.0,
                     0.0,   0.0,   0.0,   0.0 },
      new double[] { 0.0,
                     0.0, 100.0,
                     0.0,   0.0,   0.0,
                     0.0,-100.0,   0.0, 100.0 }
   };
    /* Connectivity for Two Trusses */
    public static int[][] ix = {
      new int[] {1,2},
      new int[] {2,3}
   };

    /* Generic Truss Dof Map */
    public static int[] loc = { 1, 1, 2, 2 };

    public static int[] tag = {
      vsy.SYS_DOF_TX, vsy.SYS_DOF_TY, vsy.SYS_DOF_TX, vsy.SYS_DOF_TY };

    /*
                    _ 10. load at 45 degrees
                    /|
                   /
         1 -/\/\- 2
        pin       |
                  /
                  \
                  |
                  3
                 pin
    */

    /*----------------------------------------------------------------------
                  Set environment path
    ----------------------------------------------------------------------*/
    public static void SetEnvironmentPath()
    {
        var pathVariableName = "PATH";
        var scope = EnvironmentVariableTarget.Process;
        var oldPathVariableValue = Environment.GetEnvironmentVariable(pathVariableName, scope);
        var newPathVariableValue = oldPathVariableValue + @";${CEE_SAM_EXTERNAL_LIBRARIES_BIN_PATHS}";
        Environment.SetEnvironmentVariable(pathVariableName, newPathVariableValue, scope);
    }

    /*----------------------------------------------------------------------
                          Solve for Displacement of Two Trusses.
    ----------------------------------------------------------------------*/
    public static void Main()
    {

        IntPtr sysmatrix;
        IntPtr load, soln;
        IntPtr doftab;
        int[] restag = new int[2];
        int neq = 0, nre = 0;
        int[] lodtag = new int[2];
        double[] lodval = new double[2];
        int[] lm = new int[4];
        int[] soltag = new int[2];
        double[] solval = new double[2];

        SetEnvironmentPath();
        vsy.LicenseValidate(new StringBuilder(HOOPS_LICENSE.KEY));

        /* Set number of nodes, elements */
        int numnp = 3;
        int numel = 2;
        /* Set number of nodes per element */
        int nix = 2;
        /* Set dof per node, dof per element */
        int nndofs = 2;
        int nedofs = nix * nndofs;

        /* Create degree of freedom table */
        doftab = vfs.DofTabBegin();
        vfs.DofTabDef(doftab, numnp, numel);

        /* Loop over elements to set degree of freedom use */
        vfs.DofTabSetMap(doftab, nedofs, loc, tag);
        int eid;
        for (eid = 1; eid <= numel; eid++)
        {
            vfs.DofTabElemUse(doftab, eid, nix, ix[eid - 1]);
        }

        /* Suppress all translations at nodes 1 and 3 */
        restag[0] = vsy.SYS_DOF_TX;
        restag[1] = vsy.SYS_DOF_TY;
        int nid = 1;
        vfs.DofTabNodePerm(doftab, nid, nndofs, restag);
        nid = 3;
        vfs.DofTabNodePerm(doftab, nid, nndofs, restag);

        /* Process dof table, count equations and reactions */
        vfs.DofTabProcess(doftab, ref neq, ref nre);

        /* Create system stiffness matrix */
        sysmatrix = vfs.SysMatrixBegin();
        vfs.SysMatrixDef(sysmatrix, vfs.SYSMATRIX_SYMM_SPARSE, neq);
        vfs.SysMatrixSetObject(sysmatrix, vfs.VFS_DOFTAB, doftab);

        /* PreProcess, to form matrix structure */
        vfs.SysMatrixPreProcess(sysmatrix);

        /* Initialize */
        vfs.SysMatrixInit(sysmatrix, 0.0);

        /* Assemble actual stiffness */
        for (eid = 1; eid <= numel; eid++)
        {
            vfs.DofTabElemDof(doftab, eid, nix, ix[eid - 1], ref nedofs, lm);
            vfs.SysMatrixAssem(sysmatrix, nedofs, lm, kt[eid - 1]);
        }

        /* Factorize matrix */
        vfs.SysMatrixProcess(sysmatrix);
        vfs.SysMatrixFactor(sysmatrix);

        /* Create system vector for assembled load */
        load = vfs.SysVectorBegin();
        vfs.SysVectorDef(load, neq);

        /* Define load at node 2 */
        nid = 2;
        lodtag[0] = vsy.SYS_DOF_TX;
        lodtag[1] = vsy.SYS_DOF_TY;
        vfs.DofTabNodeDof(doftab, nid, nndofs, lodtag, lm);
        lodval[0] = 0.5 * Math.Sqrt(2.0) * 10.0;
        lodval[1] = 0.5 * Math.Sqrt(2.0) * 10.0;
        vfs.SysVectorAssem(load, nndofs, lm, lodval);

        /* Create system vector for solution */
        soln = vfs.SysVectorBegin();
        vfs.SysVectorDef(soln, neq);

        /* Backsubstitution for solution */
        vfs.SysMatrixSolve(sysmatrix, load, soln);

        /* Gather and print solution */
        Console.Write("Displacements\n");
        soltag[0] = vsy.SYS_DOF_TX;
        soltag[1] = vsy.SYS_DOF_TY;
        for (nid = 1; nid <= numnp; nid++)
        {
            vfs.DofTabNodeDof(doftab, nid, nndofs, soltag, lm);
            solval[0] = 0.0;
            solval[1] = 0.0;
            vfs.SysVectorGather(soln, nndofs, lm, solval);
            Console.Write(" nid= {0}  ux= {1}  uy= {2}\n", nid, solval[0], solval[1]);
        }

        /* Delete objects */
        vfs.DofTabEnd(doftab);
        vfs.SysVectorEnd(load);
        vfs.SysVectorEnd(soln);
        vfs.SysMatrixEnd(sysmatrix);
    }
}

The output of this example program appears below.

Displacements
nid= 1  ux=   0.000000  uy=   0.000000
nid= 2  ux=   0.070711  uy=   0.070711
nid= 3  ux=   0.000000  uy=   0.000000