# CPU implementation

This function is called for each integration point during each time step of the simulation on the CPU. It defines the behavior of the material, such as its constitutive response, failure criteria, and post-failure behavior.

## `runMat()`

    void runMat(UserMatCPU data) const

#### `data`

- Type: UserMatCPU
- Description: User material data structure. See UserMatCPU for more information on the data structure.

## Example

    void MatRubber::runMat(UserMatCPU data) const
    {
        // Load material parameters
        double C1   = data.p_cmat[6];
        double C2   = data.p_cmat[7];
        double bulk = data.p_cmat[43];

        double fmat[9], c[6], eval[3];

        // Load deformation gradient matrix
        for (int i = 0; i < 9; ++i) {
            fmat[i] = data.p_f_mat[i];
        }

        // Volumetric strain and pressure
        double evol = data.p_strain[0] + data.p_strain[1] + data.p_strain[2];
        double pressure = -bulk * evol;

        mat::cauchy_green_tensor(fmat, c);

        // Re-using fmat array as eigen vector array since fmat array is no longer needed
        double* evec = fmat;

        // Get principal stretches (squared)
        mat::calc_eigen_values(c, eval);
        mat::calc_eigen_vectors(c, eval, evec);

        double alpha = 2.0 * C1 * (eval[0] - eval[2]) - 2.0 * C2 * (1.0 / eval[0] - 1.0 / eval[2]);
        double beta = 2.0 * C1 * (eval[1] - eval[2]) - 2.0 * C2 * (1.0 / eval[1] - 1.0 / eval[2]);

        eval[0] = (2.0 * alpha - 1.0 * beta) / 3.0 - pressure;
        eval[1] = (-1.0 * alpha + 2.0 * beta) / 3.0 - pressure;
        eval[2] = (-1.0 * alpha - 1.0 * beta) / 3.0 - pressure;

        // Re-using c array as local stress array since c array is not longer needed
        double* stress = c;
        for (int i = 0; i < 6; ++i) {
            stress[i] = 0.0;
        }

        for (int i = 0; i < 3; ++i) {
            int vector_offset = i * 3;
            stress[0] += eval[i] * pow(evec[vector_offset + 0], 2);
            stress[1] += eval[i] * pow(evec[vector_offset + 1], 2);
            stress[2] += eval[i] * pow(evec[vector_offset + 2], 2);
            stress[3] += eval[i] * evec[vector_offset + 0] * evec[vector_offset + 1];
            stress[4] += eval[i] * evec[vector_offset + 1] * evec[vector_offset + 2];
            stress[5] += eval[i] * evec[vector_offset + 2] * evec[vector_offset + 0];
        }

        // Save eigen values for contour plot output
        for (int i = 0; i < 3; ++i) {
            data.p_history[i] = eval[i];
        }

        // Save new stress
        for (int i = 0; i < 6; ++i) {
            data.p_stress[i] = stress[i];
        }
    }