<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://oofem.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://oofem.github.io/" rel="alternate" type="text/html" /><updated>2026-03-26T21:37:01+01:00</updated><id>https://oofem.github.io/feed.xml</id><title type="html">OOFEM</title><subtitle>OOFEM is free finite element code with object oriented architecture for solving mechanical,  transport and fluid mechanics problems.  The aim of this project is to develop efficient and robust tool for FEM computations  as well as to provide modular and extensible environment.</subtitle><entry><title type="html">Symbolic MPM mode</title><link href="https://oofem.github.io/blog/mpm-symbolic-mode/" rel="alternate" type="text/html" title="Symbolic MPM mode" /><published>2026-03-06T00:00:00+01:00</published><updated>2026-03-06T00:00:00+01:00</updated><id>https://oofem.github.io/blog/mpm-symbolic-mode</id><content type="html" xml:base="https://oofem.github.io/blog/mpm-symbolic-mode/"><![CDATA[<h2 id="symbolic-mpm-expression-based-term-definition">Symbolic MPM: Expression-Based Term Definition</h2>

<p>I’m excited to share a major advancement in OOFEM’s multiphysics module (mpm). The new <strong>symbolic term feature</strong> enables you to define individual terms directly in input files using mathematical expressions—eliminating the need for hard-coded term libraries.</p>

<h3 id="key-innovation-expression-compiler--virtual-machine">Key Innovation: Expression Compiler &amp; Virtual Machine</h3>

<p>The implementation includes:</p>
<ul>
  <li><strong>Internal Expression Compiler</strong>: Parses symbolic expressions with support for matrix algebra and mathematical operators</li>
  <li><strong>Virtual Machine Evaluation</strong>: Expressions are compiled once into optimized “code” for efficient runtime evaluation</li>
  <li><strong>Rich Operator Library</strong>: Predefined operators (functors) for divergence, gradient, field interpolation, and more</li>
</ul>

<p>This approach combines the flexibility of symbolic definitions with the performance of compiled code execution.</p>

<h2 id="example-1-1d-heat-transport">Example 1: 1D Heat Transport</h2>

<p>Let’s start with a simple example of 1D stationary heat transport:</p>

\[\lambda\frac{d^2T}{dx^2} + Q = 0\]

\[T=\bar{T}\ \rm{on}\ \Gamma_d\]

\[q\cdot n=\bar{q}\ \rm{on}\ \Gamma_q\]

<h3 id="weak-form">Weak Form</h3>

<p>The weak form can be written as</p>

\[\int_\Omega\underbrace{\frac{d\delta T}{dx}\lambda\frac{dT}{dx}}_{T_1}-\int_{\Gamma_q}\underbrace{\delta T\bar{q}}_{T2} + \int_\Omega \underbrace{\delta TQ}_{T3}=0\]

<h3 id="variable-definition">Variable Definition</h3>

<p>Define the variables appearing in the weak form:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Variable name "t" interpolation "feilin" type 1 quantity 0 size 1 dofs 1 10 # temperature 
Variable name "dt" interpolation "feilin" type 1 quantity 0 size 1 dofs 1 10 # test function temperature
</code></pre></div></div>
<h3 id="symbolic-term-definition">Symbolic Term Definition</h3>

<p>Instead of relying on hard-coded terms, we use the <code class="language-plaintext highlighter-rouge">SymbolicTerm</code> directive. For term $T_1$:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SymbolicTerm 1 variable "t"  testvariable "dt" mmode 25 lexpression "Grad(dt,gp).T*[[1.0]]*Grad(t,gp)" rexpression "Grad(dt,gp).T*[[1.0]]*Grad(t,gp)*ru(t, cell, ts)"
</code></pre></div></div>
<p><strong>Expression Components:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">rexpression</code>: Defines the weak form residual term</li>
  <li><code class="language-plaintext highlighter-rouge">lexpression</code>: Defines the linearization with respect to the trial variable (for Newton iterations)</li>
  <li><code class="language-plaintext highlighter-rouge">variable</code>: Trial variable to solve for</li>
  <li><code class="language-plaintext highlighter-rouge">testvariable</code>: Test function for weak form</li>
</ul>

<p><strong>Built-in Operators Used:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">Grad(var, gp)</code>: Evaluates gradient at Gauss point (e.g., $\nabla N^{e}(x_{gp}) $)</li>
  <li><code class="language-plaintext highlighter-rouge">ru(var, cell, ts)</code>: Retrieves nodal unknown values for variable at current cell and time step</li>
  <li><code class="language-plaintext highlighter-rouge">N(var, gp)</code>: Interpolation matrix $N^e(x_{gp})$ at Gauss point</li>
</ul>

<p><strong>Heat Source Term</strong> $T_3$ (for $Q=1$):</p>

<p>Note that this term requires no linearization since it doesn’t depend on the unknown field:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SymbolicTerm 2 variable "t"  testvariable "dt" mmode 25 lexpression "0.0" rexpression "N(w,gp).T*[[1.0]]" # constant heat source
</code></pre></div></div>
<p>The complete example is available in the <a href="https://raw.githubusercontent.com/oofem/oofem/refs/heads/devel/tests/regression/mpm/mpms06.in">tests/regression/mpm/mpms06.in</a> test case.</p>

<h2 id="example-2-multiphysicsincompressible-elasticity">Example 2: Multiphysics—Incompressible Elasticity</h2>

<p>The symbolic term concept extends naturally to multiphysics problems. Here we illustrate the mixed formulation of incompressible elasticity with pressure and displacement fields:</p>

\[\nabla p + 2\mu\nabla\cdot\rm{dev}[\nabla^s u]+f = 0\;\rm{in}\ \Omega\]

\[\frac{1}{K}p-\nabla\cdot u=0\;\rm{in}\ \Omega\]

\[u=\bar u\;\rm{on}\ \Gamma_u\]

\[\sigma n = \bar t\;\rm{on}\ \Gamma_t\]

<p>The weak form of the above equations can be written as
\(\int_\Omega\overbrace{2\mu\nabla^sw:\rm{dev}[\nabla^su]}^{T_1}\ d\Omega-\int_\Omega\overbrace{ \nabla\cdot w\ p}^{T_2}\ d\Omega=\int_{\Gamma_t}\overbrace{w\cdot \bar t}^{T_5}\ d\Gamma\)</p>

\[-\int_\Omega\underbrace{q\ \nabla\cdot u}_{T_3 = T_2^T}\ d\Omega+\int_\Omega\underbrace{\frac{1}{K}q\ p}_{T_4}\ d\Omega = 0\]

<h3 id="weak-form-of-mixed-u-p-formulation">Weak Form of Mixed u-p Formulation</h3>

<p>This is a classic mixed finite element formulation for incompressible media.</p>

<h3 id="problem-variables">Problem Variables</h3>

<ul>
  <li>$u, p$: Unknown displacement and pressure fields</li>
  <li>$w, q$: Corresponding test functions</li>
