Skip to content

Isotropic Plane Strain

Bases: ConstitutiveModel

A constitutive model for the 2D isotropic plane strain equations

Inherits

ConstitutiveModel : type The base class for FEMpy constitutive models

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
class IsoPlaneStrain(ConstitutiveModel):
    """A constitutive model for the 2D isotropic plane strain equations



    Inherits
    ----------
    ConstitutiveModel : _type_
        The base class for FEMpy constitutive models
    """

    def __init__(self, E, nu, rho, t, linear=True):
        """Create an isotropic plane stress constitutive model



        Parameters
        ----------
        E : float
            Elastic Modulus
        nu : float
            Poisson's ratio
        rho : float
            Density
        t : float
            Thickness, this will be used as the initial thickness value for all elements but can be changed later by calling setDesignVariables in the model
        linear : bool, optional
            Whether to use the linear kinematic equations for strains, by default True
        """
        # --- Design variables ---
        # This model has only one design variable, the thickness of the material
        designVars = {}
        designVars["Thickness"] = {"defaultValue": t}

        # --- States ---
        stateNames = ["X-Displacement", "Y-Displacement"]

        # --- Strains ---
        strainNames = ["e_xx", "e_yy", "gamma_xy"]

        # --- Stresses ---
        stressNames = ["sigma_xx", "sigma_yy", "tau_xy"]

        # --- Functions ---
        functionNames = ["Mass", "Von-Mises-Stress"]

        # --- Material properties ---
        self.E = E
        self.nu = nu
        self.rho = rho

        numDim = 2

        super().__init__(numDim, stateNames, strainNames, stressNames, designVars, functionNames, linear)

    def computeStrains(self, states, stateGradients, coords, dvs):
        """Given the coordinates, state value, state gradient, and design variables at a bunch of points, compute the strains at each one



        Parameters
        ----------
        states : numPoints x numStates array
            State values at each point
        stateGradients : numPoints x numStates x numDim array
            State gradients at each point
        coords : numPoints x numDim array
            Coordinates of each point
        dvs : dict of arrays of length numPoints
            Design variable values at each point

        Returns
        -------
        numPoints x numStrains array
            Strain components at each point
        """
        return strain2D(UPrime=stateGradients, nonlinear=not self.isLinear)

    def computeStrainStateGradSens(self, states, stateGradients, coords, dvs):
        """Given the coordinates, state value, state gradient, and design variables at a bunch of points, compute the
        sensitivity of the strains to the state gradient at each one



        Parameters
        ----------
        states : numPoints x numStates array
            State values at each point
        stateGradients : numPoints x numStates x numDim array
            State gradients at each point
        coords : numPoints x numDim array
            Coordinates of each point
        dvs : dict of arrays of length numPoints
            Design variable values at each point

        Returns
        -------
        numPoints x numStrains x numStates x numDim array
            Strain sensitivities, sens[i,j,k,l] is the sensitivity of strain component j at point i to state gradient du_k/dx_l
        """
        return strain2DSens(UPrime=stateGradients, nonlinear=not self.isLinear)

    def computeStresses(self, strains, dvs):
        """Given the strains and design variables at a bunch of points, compute the stresses at each one



        Parameters
        ----------
        strains : numPoints x numStrains array
            Strain components at each point
        dvs : dict of arrays of length numPoints
            Design variable values at each point

        Returns
        -------
        numPoints x numStresses array
            Stress components at each point
        """
        return isoPlaneStrainStress(strains, E=self.E, nu=self.nu)

    def computeStressStrainSens(self, strains, dvs):
        """Given the strains and design variables at a bunch of points, compute the sensitivity of the stresses to the strains at each one



        Parameters
        ----------
        strains : numPoints x numStrains array
            Strain components at each point
        dvs : dict of arrays of length numPoints
            Design variable values at each point

        Returns
        -------
        sens : numPoints x numStrains x numStates x numDim array
            Strain sensitivities, sens[i,j,k,l] is the sensitivity of strain component j at point i to state gradient du_k/dx_l
        """
        return isoPlaneStrainStressStrainSens(strains, E=self.E, nu=self.nu)

    def computeVolumeScaling(self, coords, dvs):
        """Given the coordinates and design variables at a bunch of points, compute the volume scaling parameter at each one

        For this 2D model, the volume scaling is just the thickness

        Parameters
        ----------
        coords : numPoints x numDim array
            Coordinates of each point
        dvs : dict of arrays of length numPoints
            Design variable values at each point

        Returns
        -------
        numPoints length array
            Volume scaling parameter at each point
        """
        return dvs["Thickness"]

    def getFunction(self, name):
        """Return a function that can be computed for this constitutive model

        Parameters
        ----------
        name : str
            Name of the function to compute

        Returns
        -------
        callable
            A function that can be called to compute the desired function at a bunch of points with the signature, f(states, stateGradients, coords, dvs)
            where:
            states is a numPoints x numStates array
            stateGradients is a numPoints x numStates x numDim array
            coords is a numPoints x numDim array
            dvs is a dictionary of numPoints length arrays
        """
        if name.lower() not in self.lowerCaseFuncNames:
            raise ValueError(
                f"{name} is not a valid function name for this constitutive model, valid choices are {self.functionNames}"
            )

        if name.lower() == "mass":

            def massFunc(states, stateGradients, coords, dvs):
                return np.ones(states.shape[0]) * self.rho

            func = massFunc

        if name.lower() == "von-mises-stress":

            def vmStressFunc(states, stateGradients, coords, dvs):
                strains = self.computeStrains(states, stateGradients, coords, dvs)
                stresses = self.computeStresses(strains, dvs)
                return vonMises2DPlaneStrain(stresses, self.nu)

            func = vmStressFunc

        return func

