How To: Simulation Results & Queries

  • Create a QueryResult object that specifies the domain to be sampled. It takes a single component or an assembly as input

    Intact::Assembly assembly = {component_1, component_2};
    
    Intact::QueryResult results(component_1); // sample only the defined component
    Intact::QueryResult results(assembly); // sample on the full assembly
    
  • Specify a query class and type that defines what quantity you are querying. The query classes and types available are as follows :

    • Global Query is for querying quantities defined for the entire domain/structure.

      • For Modal Simulation, the only GlobalQueryType is Frequency.

      • For Linear Buckling Simulation, the only GlobalQueryType is CriticalLoadFactor, which when multiplied by the applied load provides an estimate of the maximum load that the structure can withstand before failing due to buckling.

      • For Stress Simulation, the following GlobalQueryType queries are available:

        • Compliance is a single value.

        • TotalReactionForce is a tuple of dimension 3, representing the total reaction force.

          [Fx, Fy, Fz]
          
        • ReactionForce is a tuple of dimension 3 for each restrained boundary, in the order the boundary conditions were added to the LinearElasticScenarioDescriptor.

          [Fx, Fy, Fz]
          
        • TotalReactionMoment is 3 tuples of dimension 3, representing the moments about the origin generated by reaction forces. Using [r1, r2, r3] to represent the vector from the origin to the reaction force, and using [Fx, Fy, Fz] to represent the reaction force, the moments are:

          [0, r2 * Fx, r3 * Fx]
          [r1 * Fy, 0, r3 * Fy]
          [r1 * Fz, r2 * Fz, 0]
          
        • TotalAppliedForce is a tuple of dimension 3, representing the total applied load.

          [Fx, Fy, Fz]
          
        • TotalAppliedMoment is 3 tuples of dimension 3, representing the moments about the origin generated by the applied loads. Using [r1, r2, r3] to represent the vector from the origin to the applied load, and using [Fx, Fy, Fz] to represent the applied load, the moments are:

          [0, r2 * Fx, r3 * Fx]
          [r1 * Fy, 0, r3 * Fy]
          [r1 * Fz, r2 * Fz, 0]
          
    // GlobalQuery example
    // Create a GlobalQuery to query the first mode of a modal simulation
    Intact::QueryResult results(assembly);
    Intact::GlobalQuery frequency_query(Intact::GlobalQueryType::Frequency, Intact::DiscreteIndex(0));
    
    // Sample the simulation for the specified query
    auto freq_1 = simulator.sample(frequency_query, results);
    std::cout << freq_1.get(0, 0) << std::endl; // Print out the first mode in Hz
    
    // Example use to get all the modes
    // Note, the simulator would need this:
    // modal_scenario.modal_metadata.desired_eigenvalues = 10
    
    for (auto i = 0; i < modal_scenario.metadata.desired_eigenvalues; i++) {
        // Create the query for the current mode
        Intact::GlobalQuery query(Intact::GlobalQueryType::Frequency, Intact::DiscreteIndex(i));
    
        // Sample the query using the simulator
        auto r = simulator.sample(query, results);
    
        std::cout << r.get(0, 0) << std::endl;
    }
    
    • Field Query is for querying field quantities defined at any point in the domain. This depends on the physics type.

      • For Stress Simulation, the following FieldType inputs are available

        • Displacement tuple of dimension 3 for each point

          [x-displacement, y-displacement, z-displacement]
          
        • Strain and Stress are each a tuple of dimension 6 for each point

          [stress_xx, stress_yy, stress_zz, stress_yz, stress_xz, stress_xy]
          [strain_xx, strain_yy, strain_zz, strain_yz, strain_xz, strain_xy]
          
        • TopologicalSensitivity, StrainEnergyDensity, and VonMisesStress are each a tuple of dimension 1 for each point

      • Field Query Interface usage

        // FieldQuery example
        // Create a FieldQuery to query displacement
        Intact::QueryResult results(assembly);
        Intact::FieldQuery displacement_query(Intact::FieldType::Displacement);
        
        // Create a FieldQuery with optional input to query the y-component
        Intact::FieldQuery y_displacement_query(Intact::FieldType::Displacement, 1);
        
        // FieldQuery with optional input to query the norm of displacement
        Intact::FieldQuery displacement_magnitude_query(Intact::FieldType::Displacement, true);
        
        // Sample the simulation with the given query to create a VectorArray
        // * more info on VectorArrays are provided in the subsequent section *
        auto displacement_VectorArray1 = simulator.sample(displacement_query, results);
        auto displacement_VectorArray2 = simulator.sample(y_displacement_query, results);
        auto displacement_VectorArray3 = simulator.sample(displacement_magnitude_query, results);
        
        auto displacement1 = displacement_VectorArray1.get(i, j); // jth component of the displacement (0 = X, 1 = Y, or 2 = Z) at the ith sampling point
        auto displacement2 = displacement_VectorArray2.get(1, 0); // y-displacement value at the second sampling point
        auto displacement3 = displacement_VectorArray3.get(1, 0); // displacement magnitude at the second sampling point
        
    • For Modal Simulation, the only FieldType available is Displacement, which corresponds to the mode shape information and requires an index for the specified mode.

      // Create a field query for the displacement/mode shape of mode 1
      auto mode_num = 0; // first mode
      Intact::FieldQuery modal_field_query(Intact::Field::Displacement, Intact::DiscreteIndex(mode_num))
      
    • For Linear Buckling Simulation, the only FieldType available is Displacement, which corresponds to the mode shape information and requires an index for the specified mode.

      // Create a field query for the displacement/mode shape of mode 1
      auto mode_num = 0; // first mode
      Intact::FieldQuery buckling_field_query(Intact::Field::Displacement, Intact::DiscreteIndex(mode_num))
      