</ul>

<h3 id="symbolic-input-syntax">Symbolic Input Syntax</h3>

<p>Variables are defined in the input deck as:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Variable name "u" interpolation "feiquad" type 1 quantity 0 size 2 dofs 2 1 2 
Variable name "w" interpolation "feiquad" type 1 quantity 0 size 2 dofs 2 1 2 
Variable name "p" interpolation "feilin"  type 0 quantity 3 size 1 dofs 1 11  
Variable name "q" interpolation "feilin" type 0 quantity 3 size 1 dofs 1 11 
</code></pre></div></div>

<p><strong>Field Definitions:</strong></p>
<ul>
  <li>Fields ($u, w$): Quadratic interpolation (<code class="language-plaintext highlighter-rouge">feiquad</code>), vector fields (<code class="language-plaintext highlighter-rouge">type 1</code>), 2 DOFs (x and y components of displacement vector)</li>
  <li>Pressure fields ($p, q$): Linear interpolation (<code class="language-plaintext highlighter-rouge">feilin</code>), scalar fields (<code class="language-plaintext highlighter-rouge">type 0</code>)</li>
</ul>

<h3 id="defining-weak-form-terms">Defining Weak Form Terms</h3>

<p>Each component of the weak form is defined as a <code class="language-plaintext highlighter-rouge">SymbolicTerm</code>:</p>

<p><strong>Term $T_1$</strong>: Stiffness—displacement test function and displacement unknown, plain strain (<em>mmode 7</em>)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SymbolicTerm 1 variable "u"  testvariable "w" mmode 7 \
  lexpression "B(w,gp).T*Dm_dev(gp,ts)*B(u,gp)" \
  rexpression "B(w,gp).T*Sig_dev(u,gp,ts)"
</code></pre></div></div>
<p>Where <code class="language-plaintext highlighter-rouge">B(var,gp)</code> is the strain-displacement matrix and <code class="language-plaintext highlighter-rouge">Dm_dev</code>/<code class="language-plaintext highlighter-rouge">Sig_dev</code> are deviatoric material stiffness and stress operators.</p>

<p><strong>Term $T_2$</strong>: Coupling—displacement test and pressure unknown, plain strain (<em>mmode 7</em>)</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SymbolicTerm 2 variable "p"  testvariable "w" mmode 7 \
  lexpression "Div(w,gp).T*N(p,gp)" \
  rexpression "Div(w,gp).T*N(p,gp)*ru(p, cell, ts)"
</code></pre></div></div>
<p>Where <code class="language-plaintext highlighter-rouge">Div(var,gp)</code> computes divergence at the Gauss point.</p>

<p><strong>Terms $T_3$ and $T_4$</strong>: Pressure test—displacement and pressure unknowns:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SymbolicTerm 3 variable "u"  testvariable "dp" mmode 7 \
  lexpression "N(dp,gp).T*Div(u,gp)" \
  rexpression "N(dp,gp).T*Div(u,gp)*ru(u, cell, ts)"

SymbolicTerm 4 variable "p"  testvariable "dp" mmode 7 ctype 27 uvmt 1 \
  lexpression "N(dp,gp).T*2.4000000000024e-7*N(p,gp)" \
  rexpression "N(dp,gp).T*2.4000000000024e-7*N(p,gp)*ru(p, cell, ts)"
</code></pre></div></div>

<h3 id="integration-definition">Integration Definition</h3>

<p>Terms are integrated over specific domains ($\Omega,\ \Gamma_t$) using predefined sets:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Integral 1 domain 1 set 1 term 1
Integral 2 domain 1 set 1 term 2 factor -1.0
Integral 3 domain 1 set 1 term 3 factor -1.0
Integral 4 domain 1 set 1 term 4 
Integral 5 domain 1 set 2 term 5
</code></pre></div></div>

<p>The complete example is available in the <a href="https://raw.githubusercontent.com/oofem/oofem/refs/heads/devel/tests/regression/mpm/mpms_cook2_u2p1.in">tests/regression/mpm/mpms_cook2_u2p1.in</a> test case.</p>

<h2 id="why-symbolic-terms-matter">Why Symbolic Terms Matter</h2>

<p>This symbolic approach offers significant advantages:</p>

<ol>
  <li><strong>Flexibility</strong>: Define custom physics without modifying core libraries</li>
  <li><strong>Readability</strong>: Mathematical expressions directly mirror the weak form on paper</li>
  <li><strong>Performance</strong>: One-time compilation produces optimized VM bytecode</li>
  <li><strong>Maintainability</strong>: Physics definitions live in input files, not scattered across C++ code</li>
  <li><strong>Extensibility</strong>: Easy to add new operators and mathematical constructs</li>
</ol>

<h2 id="conclusion">Conclusion</h2>

<p>The new <strong>symbolic term feature with expression compiler and virtual machine</strong> represents a paradigm shift for OOFEM’s multiphysics capabilities. By combining mathematical expressiveness with compiled execution efficiency, it enables researchers to rapidly prototype and deploy new coupled formulations without the overhead of C++ development.</p>

<p>Stay tuned for further enhancements to the symbolic framework!</p>

<p>Feel free to share feedback or questions in the comments section below.</p>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="tutorial" /><category term="mpm" /><summary type="html"><![CDATA[Symbolic MPM: Expression-Based Term Definition]]></summary></entry><entry><title type="html">OOFEM integrates with JupiterLite</title><link href="https://oofem.github.io/blog/oofem-in-browser/" rel="alternate" type="text/html" title="OOFEM integrates with JupiterLite" /><published>2025-05-31T00:00:00+02:00</published><updated>2025-05-31T00:00:00+02:00</updated><id>https://oofem.github.io/blog/oofem-in-browser</id><content type="html" xml:base="https://oofem.github.io/blog/oofem-in-browser/"><![CDATA[<h2 id="oofem-now-runs-in-your-browser-with-jupyterlite-integration">OOFEM Now Runs in Your Browser with JupyterLite Integration</h2>

<p>OOFEM supports Python scripting through its Python bindings, enabling users to write scripts, develop custom elements, material models, and solvers—all in Python. Thanks to recent advancements, OOFEM and its binding code can now be compiled into a WebAssembly (WASM) Python module.</p>

<p>By leveraging <a href="https://github.com/pyodide/pyodide">Pyodide</a> (a WebAssembly-based Python distribution for browsers and Node.js) and <a href="https://jupyterlite.readthedocs.io/en/stable/">JupyterLite</a> (a browser-based version of JupyterLab), you can now run and interact with OOFEM entirely within your web browser—no installation needed.</p>

<p>While this might seem like a lightweight demo, it actually unlocks powerful new opportunities for teaching, training, and getting started with finite element analysis. It’s especially useful for educational settings or for newcomers exploring OOFEM for the first time.</p>

<p>Check out the <a href="https://oofem.github.io/jupyter-demos/lab/index.html?path=Welcome.ipynb">OOFEM python tutorial</a> and try out the browser-based examples directly—no setup required!</p>

