Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/CompositeSimpson.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
CompositeSimpson
==================

.. function:: beamIntegration('CompositeSimpson',tag,secTag,N)
.. function:: beamIntegration('CompositeSimpson', tag, secTag, N)
beamIntegration('CompositeSimpson', tag, N, *secTags)
:noindex:

Create a CompositeSimpson beamIntegration object.

Arguments and examples see :ref:`Lobatto-BeamIntegration`.
Composite Simpson ``beamIntegration``. Two forms as in :ref:`Lobatto-BeamIntegration`.

.. admonition:: Example

.. code-block:: python

import openseespy.opensees as ops

ops.beamIntegration('CompositeSimpson', 2, 1, 6)
ops.beamIntegration('CompositeSimpson', 3, 4, 1, 2, 2, 1)
42 changes: 42 additions & 0 deletions src/Concrete02IS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.. include:: sub.txt

==============================================
Concrete02IS material
==============================================

This command constructs a uniaxial concrete material with the same compressive envelope and tension/cyclic behavior as :doc:`Concrete02`, but with **user-defined initial stiffness** :math:`E_0`. In Concrete02 the initial stiffness is fixed at :math:`E_c = 2 f'_c / \varepsilon_{c0}`; Concrete02IS allows any :math:`E_0` (for example :math:`57000\sqrt{f'_c}` in psi units, or a secant stiffness to peak).

.. function:: uniaxialMaterial('Concrete02IS', matTag, E0, fpc, epsc0, fpcu, epsU, *optional)

Optional trailing arguments (in order): ratio between unloading slope at ``epsU`` and initial slope, tensile strength ``ft``, tension softening stiffness ``Ets``.

================================ ===========================================================================
``matTag`` |int| unique material tag
``E0`` |float| initial (elastic) stiffness
``fpc`` |float| concrete compressive strength at 28 days (compression negative)
``epsc0`` |float| concrete strain at maximum strength (negative)
``fpcu`` |float| concrete crushing strength (negative)
``epsU`` |float| concrete strain at crushing strength (negative)
================================ ===========================================================================

.. note::

Compressive parameters are taken as negative; if given positive, they are converted internally. Input :math:`E_0` affects unloading/reloading stiffness in compression. The ascending branch uses the Popovics equation (Concrete02 uses the Hognestad parabola).

.. admonition:: Example

.. code-block:: python

import openseespy.opensees as ops

fc, epsc0 = 4000.0, -0.002
fcu, epscu = -1000.0, -0.006
Ec = 2.0 * fc / (-epsc0)
ops.uniaxialMaterial('Concrete02IS', 1, Ec, fc, epsc0, fcu, epscu)
ops.uniaxialMaterial('Concrete02IS', 2, Ec, fc, epsc0, fcu, epscu, 0.1, 500.0, 1738.33)

.. seealso::

:doc:`Concrete02`.

Code developed by: Filip Filippou (Concrete02); Nasser Marafi (Concrete02IS).
27 changes: 27 additions & 0 deletions src/Damper.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.. include:: sub.txt

========================
Damper material wrapper
========================

Constructs a **Damper** uniaxial material wrapper. The wrapper uses the stress–strain response of any uniaxial material as a **stress versus strain-rate** relationship for damping: strain rate is passed as strain, and the material tangent provides the damping tangent.

.. function:: uniaxialMaterial('Damper', matTag, otherTag, *args)

``*args`` may include ``'-factors'``, ``fact1``, ``fact2``, … for multiple materials.

================================ ===========================================================================
``matTag`` |int| unique material tag
``otherTag`` |int| tag of a previously defined uniaxial material
================================ ===========================================================================

.. admonition:: Example

.. code-block:: python

import openseespy.opensees as ops

ops.uniaxialMaterial('Elastic', 1, 100.0)
ops.uniaxialMaterial('Damper', 2, 1)

Code developed by: **Michael H. Scott**
111 changes: 111 additions & 0 deletions src/Diagonal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
.. include:: sub.txt

Diagonal System
-----------------------------

This command is used to construct a Diagonal linear system of equation object. This system stores only the diagonal entries of the coefficient matrix, making it extremely memory efficient for problems where off-diagonal coupling can be neglected or lumped into the diagonal. The system is solved by direct inversion of the diagonal entries. The following command is used to construct such a system:

.. function:: system ('Diagonal', <-'lumped'>)

**Optional Parameter:**

* **-lumped** - If specified, off-diagonal matrix entries are added (lumped) to the diagonal before solving. This is useful for mass matrix lumping or when converting a coupled system to a diagonal approximation.

A diagonal system stores only the diagonal entries of an n×n matrix **A**, where:

:math:`K = \begin{bmatrix} k_{11} & 0 & \cdots & 0 \\ 0 & k_{22} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & k_{nn} \end{bmatrix}`

The solution for :math:`K u = f` is obtained directly as:

:math:`u_i = \frac{f_i}{k_{ii}} \quad \text{for } i = 1, \ldots, n`

.. note::

1. This solver requires that all diagonal entries are non-zero.
2. The system only stores n values instead of n² for a full matrix, providing significant memory savings
3. When using the **-lumped** option, the solver accumulates all off-diagonal entries in each row/column into the corresponding diagonal entry

