Examples

The following simple examples show how the functions above might be used. Further example scripts may be found in directory $OASYS/d3plot_library/examples

Capturing a sequence of static images to JPEG files

The following example loops over all frames in window #1 issuing the dialogue command "/IMAGE JPG example_file_ class="courier">nnn.jpg" which will capture each frame in a separate JPEG file.

n = GetWindowMaxFrame(1); // Here window #1 is assumed to be current
for (i=1; i<=n; i++)
{
  SetWindowFrame(1, i);
  DialogueInput("/IMAGE JPG example_file_" + i + ".jpg");
}

Looping through states extracting cut-section results

The following example works through each state in the current model in turn, setting up a cut-section at the constant X coordinate of node #100, then rotates this section through 360 degrees in 5 degree increments, printing out the resulting forces and moments at each increment.
/* We need an array with 9 subscripts to hold data */ 

var data = new Array(9);

/* Turn on cut section display in window #1 */

SetCutSection(1, STATUS, ON);

/* Loop over all states in the model in turn */

n = GetNumberOf(STATE);

for(i=1; i<=n; i++)
{
    time = GetTime(i);
    Print("Time = " + time + "\n");

/* Set sections at const X at current position of node 100, and "get" the result */

    SetCutSection(1, CONST_X, 100);

/* Note that GetCutSection() gets the forces in the current state shown in the window, and
** that to get results at a different time the state argument must be specified as here. */

    info = GetCutSection(1, 0, 0, i);

/* The following uses origin and vectors mode to sweep the section through 360 degrees in
** 5 degree increments, extracting the forces and moments at each position */

    data[0] = info.origin[X]; /* Origin stays where it currently is */
    data[1] = info.origin[Y];
    data[2] = info.origin[Z];

    for(i=0; i<=360; i+=5)
    {
        st = Math.sin(i*0.017453);
        ct = Math.cos(i*0.017453);
        
        data[3] = ct; /* X axis vector */
        data[4] = 0.0;
        data[5] = st;

        data[6] = 0.0; /* XY plane vector */
        data[7] = st;
        data[8] = ct;

        SetCutSection(1, OR_AND_V, data);
        c = GetCutForces(1);

        Print("Forces = " + c.force[X] + ", " + c.force[Y] + ", " + c.force[Z] + "\n");
        Print("Moments = " + c.moment[X] + ", " + c.moment[Y] + ", " + c.moment[Z] + "\n");
        Print("Centroid = " + c.centroid[X] + ", " + c.centroid[Y] + ", " + c.centroid[Z] + "\n");
        Print("Area = " + c.area + "\n\n");
    }
}

Calculating the max value and storing it as a UBIN component.

This example loops over all states in model #1 finding the maximum Sxx value of each solid and shell in the model, and storing it as a new scalar UBIN component in state #1.

/* If you have > 1 model then set the one you want. Model #1 is assumed in
** this example. */

SetCurrentModel(1);

/* It is assumed that only a single scalar value is required, and it is for
** solids & shells. So find out the number of states, solids and shells */

nstate = GetNumberOf(STATE);

nshell = GetNumberOf(SHELL);
nsolid = GetNumberOf(SOLID);

shell_env = new Array();
solid_env = new Array();

/* Create arrays to hold the max/min data. Here they are initialised to
** zero, which might not be a good choice if you are looking for max values
** and incoming results could be negative. Fill in your own initial value. */

for(j=1; j<=nshell; j++) shell_env[j] = 0.0;
for(j=1; j<=nsolid; j++) solid_env[j] = 0.0;
  
/* Loop over states collecting max data. 
  **
  ** Note that making the outer loop the state is more efficient than making it the
  ** element, since changing state is a more costly operation. */

for(i=1; i<=nstate; i++)
{
     SetCurrentState(i);
     Print("Doing state " + i + "\n");

     for(j=1; j<=nshell; j++)
     {
         c = GetData(SXX, SHELL, j, 1);
         if(c > shell_env[j]) shell_env[j] = c;
     }

     for(j=1; j<=nsolid; j++)
     {
        c = GetData(SXX, SOLID, j, 1);
        if(c > solid_env[j]) solid_env[j] = c;
     }
}

