Advanced Example

../../../_images/example_example.png

A more complex example demonstrating different ways of populating the blocks. For instance a node block (NodeBlock) can be populated with either setting all nodes at once with setNodes() or setting them one at a time using addNode().

This example contains two parts, two states, a scalar result, a vector result and a displacement result.

It also uses properties for the following features:

  • Show Part 1 as lines

  • Show scalar result as fringes. Set legend range 1.0 to 5.0.

  • Show vector result. Color vector arrows by fringes.

  • Set initial camera position

This example can be overwhelming to start with, but is a very good reference for more practiced users.

Source file

const bool allAtOnce = 0;

//--------------------------------------------------------------------------------------------------
// Writes the given nodes to the VTFx file
//--------------------------------------------------------------------------------------------------
bool writeNodes(int blockId, cee::vtfx::Database* database, const std::vector<float> nodes, const std::vector<int> nodeIds)
{
    // Create the node block
    cee::PtrRef<cee::vtfx::NodeBlock> nodeBlock = new cee::vtfx::NodeBlock(blockId, !nodeIds.empty());

    // Set the node data (Note: Express Writer expects interleaved node coordinates (xyzxyzxyz...))
    // -------------------------------------------------------------------------
    if (allAtOnce)
    {
        // Alt 1: Supply all nodes at once
        if (!nodeBlock->setNodes(nodes, nodeIds))
        {
            return false;
        }
    }
    else
    {
        // Alt 2: Add each node individually, using pre-allocation
        if (!nodeBlock->allocateNodes(nodes.size()))
        {
            return false;
        }

        for (size_t i = 0; i < nodes.size() / 3; i++)
        {
            if (!nodeIds.empty())
            {
                nodeBlock->addNode(nodes[i * 3], nodes[i * 3 + 1], nodes[i * 3 + 2], nodeIds[i]);
            }
            else
            {
                nodeBlock->addNode(nodes[i * 3], nodes[i * 3 + 1], nodes[i * 3 + 2]);
            }
        }
    }

    // Write the block
    // -------------------------------------------------------------------------
    if (!database->writeBlock(nodeBlock.get()))
    {
        return false;
    }

    return true;
}


//--------------------------------------------------------------------------------------------------
// Writes the given elements to the VTFx file
//--------------------------------------------------------------------------------------------------
bool writeElements(int blockId, cee::vtfx::Database* database, std::vector<int> elementNodes, cee::vtfx::ElementBlock::ElementType elementType, int nodeBlockId, std::vector<int> elementIds)
{
    // Create the element block, using index mapping for the nodes
    cee::PtrRef<cee::vtfx::ElementBlock> elementBlock = new cee::vtfx::ElementBlock(blockId, !elementIds.empty(), false);

    // Set the element data
    // -------------------------------------------------------------------------
    if (allAtOnce)
    {
        // Set all elements at once (most efficient)
        if (!elementBlock->addElements(elementType, elementNodes, elementIds))
        {
            return false;
        }
    }
    else
    {
        // Add elements individually (requires frequent re-allocations)
        
        int numElementNodes = static_cast<int>(cee::vtfx::ElementBlock::nodesPerElement(elementType));
        int numElements = static_cast<int>(elementNodes.size()) / numElementNodes;
        for (int i = 0; i < numElements; i++)
        {
            std::vector<int> currentElementNodes;
            currentElementNodes.assign(elementNodes.begin() + (i*numElementNodes), elementNodes.begin() + ((i + 1)*numElementNodes));
            if (!elementBlock->addElement(elementType, currentElementNodes, elementIds.empty() ? -1 : elementIds[i]))
            {
                return false;
            }
        }
    }

    elementBlock->setNodeBlockId(nodeBlockId);

    // Write the block
    // -------------------------------------------------------------------------
    if (!database->writeBlock(elementBlock.get()))
    {
        return false;
    }

    return true;
}