Mass Lumping
^^^^^^^^^^^^

When the **-lumped** option is specified, the Diagonal system performs **mass lumping** (also called diagonal lumping or row-sum lumping). This technique converts a consistent (coupled) mass matrix into a diagonal form by summing all entries in each row and placing the total on the diagonal.

**Mathematical Formulation:**

For a consistent mass matrix **M** with entries :math:`m_{ij}`, the lumped diagonal entry is:

:math:`\tilde{m}_{ii} = \sum_{j=1}^{n} m_{ij}`

All off-diagonal entries are set to zero: :math:`\tilde{m}_{ij} = 0` for :math:`i \neq j`


.. warning::

1. This system is only appropriate when the problem structure allows diagonal treatment
2. Mass lumping is generally only recommended for the mass matrix in dynamic analysis (ExplicitDifference integrator or CentralDifference integrator if no damping matrix is used or only mass proportional Rayleigh damping is used)
3. Lumping the stiffness matrix is rarely appropriate and can lead to poor results
4. For static analysis or implicit dynamics use full sparse solvers.
5. Ideally, lumping should be handled at the element level, especially for high-order elements (like the TenNodeTetrahedron or SixNodeTriangle) where this technique leads to negative mass values (!!).

**Implementation Details:**

When **-lumped** is specified:

.. code-block:: none

For each element matrix entry m(i,j) at DOF locations id(i), id(j):
A[id(i)] += m(i,i) // Add diagonal entry
if (lumped):
for all j ≠ i:
A[id(i)] += m(j,i) // Add all column entries to diagonal

This ensures that the total contribution from each element is preserved while creating a diagonal system.


.. admonition:: Example

The following examples show how to construct a Diagonal system

**1. Python Code - Basic diagonal system**

.. code-block:: python

import openseespy.opensees as ops

ops.system('Diagonal')

**2. Python Code - Lumped mass for explicit analysis**

.. code-block:: python

import openseespy.opensees as ops

# Setup for explicit central difference method
ops.system('Diagonal', '-lumped')
ops.constraints('Plain')
ops.numberer('Plain')
ops.integrator('CentralDifference')
ops.analysis('Transient')

**3. Python Code - Complete explicit dynamics example**

.. code-block:: python

import openseespy.opensees as ops

# ... model definition ...

# Analysis setup for blast/impact with lumped mass
ops.system('Diagonal', '-lumped')
ops.constraints('Plain')
ops.numberer('Plain')
ops.test('NormDispIncr', 1.0e-6, 10, 0)
ops.algorithm('Linear')
ops.integrator('CentralDifference')
ops.analysis('Transient')

# Time step (must satisfy CFL condition)
dt = 0.0001
ops.analyze(1000, dt)

Code Developed by: **Frank McKenna**
29 changes: 17 additions & 12 deletions src/Legendre.rst
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
.. include:: sub.txt

==============================================
Legendre
==============================================
==========
Legendre
==========

.. function:: beamIntegration('Legendre',tag,secTag,N)
.. function:: beamIntegration('Legendre', tag, secTag, N)
beamIntegration('Legendre', tag, N, *secTags)
:noindex:

Create a Gauss-Legendre beamIntegration object.
Gauss-Legendre integration is more accurate than Gauss-Lobatto; however, it is not common
in force-based elements because there are no integration points at the element ends.
Gauss–Legendre integration: more accurate than Lobatto but **no** points at the element ends by default, so less common in force-based elements. Order of accuracy: :math:`2N-1`.

**Prismatic:** ``beamIntegration('Legendre', tag, secTag, N)``.

Places ``N`` Gauss-Legendre integration points along the element. The location and weight
of each integration point are tabulated in references on numerical analysis.
The force deformation response at each integration point is defined by the section.
The order of accuracy for Gauss-Legendre integration is 2N-1.
**Non-prismatic:** ``beamIntegration('Legendre', tag, N, secTag1, …, secTagN)``.

Arguments and examples see :ref:`Lobatto-BeamIntegration`.
Arguments: see :ref:`Lobatto-BeamIntegration`.

.. admonition:: Example

.. code-block:: python

import openseespy.opensees as ops

ops.beamIntegration('Legendre', 2, 1, 6)
ops.beamIntegration('Legendre', 3, 4, 1, 2, 2, 1)
39 changes: 29 additions & 10 deletions src/Lobatto.rst
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
.. include:: sub.txt

.. _Lobatto-BeamIntegration:

=========
Lobatto
=========

.. function:: beamIntegration('Lobatto',tag,secTag,N)
.. function:: beamIntegration('Lobatto', tag, secTag, N)
beamIntegration('Lobatto', tag, N, *secTags)
:noindex:

Create a Gauss-Lobatto beamIntegration object.
Gauss-Lobatto integration is the most common approach for evaluating the response of
:doc:`ForceBeamColumn` (`Neuenhofer and Filippou 1997`_) because it places an integration point at each end of the element, where bending moments are largest in the absence of interior element loads.
Create a Gauss–Lobatto ``beamIntegration`` object. Gauss–Lobatto is common for :doc:`ForceBeamColumn` (`Neuenhofer and Filippou 1997`_) because it places an integration point at each end of the element, where bending is largest if there are no interior element loads.