/* Now create a scalar user-defined binary component to hold the result */

icomp = CreateUbinComponent("Maximum of SXX", U_SOSH, U_SCALAR, REPLACE);

/* Data has to be stored at a state, so choose state 1 */

SetCurrentState(1);

/* Then populate this user-defined component, intg point #1. */

for(j=1; j<=nshell; j++) PutUbinData(icomp, SHELL, j, 1, shell_env[j]);
for(j=1; j<=nsolid; j++) PutUbinData(icomp, SOLID, j, 1, solid_env[j]);

Extracting data by ply from a composite analysis.

Post-processing composite analyses can be difficult because the elements have many integration points, and a physical ply may not use the same integration point in two adjacent elements, meaning that post-processing by "layer" (ie by integration point) is not helpful.

This script assumes that ply information has been created using a *PART_COMPOSITE card, with each ply assigned to a separate material id of the relevant ply number, and it sorts results into a separate UBIN component by ply. In this way a given UBIN component will show results for a single ply across the whole model.

// JavaScript to plot composite data for selected elements

// Date: 26 June 2008
// Version 1.0

n = get_window_max_frame(1);
set_current_model(1);

var a = GetWindowFrame(1);

SetCurrentState(a);

nsh = GetNumberOf(SHELL);
nip = GetNumberOf(NIP_S);
npa = GetNumberOf(PART);

var part = new Array();
var part_id = new Array();
var part_flag = 0;
var co1 = 0; // part counter
var co2 = 0; // ply counter
var ply = new Array();
var ply_id = new Array();
var ply_flag = 0;
var tmp1 = 0;
var offset = {}; // part, ip
var order1= {}; // part, ip
var order2= {}; // part, ip
var max1 = {};
var max2 = {};
var iter= 0; // iteration counter
var i_flag = 0;
var t_flag = 0;

// setup part array

for (i=1; i<=npa; i++) //shell
{
  part_flag = 0;
  a = GetLabel(PART, i);
  b = GetMid(PART, i, 1);

  if (b == 0) // check to see if the part is not a Part Composite
  {
    part_flag = 1;
  }

  for(j=1; j<=co1; j++) //part
  {
    if (a == part_id[j]) // check to see if the part is already defined
    {
      part_flag = 1;
    }
  }

  if (part_flag == 0)
  {
    co1 = co1 + 1;
    part[co1] = i;
    part_id[co1] = a;
  }
}

// setup ply order array

for (i=1; i<=co1; i++) // part
{
  order1[i] = new Object;

  for(j=1; j<=nip; j++) // ip
  {
    b = GetMid(PART, part[i], j);
    order1[i][j] = b;
  }
}

// setup ply id array

for (i=1; i<=co1; i++) //part
{
  for(j=1; j<=nip; j++) //ip
  {
    b = order1[i][j];
    if (b == 0) // ply doesn't exist
    {
      ply_flag = 1;
    }

    for (k=1; k<=co2; k++) //ply already created
    {
      if (b == ply_id[k])
      {
        ply_flag = 1;
      }
    }

    if (ply_flag == 0)
    {
      co2 = co2 + 1;
      ply_id[co2] = b;
      Message(co2 +" "+ b);
    }

    ply_flag = 0;
  }
}

