Creating an output database

The following example illustrates how you can use the Abaqus C++ API commands to do the following:

  1. Create a new output database.

  2. Add model data.

  3. Add field data.

  4. Add history data.

  5. Read history data.

  6. Save the output database.

Use the following command to retrieve the example program:

abaqus fetch job=odbWrite
////////////////////////////////////////////////////
// Code to create an output database and add model,
// field, and history data. The code also reads
// history data, performs an operation on the data, and writes
// the result back to the output database.
//
// SECTION: System includes
//
#include <math.h>
//
// Begin local includes
//
#include <odb_API.h>
#include <odb_MaterialTypes.h>
#include <odb_SectionTypes.h>
//
// End local includes
//

int ABQmain(int argc, char **argv)
{
    // Create an ODB (which also creates the rootAssembly).
    int n;
    odb_String name("simpleModel");
    odb_String analysisTitle("ODB created with C++ ODB API");
    odb_String description("example illustrating C++ ODB API");
    odb_String path("odbWriteC.odb");
    odb_Odb& odb = Odb(name,
                       analysisTitle,
                       description,
                       path);

    // Model data:
    // Set up the section categories.
    odb_String sectionCategoryName("S5");
    odb_String sectionCategoryDescription("Five-Layered Shell");
    odb_SectionCategory& sCat =
        odb.SectionCategory(sectionCategoryName,
                            sectionCategoryDescription);
    int sectionPointNumber = 1;
    odb_String sectionPointDescription("Bottom");
    odb_SectionPoint spBot =
        sCat.SectionPoint(sectionPointNumber,
                          sectionPointDescription);
    sectionPointNumber = 3;
    sectionPointDescription = "Middle";
    odb_SectionPoint spMid =
        sCat.SectionPoint(sectionPointNumber,
                          sectionPointDescription);
    sectionPointNumber = 5;
    sectionPointDescription = "Top";
    odb_SectionPoint spTop =
        sCat.SectionPoint(sectionPointNumber,
                          sectionPointDescription);

    // Create few materials
    odb_MaterialApi materialApi;
    odb.extendApi(odb_Enum::odb_MATERIAL,materialApi);
    odb_String materialName("Elastic Material");
    odb_Material& material_1 =
        materialApi.Material(materialName);
    odb_SequenceSequenceDouble myTable;
    odb_SequenceDouble myData;
    myData.append(12000.00);//youngs modulus
    myData.append(0.3);//poissons ratio
    myTable.append(myData);
    odb_String type("ISOTROPIC");
    bool noCompression = false;
    bool noTension = false;
    bool temperatureDependency = false;
    int dependencies = 0;
    odb_String moduli("LONG_TERM");
    material_1.Elastic(myTable,
                       type,
                       noCompression,
                       noTension,
                       temperatureDependency,
                       dependencies,
                       moduli);

    //create few sections
    odb_SectionApi sectionApi;
    odb.extendApi(odb_Enum::odb_SECTION,
                  sectionApi);
    odb_String sectionName("Homogeneous Shell Section");
    double thickness = 2.0;
    odb_HomogeneousShellSection& section_1 =
        sectionApi.HomogeneousShellSection(sectionName,thickness,materialName);

    // Create a 2-element shell model,
    //4 integration points, 5 section points.

    odb_Part& part1 = odb.Part("part-1",
                               odb_Enum::THREE_D,
			       odb_Enum::DEFORMABLE_BODY);

    odb_SequenceInt nodeLabels;
    for(n=1; n<7; n++)
	nodeLabels.append(n);

    double c[6][3] = { {1,  0,  0.0},
	               {2,  0,  0.0},
		       {2,  1,  0.1},
		       {1,  1,  0.1},
  		       {2, -1, -0.1},
		       {1, -1, -0.1} };
    odb_SequenceSequenceFloat nodeCoor;
    for(n=0; n<nodeLabels.size(); n++) {
	odb_SequenceFloat loc;
	for(int i=0; i<3; i++)
	    loc.append(c[n][i]);
	nodeCoor.append(loc);
    }
    odb_String nodeSetName("nset-1");
    part1.addNodes(nodeLabels,
                   nodeCoor,
                   nodeSetName);

    odb_SequenceInt elLabels;
    elLabels.append(1);
    elLabels.append(2);
    odb_SequenceSequenceInt connect;
    const int numNodePerEl = 4;
    int conn[2][numNodePerEl] = { {1, 2, 3, 4},
	                          {6, 5, 2, 1} };
    for(int e=0; e<elLabels.size(); e++) {
	odb_SequenceInt l;
	for(int i=0; i<numNodePerEl; i++)
	    l.append(conn[e][i]);
	connect.append(l);
    }
    odb_String elType("S4");
    odb_String elsetName("eset-1");
    part1.addElements(elLabels,
                      connect,
                      elType,
                      elsetName,
                      sCat);

    // Instance the part.
    odb_String partInstanceName("part-1-1");
    odb_Instance& instance1 =
        odb.rootAssembly().Instance(partInstanceName, part1);
    // create instance level sets for section assignment
    elsetName = "Material 1";
    odb_Set& elset_1 = instance1.ElementSet(elsetName,
                                            elLabels);
    // section assignment on instance
    instance1.assignSection(elset_1,section_1);
    // Field data:
    // Create a step and a frame.
    odb_String stepName("step-1");
    odb_String stepDescription("first analysis step");
    odb_Step& step1 = odb.Step(stepName,
                               stepDescription,
                               odb_Enum::TIME,
			       1.0);
    int incrementNumber = 1;
    float analysisTime = 0.1;
    odb_String frameDescription("results frame for time");
    frameDescription.append(analysisTime);
    odb_Frame frame1 = step1.Frame(incrementNumber,
                                   analysisTime,
                                   frameDescription);

    // Write nodal displacements.
    odb_String fieldName("U");
    odb_String fieldDescription("Displacements");
    odb_FieldOutput& uField =
        frame1.FieldOutput(fieldName,
                           fieldDescription,
			   odb_Enum::VECTOR);

    odb_SequenceSequenceFloat dispData;
    odb_SequenceFloat dispData1[6];
    // create some displacement values
    for(n=0; n<6; n++) {
	for(int m=1; m<4; m++)
	    dispData1[n].append(n*3+m);
	dispData.append(dispData1[n]);
    }
    uField.addData(odb_Enum::NODAL,
                   instance1,
                   nodeLabels,
                   dispData);

    // Make this the default deformed field for visualization.

    step1.setDefaultDeformedField(uField);

    // Write stress tensors (output only available at
    // top/bottom section points)
    // The element defined above (S4) has 4 integration points.
    // Hence, there are 4 stress tensors per element.
    // Each Field constructor refers to only one layer of
    // section points.

    odb_SequenceSequenceFloat topData;
    odb_SequenceFloat topData1;
    for(n=1; n<5; n++)
	topData1.append(n);

    for(n=0; n<8; n++)
	topData.append(topData1);

    odb_SequenceSequenceFloat bottomData;
    odb_SequenceFloat bottomData1;
    for(n=1; n<5; n++)
	bottomData1.append(n);

    for(n=0; n<8; n++)
	bottomData.append(bottomData1);

    odb_SequenceSequenceFloat transform;

    //transform = ((1.,0.,0.), (0.,1.,0.), (0.,0.,1.))

    for(n=1; n<4; n++){
	odb_SequenceFloat transform1;
	for(int m=1; m<4; m++) {
	    if(m==n)transform1.append(1);
	    else transform1.append(0);
	}
	transform.append(transform1);
    }

    odb_SequenceString componentLabels;
    componentLabels.append("S11");
    componentLabels.append("S22");
    componentLabels.append("S33");
    componentLabels.append("S12");

    odb_SequenceInvariant validInvariants;
    validInvariants.append(odb_Enum::MISES);
    fieldName = "S";
    fieldDescription = "Stress";
    odb_FieldOutput& sField =
        frame1.FieldOutput(fieldName,
                           fieldDescription,
                           odb_Enum::TENSOR_3D_PLANAR,
                           componentLabels,
                           validInvariants);

    sField.addData(odb_Enum::INTEGRATION_POINT,
                   instance1,
		   elLabels,
                   topData,
                   spTop,
                   transform);

    sField.addData(odb_Enum::INTEGRATION_POINT,
                   instance1,
		   elLabels,
                   bottomData,
                   spBot,
                   transform);

    // For this step, make this the default
    // field for visualization.

    step1.setDefaultField(sField);

    // History data:
    // Create a HistoryRegion for a specific point.
    odb_HistoryPoint hPoint1(instance1.getNodeFromLabel(1));
    odb_String historyRegionName("historyNode0");
    odb_String historyRegionDescription(
        "Displacement and reaction force");
    odb_HistoryRegion& hRegionStep1 =
        step1.HistoryRegion(historyRegionName,
                            historyRegionDescription,
                            hPoint1);

    // Create variables for this history output in step1.

    odb_String historyOutputName("U1");
    odb_String historyOutputDescription("Displacement");
    odb_HistoryOutput& hOutputStep1U1 =
        hRegionStep1.HistoryOutput(historyOutputName,
                                   historyOutputDescription,
                                   odb_Enum::SCALAR);
    historyOutputName = "RF1";
    historyOutputDescription = "Reaction Force";
    odb_HistoryOutput& hOutputStep1Rf1 =
        hRegionStep1.HistoryOutput(historyOutputName,
                                   historyOutputDescription,
                                   odb_Enum::SCALAR);
    // Add history data for step1.

    hOutputStep1U1.addData(0.0, 0.0);
    hOutputStep1Rf1.addData(0.0,0.0);
    hOutputStep1U1.addData(0.1, 0.1);
    hOutputStep1Rf1.addData(0.1,0.1);
    hOutputStep1U1.addData(0.3, 0.3);
    hOutputStep1Rf1.addData(0.3,0.3);
    hOutputStep1U1.addData(1.0, 0.5);
    hOutputStep1Rf1.addData(1.0,0.5);

    // Create another step for history data.
    stepName = "step-2";
    stepDescription = "second analysis step";
    odb_Step& step2 = odb.Step(stepName,
                               stepDescription,
                               odb_Enum::TIME,
			       1.0);


    // Create new history region

    odb_HistoryPoint hPoint2(instance1.getNodeFromLabel(1));

    odb_HistoryRegion& hRegionStep2 =
        step2.HistoryRegion(historyRegionName,
                            historyRegionDescription,
                            hPoint2);

    //Create new history output
    historyOutputName = "U1";
    historyOutputDescription = "Displacement";
    odb_HistoryOutput& hOutputStep2U1 =
        hRegionStep2.HistoryOutput(historyOutputName,
                                   historyOutputDescription,
                                   odb_Enum::SCALAR);

    historyOutputName = "RF1";
    historyOutputDescription = "Reaction Force";
    odb_HistoryOutput& hOutputStep2Rf1 =
        hRegionStep2.HistoryOutput(historyOutputName,
                                   historyOutputDescription,
                                   odb_Enum::SCALAR);


    // Add history data for the second step.

    hOutputStep2U1.addData(1.2, 0.8);
    hOutputStep2Rf1.addData(1.2,0.9);
    hOutputStep2U1.addData(1.9, 0.9);
    hOutputStep2Rf1.addData(1.9,1.1);
    hOutputStep2U1.addData(3.0, 1.3);
    hOutputStep2Rf1.addData(3.0,1.3);
    hOutputStep2U1.addData(4.0, 1.5);
    hOutputStep2Rf1.addData(4.0,1.5);

    // Square the history data U, and store as new history output
    historyOutputName = "squareU1";
    historyOutputDescription = "Square of displacements";
    odb_HistoryOutput&  hOutputStep1sumU1 =
        hRegionStep1.HistoryOutput(historyOutputName,
                                   historyOutputDescription,
                                   odb_Enum::SCALAR);
    historyOutputName = "squareU2";
    odb_HistoryOutput&  hOutputStep2sumU1 =
        hRegionStep2.HistoryOutput(historyOutputName,
                                   historyOutputDescription,
                                   odb_Enum::SCALAR);

    // Get XY Data from the two steps.

    odb_HistoryOutputRepository& historyOutputs1 =
        hRegionStep1.historyOutputs();
    historyOutputName = "U1";
    odb_HistoryOutput& u1FromStep1 =
        historyOutputs1[historyOutputName];

    odb_HistoryOutputRepository& historyOutputs2 =
	hRegionStep2.historyOutputs();
    odb_HistoryOutput& u1FromStep2 =
        historyOutputs2[historyOutputName];

    odb_SequenceSequenceFloat hdata1 = u1FromStep1.data();
    odb_SequenceSequenceFloat hdata2 = u1FromStep2.data();

    // Add the squared displacement to the two steps.

    for(n=0; n<hdata1.size(); n++){
	odb_SequenceFloat hdata11=hdata1.get(n);
	hOutputStep1sumU1.addData(hdata11.get(0),
	    pow((double)hdata11.get(1),(int)2));
    }

    for(n=0; n<hdata2.size(); n++){
	odb_SequenceFloat hdata22=hdata2.get(n);
	hOutputStep2sumU1.addData(hdata22.get(0),
	    pow((double)hdata22.get(1),(int)2));
    }


    // Save the results in the output database.
    // Use the Visualization module of Abaqus/CAE to
    // view the contents of the output database.

    odb.save();
    odb.close();
    return 0;
}