__init__(E, nu, rho, t, linear=True)

Create an isotropic plane stress constitutive model

Parameters

E : float Elastic Modulus nu : float Poisson's ratio rho : float Density t : float Thickness, this will be used as the initial thickness value for all elements but can be changed later by calling setDesignVariables in the model linear : bool, optional Whether to use the linear kinematic equations for strains, by default True

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def __init__(self, E, nu, rho, t, linear=True):
    """Create an isotropic plane stress constitutive model



    Parameters
    ----------
    E : float
        Elastic Modulus
    nu : float
        Poisson's ratio
    rho : float
        Density
    t : float
        Thickness, this will be used as the initial thickness value for all elements but can be changed later by calling setDesignVariables in the model
    linear : bool, optional
        Whether to use the linear kinematic equations for strains, by default True
    """
    # --- Design variables ---
    # This model has only one design variable, the thickness of the material
    designVars = {}
    designVars["Thickness"] = {"defaultValue": t}

    # --- States ---
    stateNames = ["X-Displacement", "Y-Displacement"]

    # --- Strains ---
    strainNames = ["e_xx", "e_yy", "gamma_xy"]

    # --- Stresses ---
    stressNames = ["sigma_xx", "sigma_yy", "tau_xy"]

    # --- Functions ---
    functionNames = ["Mass", "Von-Mises-Stress"]

    # --- Material properties ---
    self.E = E
    self.nu = nu
    self.rho = rho

    numDim = 2

    super().__init__(numDim, stateNames, strainNames, stressNames, designVars, functionNames, linear)

computeStrainStateGradSens(states, stateGradients, coords, dvs)

Given the coordinates, state value, state gradient, and design variables at a bunch of points, compute the sensitivity of the strains to the state gradient at each one

Parameters

states : numPoints x numStates array State values at each point stateGradients : numPoints x numStates x numDim array State gradients at each point coords : numPoints x numDim array Coordinates of each point dvs : dict of arrays of length numPoints Design variable values at each point

Returns

numPoints x numStrains x numStates x numDim array Strain sensitivities, sens[i,j,k,l] is the sensitivity of strain component j at point i to state gradient du_k/dx_l

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
def computeStrainStateGradSens(self, states, stateGradients, coords, dvs):
    """Given the coordinates, state value, state gradient, and design variables at a bunch of points, compute the
    sensitivity of the strains to the state gradient at each one



    Parameters
    ----------
    states : numPoints x numStates array
        State values at each point
    stateGradients : numPoints x numStates x numDim array
        State gradients at each point
    coords : numPoints x numDim array
        Coordinates of each point
    dvs : dict of arrays of length numPoints
        Design variable values at each point

    Returns
    -------
    numPoints x numStrains x numStates x numDim array
        Strain sensitivities, sens[i,j,k,l] is the sensitivity of strain component j at point i to state gradient du_k/dx_l
    """
    return strain2DSens(UPrime=stateGradients, nonlinear=not self.isLinear)

computeStrains(states, stateGradients, coords, dvs)

Given the coordinates, state value, state gradient, and design variables at a bunch of points, compute the strains at each one

Parameters

states : numPoints x numStates array State values at each point stateGradients : numPoints x numStates x numDim array State gradients at each point coords : numPoints x numDim array Coordinates of each point dvs : dict of arrays of length numPoints Design variable values at each point

Returns