<p>The support by <a href="https://github.com/eudoxos">Václav Šmilauer</a> is highly acknowledged.</p>

<p><img src="/assets/images/oofem-jupyterlite-screenshot.png" alt="Screenshot of JupyterLite with oofem" width="50%" height="50%" /></p>

<hr />

<p>With this we conclude today post on oofem JupyterLite integration. 
Hope you enjoyed and stay tuned for following updates!</p>

<p>You are welcome to leave a comment below to give a feedback.</p>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="tutorial" /><category term="python" /><category term="JupyterLite" /><summary type="html"><![CDATA[OOFEM Now Runs in Your Browser with JupyterLite Integration]]></summary></entry><entry><title type="html">Example of Incompressible elasticity with mpm symbolic module</title><link href="https://oofem.github.io/blog/mpm-incompressible-elasticity-up-formulation/" rel="alternate" type="text/html" title="Example of Incompressible elasticity with mpm symbolic module" /><published>2025-02-02T00:00:00+01:00</published><updated>2025-02-02T00:00:00+01:00</updated><id>https://oofem.github.io/blog/mpm-incompressible-elasticity-up-formulation</id><content type="html" xml:base="https://oofem.github.io/blog/mpm-incompressible-elasticity-up-formulation/"><![CDATA[<h2 id="mixed-formulation-for-incompressible-elasticity-using-mpm-symbolic-module">Mixed formulation for incompressible elasticity using MPM symbolic module</h2>
<p>A formulation of the elasticity problem able to represent the incompressible behavior can be written using mixed approach involving pressure and displacement fields</p>

\[\nabla p + 2\mu\nabla\cdot\rm{dev}[\nabla^s u]+f = 0\;\rm{in}\ \Omega\]

\[\frac{1}{K}p-\nabla\cdot u=0\;\rm{in}\ \Omega\]

\[u=\bar u\;\rm{on}\ \Gamma_u\]

\[\sigma n = \bar t\;\rm{on}\ \Gamma_t\]

<p>The weak form of the above equations can be written as
\(\int_\Omega\overbrace{2\mu\nabla^sw:\rm{dev}[\nabla^su]}^{T_1}\ d\Omega-\int_\Omega\overbrace{ \nabla\cdot w\ p}^{T_2}\ d\Omega=\int_{\Gamma_t}\overbrace{w\cdot \bar t}^{T_3}\ d\Gamma\)</p>

\[-\int_\Omega\underbrace{q\ \nabla\cdot u}_{T_4 = T_2^T}\ d\Omega+\int_\Omega\underbrace{\frac{1}{K}q\ p}_{T_5}\ d\Omega = 0\]

<p>where</p>
<ul>
  <li>$u, p$ are unknown displacement and pressure fields (<em>Variables</em>).</li>
  <li>$w, q$ are test fields (<em>Variables</em>)
In order to obtain stable results, the approximations should satisfy Babuška-Brezzi condition or some form of stabilization would be required. 
To satisfy the B-B condition, the approximation order of displacement should be higher than that of hydrostatic pressure.
In the following  we will consider 2D case.</li>
</ul>

<p>In the input deck, the <em>Variables</em> ($u,p,w,q$) can be set up using following syntax</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Variable name "u" interpolation "feilin" type 1 quantity 0 size 2 dofs 2 1 2 
Variable name "w" interpolation "feilin" type 1 quantity 0 size 2 dofs 2 1 2 
Variable name "p" interpolation "feiconst"  type 0 quantity 3 size 1 dofs 1 11  
Variable name "q" interpolation "feiconst" type 0 quantity 3 size 1 dofs 1 11 
</code></pre></div></div>
<p>where <em>interpolation</em> determines the interpolation used for specific field. Here we use linear approximation (<em>interpolation “feilin”</em>) for displacement field and related test field and constant approximation (<em>interpolation “feiconst”</em>) for pressure (so called Q1P0 element).
The $u, w$ fields are vector fields (<em>type 1</em>) with physical meaning of displacement (<em>quantity 0</em>) and two degrees of freedom (<em>size 2 dofs 2 1 2</em>). And $p, q$ are scalar fields (<em>type 0</em>) with physical meaning of pressure (<em>quantity 3 size 1 dofs 1 11</em>).</p>

<p>The weak form above consists of several terms to be evaluated</p>
<ul>
  <li>$T_1$: This is represented by <em>BTSigmaTerm</em>, evaluated for $w$ test field and $u$ as unknown field, under plain strain assumptions (<em>mmode 7</em>) and considering deviatoric part only (<em>lhsmatmode 29</em>)
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BTSigmaTerm 1 variable "u"  testvariable "w" mmode 7 lhsmatmode 29
</code></pre></div>    </div>
  </li>
  <li>$T_2$: represented by <em>BTamNTerm</em>, evaluated for $w$ test field and $u$ as unknown field, under plain strain assumptions (<em>mmode 7</em>) and with scalar parameter equal to 1.0 (<em>atype 28</em>)
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BTamNTerm 2 variable "p" testvariable "w" mmode 7 atype 28
</code></pre></div>    </div>
  </li>
  <li>Similarly, we set up remaining three terms $T_3, T_4=T_2^T$ and $T_5$:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NTamTBTerm 3 variable "u" testvariable "q" mmode 7 atype 28
NTcN 4 variable "p" testvariable "q" mmode 7 ctype 27
NTfTerm 5 variable "u" testvariable "w" mmode 6 flux 2 0. 6.25
</code></pre></div>    </div>
    <p>The terms are integrated over specific domains ($\Omega,\ \Gamma_t$), defined using corresponding sets (defined bellow in the example):</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Integral 1 domain 1 set 1 term 1
Integral 2 domain 1 set 1 term 2 factor -1.0
Integral 3 domain 1 set 1 term 3 factor -1.0
Integral 4 domain 1 set 1 term 4 factor -1.0
Integral 5 domain 1 set 2 term 5
</code></pre></div>    </div>
    <h2 id="example-cook-membrane">Example: Cook membrane</h2>
    <p>The Cook’s membrane is a standard benchmark problem. 
 It consists of a tapered plate clamped
 on one of its sides with a transversal distributed load
 applied to the opposite side. The plate is in plain strain
 and its dimensions, as well as the material parameters
 and boundary conditions, are shown in figure bellow</p>
  </li>
</ul>

<p><img src="https://oofem.github.io/assets/images/cookGeometry.png" alt="Cook membrane geometry and boundary conditions" /></p>