//////////////////////////// proccessing loop
while (i_flag == 0)
{
  iter = iter + 1;
  Message("Iteration "+ iter);
  if(iter > 1)
  {
    for (i=1; i<=co1; i++) // part
    {
      for(j=1; j<=co2; j++) // ip
      {
        order1[i][j] = order2[i][j];
      }
    }
  }
//// ply order array

  for (i=1; i<=co2; i++) //ply
  {
    ply[i] = new object;

    for(j=1; j<=co1; j++) //part
    {
      ply[i][j] = new object;

      for(k=1; k<=co2; k++) //ply
      {
        b = order1[j][k];
        if (b == ply_id[i])
        {
          ply[i][j] = k
        }
      }
    }
  }
//// find max position for each ply

  for (i=1; i<=co2; i++)
  {
    max1[i] = 0;

    for(j=1; j<=co1; j++)
    {
      if (typeof(ply[i][j]) == "object")
      {
        ply[i][j] = 0;
      }
  
      max1[i] = Math.max(max1[i], ply[i][j]);
    }
  }

  for (i=1; i<=co2; i++)
  {
    Message(i +" "+ ply_id[i] + " "+ max1[i]);
  }

  // offset ply
  for (i=1; i<=co1; i++) // part
  {
    order2[i] = new Object;
    max = 0;
    pos2 = 0;

    for(j=1; j<=co2; j++) // ip
    {
      pos1 = j;
      b = order1[i][j]; // ply id 
      for(k=1; k<=co2; k++) // ply
      {
        if(ply_id[k] == b)
        {
          max = max1[k]
        }
      }

      if(b != null && b != 0)
      {
        p_off = Math.max((pos2 - pos1 + 1),0);
        pos2 = Math.max(max, (p_off + pos1));
        order2[i][pos2] = b;
      }
    }
  }

  i_flag = 1;
  for (i=1; i<=co1; i++) // part
  {
    for(j=1; j<=co2; j++) // ip
    {
      if(order1[i][j] != order2[i][j]) i_flag = 0;
    }
  }
}
////////////////// create table

var we = new Window("Ply Layout", 0.2, 0.3, 0.5, 0.6 ); 
var x1 = 0;
var x2 = 0;
var y1 = 0
var y2 = 0;
var part = new Widget(we, Widget.LABEL, 0, Math.max((co1*10)+30, 70), 10, 20, "PART");
part.justify=Widget.CENTRE;

for (i=1; i<=co2; i++) // ply 
{
  t_flag = 1;
  y1 = (i*10) + 20; 
  y2 = y1 + 10; 

  for(j=1; j<=co1; j++) // part 
  { 
    x1 = (j*10) + 10;
    x2 = x1 + 10;
    if(i == 1)
    {
      var partl = new Widget(we, Widget.LABEL, x1, x2, 20, 30, ""+part_id[j]);
    }
    
    var mark = new Widget(we,
    Widget.BUTTON, x1, x2, y1, y2, " ");

    if (order2[j][i] != 0 && order2[j][i] != null)
    {
      mark.text= ""+order2[j][i];
      mark.background=Widget.BLUE;
      mark.foreground=Widget.WHITE;
      t_flag = 0;
    }
  }

  if(t_flag == 1)
  {
    var yn = i;
    i = co2+1;
  }
}

var ply = new Widget(we, Widget.LABEL, 10, 20, (yn*5)+25, (yn*5)+35, "PLY");
var exit = new Widget(we, Widget.BUTTON, 20, 60, (y1+20), (y2+20), "Exit");
exit.background = Widget.DARKRED; 
exit.foreground = Widget.WHITE; 
exit.onClick = ex_clicked;
we.Show(false)
////////////////////////////////////////////////////////////////////////////////
function ex_clicked()
{
  Exit();
}
///////////////////////////////////////////////////////////////////////////////
    


Using the Window and Widget classes to present ply data graphically

This example demonstrates the use of Menu Window and Widget classes of the common API shared with PRIMER to present information to the user graphically, and to interact with them.

It goes through a laminate model using *PART_COMPOSITE and sorts the plies into usage by part. This information is then presented to the user as shown in the figure here and the script pauses until the user clicks on "Exit" in order to continue.

SetCurrentModel(1);
SetCurrentState(1);

nsh = GetNumberOf(SHELL);
nip = GetNumberOf(NIP_S);
npa = GetNumberOf(PART);

var part = new Array();
var part_id = new Array();
var part_flag = 0;
var co1 = 0; // part counter
var co2 = 0; // ply counter

var ply = new Array();
var ply_id = new Array();
var ply_flag = 0;

var tmp1 = 0;

