Hello Everyone,
I want to have a linearly increasing load on one of the edges and a constant value after time t = 20s. As long as I have constant load throughout, everything is fine. Bur when I update the load on the boundary with time (lines 108 - 119), the output file behaves weird. The time in paraview starts at my end time = 2000s and goes to 20001. Although there should be 200 steps. I also printed out the values in the time loop. I see that the time and the load is getting updated. However, I do not see why the output files are behaving weird. I am using Ubuntu 22 and dolfinx 0.7.2 and Paraview 5.12(latest). Any help/suggestions to fix this issue? I am attaching the minimum example below
from dolfinx import log, default_scalar_type
from dolfinx.fem.petsc import NonlinearProblem
from dolfinx.nls.petsc import NewtonSolver
from dolfinx.io import VTXWriter
from dolfinx import nls
import numpy as np
import ufl
import dolfinx
print(f"DOLFINx version: {dolfinx.__version__} based on GIT commit: {dolfinx.git_commit_hash} of https://github.com/FEniCS/dolfinx/")
from mpi4py import MPI
from dolfinx import fem, mesh, plot
from petsc4py.PETSc import ScalarType
from petsc4py import PETSc #solvers
#-------------------------------------------------------------------#
# Geometry
domain = mesh.create_rectangle(MPI.COMM_WORLD, [[0.0, 0.0], [10.0, 10.0]], [20, 20], mesh.CellType.quadrilateral)
#-------------------------------------------------------------------#
# Function Spaces and Mixed Space
u_el = ufl.VectorElement("CG", domain.ufl_cell(), 2)
p_el = ufl.FiniteElement("CG", domain.ufl_cell(), 1)
element = ufl.MixedElement([u_el, p_el])
V = fem.FunctionSpace(domain, element)
up = fem. Function(V)
u_sp = fem.FunctionSpace(domain, u_el)
p_sp = fem.FunctionSpace(domain, p_el)
Vu, up_to_u = V.sub(0).collapse()
u_n = fem. Function(Vu)
Vp, V_to_Vp = V.sub(1).collapse()
u, p = ufl.split(up)
(del_u, del_p) = ufl.TestFunctions(V)
#-------------------------------------------------------------------#
# Define temporal parameters
t = 0 # Start time
T = 2000.0 # Final time
num_steps = 200
dt = T / num_steps # time step size
#-------------------------------------------------------------------#
# Boundary Detection
boundaries = [
(1, lambda x: np.isclose(x[0], 0)),
(2, lambda x: np.isclose(x[1], 0)),
(3, lambda x: np.isclose(x[0], 10.0)),
(4, lambda x: np.isclose(x[1], 10.0)),]
facet_indices, facet_markers = [], []
fdim = domain.topology.dim - 1
dim = domain.topology.dim
for (marker, locator) in boundaries:
facets = mesh.locate_entities(domain, fdim, locator)
facet_indices.append(facets)
facet_markers.append(np.full_like(facets, marker))
facet_indices = np.hstack(facet_indices).astype(np.int32)
facet_markers = np.hstack(facet_markers).astype(np.int32)
sorted_facets = np.argsort(facet_indices)
facet_tag = mesh.meshtags(domain, fdim, facet_indices[sorted_facets], facet_markers[sorted_facets])
# Boundary Conditions
def bc_vec_zero(x):
return np.zeros((2, x.shape[1]), dtype=PETSc.ScalarType)
def bc_scalar_zero(x):
return np.zeros((1, x.shape[1]), dtype=PETSc.ScalarType)
list_bc = []
# Displacement Boundary
u_bc = fem.Function(u_sp)
u_bc.interpolate(bc_vec_zero)
facets = facet_tag.indices[facet_tag.values == 2]
bottom_dofs = fem.locate_dofs_topological((V.sub(0).sub(1), u_sp.sub(1)), fdim, facets)
list_bc.append(fem.dirichletbc(u_bc, bottom_dofs, V.sub(0)))
facets = facet_tag.indices[facet_tag.values == 1]
left_dofs = fem.locate_dofs_topological((V.sub(0).sub(0), u_sp.sub(0)), fdim, facets)
list_bc.append(fem.dirichletbc(u_bc, left_dofs, V.sub(0)))
facets = facet_tag.indices[facet_tag.values == 3]
right_dofs = fem.locate_dofs_topological((V.sub(0).sub(0), u_sp.sub(0)), fdim, facets)
list_bc.append(fem.dirichletbc(u_bc, right_dofs, V.sub(0)))
# Pressure Boundary
p_bc = fem.Function(p_sp)
p_bc.interpolate(bc_scalar_zero)
facets = facet_tag.indices[facet_tag.values == 4]
top_dofs = fem.locate_dofs_topological((V.sub(1), p_sp), fdim, facets)
list_bc.append(fem.dirichletbc(p_bc, top_dofs, V.sub(1)))
# Load Boundary
def load_func(t):
if t == 0:
eval = 0
elif t <= 20.0:
eval = -(10000/20) * t
else:
eval = -10000
return eval
load = fem.Constant(domain, ScalarType(load_func(t)))
print(load.value)
load_bc = load * ufl.FacetNormal(domain)
#-------------------------------------------------------------------#
# Parameters
# Material Parameters
mat_k_FOS = 1e-4
mat_gamma_FR = 1e4
mat_rho_SR = 2e3
mat_rho_FR = 1e3
mat_n_SOS = 0.67
# Spatial dimension
d = len(u)
# Identity tensor
I = ufl.variable(ufl.Identity(d))
# Deformation gradient
F = ufl.variable(I + ufl.grad(u))
# Right Cauchy-Green tensor
b = ufl.variable(F * F.T)
# Invariants of deformation tensors
J = ufl.variable(ufl.det(F))
# Solid Velocity
vel_s = (u - u_n) / dt
# Darcy
dar = - (ufl.grad(p))
# Stress
mu_1 = default_scalar_type(5.58e6)
lmbda_1 = default_scalar_type(8.38e6)
P_ef_2 = (1/J) * (mu_1 * (b - I) + lmbda_1 * ufl.ln(J) * I)
P = P_ef_2 - p*I
# Integration measures
ds = ufl.Measure('ds', domain=domain, subdomain_data=facet_tag)
dx = ufl.Measure("dx", domain=domain)
# Weak Form
Mom_B = ufl.inner(P, ufl.grad(del_u)) * ufl.dx - ufl.inner(del_u, load_bc) * ds(4)
Vol_B = (ufl.div(vel_s) * del_p + ufl.inner(dar, ufl.grad(del_p))) * ufl.dx
weak_form = Mom_B + Vol_B
#-------------------------------------------------------------------#
# Solver
# Initialise non-linear problem
problem = NonlinearProblem(weak_form, up, list_bc)
# Initialise newton solver
solver = NewtonSolver(domain.comm, problem)
# Set Newton solver options
solver.atol = 1e-8
solver.rtol = 1e-8
solver.convergence_criterion = "incremental"
solver.max_it = 100000
# Configure mumps
ksp = solver.krylov_solver
opts = PETSc.Options()
option_prefix = ksp.getOptionsPrefix()
opts[f"{option_prefix}ksp_type"] = "preonly"
opts[f"{option_prefix}pc_type"] = "lu"
opts[f"{option_prefix}pc_factor_mat_solver_type"] = "mumps"
ksp.setFromOptions()
# Initialize history values
u_n.x.array[:] = 0.0
#-------------------------------------------------------------------#
# --- Solve problem ---
duration_solve = 0.0
for n in range(num_steps):
# Update time
t += dt
# Update time
load.value = load_func(t)
print(load.value)
# Solve newton-steps
duration_solve -= MPI.Wtime()
niter, converged = solver.solve(up)
duration_solve += MPI.Wtime()
PETSc.Sys.Print(
"Phys. Time {:.4f}, Calc. Time {:.4f}, Num. Iter. {}".format(
t, duration_solve, niter
)
)
u_n.x.array[:] = up.x.array[up_to_u]
u = up.sub(0).collapse()
p = up.sub(1).collapse()
u.name = "disp"
file1 = dolfinx.io.VTXWriter(domain.comm, "output1.bp", u, "bp4")
file1.write(t)
print(t)
file1.close()
p.name = "pressure"
file2 = dolfinx.io.VTXWriter(domain.comm, "output2.bp", p, "bp4")
file2.write(t)
file2.close()
Thank you in advance