Skip to content

Basic Usages

First look at the Model class

The primary usage of this project is to use the Model class:

from micromechanical import Model

model = Model("ChangHicher-OSIMSAND")

Where ChangHicher-OSIMSAND is the type of the model separated by the type of the micromechanical model (ChangHicher) and the contact law (OSIMSAND). To check the available micromechanical models and contact laws, use the backends object:

>>> from micromechanical import backends
>>> backends.current.models.keys()
dict_keys(['ChangHicher'])
>>> backends.current.contacts.keys()
dict_keys(['Elastic', 'Coulomb', 'Hyperbolic', 'Exponential', 'Hypoplastic', 'MCC', 'OSIMSAND', 'SANISAND', 'SIMSAND'])

Note

The CH model is an alias for the ChangHicher model.

The Model class manages everything for the micromechanical simulation, it contains the following attributes and methods:

classDiagram
    note for ModelBase "Base class"
    class ModelBase {
        MicromechanicalBase model
        dict experiments
        setParameters()
        run()

        availableDatasets()
        readExperiments()
        loadExperiments()
        saveExperiments()
        iterateExperiments()
        simulateExperiments()
    }

    note for ContactModel "Setting up contact law"
    ContactModel <|-- ModelBase
    class ContactModel {
        setPlasticMethod()
    }

    note for IntegrationModel "Setting up integration points"
    IntegrationModel <|-- ModelBase
    class IntegrationModel {
        setIntegrationParameters()
        setAnisotropicParameters()
    }

    note for MaterialModel "Setting up material properties"
    MaterialModel <|-- ModelBase
    class MaterialModel {
        setMaterialAnisotropicParameters()
    }

    note for LoadModel "Setting up load phases"
    LoadModel <|-- ModelBase
    class LoadModel {
        addLoadPhase()
        addIsotropicPhase()
        addDrainedTriaxialPhase()
        addUndrainedTriaxialPhase()
        addConfinementPhase()
    }

    note for IOModel "Import and export models"
    IOModel <|-- ContactModel
    IOModel <|-- IntegrationModel
    IOModel <|-- MaterialModel
    IOModel <|-- LoadModel
    class IOModel {
        ModelIO io
    }

    note for CalibrationModel "Calibrate experiments"
    CalibrationModel <|-- IOModel
    class CalibrationModel {
        fitness()
        calibrate()
    }

    note for VisualizationModel "Visualize experiments"
    VisualizationModel <|-- CalibrationModel
    class VisualizationModel {
        plot()
        macroplot()
        microplot()
        microplots()
        scatter()
        fabricplot()
    }

    note for Model "Top-level class"
    Model <|-- VisualizationModel

Setting up the micromechanical model

The micromechanical model is set up by the Model class, which is the top-level class for the micromechanical simulation. The Model class is a subclass of

Setting up the contact law

The following diagram shows the contact-law-related methods:

classDiagram
    class ContactModel {
        setPlasticMethod()
    }

You can set up the plastic method used for the elastoplastic contact law by the setPlasticMethod() method:

model.setPlasticMethod("CPA")  # Explicit, CPA, CPPM

Setting up the integration points

The following diagram shows the integration-related methods:

classDiagram
    class IntegrationModel {
        setIntegrationParameters()
        setAnisotropicParameters()
    }

You can set up the npv (number of contacts per volume, in m^3) and radius (radius of the particles, in m) by the setIntegrationParameters() method:

model.setIntegrationParameters(npv=1e9, radius=0.65e-3)

If the material is anisotropic, you can set up the anisotropic parameter by the setAnisotropicParameters() method:

model.setAnisotropicParameters(type="chang1990", evolution="wan2004", a20=0.0, a22=0.0, b22=0.0, chi=0.0)

Setting up the material properties

The following diagram shows the material-related methods:

classDiagram
    class ModelBase {
        setParameters()
    }
    class MaterialModel {
        setMaterialAnisotropicParameters()
    }

You can set up the material properties by the above contact-law-specific methods to set up the material properties, for example:

model.setCoulombParameters(kt0=32.0, R=2.5, phi=30.0)

For a list of parameters required for each contact law, use the requiredParameters() method:

>>> model.requiredParameters("ChangHicher", "Coulomb")
['kt0', 'R', 'phi']

All the above contact-law-specific methods are wrappers of the setParameters() method, which can be used to set up the material properties directly.

You can also use the setMaterialAnisotropicParameters() method to set up the material anisotropic parameters similar to the integration points:

model.setMaterialAnisotropicParameters("phi", type="chang1990", evolution="wan2004", a20=0.0, a22=0.0, b22=0.0, chi=0.0)

Setting up the load phases

The following diagram shows the load-related methods:

classDiagram
    class LoadModel {
        addLoadPhase()
        addIsotropicPhase()
        addDrainedTriaxialPhase()
        addUndrainedTriaxialPhase()
        addConfinementPhase()
    }

You can set up the load phases by the above methods, for example:

model.addIsotropicPhase(sigc=-100.0, steps=100)
model.addDrainedTriaxialPhase(sigc=-100.0, epsa_max=-0.3, steps=100)

The above code will add two load phases, the first one is an isotropic compression phase with a constant confining pressure of 100.0 kPa, the second one is a drained triaxial compression phase with a constant confining pressure of 100.0 kPa and a maximum axial strain of 30%.

If the predefined load phases are not enough, you can use the addLoadPhase() method to add a custom load phase:

import numpy as np
from micromechanical import backends

phase = backends.current.LoadPhase(
    initial=np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0]),
    final=np.array([-100.0, -100.0, -100.0, 0.0, 0.0, 0.0]),
    control=np.array([0.0, 0.0, 0.0, 1.0, 1.0, 1.0]),  # 0 for stress control, 1 for strain control
    total=np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0]),  # 0 for incremental stress/strain, 1 for total stress/strain
    steps=100,
)
model.addLoadPhase(phase)

The above code will create an isotropic compression load phase with a constant confining pressure of 100.0 kPa. For multiple load phases, you must make sure that the final state of the previous load phase is the same as the initial state of the next load phase when the control types are the same.

Reading and saving experiments

The following diagram shows the experiment-related methods:

classDiagram
    class ModelBase {
        availableDatasets()
        readExperiments()
        loadExperiments()
        saveExperiments()
        iterateExperiments()
    }

You can read the experiments from a JSON file by the readExperiments() method:

model.readExperiments("path/to/experiments.json")

You must make sure the JSON file represents a dictionary of the Experiment-like objects.

If the file path does not exist, built-in experiments will be searched and loaded, you can check the available experiments by the availableDatasets() method:

>>> model.availableDatasets()
['FC']

Simulation, calibration, and visualization

After setting up the micromechanical model, you can simulate, calibrate, and visualize the experiments.

Simulation

The following diagram shows the simulation-related methods:

classDiagram
    class ModelBase {
        run()
    }

    class ModelBase {
        simulateExperiments()
    }

After setting up everything above, you can use the run() method to run the simulation:

sv = model.run()

The returned value is a SVExporter object, which contains the simulation results. For more information about the usage of the SVExporter object, see SVExporter.

Alternatively, You can simulate the experiments with the experiments' configurations by the simulateExperiments() method:

svs = model.simulateExperiments()

A SVExporter object or a dictionary of SVExporter objects will be returned (if there are multiple experiments), which can be used for post-processing and visualization.

Calibration

The following diagram shows the calibration-related methods:

classDiagram
    class CalibrationModel {
        fitness()
        calibrate()
    }

You can calibrate the experiments by the calibrate() method:

parameters, result = model.calibrate(includes=["phi"])

The above code will calibrate the experiments with the phi parameter included, the parameters is a dictionary of the calibrated parameters, the result is a dictionary of the calibration results.

Visualization

The following diagram shows the visualization-related methods:

classDiagram
    class VisualizationModel {
        plot()
        macroplot()
        microplot()
        scatter()
        fabricplot()
    }

You can visualize the simulation by the macroplot() method:

fig = model.macroplot()

The above code will run the simulation first using the run() method if the simulation with the same configuration has not been run before and cached, then plot the simulation results. You can also specify the data parameter to plot the simulation results from a previously run simulation. The above code will return a matplotlib figure object, which can be used for further customization. See the description of other methods for more information.