<p>The complete OOFEM input deck for mesh consisting of 2x2 is shown below</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cook2.out
Demo of symbolic mpm problem; Cook membrane benchmark
# 
test nsteps 1 nvariables 4 nterms 5 nintegrals 5 lhsterms 4 1 2 3 4 rhsterms 1 5
Variable name "u" interpolation "feilin" type 1 quantity 0 size 2 dofs 2 1 2 # displacement 
Variable name "w" interpolation "feilin" type 1 quantity 0 size 2 dofs 2 1 2 # test function
Variable name "p" interpolation "feiconst"  type 0 quantity 3 size 1 dofs 1 11 # pressure 
Variable name "q" interpolation "feiconst" type 0 quantity 3 size 1 dofs 1 11 # test function
BTSigmaTerm 1 variable "u"  testvariable "w" mmode 7 lhsmatmode 29
BTamNTerm 2 variable "p" testvariable "w" mmode 7 atype 28
NTamTBTerm 3 variable "u" testvariable "q" mmode 7 atype 28
NTcN 4 variable "p" testvariable "q" mmode 7 ctype 27
NTfTerm 5 variable "u" testvariable "w" mmode 6 flux 2 0. 6.25
#NTfTerm 5 variable "u" testvariable "w" mmode 6 flux 2 0. 31.25
Integral 1 domain 1 set 1 term 1
Integral 2 domain 1 set 1 term 2 factor -1.0
Integral 3 domain 1 set 1 term 3 factor -1.0
Integral 4 domain 1 set 1 term 4 factor -1.0
Integral 5 domain 1 set 2 term 5
domain HeatTransfer
outputmanager tstep_all dofman_all element_all
ndofman 9 nelem 6 nbc 1 ncrosssect 1 nic 0 nltf 2 nmat 1 nset 3
Node 1 coords 3 0.0 0.0 0.0
Node 2 coords 3 24.0 22.0 0.0
Node 3 coords 3 48.0 44.0 0.0
Node 4 coords 3 0.0 22.0 0.0
Node 5 coords 3 24.0 37.0 0.0
Node 6 coords 3 48.0 52.0 0.0
Node 7 coords 3 0.0 44.0 0.0
Node 8 coords 3 24.0 52.0 0.0
Node 9 coords 3 48.0 60.0 0.0
q1 1 nodes 4 1 2 5 4 mat 1 crosssect 1
q1 2 nodes 4 2 3 6 5 mat 1 crosssect 1
q1 3 nodes 4 4 5 8 7 mat 1 crosssect 1
q1 4 nodes 4 5 6 9 8 mat 1 crosssect 1
l1 5 nodes 2 3 6 mat 1 crosssect 1
l1 6 nodes 2 6 9 mat 1 crosssect 1
simplecs 1 thick 5.0
isole 1 d 1 e 250 n 0.49999 talpha 1.
# clamped-displacement
boundarycondition 1 loadtimefunction 1 set 3 values 2 0 0   dofs 2 1 2
constantfunction 1 f(t) 1
PiecewiseLinFunction 2 nPoints 4 t 4 -10. 0. 1. 5. f(t) 4 0. 0. 1.0 1.0
set 1 elementranges  {(1 4)}
set 2 elementranges  {(5 6)}
set 3 elementedges 4 1 4 3 4
</code></pre></div></div>
<p>The complete input deck can be found in <a href="https://raw.githubusercontent.com/oofem/oofem/refs/heads/mpm2/tests/mpm/cook2_u1p0.in">tests/mpm/cook2_u1p0.in</a> file.</p>

<h3 id="switching-to-high-order-interpolation">Switching to high-order interpolation</h3>
<p>To switch to high order element Q2P1 with quadratic interpolation of displacement and linear interpolation of pressure we need just to use different interpolations for variables. The updated variable input records are following</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Variable name "u" interpolation "feiquad" type 1 quantity 0 size 2 dofs 2 1 2 # displacement 
Variable name "w" interpolation "feiquad" type 1 quantity 0 size 2 dofs 2 1 2 # test function
Variable name "p" interpolation "feilin"  type 0 quantity 3 size 1 dofs 1 11 # pressure 
Variable name "q" interpolation "feilin" type 0 quantity 3 size 1 dofs 1 11 # test function
</code></pre></div></div>
<p>The complete input deck can be found in <a href="https://raw.githubusercontent.com/oofem/oofem/refs/heads/mpm2/tests/mpm/cook2_u2p1.in">tests/mpm/cook2_u2p1.in</a> file.</p>

<p>Note: At the time of writing, the oofem version from mpm2 branch is required to run the example.</p>

<p>To illustrate the convergence, sequence of uniform meshes of the plate is considered,
 starting from a mesh consisting of a single elements and proceeding by uniform refinement.</p>

<p>The figure below shows the vertical displacement of the plane tip plotted against the number of element segments along each side. The solution is compared to reference solution <sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup>.</p>

<p><img src="https://oofem.github.io/assets/images/cookConvergence.png" alt="Cook membrane convergence graph" /></p>

<p>With this I conclude today post on mpm module. 
Hope you enjoyed and stay tuned for following updates!</p>

<p>You are welcome to leave a comment below to give a feedback.</p>

<h3 id="references">References</h3>
<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Ignacio Romero, Manfred Bischoff, Incompatible Bubbles: A non-conforming finite element formulation for linear elasticity, Computer Methods in Applied Mechanics and Engineering, Volume 196, Issues 9–12, 2007, Pages 1662-1672, ISSN 0045-7825, https://doi.org/10.1016/j.cma.2006.09.010. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="tutorial" /><category term="mpm" /><summary type="html"><![CDATA[Mixed formulation for incompressible elasticity using MPM symbolic module A formulation of the elasticity problem able to represent the incompressible behavior can be written using mixed approach involving pressure and displacement fields]]></summary></entry><entry><title type="html">First steps with symbolic mpm module (input file syntax)</title><link href="https://oofem.github.io/blog/mpm-inputfile-interface/" rel="alternate" type="text/html" title="First steps with symbolic mpm module (input file syntax)" /><published>2025-01-28T00:00:00+01:00</published><updated>2025-01-28T00:00:00+01:00</updated><id>https://oofem.github.io/blog/mpm-inputfile-interface</id><content type="html" xml:base="https://oofem.github.io/blog/mpm-inputfile-interface/"><![CDATA[<h2 id="first-steps-with-new-oofem-multi-physics-module-mpm">First steps with new OOFEM multi-physics module (MPM)</h2>

<p>What is MPM?
MPM is new multi-physic OOFEM module, developed to make implementation of multi-physics problems more simple. In this tutorial we will focus on symbolic MPM extension. This extension is somehow different from traditional OOFEM modules.</p>

<p>In traditional OOFEM problem setup, the user discretizes the problem using problem-specific elements, boundary conditions, etc. that provide necessary functionality to solve the problem.
On the other hand, the symbolic MPM module allows to use universal, problem independent elements. These elements just define geometry. What is going to be evaluated is defined using <strong>Terms</strong>, that are evaluated on elements and integrated using <strong>Integrals</strong>. <strong>Terms</strong> can be evaluated on any element using user defined <strong>Interpolations</strong>. In this way, the problem definition is more like defining the weak form of the problem.</p>