numPoints x numStrains array Strain components at each point

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def computeStrains(self, states, stateGradients, coords, dvs):
    """Given the coordinates, state value, state gradient, and design variables at a bunch of points, compute the strains at each one



    Parameters
    ----------
    states : numPoints x numStates array
        State values at each point
    stateGradients : numPoints x numStates x numDim array
        State gradients at each point
    coords : numPoints x numDim array
        Coordinates of each point
    dvs : dict of arrays of length numPoints
        Design variable values at each point

    Returns
    -------
    numPoints x numStrains array
        Strain components at each point
    """
    return strain2D(UPrime=stateGradients, nonlinear=not self.isLinear)

computeStressStrainSens(strains, dvs)

Given the strains and design variables at a bunch of points, compute the sensitivity of the stresses to the strains at each one

Parameters

strains : numPoints x numStrains array Strain components at each point dvs : dict of arrays of length numPoints Design variable values at each point

Returns

sens : numPoints x numStrains x numStates x numDim array Strain sensitivities, sens[i,j,k,l] is the sensitivity of strain component j at point i to state gradient du_k/dx_l

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def computeStressStrainSens(self, strains, dvs):
    """Given the strains and design variables at a bunch of points, compute the sensitivity of the stresses to the strains at each one



    Parameters
    ----------
    strains : numPoints x numStrains array
        Strain components at each point
    dvs : dict of arrays of length numPoints
        Design variable values at each point

    Returns
    -------
    sens : numPoints x numStrains x numStates x numDim array
        Strain sensitivities, sens[i,j,k,l] is the sensitivity of strain component j at point i to state gradient du_k/dx_l
    """
    return isoPlaneStrainStressStrainSens(strains, E=self.E, nu=self.nu)

computeStresses(strains, dvs)

Given the strains and design variables at a bunch of points, compute the stresses at each one

Parameters

strains : numPoints x numStrains array Strain components at each point dvs : dict of arrays of length numPoints Design variable values at each point

Returns

numPoints x numStresses array Stress components at each point

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
def computeStresses(self, strains, dvs):
    """Given the strains and design variables at a bunch of points, compute the stresses at each one



    Parameters
    ----------
    strains : numPoints x numStrains array
        Strain components at each point
    dvs : dict of arrays of length numPoints
        Design variable values at each point

    Returns
    -------
    numPoints x numStresses array
        Stress components at each point
    """
    return isoPlaneStrainStress(strains, E=self.E, nu=self.nu)

computeVolumeScaling(coords, dvs)

Given the coordinates and design variables at a bunch of points, compute the volume scaling parameter at each one

For this 2D model, the volume scaling is just the thickness

Parameters

coords : numPoints x numDim array Coordinates of each point dvs : dict of arrays of length numPoints Design variable values at each point

Returns

numPoints length array Volume scaling parameter at each point

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
def computeVolumeScaling(self, coords, dvs):
    """Given the coordinates and design variables at a bunch of points, compute the volume scaling parameter at each one

    For this 2D model, the volume scaling is just the thickness

    Parameters
    ----------
    coords : numPoints x numDim array
        Coordinates of each point
    dvs : dict of arrays of length numPoints
        Design variable values at each point

    Returns
    -------
    numPoints length array
        Volume scaling parameter at each point
    """
    return dvs["Thickness"]

getFunction(name)

Return a function that can be computed for this constitutive model

Parameters

name : str Name of the function to compute

Returns

callable A function that can be called to compute the desired function at a bunch of points with the signature, f(states, stateGradients, coords, dvs) where: states is a numPoints x numStates array stateGradients is a numPoints x numStates x numDim array coords is a numPoints x numDim array dvs is a dictionary of numPoints length arrays

Source code in FEMpy/Constitutive/IsoPlaneStrain.py
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
def getFunction(self, name):
    """Return a function that can be computed for this constitutive model

    Parameters
    ----------
    name : str
        Name of the function to compute

    Returns
    -------
    callable
        A function that can be called to compute the desired function at a bunch of points with the signature, f(states, stateGradients, coords, dvs)
        where:
        states is a numPoints x numStates array
        stateGradients is a numPoints x numStates x numDim array
        coords is a numPoints x numDim array
        dvs is a dictionary of numPoints length arrays
    """
    if name.lower() not in self.lowerCaseFuncNames:
        raise ValueError(
            f"{name} is not a valid function name for this constitutive model, valid choices are {self.functionNames}"
        )

    if name.lower() == "mass":

        def massFunc(states, stateGradients, coords, dvs):
            return np.ones(states.shape[0]) * self.rho

        func = massFunc

    if name.lower() == "von-mises-stress":

        def vmStressFunc(states, stateGradients, coords, dvs):
            strains = self.computeStrains(states, stateGradients, coords, dvs)
            stresses = self.computeStresses(strains, dvs)
            return vonMises2DPlaneStrain(stresses, self.nu)

        func = vmStressFunc

    return func