//--------------------------------------------------------------------------------------------------
// Writes the given geometry to the VTFx file
//--------------------------------------------------------------------------------------------------
bool writeGeometry(cee::vtfx::Database* database, const std::vector<int>& elementParts)
{
    cee::PtrRef<cee::vtfx::GeometryBlock> geoBlock = new cee::vtfx::GeometryBlock(1); // Only one geometry per state

    size_t geoIndex = 0;

    // Set the element data
    // -------------------------------------------------------------------------
    if (!geoBlock->setElementBlocks(geoIndex, elementParts, elementParts)) // There's one part for each element block. Use same id array for simplicity.
    {
        return false;
    }

    // Write the block
    // -------------------------------------------------------------------------
    if (!database->writeBlock(geoBlock.get()))
    {
        return false;
    }

    // Set info
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::GeometryInfoBlock> infoBlock = new cee::vtfx::GeometryInfoBlock(1); // Only one geometry per state
    for (size_t i = 0; i < elementParts.size(); i++)
    {
        infoBlock->addPartInfo(geoIndex, elementParts[i], cee::Str("Part %1").arg((int)i));
    }

    if (!database->writeBlock(infoBlock.get()))
    {
        return false;
    }

    return true;
}


//--------------------------------------------------------------------------------------------------
// Writes 1D/3D result values for one part to the file
//--------------------------------------------------------------------------------------------------
bool writeResult(int blockId, cee::vtfx::Database* database, const std::vector<float>& resultValues, int mapToBlock, cee::vtfx::Block::BlockType mapToBlockType, cee::vtfx::ResultValuesBlock::ResultValueDimension dimension)
{
    // Create the result values block
    cee::PtrRef<cee::vtfx::ResultValuesBlock> resultValuesBlock = new cee::vtfx::ResultValuesBlock(blockId, dimension, false);
    resultValuesBlock->setMapToBlockId(mapToBlock, mapToBlockType);

    // Set the result values
    // -------------------------------------------------------------------------
    if (allAtOnce)
    {
        // Alt 1: Set data directly
        if (!resultValuesBlock->setResultValues(resultValues))
        {
            return false;
        }
    }
    else
    {
        // Alt 2: Add each result value individually (using pre-allocation)
        if (dimension == cee::vtfx::ResultValuesBlock::SCALAR1D)
        {
            if (!resultValuesBlock->allocateResultValues(static_cast<int>(resultValues.size())))
            {
                return false;
            }

            for (size_t i = 0; i < resultValues.size(); i++)
            {
                resultValuesBlock->addResultValue1d(resultValues[i]);
            }
        }
        else // assuming dimension VECTOR3D
        {
            if (!resultValuesBlock->allocateResultValues(static_cast<int>(resultValues.size()) / 3))
            {
                return false;
            }

            for (size_t i = 0; i < resultValues.size() / 3; i++)
            {
                resultValuesBlock->addResultValue3d(resultValues[3 * i], resultValues[3 * i + 1], resultValues[3 * i + 2]);
            }
        }
    }

    // Write the block
    // -------------------------------------------------------------------------
    if (!database->writeBlock(resultValuesBlock.get()))
    {
        return false;
    }

    return true;
}