Sample and Export Results

  • Sampling results in-memory

    • Methods to sample results of the simulation and store/print VectorArray results from the queries created above.

      // Query results
      Intact::QueryResult results(assembly);
      Intact::FieldQuery stress_query(Intact::FieldType::Stress); // a field is needed to create a field query
      auto stress_VectorArray = simulator.sample(stress_query, results);
      
    • This sampling is stored in a VectorArray of size n_tuple by dimension, n_tuple is the number of points sampled in the component/assembly and dimension depends on the query type. For example, FieldQuery(Intact::FieldType::Displacement) has a dimension of 3 for each displacement component, thus VectorArray.get(i, 2) would get the z-displacement of point i.

      // Get the number of tuples (vectors) in the VectorArray (one per point results are sampled at)
      auto n_tuples = stress_VectorArray.n_tuples();
      
      // Get the dimension of each vector - in this case 6, one value for each stress component
      auto dimension = stress_VectorArray.dimension();
      
      auto stress_xx = stress_VectorArray.get(i, 0); // stress_xx at i-th sample point
      auto stress_yy = stress_VectorArray.get(i, 1); // stress_yy at i-th sample point
      auto stress_ij = stress_VectorArray.get(i, j); // jth stress component (0, 1, 2, 3, 4, or 5) of the ith tuple
      
  • Export results to a file: Once the query is created, results can be used to write a file which contains all solution fields in VTK UnstructuredGrid format via the results.writeVTK method which has two inputs:

    • file name "*.vtu"

    • UnitSystem is an attribute in the *.vtu ( Note that this argument is just metadata in the *.vtu file. The result magnitudes are in the unit of the scenario regardless of the unit system specified. )

    // Write results to a file (unit system is saved as a metadata in the vtu file)
    Intact::QueryResult results(assembly);
    Intact::FieldQuery stress_query(Intact::FieldType::VonMisesStress);
    simulator.sample(stress_query, results);
    
    // Write results to a file (unit system is saved as a metadata in the vtu file)
    results.writeVTK("cantilever_beam_results.vtu", Intact::UnitSystem::MeterKilogramSecond);
    

Sampling on Custom Geometries

  • Another important functionality is the ability to specify a point set to sample on. This can be done by creating a new sampling_component consisting of vertices at the desired sampling locations. Note that the sampling_component is not to be included in the assembly that is being simulated.

    // Create an empty MeshModel to store vertices for desired sampling locations
    auto sampling_geometry = Intact::MeshModel();
    
    // Add the desired sampling point locations and store their ID for later use
    auto test_index1 = sampling_geometry.addVertex({6.0, 0.0, 0.0});
    auto test_index2 = sampling_geometry.addVertex({3.0, 0.0, 0.0});
    
    auto sampling_component = Intact::MaterialDomain(sample_geometry, "material_name", scenario);
    
    // Define the assembly to be simulated (note that the sampling_component is not included)
    auto component = Intact::MaterialDomain(component_geometry, "material_name", scenario);
    Intact::Assembly assembly = {component};
    Intact::StressSimulator simulator(assembly, scenario);
    simulator.solve();
    
    Intact::FieldQuery displacement_query(Intact::Field::Displacement);
    Intact::QueryResult sampled_results(sampling_component) // sample only the custom point set
    auto sampled_VectorArray = simulator.sample(displacement_query, sampled_results);
    
    auto displacement_index1 = sampled_VectorArray.get(test_index1, 0); // x-displacement at above specified index1
    auto displacement_index2 = sampled_VectorArray.get(test_index2, 1); // y-displacement at above specified index2