var offset = {}; // part, ip
var order1= {}; // part, ip
var order2= {}; // part, ip

var max1 = {};
var max2 = {};

var iter= 0; // iteration counter
var i_flag = 0;
var t_flag = 0;

// setup part array
for (i=1; i<=nsh; i++) //shell
{
  part_flag = 0;
  a = GetPid(SHELL, i);
  a = GetLabel(PART, a);
  b = GetMid(SHELL, i, 1);

  for(j=1; j<=co1; j++) //part
  {
    if (a == part_id[j] || b == 0) // check to see if the part is already defined or not a Part Composite
    {
      part_flag = 1;
    }
  }

  if (part_flag == 0)
  {
    co1 = co1 + 1;
    part[co1] = i;
    part_id[co1] = a;
  }
}

    // setup ply order array
      
for (i=1; i<=co1; i++) // part
{
  order1[i] = new Object;
  for(j=1; j<=nip; j++) // ip
  {
    b = GetMid(SHELL, part[i], j);
    order1[i][j] = b;
  }
}

// setup ply id array
for (i=1; i<=co1; i++) //part
{
  for(j=1; j<=nip; j++) //ip
  {
    b = order1[i][j];
    for (k=1; k<=co2; k++) //ply
    {
      if (b == ply_id[k] || b == 0)
      {
        ply_flag = 1
      }
    }
    if (ply_flag == 0)
    {
      co2 = co2 + 1;
      ply_id[co2] = b;
    }
    ply_flag = 0;
  }
}
//////////////////////////// processing loop
while (i_flag == 0)
{
  iter = iter + 1;
  Message("Iteration "+ iter);

  if(iter > 1)
  {
    for (i=1; i<=co1; i++) // part
    {
      for(j=1; j<=co2; j++) // ip
      {
        order1[i][j] = order2[i][j];
      }
    }
  }

//// ply order array
  for (i=1; i<=co2; i++) //ply
  {
    ply[i] = new Object;
    for(j=1; j<=co1; j++) //part
    {
      ply[i][j] = new Object;
      for(k=1; k<=co2; k++) //ply
      {
        b = order1[j][k];
        if (b == ply_id[i])
        {
          ply[i][j] = k
        }
      }
    }
  }

//// find max position for each ply
  for (i=1; i<=co2; i++)
  {
    max1[i] = 0;
    for(j=1; j<=co1; j++)
    {
      if (typeof(ply[i][j]) == "object")
      {
        ply[i][j] = 0;
      }
      max1[i] = Math.max(max1[i], ply[i][j]);
    }
  }

// offset ply
  for (i=1; i<=co1; i++) // part
  {
    tmp1 = 0;
    offset[i] = new Object;
    for(j=1; j<=co2; j++) // ip
    {
      b = order1[i][j];
      for(k=1; k<=co2; k++) // ply
      {
        if(ply_id[k] == b)
        {
          if(max1[k] > j)
          {
            tmp1 = max1[k] - j;
          }
        }
      }
      offset[i][j] =tmp1
    }
  }

  for (i=1; i<=co1; i++) // part
  {
    order2[i] = new Object;
    for(j=1; j<=co2; j++) // ip
    {
      a = offset[i][j];
      b = order1[i][j];
      order2[i][j+a] = b;
    }
  }

  i_flag = 1;
  for (i=1; i<=co1; i++) // part
  {
    for(j=1; j<=co2; j++) // ip
    {
      if(offset[i][j] != 0) i_flag = 0;
    }
  }
}

////////////////// create table
    
var we = new Window("Ply Layout", 0.2, 0.3, 0.5, 0.6 ); 
var x1 = 0;
var x2 = 0;
var y1 = 0
var y2 = 0;

var part = new Widget(we, Widget.LABEL, (co1*5)+15, (co1*5)+25, 10, 20, "PART");
part.justify=Widget.CENTRE;

