# After convergence of an alternate minimization step, we compute the vertical force acting on the top surface. For this purpose, we previously defined a function `v` with a vertical component equal to 1 on the top boundary and zero everywhere. The action of the residual form in this field is precisely the resulting vertical force of the imposed boundary conditions.
# We also compute the total stored and dissipated energy. The former has been defined in `PhaseFieldDisplacement.mfront` and the second in `PhaseFieldDamage.mfront`.
# In[]:
# In[4]:
tol,Nitermax=1e-3,500
...
...
@@ -374,16 +374,16 @@ for (i, t) in enumerate(loading[1:]):
# Load-displacement and energy evolution curves show that there is a phase of brutal crack nucleation followed by a more stable crack propagation phase towards the plate boundaries. The solution vertical symmetry is lost in the last load steps when approaching the plate boundaries as already mentioned in [@bourdin2000numerical].
# This demo is a direct transposition of the [transient thermo-elasticity demo](https://comet-fenics.readthedocs.io/en/latest/demo/thermoelasticity/thermoelasticity_transient.html) using a pure `FEniCS` formulation. We will show how to compute fully coupled thermo-mechanical problems using `MFront`, which can pave the way to more complex thermo-mechanical behaviours including plasticity for instance.
#
# ## Constitutive equations
#
# The constitutive equations are derived from the following expression of
# The computation of the consistent tangent operator is only required if
# the `computeTangentOperator_` boolean value is true. Again, their
# computations is straightforward [2]:
#
# ``` cxx
# if (computeTangentOperator_) {
# ∂σ∕∂Δεᵗᵒ = λ ⋅ (I₂ ⊗ I₂) + 2 ⋅ μ ⋅ I₄;
# ∂σ∕∂ΔT = -κ ⋅ I₂;
# ∂s∕∂ΔT = Cₑ / Tʳᵉᶠ;
# ∂s∕∂Δεᵗᵒ = κ ⋅ Cₑ / Tʳᵉᶠ ⋅ I₂;
# ∂j∕∂Δ∇T = -k ⋅ tmatrix<N, N, real>::Id();
# }
# ```
#
# A final curly bracket then ends the `@Integrator` code block:
#
# ``` cxx
# }
# ```
#
# [1] We may also note that those blocks are third order tensors that are
# not yet supported by `MFront`.
#
# [2] `N` is the space dimension. `real` is a type alias to the numeric
# type used, which depends on the interface used.
# ## `FEniCS` implementation
#
# ### Problem position
#
# The problem consists of a quarter of a square plate perforated by a circular hole. A temperature increase of $\Delta T=+10^{\circ}\text{C}$ will be applied on the hole boundary. Symmetry conditions are applied on the corresponding symmetry planes and stress and flux-free boundary conditions are adopted on the plate outer boundary. Similarly to the [original demo](https://comet-fenics.readthedocs.io/en/latest/demo/thermoelasticity/thermoelasticity_transient.html), we will formulate the problem using the temperature variation as the main unknown.
#
# We first import the relevant modules then define the mesh and some constants.
# We now define the relevant FunctionSpace for the considered problem. Since we will adopt a monolithic approach i.e. in which both fields are coupled and solved at the same time, we will need to resort to a Mixed FunctionSpace for both the displacement $\boldsymbol{u}$ and the temperature variation $\Theta = T-T^\text{ref}$.
# In[2]:
Vue=VectorElement("CG",mesh.ufl_cell(),2)# displacement finite element
Vte=FiniteElement("CG",mesh.ufl_cell(),1)# temperature finite element
# with $V_U$ and $V_T$ being the displacement and temperature function spaces.
#
# The time derivative in the heat equation is now replaced by an implicit Euler scheme, so that the previous weak form at the time increment $n+1$ is now:
# where $s^{n+1},\bj^{n+1}$ correspond to the *unknown* entropy and heat flux at time $t_{n+1}$.
#
# Since both the entropy and the stress tensor depend on the temperature and the total strain, we obtain a fully coupled problem at $t=t_{n+1}$ for $(\boldsymbol{u}_{n+1},T_{n+1})\in V_U\times V_T$. With the retained boundary conditions both right-hand sides in $\eqref{eq:coupled-system}$.
#
# We now load the material behaviour and define the corresponding `MFrontNonlinearProblem`. One notable specificity of the present example is that the unknown field `v` belongs to a mixed function space. Therefore, we cannot rely on automatic registration for the strain and temperature gradient. We will have to specify explicitly their UFL expression with respect to the displacement `u` and temperature variation `Theta` sub-functions of the mixed unknown `v`. We also register the `"Temperature"` external state variable with respect to `Theta`.
# Similarly to the [Transient heat equation with phase change demo](https://thelfer.github.io/mgis/web/mgis_fenics_heat_equation_phase_change.html), we need to specify explicitly the coupled thermo-mechanical residual expression using the stress, heat flux and entropy variables. For the implicit Euler scheme, we will need to define the entropy at the previous time step. For the mechanical residual, note that the stress variable `sig` is represented in the form of its vector of components. The computation of $\bsig :\nabla^s\widehat{\boldsymbol{u}}$ therefore requires to express $\widehat{\beps}=\nabla^s\widehat{\boldsymbol{u}}$ in the same way. For this purpose, we could use the `mgis.fenics.utils.symmetric_tensor_to_vector` on the tensorial UFL expression `sym(grad(u))`. Another possibility is to get the corresponding `"Strain"` gradient object (expressed in vectorial form) and get his variation with respect to `v_`.
# The problem is now solved by looping over time increments. Because of the typical exponential time variation of temperature evolution of the heat equation, time steps are discretized on a non-uniform (logarithmic) scale. $\Delta t$ is therefore updated at each time step. The previous entropy field `s_old` is updated at the end of each step.
# In[5]:
Nincr=10
t=np.logspace(1,4,Nincr+1)
Nx=100
x=np.linspace(R,L,Nx)
T_res=np.zeros((Nx,Nincr+1))
for(i,dti)inenumerate(np.diff(t)):
print("Increment "+str(i+1))
dt.assign(dti)
problem.solve(v.vector())
s_old.assign(s)
T_res[:,i+1]=[v(xi,0.0)[2]forxiinx]
# At each time increment, the variation of the temperature increase $\Delta T$ along a line $(x, y=0)$ is saved in the `T_res` array. This evolution is plotted below. As expected, the temperature gradually increases over time, reaching eventually a uniform value of $+10^{\circ}\text{C}$ over infinitely long waiting time. We check that we obtain the same solution as the pure `FEniCS` demo.