<p>The basic design ideas behind MPM are following:</p>
<ul>
  <li>MPM defines <strong>Interpolations</strong>, <strong>Variables</strong>, <strong>Terms</strong>, <strong>Integrals</strong> as reusable blocks to create multiphysics formulations</li>
  <li><strong>Variables</strong> represent unknown fields (or test felds) in a weak form of the problem. The variable has its interpolation, type (scalar, vector) and physical meaning defined.</li>
  <li><strong>Terms</strong> represent an integrand in weak formulation to be evaluated (integrated). Term definition is independent on underlying element geometry and interpolation. It defines two key methods:
    <ul>
      <li>method to evaluate the term value, typically contributing to RHS of discrete system.</li>
      <li>method to evaluate the consistent linearization of the term, so if Term is T(u), depending on unknown u, this term evaluates dT/du, which typically contributes to the LHS.</li>
    </ul>
  </li>
  <li><strong>Interpolations</strong> are representing different FE interpolations.</li>
  <li><strong>Integral</strong> represents the integral of term in a weak form. It can compute its contributions to the discrete set of equations.</li>
</ul>

<p>The concept allows for parametrization with different element geometries and interpolations. Also, the components (interpolations, terms) can be reused/shared between different formulations.
In the <a href="https://oofem.github.io/blog/mpm-introduction/">previous post on mpm module</a> I have introduced the Python interface of MPM module. In this post, I will illustrate mpm features on example set-up from traditional OOFEM input deck.</p>

<p>We will consider the same linear 2D elasticity problem, defined by following weak form of equilibrium equations:</p>

\[\int_\Omega (\partial w)^T \sigma (\partial u)\ d\Omega = \int_\Omega w^T \rho g d\Omega + \int_\Gamma w^T t d\Gamma\]

<p>where</p>
<ul>
  <li>u,w are variables (fileds), represented by <em>Variable</em> class instances</li>
  <li>$\left[ (\partial w)^T \sigma (\partial u)\right] $ and $\left[ (w)^Tt \right]$ are Terms, parametrized (to be evaluated) by u,w, represented by classes <em>BTSigmaTerm</em> and <em>NTfTerm</em> (derived from parent <em>Term</em> class).</li>
</ul>

<p>When term is evaluated, the interpolations of the test and unknown fields as well as the element geometry are substituted. In the following notation, the approximations on the element level are expressed as $u^e=\sum N_u r_u$ and $w^e=\sum N_w r_w$.</p>

<h3 id="simple-example">Simple example</h3>

<p>We will use OOFEM input deck to demonstrate the concept of setting up the problem of cantilever beam fixed on the left-hand side and loaded by distributed loading on free, right-hand edge.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     y↑ 
      |6              7               8               9                10
      +---------------+---------------+---------------+---------------+  +­­­­­­­­­­↑
      |               |               |               |               |  |↑
      |               |               |               |               |  |↑
      |       1       |       2       |       3       |       4       | 5|↑
      |               |               |               |               |  |↑
      |               |               |               |               |  |↑
      +---------------+---------------+---------------+---------------+  +↑ fy=1.0   ---&gt;x
      1               2               3               4                 5
</code></pre></div></div>
<p>In the following I illustrate the setup of the problem using traditional oofem input deck syntax, which has been extended to allow for definition of Variables, Terms, and Integrals. If you are already familiar with OOFEM input syntax you will conceptually understand, the details and syntax can be found in OOFEM input manual. For presentation purposes, the complete input deck has been broken into parts to allow for intermediate comments:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>demo.out
Demo of symbolic mpm problem; bending of clamped cantilever (l=3, h=0.3) loaded at the free end
#
# Note the new input sections for Terms, Variables and Integrals
# this exampkle requires oofem to be compiled with MPM support (USE_MPM=ON)
#  
test nsteps 1 nvariables 2 nterms 2 nintegrals 2 lhsterms 1 1 rhsterms 1 2 nmodules 1
#vtkxml primvars 1 1 tstep_all
errorcheck
</code></pre></div></div>
<p>Introduce test and unknown vector fields with linear approximation space:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Variable name "u" interpolation "feilin" type 1 quantity 0 size 2 dofs 2 1 2 # displacement 
Variable name "w" interpolation "feilin" type 1 quantity 0 size 2 dofs 2 1 2 # test function
</code></pre></div></div>
<p>Set up Terms appearing in the weak form</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BTSigmaTerm 1 variable "u"  testvariable "w" mmode 6
NTfTerm 2 variable "u" testvariable "w" mmode 6 flux 2 0. 1.
</code></pre></div></div>
<p>Set up two integrals (one over the volume, second over the boundary where load is applied)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Integral 1 domain 1 set 1 term 1
Integral 2 domain 1 set 2 term 2
</code></pre></div></div>
<p>The input file continues with traditional records. Note that we are using universal elements (quads q1 and lines l1)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>domain HeatTransfer
outputmanager tstep_all dofman_all element_all
ndofman 10 nelem 5 nbc 2 ncrosssect 1 nic 0 nltf 2 nmat 1 nset 4
# Set up nodes
node 1  coords 3 0.            0.           0.
node 2  coords 3 0.75          0.           0.
node 3  coords 3 1.5           0.           0.
node 4  coords 3 2.25          0.           0.
node 5  coords 3 3.0           0.           0.
node 6  coords 3 0.            0.3          0.
node 7  coords 3 0.75          0.3          0.
node 8  coords 3 1.5           0.3          0.
node 9  coords 3 2.25          0.3          0.
node 10 coords 3 3.0           0.3          0.
# Set up universal (quad) elements
q1 1 nodes 4 1 2 7 6  mat 1 crosssect 1
q1 2 nodes 4 2 3 8 7  mat 1 crosssect 1
q1 3 nodes 4 3 4 9 8  mat 1 crosssect 1
q1 4 nodes 4 4 5 10 9 mat 1 crosssect 1
# boundary element 
l1 5 nodes 2 5 10     mat 1 crosssect 1
# Traditional set up of materials, cross sections boundary conditions and sets
simplecs 1 thick 1.0
isole 1 d 1 e 1 n 0.3 talpha 1.
# x-displacement
boundarycondition 1 loadtimefunction 1 set 3 values 1 0   dofs 1 1 
# y-displacement
boundarycondition 2 loadtimefunction 1 set 4 values 1 0   dofs 1 2 
#
#
constantfunction 1 f(t) 1
PiecewiseLinFunction 2 nPoints 4 t 4 -10. 0. 1. 5. f(t) 4 0. 0. 1.0 1.0 
set 1 elements 4 1 2 3 4
# 
set 2 elements 1 5
# x-bc, note that set 3 is defined using element edge
set 3 elementedges 2 1 4
# y-bc, note that set 3 is defined using element edge
#set 4 nodes 3 1 6 11
set 4 elementedges 2 1 4 
</code></pre></div></div>
<p>Save the above input file into demo.in file.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./oofem -f demo.in
</code></pre></div></div>
<p>The complete input deck can be found in <a href="https://raw.githubusercontent.com/oofem/oofem/refs/heads/mpm2/tests/mpm/mpms03.in">tests/mpm/mpms03.in</a> file.</p>