for (i=1; i<=co2; i++) // ply 
{
  t_flag = 1;
  y1 = (i*10) + 20; 
  y2 = y1 + 10; 

  for(j=1; j<=co1; j++) // part 
  { 
    x1 = (j*10) + 10;
    x2 = x1 + 10;
    if(i == 1)
    {
      Message("a"+ part_id[j]);
      var partl = new Widget(we, Widget.LABEL, x1, x2, 20, 30, ""+part_id[j]);
    }

    var mark = new Widget(we, Widget.BUTTON, x1, x2, y1, y2, " ");

    if (order2[j][i] != 0 && order2[j][i] != null)
    {
      mark.text= ""+order2[j][i];
      mark.background=Widget.BLUE;
      mark.foreground=Widget.WHITE;
      t_flag = 0;
    }
  }

  if(t_flag == 1)
  {
    var yn = i;
    i = co2+1;
  }
}

var ply = new Widget(we, Widget.LABEL, 10, 20, (yn*5)+25, (yn*5)+35, "PLY");
var exit = new Widget(we, Widget.BUTTON, 20, 60, (y1+20), (y2+20), "Exit");
exit.background = Widget.DARKRED; 
exit.foreground = Widget.WHITE; 
exit.onClick = ex_clicked;
we.Show(false);

////////////////////////////////////////////////////////////////////////////////
function ex_clicked()
{
  Exit();
}

Using the File class to write data to file.

This example extracts maximum and minimum Z displacement values of nodes and writes them to a file "reporter_variables" that can be used to set up variables in Reporter. It demonstrates the use of the File class to open a file, write to it, and close it.

var fence_part_min = 4;
var fence_part_max = 7;

var max_states;
var istate;
var ipart;
var nnode;
var inode;
var objElem;
var internal_pid;
var external_pid;

var z_max = 0;
var z_min = 0;
var max_node = 0;
var min_node = 0;
var max_state = 0;
var min_state = 0;

var f;

/* Get the number of states in the current model */

max_states = GetNumberOf(STATE);

/* Get the number of nodes in the current model */

nnode = GetNumberOf(NODE);

print("Start of loop\n");

/* Loop over each state */

for(istate=1; istate<=max_states; istate++)
{
  SetCurrentState(istate); 
  print("State " + istate + "\n");

/* Loop over each node */

  for(inode=1; inode<=nnode; inode++)
  {
/* Get shell elements at node */

    if(objElem = GetElemsAtNode(inode, SHELL))
    {
      if(objElem.nn > 0)
      {

/* Get the external PID */
        
        internal_pid = GetPid(SHELL, objElem.list[0]);
        external_pid = GetLabel(PART, internal_pid);

/* Check it against parts to test */
        
        if(external_pid >= fence_part_min && external_pid<=fence_part_max)
        {
          temp = GetData(DZ, NODE, inode);

          if(temp > z_max) 
          {
            max_state = istate; /* Store the state the maximum occurs */
            max_node = inode; /* Store the node the maximum occurs at */
            z_max = temp; /* Store the maximum */
          }

          if(temp < z_min)
          {
            min_state = istate; /* Store the state the minimum occurs */
            min_node = inode; /* Store the node the minimum occurs at */
            z_min = temp; /* Store the minimum */
          }
        }
      }
    }
  }
}

/* Open a file to write the variables to */

f = new File("./reporter_variables", File.WRITE);

/* Write to the file */

f.Writeln("VAR Z_MAX DESCRIPTION='Maximum z displacement' VALUE='" + z_max + "'");
f.Writeln("VAR Z_MIN DESCRIPTION='Minimum z displacement' VALUE='" + z_min + "'");
f.Writeln("VAR Z_MAX_NODE DESCRIPTION='Node with maximum z displacement' VALUE='" + max_node + "'");
f.Writeln("VAR Z_MIN_NODE DESCRIPTION='Node with minimum z displacement' VALUE='" + min_node + "'");
f.Writeln("VAR Z_MAX_STATE DESCRIPTION='State with maximum z displacement' VALUE='" + max_state + "'");
f.Writeln("VAR Z_MIN_STATE DESCRIPTION='State with minimum z displacement' VALUE='" + min_state + "'");

/* Close the file */

f.Close();

Next section