//--------------------------------------------------------------------------------------------------
// Creates case properties
//--------------------------------------------------------------------------------------------------
bool createProperties(cee::vtfx::Case* currentCase)
{
    cee::PtrRef<cee::PropertySetCollection> vtfxProps = new cee::PropertySetCollection;

    cee::PtrRef<cee::PropertySet> partSettings = new cee::PropertySet("part_settings");
    partSettings->setValue("context_geometry_index", static_cast<unsigned int>(0));
    partSettings->setValue("context_part_id", 1);
    partSettings->setValue("draw_style", "line");
    vtfxProps->addPropertySet(partSettings.get());

    cee::PtrRef<cee::PropertySet> scalarSelection = new cee::PropertySet("result_selection");
    scalarSelection->setValue("fringes_result_id", 1);
    vtfxProps->addPropertySet(scalarSelection.get());

    cee::PtrRef<cee::PropertySet> colorMapper = new cee::PropertySet("color_mapper_filled_contours_uniform");
    colorMapper->setValue("context_result_id", 1);
    colorMapper->setValue("range_min", 1.0);
    colorMapper->setValue("range_max", 5.0);
    vtfxProps->addPropertySet(colorMapper.get());

    cee::PtrRef<cee::PropertySet> vectorSelection = new cee::PropertySet("result_selection");
    std::vector<cee::Variant> vectorIds;
    vectorIds.push_back(1);
    vectorSelection->setValue("vector_result_ids", vectorIds);
    vtfxProps->addPropertySet(vectorSelection.get());

    cee::PtrRef<cee::PropertySet> vectorSettings = new cee::PropertySet("vector_settings");
    vectorSettings->setValue("context_result_id", 1);
    vectorSettings->setValue("color_mode", "color_by_fringes");
    vtfxProps->addPropertySet(vectorSettings.get());

    cee::PtrRef<cee::PropertySet> camera = new cee::PropertySet("camera");
    camera->setValue("eye", cee::Vec3d(2.0, -7.5, 1-0));
    camera->setValue("vrp", cee::Vec3d(2.0, -5.5, 1.0));
    camera->setValue("vup", cee::Vec3d(0.0, 0.0, 1.0));
    vtfxProps->addPropertySet(camera.get());

    // Write the block
    if (!currentCase->setProperties(vtfxProps.get()))
    {
        return false;
    }

    return true;
}



cee::PtrRef<cee::Instance>  g_componentInstance;