<h3 id="simple-example---quadratic-interpolation">Simple example - quadratic interpolation</h3>

<p>Let’s switch now to quadratic interpolation. The nice thing here is that it is sufficient to change only two lines in input file to get solved the problem using quadratic interpolation. We just need to locate the records defining test and unknown fields and update the interpolation:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Variable name "u" interpolation "feiquad" type 1 quantity 0 size 2 dofs 2 1 2 # displacement 
Variable name "w" interpolation "feiquad" type 1 quantity 0 size 2 dofs 2 1 2 # test function
</code></pre></div></div>
<p>All the magic needed to introduce additional nodes on shared edges, setting up integration rules, etc. will happen automatically for you.
The complete input deck can be found in <a href="https://raw.githubusercontent.com/oofem/oofem/refs/heads/mpm2/tests/mpm/mpms04.in">tests/mpm/mpms04.in</a> file.</p>

<h3 id="simple-example---results--conclusions">Simple example - results &amp; conclusions</h3>
<p>The analytical solution (beam theory, assuming only the bending moment contribution) is <br />
$w_{ex}=FL^3/(3EI) = 0.3\times3^3/(3\times1\times0.3^3/12.)=1200$.</p>

<p>The resulting end deflection (node 10), obtained with linear approximation is $w_{lin}=345.03$.
The deflection obtained using quadratic interpolation is $w_q=1178.8$, clearly demonstrating the superior convergence properties of quadratic interpolation over the linear one.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>linear approx.</th>
      <th>quadratic approx.</th>
      <th>exact (beam theory)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>End deflection</td>
      <td>345.03</td>
      <td>1178.8</td>
      <td>1200.0</td>
    </tr>
  </tbody>
</table>

<p>However, the purpose of this post was to illustrate the power of MPM symbolic module and its capabilities. 
With this I conclude today post on mpm module.</p>

<p>Hope you enjoyed and stay tuned for following updates!
You can leave a comment below to give a feedback.</p>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="tutorial" /><category term="mpm" /><summary type="html"><![CDATA[First steps with new OOFEM multi-physics module (MPM)]]></summary></entry><entry><title type="html">First steps with new OOFEM multi-physics module (mpm)</title><link href="https://oofem.github.io/blog/mpm-introduction/" rel="alternate" type="text/html" title="First steps with new OOFEM multi-physics module (mpm)" /><published>2024-05-25T00:00:00+02:00</published><updated>2024-05-25T00:00:00+02:00</updated><id>https://oofem.github.io/blog/mpm-introduction</id><content type="html" xml:base="https://oofem.github.io/blog/mpm-introduction/"><![CDATA[<h2 id="first-steps-with-new-oofem-multi-physics-module-mpm">First steps with new OOFEM multi-physics module (MPM)</h2>

<p>What is MPM?
MPM is new multi-physic OOFEM module, developed to make implementation of multi-physics problems more simple.</p>

<p>What are the design ideas behind MPM?</p>
<ul>
  <li>MPM defines <strong>Interpolations</strong>, <strong>Variables</strong>, <strong>Terms</strong>, <strong>Integrals</strong> as reusable blocks to create multi-physics formulations</li>
  <li><strong>Variables</strong> represent unknown fields (or test fields) in a weak form of the problem. The variable has its interpolation, type (scalar, vector) and physical meaning defined.</li>
  <li><strong>Terms</strong> represent an integrand in weak formulation to be evaluated (integrated). Term definition is independent on underlying element geometry and interpolation. It defines two key methods:
    <ul>
      <li>method to evaluate the term value, typically contributing to RHS of discrete system.</li>
      <li>method to evaluate the consistent linearization of the term, so if Term is T(u), depending on unknown u, this term evaluates dT/du, which typically contributes to the LHS.</li>
    </ul>
  </li>
  <li><strong>Interpolations</strong> are representing different FE interpolations.</li>
  <li><strong>Integral</strong> represents the integral of term in a weak form. It can compute its contributions to the discrete set of equations.</li>
</ul>

<p>The concept allows for parametrization with different element geometries and interpolations. Also, the components (interpolations, terms) can be reused/shared between different formulations.
I will illustrate the concept using oofem python bindings, which allows for fast prototyping.</p>

<p>In the example below, we reuse already defined terms in oofem, but it is possible to define your own terms, interpolations, etc.</p>

<p>As an example, consider the weak form of equilibrium equations:</p>

\[\int_\Omega (\partial w)^T \sigma (\partial u)\ d\Omega = \int_\Omega w^T \rho g d\Omega + \int_\Gamma w^T t d\Gamma\]

<p>where</p>
<ul>
  <li>u,w are variables (fileds), represented by <em>Variable</em> class instances</li>
  <li>$\left[ (\partial w)^T \sigma (\partial u)\right] $ and $\left[ (w)^Tt \right]$ are Terms, parametrized (to be evaluated) by u,w, represented by classes <em>BTSigmaTerm</em> and <em>NTfTerm</em> (derived from parent <em>Term</em> class).</li>
</ul>

<p>When term is evaluated, the interpolations of the test and unknown fields as well as the element geometry are substituted. In the following notation, the approximations on the element level are expressed as $u^e=\sum N_u r_u$ and $w^e=\sum N_w r_w$. As this in general yields to a nonlinear system of equations, the term on left hand side evaluates</p>
<ul>
  <li>residual contribution for given element, essentially evaluating itself with all variables known. In our example this corresponds to evaluating $\int_\Omega^e (\partial N_w)^T\sigma(\partial N_u r_u)\ d\Omega^e$</li>
  <li>its linearization, corresponding in our case to $\int_\Omega^e (\partial N_w)^T \frac{\partial \sigma}{\partial \varepsilon} (\partial N_u)\ d\Omega^e$.</li>
</ul>

<h3 id="simple-example">Simple example</h3>
<p>We will use OOFEM python interface to demonstrate the concept on the problem presented above.
First set up simple mesh, consisting of single quad element, defined by four nodes. Plus standard definition of materials, boundary conditions, etc.</p>

<p>The demo plane-stress elasticity problem consist of two elements. One is quad element representing the domain, the second is boundary element (linear segment) representing boundary between nodes 2,3 subjected to distributed loading.
Node 1 is fixed in all directions, node 4 is fixed in x direction.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     y↑ 4[0,5]         3[3,4]
      +---------------+  +→
      |               |  |→
      |               |  |→
      |       1       | 2|→
      |               |  |→
      |               |  |→
      +---------------+  +→ fx=1.0   ---&gt;x
      1 [0,0]           2[1,2]
</code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Requires oofempy compiled with __MPM_MODULE ON
</span><span class="kn">import</span> <span class="nn">sys</span>
<span class="n">sys</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">extend</span><span class="p">([</span><span class="s">'/home/bp/devel/oofem.git/build'</span><span class="p">,</span> <span class="s">'/home/bp/devel/oofem.git/bindings/python'</span><span class="p">])</span>
<span class="kn">import</span> <span class="nn">oofempy</span>
<span class="kn">import</span> <span class="nn">util</span>

 