**Prismatic** — one section for all points: ``(tag, secTag, N)``.

**Non-prismatic** — one section tag per point, in order from node *I* to *J*: ``(tag, N, secTag1, secTag2, …, secTagN)``.

================================ ===========================================================================
``tag`` |int| unique beam integration tag
``secTag`` |int| (prismatic) one defined section for all points
``N`` |int| number of integration points
``secTags`` |listi| (non-prismatic) ``N`` section tags
================================ ===========================================================================

.. note::

The non-prismatic form assigns different sections along the length (e.g. tapering reinforcement) without relying on hinge-only schemes. The same two forms exist for :doc:`Legendre`, :doc:`Radau`, :doc:`NewtonCotes`, :doc:`Trapezoidal`, and :doc:`CompositeSimpson`.

.. admonition:: Example

Prismatic: 6 points, section tag 1. Non-prismatic: 3 sections ``[1, 2, 1]`` at 3 Lobatto points.

.. code-block:: python

======================== =============================================================
``tag`` |int| tag of the beam integration.
``secTag`` |int| A previous-defined section object.
``N`` |int| Number of integration points along the element.
======================== =============================================================
import openseespy.opensees as ops

ops.beamIntegration('Lobatto', 2, 1, 6)
sec_tag_list = [1, 2, 1]
ops.beamIntegration('Lobatto', 3, len(sec_tag_list), *sec_tag_list)
26 changes: 26 additions & 0 deletions src/MultiplierUni.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.. include:: sub.txt

============================
Multiplier material wrapper
============================

Constructs a **Multiplier** uniaxial material wrapper: stress and tangent of the wrapped material are multiplied by a factor. Typical uses include overstrength factors and p-y multipliers (e.g. pile group shadowing).

.. function:: uniaxialMaterial('Multiplier', matTag, otherTag, multiplier)

================================ ===========================================================================
``matTag`` |int| unique material tag
``otherTag`` |int| tag of a previously defined uniaxial material
``multiplier`` |float| factor applied to stress and tangent
================================ ===========================================================================

.. admonition:: Example

.. code-block:: python

import openseespy.opensees as ops

ops.uniaxialMaterial('Elastic', 1, 100.0)
ops.uniaxialMaterial('Multiplier', 2, 1, 0.8)

Code developed by: **Michael H. Scott**
28 changes: 16 additions & 12 deletions src/NewtonCotes.rst
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
.. include:: sub.txt

.. _NewtonCotes-BeamIntegration:
=============

==============
NewtonCotes
=============
==============

.. function:: beamIntegration('NewtonCotes',tag,secTag,N)
.. function:: beamIntegration('NewtonCotes', tag, secTag, N)
beamIntegration('NewtonCotes', tag, N, *secTags)
:noindex:

Create a Newton-Cotes beamIntegration object.
Newton-Cotes places integration points uniformly along the element, including a point at
each end of the element.
Newton–Cotes integration: points uniformly spaced along the element, **including** both ends. Order of accuracy: :math:`N-1`.

**Prismatic:** ``('NewtonCotes', tag, secTag, N)``.

**Non-prismatic:** ``('NewtonCotes', tag, N, *secTags)``.

.. admonition:: Example

Places ``N`` Newton-Cotes integration points along the element. The weights for the uniformly
spaced integration points are tabulated in references on numerical analysis. The force deformation
response at each integration point is defined by the section.
The order of accuracy for Gauss-Radau integration is N-1.
.. code-block:: python

Arguments and examples see :ref:`Lobatto-BeamIntegration`.
import openseespy.opensees as ops

ops.beamIntegration('NewtonCotes', 2, 1, 6)
ops.beamIntegration('NewtonCotes', 3, 4, 1, 2, 2, 1)
34 changes: 34 additions & 0 deletions src/PenaltyUni.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.. include:: sub.txt

==========================
Penalty material wrapper
==========================

Constructs a **Penalty** uniaxial material wrapper that adds a small stiffness to the wrapped material. Helps avoid singular stiffness from perfect plasticity; lightweight alternative to placing the wrapped material in parallel with an elastic material.

.. function:: uniaxialMaterial('Penalty', matTag, otherTag, penalty, *args)

Optional ``'-noStress'``: penalty stiffness is added only to the tangent, not to stress.

================================ ===========================================================================
``matTag`` |int| unique material tag
``otherTag`` |int| tag of a previously defined uniaxial material
``penalty`` |float| stiffness added to tangent (and optionally stress); same units as tangent
================================ ===========================================================================

.. note::

Use a small penalty value so the response stays dominated by the wrapped material.

.. admonition:: Example

.. code-block:: python

import openseespy.opensees as ops

E = 29000.0
penalty = 0.05 * E
ops.uniaxialMaterial('Elastic', 1, E)
ops.uniaxialMaterial('Penalty', 2, 1, penalty)

Code developed by: **Michael H. Scott**
Loading