This page describes the mtest module

The MaterialProperty class

Description

The MaterialProperty class handles a material property.

This class has the following core interface:

As described in the next paragraph, several convenient methods and operators are also provided to simplify the usage of this class.

Usage

Here is an example of the usage of the MaterialProperty class.

import mtest
young_modulus = mtest.MaterialProperty(
    'src/libCastemVanadium.so', 'VanadiumAlloy_YoungModulus_SRMA')

Note that the MaterialProperty constructor automatically detects the interface used to generate the material property and instantiates the proper concrete implementation internally. In this case, an instance of the CastemMaterialProperty class is instanciated.

The arguments of the material property can then be set and the material property can be evaluated:

young_modulus.setVariableValue('Temperature', 562)
E = young_modulus.getValue()

Setting the variables’ values and evaluating the material property can be tedious. To avoid this, overloaded versions of the getValue are available:

# using a dictionary
E = young_modulus.getValue({'Temperature': 562})
# for material properties with only one argument
E = young_modulus.getValue(562)

To make the code even more explicit, the call operator can also be used, as follows:

# using a dictionary
E = young_modulus({'Temperature': 562})
# for material properties with only one argument
E = young_modulus(562)

The Behaviour class

Rationale

The Behaviour class retrieves information in a shared library about a behaviour specific implementation.

Contrary the tfel.system.ExternalBehaviourDescription class, the information given by the Behaviour class takes into account the variables that are implicitly declared by the interface to match its specific (internal) requirements.

For example, if a behaviour requires the stiffness tensor to be given by the calling code (see the @RequireStiffnessTensor MFront’ keyword for details), additional material properties are provided to the behaviour. The number of those additional material properties may depend on the modelling hypothesis (mostly for orthotropic behaviours): the calling code generally only not provides the minimal number of material properties needed, in order to reduce the cost of handling those extra material properties.

One can give some other examples:

Usage

import mtest
b = mtest.Behaviour('aster','libAsterBehaviour.so','asterplasticity','PlaneStrain')

Methods available

The following methods are available:

The MTest class

Here is a first example of the MTest class usage:

import tfel.tests
from mtest import *

m = MTest()

umax = 3.e-6

setVerboseMode(VerboseLevel.VERBOSE_LEVEL2)
m.setPredictionPolicy(PredictionPolicy.LINEARPREDICTION)

m.setBehaviour("umat","src/libUmatBehaviour.so","umattvergaard")
m.setMaterialProperty('NormalStiffness',2.e16)
m.setMaterialProperty('TangentialStiffness',2.e16)
m.setMaterialProperty('MassDensity',0.)
m.setMaterialProperty('NormalThermalExpansion',0.)
m.setMaterialProperty('MaximumStress',200.e6)
m.setMaterialProperty('MaximumOpeningDisplacement',3.e-6)

m.setExternalStateVariable("Temperature",293.15)
m.setImposedOpeningDisplacement('Un',{0.:0.,1800.:umax/2,
                      2400.:0.,2600:-1.e-8,3000:0.,
                      3600.:umax})

m.setTimes([3.6*i for i in range(0,1001)])
m.setOutputFileName("castemtvergaard.res")
m.execute()

This example shows that there is almost a one to one mapping between the keywords used in mtest input file and the methods of the MTest class.

The last instruction will execute all the time steps defined the time discretization defined using the setTimes method.

This is not convenient and the mtest module allows you to precisely define and manage how the computations are performed.

The three last line are indeed equivalent to:

s  = MTestCurrentState()
wk = MTestWorkSpace()

m.setOutputFileName("castemtvergaard.res")
m.completeInitialisation()
m.initializeCurrentState(s)
m.initializeWorkSpace(wk)

t = [3.6*i for i in range(0,1001)]
# values at 0
m.printOutput(t[0],s)

# do the job
for i in range(0,len(t)-1):
    m.setEvolutionValue('Un',t[i+1],umax*t[i+1]/t[-1])
    m.execute(s,wk,t[i],t[i+1])
    m.printOutput(t[i+1],s)

The previous example introduces two classes: the MTestWorkSpace class and the MTestCurrentState class.

The MTestWorkSpace is of no interest for the end-user. It only manages to memory allocated to perform the computation: this memory is allocated once when calling the initializeWorkSpace of the MTest class.