<span class="c1"># Create a new dummy problem (placeholder for our demo) with one domain.
</span><span class="n">problem</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">dummyProblem</span><span class="p">(</span><span class="n">nSteps</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">outFile</span><span class="o">=</span><span class="s">'test_7.out'</span><span class="p">)</span>
<span class="n">domain</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">domain</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">problem</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">domainType</span><span class="p">.</span><span class="n">_HeatTransferMode</span><span class="p">,</span> <span class="n">tstep_all</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">dofman_all</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">element_all</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">problem</span><span class="p">.</span><span class="n">setDomain</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
   
<span class="c1"># Define nodes
</span><span class="n">n1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">node</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">coords</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mf">0.</span> <span class="p">))</span>
<span class="n">n2</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">node</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">coords</span><span class="o">=</span><span class="p">(</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">,</span> <span class="mf">0.</span> <span class="p">))</span>
<span class="n">n3</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">node</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">coords</span><span class="o">=</span><span class="p">(</span><span class="mf">1.</span><span class="p">,</span> <span class="mf">1.</span><span class="p">,</span> <span class="mf">0.</span> <span class="p">))</span>
<span class="n">n4</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">node</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">coords</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mf">0.</span> <span class="p">))</span>
   
<span class="c1"># Defdine elements, note that q1 defines just element geometry.
</span><span class="n">q1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">q1</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">),</span> <span class="n">mat</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">crossSect</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># quad element #1
</span><span class="n">l1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">l1</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">),</span> <span class="n">mat</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">crossSect</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>     <span class="c1"># boundary element #2
</span>
<span class="c1"># Dirichlet Boundary conditions
</span><span class="n">bc1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">boundaryCondition</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">loadTimeFunction</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">dofs</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">),</span> <span class="n">values</span><span class="o">=</span><span class="p">(</span><span class="mf">0.</span><span class="p">,</span><span class="mf">0.</span><span class="p">),</span> <span class="nb">set</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">bc2</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">boundaryCondition</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">loadTimeFunction</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">dofs</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,),</span>  <span class="n">values</span><span class="o">=</span><span class="p">(</span><span class="mf">0.</span><span class="p">,),</span>   <span class="nb">set</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="c1"># material and cross section
</span><span class="n">mat</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">isoLE</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">d</span><span class="o">=</span><span class="mf">1.</span><span class="p">,</span> <span class="n">e</span><span class="o">=</span><span class="mf">1.</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mf">0.3</span><span class="p">,</span> <span class="n">talpha</span><span class="o">=</span><span class="mf">1.</span><span class="p">)</span>
<span class="n">cs</span>  <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">simpleCS</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">mat</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">thickness</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span>
<span class="c1"># time functions
</span><span class="n">ltf1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">constantFunction</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">f_t</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span>
<span class="c1"># some sets (groups of nodes and elements) for later use
</span><span class="n">s1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">createSet</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,))</span>
<span class="n">s2</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">createSet</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="p">(</span><span class="mi">4</span><span class="p">,))</span>
<span class="n">s3</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">createSet</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">elements</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,))</span>
<span class="n">bs1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">createSet</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">elements</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,))</span>
<span class="n">util</span><span class="p">.</span><span class="n">setupDomain</span><span class="p">(</span><span class="n">domain</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span><span class="n">n2</span><span class="p">,</span><span class="n">n3</span><span class="p">,</span><span class="n">n4</span><span class="p">),</span> <span class="n">elems</span><span class="o">=</span><span class="p">(</span><span class="n">q1</span><span class="p">,</span><span class="n">l1</span><span class="p">),</span> <span class="n">css</span><span class="o">=</span><span class="p">(</span><span class="n">cs</span><span class="p">,),</span> <span class="n">mats</span><span class="o">=</span><span class="p">(</span><span class="n">mat</span><span class="p">,),</span> <span class="n">bcs</span><span class="o">=</span><span class="p">(</span><span class="n">bc1</span><span class="p">,</span><span class="n">bc2</span><span class="p">),</span> <span class="n">ics</span><span class="o">=</span><span class="p">(),</span> <span class="n">ltfs</span><span class="o">=</span><span class="p">(</span><span class="n">ltf1</span><span class="p">,),</span> <span class="n">sets</span><span class="o">=</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span><span class="n">s2</span><span class="p">,</span><span class="n">s3</span><span class="p">,</span><span class="n">bs1</span><span class="p">))</span>

</code></pre></div></div>

<p>Now the interesting part begins:</p>
<ul>
  <li>Define the $u$ and $w$ fields (variables), with linear interpolation, with physical meaning of Displacement vector of size 2, with two degrees of freedom u,v (2D)</li>
  <li>Create instances of BTSigmaTerm, NTfTerm to be evaluated for $u,w$ in plane stress mode.</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">interpolation</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">linearinterpolation</span><span class="p">()</span>
<span class="n">w</span><span class="o">=</span> <span class="n">u</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">Variable</span><span class="p">(</span><span class="n">interpolation</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">VariableQuantity</span><span class="p">.</span><span class="n">Displacement</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">VariableType</span><span class="p">.</span><span class="n">vector</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="bp">None</span><span class="p">)</span>
<span class="n">mt</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">BTSigmaTerm</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">MaterialMode</span><span class="p">.</span><span class="n">_PlaneStress</span><span class="p">)</span>
<span class="n">lt</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">NTfTerm</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">u</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">MaterialMode</span><span class="p">.</span><span class="n">_PlaneStress</span><span class="p">)</span>
<span class="n">tstep</span> <span class="o">=</span> <span class="n">problem</span><span class="p">.</span><span class="n">giveNextStep</span><span class="p">()</span>

</code></pre></div></div>

<p>Now define integrals forming our weak form. Integral <code class="language-plaintext highlighter-rouge">I1</code> over $\Omega$, defined by set <code class="language-plaintext highlighter-rouge">s3</code> (containing element 1) and boundary integral <code class="language-plaintext highlighter-rouge">I2</code> over boundary edge 2-3, defined by set <code class="language-plaintext highlighter-rouge">bs1</code>.<br />
The integrals need to be initialized (allocates the needed DOFs, sets up the element integration rules, etc.) as well as the entire problem (number the equations).</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">I1</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">Integral</span><span class="p">(</span><span class="n">domain</span><span class="p">,</span> <span class="n">s3</span><span class="p">,</span> <span class="n">mt</span><span class="p">)</span>
<span class="n">problem</span><span class="p">.</span><span class="n">addIntegral</span><span class="p">(</span><span class="n">I1</span><span class="p">)</span>
<span class="n">I1</span><span class="p">.</span><span class="n">initialize</span><span class="p">()</span>