//--------------------------------------------------------------------------------------------------
// Main function, program entry point
//--------------------------------------------------------------------------------------------------
int main()
{
    // Initialize components and set up logging to console
    // -------------------------------------------------------------------------
    g_componentInstance = cee::CoreComponent::initialize(HOOPS_LICENSE);
    cee::vtfx::VTFxComponent::initialize(g_componentInstance.get());

    cee::PtrRef<cee::LogDestinationConsole> log = new cee::LogDestinationConsole();
    cee::CoreComponent::logManager()->setDestination(log.get());
    cee::CoreComponent::logManager()->setLevel("", 3);               // Log errors, warnings and info

    const cee::Str fileName = "Example1.vtfx";

    // Create the VTFx file
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::File> file = new cee::vtfx::File;

    // Create VTFx file settings struct
    // -------------------------------------------------------------------------
    cee::vtfx::FileSettings fileSettings;
    fileSettings.binary = true;
    fileSettings.compressionLevel = 5; // 0 to 9
    fileSettings.applicationName = "VTFx: VTFxExample";
    fileSettings.vendorName = "My Company AS";
    fileSettings.createDigitalSignature = false;

    // Let the API create the VTFx file 
    if (!file->create(fileName, fileSettings))
    {
        return EXIT_FAILURE;
    }

    // Create a single database (could have many)
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::Database> singleDatabase = new cee::vtfx::Database(file.get(), "Single Database", 1); // database id 1

    // Create a single case (could have many)
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::Case> singleCase = new cee::vtfx::Case(file.get(), "Single Case", 1, 1); // case ID 1 using database with id 1

    // Part 1
    // -------------------------------------------------------------------------
    // Write nodes
    std::vector<float> nodesPart1(NODES_PART_1, NODES_PART_1 + sizeof(NODES_PART_1) / sizeof(float));
    std::vector<int> nodesPart1Ids(NODES_PART_1_IDS, NODES_PART_1_IDS + sizeof(NODES_PART_1_IDS) / sizeof(int));
    if (!writeNodes(1, singleDatabase.get(), nodesPart1, nodesPart1Ids))
    {
        return EXIT_FAILURE;
    }

    // Write elements
    std::vector<int> connectsPart1(CONNECTS_PART_1, CONNECTS_PART_1 + sizeof(CONNECTS_PART_1) / sizeof(int));
    std::vector<int> elementPart1(ELEMENTS_PART_1_IDS, ELEMENTS_PART_1_IDS + sizeof(ELEMENTS_PART_1_IDS) / sizeof(int));
    if (!writeElements(1, singleDatabase.get(), connectsPart1, elementTypePart1, 1, elementPart1))
    {
        return EXIT_FAILURE;
    }
    
    // Part 2
    // -------------------------------------------------------------------------
    // Write nodes
    std::vector<float> nodesPart2(NODES_PART_2, NODES_PART_2 + sizeof(NODES_PART_2) / sizeof(float));
    std::vector<int> nodesPart2Ids(NODES_PART_2_IDS, NODES_PART_2_IDS + sizeof(NODES_PART_2_IDS) / sizeof(int));
    if (!writeNodes(2, singleDatabase.get(), nodesPart2, nodesPart2Ids))
    {
        return EXIT_FAILURE;
    }

    // Write elements
    std::vector<int> connectsPart2(CONNECTS_PART_2, CONNECTS_PART_2 + sizeof(CONNECTS_PART_2) / sizeof(int));
    std::vector<int> elementPart2(ELEMENTS_PART_2_IDS, ELEMENTS_PART_2_IDS + sizeof(ELEMENTS_PART_2_IDS) / sizeof(int));
    if (!writeElements(2, singleDatabase.get(), connectsPart2, elementTypePart2, 2, elementPart2))
    {
        return EXIT_FAILURE;
    }

    
    // Write Geometry definition
    // -------------------------------------------------------------------------
    std::vector<int> elementParts(ELEMENT_PARTS, ELEMENT_PARTS + sizeof(ELEMENT_PARTS) / sizeof(int));
    if (!writeGeometry(singleDatabase.get(), elementParts))
    {
        return EXIT_FAILURE;
    }

    // Write the scalar result values
    // -------------------------------------------------------------------------
    // Write result values for each part for each step (here 2 parts, 2 steps)
    std::vector<float> result1P1S1(RESULT1_P1_S1, RESULT1_P1_S1 + sizeof(RESULT1_P1_S1) / sizeof(int));
    if (!writeResult(1, singleDatabase.get(), result1P1S1, 1, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::SCALAR1D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result1P1S2(RESULT1_P1_S2, RESULT1_P1_S2 + sizeof(RESULT1_P1_S2) / sizeof(int));
    if (!writeResult(11, singleDatabase.get(), result1P1S2, 1, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::SCALAR1D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result1P2S1(RESULT1_P2_S1, RESULT1_P2_S1 + sizeof(RESULT1_P2_S1) / sizeof(int));
    if (!writeResult(2, singleDatabase.get(), result1P2S1, 2, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::SCALAR1D))
    {
        return EXIT_FAILURE;
    }
    
    std::vector<float> result1P2S2(RESULT1_P2_S2, RESULT1_P2_S2 + sizeof(RESULT1_P2_S2) / sizeof(int));
    if (!writeResult(12, singleDatabase.get(), result1P2S2, 2, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::SCALAR1D))
    {
        return EXIT_FAILURE;
    }

    // Write the scalar result definition
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::ResultBlock> scalarResult = new cee::vtfx::ResultBlock(1, cee::vtfx::ResultBlock::SCALAR, cee::vtfx::ResultBlock::NODE_MAPPING);
    if (!scalarResult->addResultValuesBlock(1, 1)  || // Assign the result values blocks to state IDs. Order is not significant.
        !scalarResult->addResultValuesBlock(11, 2) ||
        !scalarResult->addResultValuesBlock(2, 1)  ||
        !scalarResult->addResultValuesBlock(12, 2))
    {
        return EXIT_FAILURE;
    }

    scalarResult->setResultId(1);
    scalarResult->setName("My scalar result");
    scalarResult->setUnit("m^2");

    if (!singleDatabase->writeBlock(scalarResult.get()))
    {
        return EXIT_FAILURE;
    }

    // Write the vector result values
    // -------------------------------------------------------------------------
    // Write result values for each part for each step (here 2 parts, 2 steps)
    std::vector<float> result2P1S1(RESULT2_P1_S1, RESULT2_P1_S1 + sizeof(RESULT2_P1_S1) / sizeof(float));
    if (!writeResult(101, singleDatabase.get(), result2P1S1, 1, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result2P1S2(RESULT2_P1_S2, RESULT2_P1_S2 + sizeof(RESULT2_P1_S2) / sizeof(float));
    if (!writeResult(111, singleDatabase.get(), result2P1S2, 1, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result2P2S1(RESULT2_P2_S1, RESULT2_P2_S1 + sizeof(RESULT2_P2_S1) / sizeof(float));
    if (!writeResult(102, singleDatabase.get(), result2P2S1, 2, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result2P2S2(RESULT2_P2_S2, RESULT2_P2_S2 + sizeof(RESULT2_P2_S2) / sizeof(float));
    if (!writeResult(112, singleDatabase.get(), result2P2S2, 2, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    // Write the vector result definition
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::ResultBlock> vectorResult = new cee::vtfx::ResultBlock(2, cee::vtfx::ResultBlock::VECTOR, cee::vtfx::ResultBlock::NODE_MAPPING);
    if (!vectorResult->addResultValuesBlock(101, 1) || // Assign the result values blocks to state IDs. Order is not significant.
        !vectorResult->addResultValuesBlock(111, 2) ||
        !vectorResult->addResultValuesBlock(102, 1) ||
        !vectorResult->addResultValuesBlock(112, 2))
    {
        return EXIT_FAILURE;
    }
    vectorResult->setResultId(1);
    vectorResult->setName("My vector result");

    if (!singleDatabase->writeBlock(vectorResult.get()))
    {
        return EXIT_FAILURE;
    }

    
    // Write the Displacement result values
    // -------------------------------------------------------------------------
    // Write result values for each part for each step (here 2 parts, 2 steps)
    std::vector<float> result3P1S1(RESULT3_P1_S1, RESULT3_P1_S1 + sizeof(RESULT3_P1_S1) / sizeof(float));
    if (!writeResult(201, singleDatabase.get(), result3P1S1, 1, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result3P1S2(RESULT3_P1_S2, RESULT3_P1_S2 + sizeof(RESULT3_P1_S2) / sizeof(float));
    if (!writeResult(211, singleDatabase.get(), result3P1S2, 1, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result3P2S1(RESULT3_P2_S1, RESULT3_P2_S1 + sizeof(RESULT3_P2_S1) / sizeof(float));
    if (!writeResult(202, singleDatabase.get(), result3P2S1, 2, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    std::vector<float> result3P2S2(RESULT3_P2_S2, RESULT3_P2_S2 + sizeof(RESULT3_P2_S2) / sizeof(float));
    if (!writeResult(212, singleDatabase.get(), result3P2S2, 2, cee::vtfx::Block::NODES, cee::vtfx::ResultValuesBlock::VECTOR3D))
    {
        return EXIT_FAILURE;
    }

    // Write the displacement result definition
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::ResultBlock> displacementResult = new cee::vtfx::ResultBlock(3, cee::vtfx::ResultBlock::DISPLACEMENT, cee::vtfx::ResultBlock::NODE_MAPPING);
    if (!displacementResult->addResultValuesBlock(201, 1) || // Assign the result values blocks to state ids. Order is not significant.
        !displacementResult->addResultValuesBlock(211, 2) ||
        !displacementResult->addResultValuesBlock(202, 1) ||
        !displacementResult->addResultValuesBlock(212, 2))
    {
        return EXIT_FAILURE;
    }
    displacementResult->setResultId(1);
    displacementResult->setName("My displacement result");

    if (!singleDatabase->writeBlock(displacementResult.get()))
    {
        return EXIT_FAILURE;
    }
    

    // Write state information info (here we have two "steps" of a time series)
    // -------------------------------------------------------------------------
    cee::PtrRef<cee::vtfx::StateInfoBlock> stepInfo = new cee::vtfx::StateInfoBlock;

    if (!stepInfo->addStateInfo(1, "First step", 1.0f, cee::vtfx::StateInfoBlock::TIME) ||
        !stepInfo->addStateInfo(2, "Second and last step", 5.0f, cee::vtfx::StateInfoBlock::TIME))
    {
        return EXIT_FAILURE;
    }

    if (!singleDatabase->writeBlock(stepInfo.get()))
    {
        return EXIT_FAILURE;
    }

    // Create properties
    // -------------------------------------------------------------------------
    if (!createProperties(singleCase.get()))
    {
        return EXIT_FAILURE;
    }

    // Finally close the file
    // -------------------------------------------------------------------------
    if (!file->close())
    {
        return EXIT_FAILURE;
    }
    
    std::cout << "Exported successfully to file: " << fileName.toStdString() << std::endl;
    std::cout << std::endl << "Press enter to exit..." << std::endl;
    std::cin.ignore();

    return EXIT_SUCCESS;
}

Header file

// Part 1
// -----------------------------------------------------------------------------
// Nodes for part 1
const float NODES_PART_1[] =
{
    0.0f, 0.0f, 0.0f,
    1.0f, 0.0f, 0.0f,
    1.0f, 1.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 1.0f,
    1.0f, 0.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    0.0f, 1.0f, 1.0f,
    0.0f, 0.0f, 2.0f,
    1.0f, 0.0f, 2.0f,
    1.0f, 1.0f, 2.0f,
    0.0f, 1.0f, 2.0f
};

const int NODES_PART_1_IDS[] =
{
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
};


// Elements for part 1
const int CONNECTS_PART_1[] =
{
    0, 1, 2, 3, 4, 5, 6, 7,
    4, 5, 6, 7, 8, 9, 10, 11
};
const cee::vtfx::ElementBlock::ElementType elementTypePart1 = cee::vtfx::ElementBlock::HEXAHEDRONS;

const int ELEMENTS_PART_1_IDS[] =
{
    1, 2
};


// Part 2
// -----------------------------------------------------------------------------
// Nodes for part 2
const float NODES_PART_2[] =
{
    2.0f, 0.0f, 0.0f,
    3.0f, 0.0f, 0.0f,
    3.0f, 1.0f, 0.0f,
    2.0f, 1.0f, 0.0f,
    4.0f, 0.0f, 0.0f,
    4.0f, 1.0f, 0.0f
};

const int NODES_PART_2_IDS[] =
{
    101, 102, 103, 104, 105, 106
};


// Elements for part 2
const int CONNECTS_PART_2[] =
{
    0, 1, 2, 3,
    1, 4, 5, 2
};
const cee::vtfx::ElementBlock::ElementType elementTypePart2 = cee::vtfx::ElementBlock::QUADS;

const int ELEMENTS_PART_2_IDS[] = 
{
    3, 4
};


// Geometry definition
// -----------------------------------------------------------------------------
const int ELEMENT_PARTS[] =
{
    1, 2
};


// Time step 1 - Scalar Result 1
// -----------------------------------------------------------------------------
const float RESULT1_P1_S1[] =
{
    0.0,
    0.5,
    1.5,
    2.0,
    3.0,
    4.0,
    5.0,
    6.0,
    6.5,
    7.0,
    7.5,
    8.0
};
const float RESULT1_P2_S1[] =
{
    1.0,
    5.0,
    3.0,
    2.0,
    5.0,
    1.0
};



// Time step 2 - Scalar Result 1
// -----------------------------------------------------------------------------
const float RESULT1_P1_S2[] =
{
    8.1f,
    9.6f,
    5.8f,
    3.5f,
    7.4f,
    9.7f,
    2.7f,
    6.5f,
    3.2f,
    4.6f,
    3.7f,
    2.2f
};
const float RESULT1_P2_S2[] =
{
    1.5f,
    2.1f,
    4.5f,
    5.5f,
    2.1f,
    1.1f
};



// Time step 1 - Vector Result 1
// -----------------------------------------------------------------------------
const float RESULT2_P1_S1[] =
{
    0.0, 0.0, 0.0,
    1.0, 0.0, 0.0,
    1.0, 1.0, 0.0,
    0.0, 1.0, 0.0,
    0.0, 0.0, 1.0,
    1.0, 0.0, 1.0,
    1.0, 1.0, 1.0,
    0.0, 1.0, 1.0,
    0.0, 0.0, 2.0,
    1.0, 0.0, 2.0,
    1.0, 1.0, 2.0,
    0.0, 1.0, 2.0
};
const float RESULT2_P2_S1[] =
{
    2.0, 0.0, 0.0,
    3.0, 0.0, 0.0,
    3.0, 1.0, 0.0,
    2.0, 1.0, 0.0,
    4.0, 0.0, 0.0,
    4.0, 1.0, 0.0,
};


// Time step 2 - Vector Result 2
// -----------------------------------------------------------------------------
const float RESULT2_P1_S2[] =
{
    1.0, 8.0, 1.0,
    3.0, 2.0, 5.0,
    5.0, 8.0, 7.0,
    3.0, 4.0, 9.0,
    5.0, 2.0, 3.0,
    7.0, 1.0, 2.0,
    2.0, 7.0, 1.0,
    5.0, 6.0, 5.0,
    7.0, 5.0, 8.0,
    6.0, 4.0, 0.0,
    4.0, 2.0, 0.0,
    1.0, 2.0, 2.0
};
const float RESULT2_P2_S2[] =
{
    1.0, 4.0, 2.0,
    6.0, 8.0, 5.0,
    8.0, 7.0, 7.0,
    3.0, 3.0, 8.0,
    7.0, 5.0, 2.0,
    3.0, 3.0, 1.0,
};


// Time step 1 - Displacement Result 1
// -----------------------------------------------------------------------------
const float RESULT3_P1_S1[] =
{
    0.0f, 0.0f, 0.0f,
    1.0f, 0.0f, 0.0f,
    1.0f, 1.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 1.0f,
    1.0f, 0.0f, 1.0f,
    1.0f, 1.0f, 1.0f,
    0.0f, 1.0f, 1.0f,
    0.0f, 0.0f, 2.0f,
    1.0f, 0.0f, 2.0f,
    1.0f, 1.0f, 2.0f,
    0.0f, 1.0f, 2.0f
};
const float RESULT3_P2_S1[] =
{
    2.0, 0.0, 0.0,
    3.0, 0.0, 0.0,
    3.0, 1.0, 0.0,
    2.0, 1.0, 0.0,
    4.0, 0.0, 0.0,
    4.0, 1.0, 0.0,
};

// Time step 2 - Displacement Result 1
// -----------------------------------------------------------------------------
const float RESULT3_P1_S2[] =
{
    0.0f, 0.0f, 0.0f,
    1.5f, 0.0f, 0.0f,
    1.5f, 1.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 1.0f,
    1.5f, 0.0f, 1.0f,
    1.5f, 1.0f, 1.0f,
    0.0f, 1.0f, 1.0f,
    0.0f, 0.0f, 2.0f,
    1.5f, 0.0f, 2.0f,
    1.5f, 1.0f, 2.0f,
    0.0f, 1.0f, 2.0f
};
const float RESULT3_P2_S2[] =
{
    2.0, 0.0, 0.0,
    3.0, 0.0, 0.0,
    3.0, 1.0, 0.0,
    2.0, 1.0, 0.0,
    4.0, 0.0, 0.5,
    4.0, 1.0, 0.5,
};