The MTestCurrentState class will be discussed in depth in the next section.

The MTestCurrentState class

The MTestCurrentState is a wrapper class around the StudyCurrentState class discussed later.

It has been introduced for backward compatibility with previous versions of TFEL and have a simpler interface for studies handled by the MTest class (one structure, one integration point..).

This structure contains the state of the (unique) integration point at the beginning and at the end of the time step.

Fields of the MTestCurrentState class

The MTestCurrentState class provides the following fields:

The meaning of the driving variables depends on the type of behaviour treated:

The meaning of the thermodynamic forces also depends on the type of behaviour treated:

Methods of the MTestCurrentState class

The MTestCurrentState class provide the copy method to get a deep copy of the structure. It is mandatory to use such a copy in some advanced usage of the MTest class. This includes the following cases:

The MTestCurrentState also provides getInternalStateVariableValue and setInternalStateVariableValue methods, which are described more in depth below.

The PipeTest class

Here is an example:

import tfel.tests
from mtest import PipeTest,StudyCurrentState,SolverWorkSpace, \
    setVerboseMode, VerboseLevel

setVerboseMode(VerboseLevel.VERBOSE_QUIET)

t = PipeTest()
# geometry and meshing
t.setInnerRadius(4.2e-3)
t.setOuterRadius(4.7e-3)
t.setNumberOfElements(10)
t.setElementType('Linear')

# modelling hypothesis
t.setAxialLoading('None')
t.performSmallStrainAnalysis()

t.setTimes([0,1])
t.setInnerPressureEvolution(1.5e6)
t.setOuterPressureEvolution({0:1.5e6,1:10e6})

t.setBehaviour('castem','../../src/libUmatBehaviour.so','umatelasticity')
t.setMaterialProperty('YoungModulus',150e9)
t.setMaterialProperty('PoissonRatio',0.3)
t.setExternalStateVariable('Temperature',293.15)

t.setOutputFileName("pipe.res")

t.execute()

The StudyCurrentState, StructureCurrentState and CurrentState classes

The StudyCurrentState class

As with the MTest class, the user can have precise control of how the computations are performed. The last instruction of the previous example can be changed by the following code:

s  = StudyCurrentState()
wk = SolverWorkSpace()

t.completeInitialisation()
t.initializeCurrentState(s)
t.initializeWorkSpace(wk)

# values at 0
t.printOutput(0,s)
# resolution from 0 to 1
t.execute(s,wk,0.,1.)
# values at 1
t.printOutput(1.,s)

This code introduces two new classes: SolverWorkSpace and StudyCurrentState. Only the latter is interesting for the end user.

The StudyCurrentState has been designed to encapsulate all the test cases handled by MTest, in the current and future versions of TFEL.

The StudyCurrentState provides the following fields:

Some of those fields are the same than those described earlier when discussing the MTestCurrentState class. Indeed, the MTestCurrentState is just a wrapper around the StudyCurrentState.

In the case of pipes, the unknowns are the radial displacements of the nodes of the pipe mesh and the axial displacement. There are no Lagrange multipliers.

The StructureCurrentState class

A study may contains one or several structures. The current state of those structures are handled by the StructureCurrentState class which can be retrieved from a StudyCurrentState object using the getStructureCurrentState method. This latter method takes the name of the structure as argument.

In the case of pipes, only one unnamed structure is defined (See the example below).

The StructureCurrentState has mostly one field: istates which contains CurrentState objects describing each integration points.

For a pipe, integration points in the istates array are ordered using their position from the closest to the inner radius of the pipe to the closest to the outer radius of the pipe.

The CurrentState class

The CurrentState class contains the values at integration points. It contains the following fields:

Those fields are the same than those of the MTestCurrentState which indeed acts as a proxy for the unique integration point it handles.

Here is an example of use of the StudyCurrentState class:

# get the structure current state
scs = s.getStructureCurrentState("")
# iterate of over the integration points
for cs in scs.istates:
    #print the radial stress, the axial stress, the hoop stress
    print(str(cs.s1[0])+" "+str(cs.s1[1])+" "+str(cs .s1[1]))

Accessing the values of the internal state variables

The internal state variables are stored in the iv_1, iv0 and iv1 fields. Beware that access to those fields creates a copy of the underlying array of values.