<span class="n">I2</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">Integral</span><span class="p">(</span><span class="n">domain</span><span class="p">,</span> <span class="n">bs1</span><span class="p">,</span> <span class="n">lt</span><span class="p">)</span>
<span class="n">I2</span><span class="p">.</span><span class="n">initialize</span><span class="p">()</span>

<span class="n">problem</span><span class="p">.</span><span class="n">postInitialize</span><span class="p">()</span>
<span class="n">problem</span><span class="p">.</span><span class="n">forceEquationNumbering</span><span class="p">()</span>

</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>OctreeLocalizer: init
Spatial localizer init done
</code></pre></div></div>

<p>We are now approaching the part where we will use all the concepts:</p>
<ul>
  <li>Create sparse matrix instance (<em>lhs</em>) to hold stiffness matrix</li>
  <li>The stiffness matrix is assembled by integral <em>I1</em> instance using its <em>assemble_lhs</em> method, that will integrate the linearization of our term over all elements in domain defined by integral domain.</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">lhs</span><span class="o">=</span><span class="n">oofempy</span><span class="p">.</span><span class="n">skyline</span><span class="p">()</span>
<span class="n">lhs</span><span class="p">.</span><span class="n">buildInternalStructure</span><span class="p">(</span><span class="n">problem</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">EModelDefaultEquationNumbering</span><span class="p">());</span>
<span class="n">I1</span><span class="p">.</span><span class="n">assemble_lhs</span><span class="p">(</span><span class="n">lhs</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">EModelDefaultEquationNumbering</span><span class="p">(),</span> <span class="n">tstep</span><span class="p">)</span>
<span class="n">lhs</span><span class="p">.</span><span class="n">printYourself</span><span class="p">()</span>
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>FloatMatrix with dimensions : 5 5
 4.945e-01  -1.786e-01   5.495e-02  -1.374e-02   1.786e-01  
-1.786e-01   4.945e-01   1.374e-02  -3.022e-01  -2.473e-01  
 5.495e-02   1.374e-02   4.945e-01   1.786e-01  -1.374e-02  
-1.374e-02  -3.022e-01   1.786e-01   4.945e-01   5.495e-02  
 1.786e-01  -2.473e-01  -1.374e-02   5.495e-02   4.945e-01  
</code></pre></div></div>

<p>Assemble load vector forming right hand side of the problem</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">rhs</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">FloatArray</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>

<span class="n">I2</span><span class="p">.</span><span class="n">assemble_rhs</span><span class="p">(</span><span class="n">rhs</span><span class="p">,</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">EModelDefaultEquationNumbering</span><span class="p">(),</span> <span class="n">tstep</span><span class="p">)</span>
<span class="n">rhs</span><span class="p">.</span><span class="n">printYourself</span><span class="p">()</span>

</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>FloatArray of size : 5 
 5.000e-01   0.000e+00   5.000e-01   0.000e+00   0.000e+00  
</code></pre></div></div>

<p>Finally, use suitable linear solver to solve for unknown displacement field.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">r</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">FloatArray</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="n">linsolv</span> <span class="o">=</span> <span class="n">oofempy</span><span class="p">.</span><span class="n">ldltfactorization</span><span class="p">(</span><span class="n">domain</span><span class="p">,</span> <span class="n">problem</span><span class="p">)</span>
<span class="n">linsolv</span><span class="p">.</span><span class="n">solve</span><span class="p">(</span><span class="n">lhs</span><span class="p">,</span> <span class="n">rhs</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
<span class="k">print</span> <span class="p">(</span><span class="s">"Displacement vector = "</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Displacement vector =  &lt;oofempy.FloatArray: {1, -2.77556e-17, 1, -0.3, -0.3, }&gt;
</code></pre></div></div>

<p>Hope you enjoyed!</p>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="tutorial" /><category term="mpm" /><summary type="html"><![CDATA[First steps with new OOFEM multi-physics module (MPM)]]></summary></entry><entry><title type="html">Welcome to OOFEM.github.io !</title><link href="https://oofem.github.io/blog/welcome-to-oofem-gitub-io/" rel="alternate" type="text/html" title="Welcome to OOFEM.github.io !" /><published>2024-04-21T20:15:30+02:00</published><updated>2024-04-21T20:15:30+02:00</updated><id>https://oofem.github.io/blog/welcome-to-oofem-gitub-io</id><content type="html" xml:base="https://oofem.github.io/blog/welcome-to-oofem-gitub-io/"><![CDATA[<p>This site is set up to provide a platform for blogging about the OOFEM project.</p>

<p>Particularly, the following posts are welcome:</p>
<ul>
  <li>Feature previews: Share sneak peeks of upcoming features or enhancements. This generates excitement and anticipation among your users.</li>
  <li>New features: Inform the community about the latest features you’ve implemented. Explain how they work, their benefits, and how users can leverage them effectively.</li>
  <li>Present your interesting work: Document and discuss challenges you’ve encountered when solving particular problem. Describe your model and present results as this can be
both educational and engaging.</li>
  <li>Present your papers and research findings obtained with the help of OOFEM: Diseminate and share your results with OOFEM community.</li>
  <li>Project-Related Announcements: Keep community informed about project milestones, releases, and other significant updates.</li>
</ul>

<p>To contribute, clone the <a href="https://github.com/oofem/oofem.github.io">oofem.github.io</a> repository. Create new post in _posts directory and make a pull request. Please follow Minimal-mistakes and Jekyll <a href="https://mmistakes.github.io/minimal-mistakes/docs/posts/">conventions and formatting</a>.</p>

<p>Remember, fostering a culture of knowledge sharing and collaboration will inspire users to actively participate and contribute to the OOFEM project. 🌟📝</p>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="announcement" /><summary type="html"><![CDATA[This site is set up to provide a platform for blogging about the OOFEM project.]]></summary></entry><entry><title type="html">Autumn 2024 training course</title><link href="https://oofem.github.io/blog/Autumn-training-course/" rel="alternate" type="text/html" title="Autumn 2024 training course" /><published>2024-04-21T00:00:00+02:00</published><updated>2024-04-21T00:00:00+02:00</updated><id>https://oofem.github.io/blog/Autumn-training-course</id><content type="html" xml:base="https://oofem.github.io/blog/Autumn-training-course/"><![CDATA[<p>OOFEM.org is announcing the 2024 autumn training course for Ph.D. students, engineers, 
and researchers to allow them to quickly acquire the knowledge and practical skills necessary to employ OOFEM.</p>

<p>Course date: 9-11. September, 2024
Venue: Czech Technical University, Prague, Czech Republic
See <a href="https://oofem.org/doku.php?id=en:courses">Courses page</a> for more information and registration</p>]]></content><author><name>Bořek Patzák</name></author><category term="blog" /><category term="announcement" /><category term="training" /><summary type="html"><![CDATA[OOFEM.org is announcing the 2024 autumn training course for Ph.D. students, engineers, and researchers to allow them to quickly acquire the knowledge and practical skills necessary to employ OOFEM.]]></summary></entry></feed>