You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
3.1 KiB

3 years ago
"""Solve nonlinear corrections to Darcy flow
"""
import dolfin as df
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as ticker
import sys
import os
from time import time
def solve_nonlinear_poisson(input, alpha1, alpha2, save_dir):
if not os.path.exists(save_dir):
os.makedirs(save_dir)
perm = input
flux_order = 3
ngy, ngx = perm.shape[0], perm.shape[1]
# Create mesh and define function space
mesh = df.UnitSquareMesh(ngy-1, ngx-1)
K_CG = df.FunctionSpace(mesh, "Lagrange", 1)
K = df.Function(K_CG)
ordering = df.dof_to_vertex_map(K_CG)
K.vector()[:] = perm.flatten(order='C')[ordering]
def boundary(x, on_boundary):
return x[0] < df.DOLFIN_EPS or x[0] > 1.0 - df.DOLFIN_EPS
left = df.CompiledSubDomain("near(x[0], 0.0) && on_boundary")
right = df.CompiledSubDomain("near(x[0], 1.0) && on_boundary")
top = df.CompiledSubDomain("near(x[1], 1.0) && on_boundary")
bottom = df.CompiledSubDomain("near(x[1], 0.0) && on_boundary")
boundaries = df.MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)
# boundaries.set_all(0)
left.mark(boundaries, 1)
top.mark(boundaries, 2)
right.mark(boundaries, 3)
bottom.mark(boundaries, 4)
ds = df.Measure("ds", domain=mesh, subdomain_data=boundaries)
# Discontinuous Raviart-Thomas
DRT = df.FiniteElement("DRT", mesh.ufl_cell(), flux_order)
# Lagrange
CG = df.FiniteElement("CG", mesh.ufl_cell(), flux_order + 1)
W = df.FunctionSpace(mesh, DRT * CG)
ww = df.Function(W)
sigma, u = df.split(ww)
tau, v = df.TestFunctions(W)
dw = df.TrialFunction(W)
# Define boundary condition
gamma = df.Expression("1.0 - x[0]", degree=1)
bc = df.DirichletBC(W.sub(1), gamma, boundary)
g = df.Constant(0.0)
f = df.Constant(0.0)
def flux(sigma):
s1 = sigma[0]
s2 = sigma[1]
nonlinear1 = alpha1 * df.sqrt(K) * df.as_vector([s1 ** 2, s2 ** 2])
nonlinear2 = alpha2 * K * df.as_vector([s1 ** 3, s2 ** 3])
nonlinear = nonlinear1 + nonlinear2
return nonlinear
F = (df.dot(sigma, tau) + df.dot(K * df.grad(u), tau) + df.dot(flux(sigma), tau)\
+ df.dot(sigma, df.grad(v)) + f * v) * df.dx + g * v * ds(2) + g * v * ds(4)
J = df.derivative(F, ww, dw)
# Compute solution
problem = df.NonlinearVariationalProblem(F, ww, bc, J)
solver = df.NonlinearVariationalSolver(problem)
prm = solver.parameters
prm['newton_solver']['absolute_tolerance'] = 1E-8
prm['newton_solver']['relative_tolerance'] = 1E-6
prm['newton_solver']['maximum_iterations'] = 10
prm['newton_solver']['relaxation_parameter'] = 1.0
tic = time()
solver.solve()
print(f'time taken {time()-tic} seconds')
(sigma_, u_) = ww.split()
u_mat = u_.compute_vertex_values(mesh).reshape(64, 64)
grad_u = sigma_.compute_vertex_values(mesh)
sigma1 = grad_u[:4096].reshape(64, 64)
sigma2 = grad_u[4096:].reshape(64, 64)
output = np.stack((u_mat, sigma1, sigma2))
print('output shape: {output.shape}')
return output