The CurrentState also provides a method called getInternalStateVariableValue which has two overloads.

The first one takes the name of a variable and returns its value at the end of the time step.

The second one has one more argument: the depth of the values to be accessed:

Initial values of the internal state variables

The initial values of the internal state variables can be specified by the setInternalStateVariableInitialValue method of the MTest or PipeTest class. This method takes the name of internal state variable and a list of floats (a float is accepted for scalar internal state variables).

The values are stored in the MTest or PipeTest object and will be used every time the initializeCurrentState method is called.

Here is an example of use of the getInternalStateVariableValue method:

scs = s.getStructureCurrentState("")
# get the maximum of the equivalent plastic strain over the integration points
p = max([cs.getInternalStateVariableValue('EquivalentPlasticStrain') for cs in scs.istates])

Modifying the values of the internal state variables

Sometimes, it can be useful to modify the values of the internal state variables during the computation. This can

The internal state variables are stored in the iv_1, iv0 and iv1 fields. Access to those variables creates a copy of the underlying array of values. Thus, modifying those values has no effect of the CurrentState object.

To modify the values of a CurrentState, one may of the two overloads of the setInternalStateVariableValue method:

Here is an example of use of the setInternalStateVariableValue method:

scs = s.getStructureCurrentState("")
# iterate of over the integration points
for cs in scs.istates:
    # set the value of the equivalent plastic strain
    cs.setInternalStateVariableValue('EquivalentPlasticStrain',2.e-2)

Example of use of the PipeTest class

from mtest import PipeTest,StudyCurrentState,SolverWorkSpace, \
    setVerboseMode, VerboseLevel

# no output
setVerboseMode(VerboseLevel.VERBOSE_QUIET)

Re = 4.18e-3
Fz = 3.1415926*Re*Re*20e6

t = PipeTest()

# geometric and meshing options
t.setInnerRadius(0)
t.setOuterRadius(Re)
t.setNumberOfElements(1)
t.setElementType('Quadratic')

# Type of loading
t.setAxialLoading('ImposedAxialForce')

# no geometrical update
t.performSmallStrainAnalysis()

# by default, with the 'castem' interface, one does not use the
# consistent tangent operator. Using the acceleration algorithm
# is mandatory for convergence.
t.setUseCastemAccelerationAlgorithm(True)

# axial loading
t.setAxialForceEvolution({0.:0.,1.e-6 :Fz,3600:Fz})

# definition of the mechanical behaviour and the material properties
t.setBehaviour('castem','../../src/libUmatBehaviour.so','umatnorton')
t.setMaterialProperty('YoungModulus',150e9)
t.setMaterialProperty('PoissonRatio',0.3)
t.setMaterialProperty('A',8.e-67)
t.setMaterialProperty('E',8.2)

# temperature (mandatory)
t.setExternalStateVariable('Temperature',293.15)

# results file
t.setOutputFileName('pipe4.res')

s  = StudyCurrentState()
wk = SolverWorkSpace()

# complete initialisation of the problem
t.completeInitialisation()
t.initializeCurrentState(s)
t.initializeWorkSpace(wk)

# time discretization
times = [0]+[1.e-6+((3600.-1.e-6)/20.)*i for i in range(21)];

# get the state of the pipe (unique structure defined)
scs = s.getStructureCurrentState("")
p   = max([cs.getInternalStateVariableValue("EquivalentViscoplasticStrain")
           for cs in scs.istates])
print(str(times[0])+" "+str(p))

# loop over the time steps
for i in range(0,len(times)-1):
    # search the mechanical equilibrium at the end of the time step
    t.execute(s,wk,times[i],times[i+1])
    # write in the output file
    t.printOutput(times[i+1],s)
    # iterate of over the integration points
    p = max([cs.getInternalStateVariableValue("EquivalentViscoplasticStrain")
             for cs in scs.istates])
    print(str(times[i+1])+" "+str(p))

References

1.
Helfer, Thomas. Extension of monodimensional fuel performance codes to finite strain analysis using a Lagrangian logarithmic strain framework. Nuclear Engineering and Design. July 2015. Vol. 288, p. 75–81. DOI 10.1016/j.nucengdes.2015.02.010. Available from: http://www.sciencedirect.com/science/article/pii/S0029549315000928