def __init__(self, V, **kwargs): # Call parent ParametrizedProblem.__init__( self, os.path.join("test_eim_approximation_14_tempdir", expression_type, basis_generation, "mock_problem")) # Minimal subset of a ParametrizedDifferentialProblem self.V = V self._solution = Function(V) self.components = ["u", "s", "p"] # Parametrized function to be interpolated x = SpatialCoordinate(V.mesh()) mu = SymbolicParameters(self, V, (1., )) self.f00 = (1 - x[0]) * cos(3 * pi * mu[0] * (1 + x[0])) * exp(-mu[0] * (1 + x[0])) self.f01 = (1 - x[0]) * sin(3 * pi * mu[0] * (1 + x[0])) * exp(-mu[0] * (1 + x[0])) # Inner product f = TrialFunction(self.V) g = TestFunction(self.V) self.inner_product = assemble(inner(f, g) * dx) # Collapsed vector and space self.V0 = V.sub(0).collapse() self.V00 = V.sub(0).sub(0).collapse() self.V1 = V.sub(1).collapse()
def setChargeDensity(self): print("Setting charge density...") if self.eqn == "laplace": return dolfin.Constant("0.0") * self.v * self.dx elif self.eqn == "poisson": #use equilibrium charge density self.dp.dopingCalc() temp = -self.dp.getAsFunction(self.dp.rho, self.mesh, "x[2]") # dolfin.plot(temp) # plt.savefig(os.path.join(self.exporter.abs_in_dir,"temp.pdf")) return -self.dp.getAsFunction(self.dp.rho, self.mesh, "x[2]") * self.v * self.dx else: #use the poisson boltzmann definition for charge density. ni = 1E-14 #in ang^-3 ni_exp = dolfin.Expression('x[2] < depth + DOLFIN_EPS ? p1 : p2', \ depth=self.bounds["dielectric"], p1=dolfin.Constant(ni), \ p2=dolfin.Constant(0), degree=1, domain=self.mesh) q = self.q k = 1.38064852E-23 # Boltzmann constant - metre^2 kilogram / second^2 Kelvin T = self.temp self.dp.dopingCalc() nd = dolfin.Expression('x[2] < depth + DOLFIN_EPS ? p1 : p2', \ depth=self.dp.depth, p1=dolfin.Constant(self.dp.d_conc), p2=dolfin.Constant(0), degree=1, domain=self.mesh) if self.eqn == "linpoisboltz": return -2*q*q*ni_exp/k/T*self.u*self.v*self.dx \ -q*nd*self.v*self.dx elif self.eqn == "poisboltz": return q*ni_exp*dolfin.exp(q/k/T*(self.u))*self.v*self.dx \ - q*ni_exp*dolfin.exp(-q/k/T*self.u)*self.v*self.dx \ - q*nd*self.v*self.dx
def updateCoefficients(self): # Init coefficient matrix x, y = SpatialCoordinate(self.mesh) self.a = 0.5 * as_matrix( [[cos(self.gamma[0]), sin(self.gamma[0])], [- sin(self.gamma[0]), cos(self.gamma[0])]]) \ * as_matrix([[20, 1], [1, 0.1]]) \ * as_matrix( [[cos(self.gamma[0]), - sin(self.gamma[0])], [sin(self.gamma[0]), cos(self.gamma[0])]]) self.b = as_vector([Constant(0.0), Constant(1.0)]) self.c = Constant(-10.0) self.u_ = (2*x-1.) \ * (exp(1 - abs(2*x-1.)) - 1) \ * (y + (1 - exp(y/self.delta))/(exp(1/self.delta)-1)) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) \ + inner(self.b, grad(self.u_)) \ + self.c * self.u_ # Set boundary conditions self.g = Constant(0.0)
def W_1(self, I_1, diff=0, *args, **kwargs): r""" Isotropic contribution. If `diff = 0`, return .. math:: \frac{a}{2 b} \left( e^{ b (I_1 - 3)} -1 \right) If `diff = 1`, return .. math:: \frac{a}{b} e^{ b (I_1 - 3)} If `diff = 2`, return .. math:: \frac{a b}{2} e^{ b (I_1 - 3)} """ a = self.a b = self.b if diff == 0: return a / (2.0 * b) * (dolfin.exp(b * (I_1 - 3)) - 1) elif diff == 1: return a / 2.0 * dolfin.exp(b * (I_1 - 3)) elif diff == 2: return a * b / 2.0 * dolfin.exp(b * (I_1 - 3))
def initControl(self): self.controlSpace = [FunctionSpace(self.mesh, "DG", 0)] x, y = SpatialCoordinate(self.mesh) u_ = (2*x-1.) \ * (exp(1 - abs(2*x-1.)) - 1) \ * (y + (1 - exp(y/self.delta))/(exp(1/self.delta)-1)) cs = self.controlSpace[0] du = self.u - u_ du_xx = Dx(Dx(du, 0), 0) du_xy = Dx(Dx(du, 0), 1) du_yx = Dx(Dx(du, 1), 0) du_yy = Dx(Dx(du, 1), 1) du_xx_proj = project(du_xx, cs) du_xy_proj = project(du_xy, cs) du_yx_proj = project(du_yx, cs) du_yy_proj = project(du_yy, cs) # Use the UserExpression gamma_star = Gallistl_Sueli_1_optControl(du_xx_proj, du_xy_proj, du_yx_proj, du_yy_proj, self.alphamin, self.alphamax) # Interpolate evaluates expression in centers of mass # Project evaluates expression in vertices self.gamma = [gamma_star]
def W_4(self, I4, direction, diff=0, use_heaviside=False, *args, **kwargs): r""" Anisotropic contribution. If `diff = 0`, return .. math:: \frac{a_f}{2 b_f} \left( e^{ b_f (I_{4f_0} - 1)_+^2} -1 \right) If `diff = 1`, return .. math:: a_f (I_{4f_0} - 1)_+ e^{ b_f (I_{4f_0} - 1)^2} If `diff = 2`, return .. math:: a_f h(I_{4f_0} - 1) (1 + 2b(I_{4f_0} - 1)) e^{ b_f (I_{4f_0} - 1)_+^2} where .. math:: h(x) = \frac{\mathrm{d}}{\mathrm{d}x} \max\{x,0\} is the Heaviside function. """ assert direction in ["f", "s", "n"] a = getattr(self, f"a_{direction}") b = getattr(self, f"b_{direction}") if I4 == 0: return 0 if diff == 0: try: if float(a) > dolfin.DOLFIN_EPS: if float(b) > dolfin.DOLFIN_EPS: return (a / (2.0 * b) * (dolfin.exp(b * subplus(I4 - 1)**2) - 1.0)) else: return a / 2.0 * subplus(I4 - 1)**2 else: return 0.0 except Exception: # Probably failed to convert a and b to float return a / (2.0 * b) * (dolfin.exp(b * subplus(I4 - 1)**2) - 1.0) elif diff == 1: return a * subplus(I4 - 1) * dolfin.exp(b * pow(I4 - 1, 2)) elif diff == 2: return (a * heaviside(I4 - 1) * (1 + 2.0 * b * pow(I4 - 1, 2)) * dolfin.exp(b * pow(I4 - 1, 2)))
def QoI_FEM(x0,y0,lam1,lam2,gridx,gridy,p): mesh = fn.UnitSquareMesh(gridx, gridy) V = fn.FunctionSpace(mesh, "Lagrange", p) # Define diffusion tensor (here, just a scalar function) and parameters A = fn.Expression((('exp(lam1)','a'), ('a','exp(lam2)')), a = fn.Constant(0.0), lam1 = lam1, lam2 = lam2, degree=3) u_exact = fn.Expression("sin(lam1*pi*x[0])*cos(lam2*pi*x[1])", lam1 = lam1, lam2 = lam2, degree=2+p) # Define the mix of Neumann and Dirichlet BCs class LeftBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[0] < fn.DOLFIN_EPS) class RightBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[0] > 1.0 - fn.DOLFIN_EPS) class TopBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[1] > 1.0 - fn.DOLFIN_EPS) class BottomBoundary(fn.SubDomain): def inside(self, x, on_boundary): return (x[1] < fn.DOLFIN_EPS) # Create a mesh function (mf) assigning an unsigned integer ('uint') # to each edge (which is a "Facet" in 2D) mf = fn.MeshFunction('size_t', mesh, 1) mf.set_all(0) # initialize the function to be zero # Setup the boundary classes that use Neumann boundary conditions NTB = TopBoundary() # instatiate NTB.mark(mf, 1) # set all values of the mf to be 1 on this boundary NBB = BottomBoundary() NBB.mark(mf, 2) # set all values of the mf to be 2 on this boundary NRB = RightBoundary() NRB.mark(mf, 3) # Define Dirichlet boundary conditions Gamma_0 = fn.DirichletBC(V, u_exact, LeftBoundary()) bcs = [Gamma_0] # Define data necessary to approximate exact solution f = ( fn.exp(lam1)*(lam1*fn.pi)**2 + fn.exp(lam2)*(lam2*fn.pi)**2 ) * u_exact g1 = fn.Expression("-exp(lam2)*lam2*pi*sin(lam1*pi*x[0])*sin(lam2*pi*x[1])", lam1=lam1, lam2=lam2, degree=2+p) #pointing outward unit normal vector, pointing upaward (0,1) g2 = fn.Expression("exp(lam2)*lam2*pi*sin(lam1*pi*x[0])*sin(lam2*pi*x[1])", lam1=lam1, lam2=lam2, degree=2+p) #pointing downward (0,1) g3 = fn.Expression("exp(lam1)*lam1*pi*cos(lam1*pi*x[0])*cos(lam2*pi*x[1])", lam1=lam1, lam2=lam2, degree=2+p) fn.ds = fn.ds(subdomain_data=mf) # Define variational problem u = fn.TrialFunction(V) v = fn.TestFunction(V) a = fn.inner(A*fn.grad(u), fn.grad(v))*fn.dx L = f*v*fn.dx + g1*v*fn.ds(1) + g2*v*fn.ds(2) + g3*v*fn.ds(3) #note the 1, 2 and 3 correspond to the mf # Compute solution u = fn.Function(V) fn.solve(a == L, u, bcs) return u(x0,y0)
def updateCoefficients(self): # Init coefficient matrix x, y = SpatialCoordinate(self.mesh) off_diag = conditional(x * y > 0, 1.0, -1.0) self.a = as_matrix([[2.0, off_diag], [off_diag, 2.0]]) self.u_ = x * y * (1 - exp(1 - abs(x))) * (1 - exp(1 - abs(y))) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) # Set boundary conditions to exact solution self.g = self.u_
def df_dlmbda(self, u, lmbda): v = TestFunction(self.V) ufun = Function(self.V) ufun.vector()[:] = u out = -assemble(exp(ufun) * v * dx) self.bc.apply(out) return out
def assembleA(self, x, assemble_adjoint=False, assemble_rhs=False): """ Assemble the matrices and rhs for the forward/adjoint problems """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[STATE]) c = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) Avarf = dl.inner( dl.exp(c) * dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx if not assemble_adjoint: bform = dl.inner(self.f, test) * dl.dx Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc) else: # Assemble the adjoint of A (i.e. the transpose of A) s = vector2Function(x[STATE], self.Vh[STATE]) bform = dl.inner(dl.Constant(0.), test) * dl.dx Matrix, _ = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0) Bu = -(self.B * x[STATE]) Bu += self.u_o rhs = dl.Vector() self.B.init_vector(rhs, 1) self.B.transpmult(Bu, rhs) rhs *= 1.0 / self.noise_variance if assemble_rhs: return Matrix, rhs else: return Matrix
def f(self, u, lmbda): v = TestFunction(self.V) ufun = Function(self.V) ufun.vector()[:] = u out = (self.a * u - 10 * assemble(ufun * v * dx) + 10 * lmbda * assemble(exp(ufun) * v * dx)) return out
def perm_update_rutqvist_newton(mesh, p, p0, phi0, phi, coeff): DG0 = TensorFunctionSpace(mesh, 'DG', 0) mult_min = 1e-10 expr = exp(coeff * (phi / phi0 - 1.0)) mult = conditional(ge(expr, 0.0), expr, mult_min) p = p0 * mult return project(p, DG0)
def updateCoefficients(self): # Init coefficient matrix x, y = SpatialCoordinate(self.mesh) self.a = 0.5 * as_matrix( [[cos(self.gamma[0]), sin(self.gamma[0])], [- sin(self.gamma[0]), cos(self.gamma[0])]]) \ * as_matrix([[1, sin(self.gamma[1])], [0, cos(self.gamma[1])]]) \ * as_matrix([[1, 0], [sin(self.gamma[1]), cos(self.gamma[1])]]) \ * as_matrix( [[cos(self.gamma[0]), - sin(self.gamma[0])], [sin(self.gamma[0]), cos(self.gamma[0])]]) self.b = as_vector([Constant(0.0), Constant(0.0)]) self.c = -pi**2 self.u_ = exp(x * y) * sin(pi * x) * sin(pi * y) # Init right-hand side self.f = - sqrt(3) * (sin(self.gamma[1])/pi)**2 \ + 111111 # TODO work here # Set boundary conditions self.g = Constant(0.0)
def softplus(y1, y2, alpha=1): # The softplus function is a differentiable approximation # to the ramp function. Its derivative is the logistic function. # Larger alpha makes a sharper transition. return Max(y1, y2) + (1. / alpha) * ln(1 + exp(alpha * (Min(y1, y2) - Max(y1, y2))))
def f(self, u, lmbda): v = TestFunction(self.V) ufun = Function(self.V) ufun.vector()[:] = u out = self.a * u - lmbda * assemble(exp(ufun) * v * dx) DirichletBC(self.V, ufun, "on_boundary").apply(out) return out
def __init__(self, mock_problem, expression_type, basis_generation): self.V = mock_problem.V # Parametrized function to be interpolated mu = SymbolicParameters(mock_problem, self.V, (1., )) x = SpatialCoordinate(self.V.mesh()) f = (1 - x[0]) * cos(3 * pi * mu[0] * (1 + x[0])) * exp(-mu[0] * (1 + x[0])) # folder_prefix = os.path.join("test_eim_approximation_09_tempdir", expression_type, basis_generation) assert expression_type in ("Function", "Vector", "Matrix") if expression_type == "Function": # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedExpressionFactory(f), folder_prefix, basis_generation) elif expression_type == "Vector": v = TestFunction(self.V) form = f * v * dx # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) elif expression_type == "Matrix": u = TrialFunction(self.V) v = TestFunction(self.V) form = f * u * v * dx # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) else: # impossible to arrive here anyway thanks to the assert raise AssertionError("Invalid expression_type")
def compute_velocity(mesh, Vh, a, u): #export the velocity field v = - exp( a ) \grad u: then we solve ( exp(-a) v, w) = ( u, div w) Vv = dl.FunctionSpace(mesh, 'RT', 1) v = dl.Function(Vv, name="velocity") vtrial = dl.TrialFunction(Vv) vtest = dl.TestFunction(Vv) afun = dl.Function(Vh[PARAMETER], a) ufun = dl.Function(Vh[STATE], u) Mv = dl.exp(-afun) * dl.inner(vtrial, vtest) * dl.dx n = dl.FacetNormal(mesh) class TopBoundary(dl.SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 1 - dl.DOLFIN_EPS Gamma_M = TopBoundary() boundaries = dl.FacetFunction("size_t", mesh) boundaries.set_all(0) Gamma_M.mark(boundaries, 1) dss = dl.Measure("ds")[boundaries] rhs = ufun * dl.div(vtest) * dl.dx - dl.dot(vtest, n) * dss(1) bcv = dl.DirichletBC(Vv, dl.Expression(("0.0", "0.0")), v_boundary) dl.solve(Mv == rhs, v, bcv) return v
def updateCoefficients(self): # Init coefficient matrix x = SpatialCoordinate(self.mesh)[0] self.a = as_matrix([[.5 * (x * self.gamma[0] * self.sigmax)**2]]) self.b = as_vector([x * (self.gamma[0] * (self.mu - self.r) + self.r)]) self.c = Constant(0.0) # Init right-hand side self.f = Constant(0.0) self.u_ = exp( ((self.mu - self.r)**2 / (2 * self.sigmax**2) * self.alpha / (1 - self.alpha) + self.r * self.alpha) * (self.T[1] - self.t)) * (x**self.alpha) / self.alpha self.u_T = (x**self.alpha) / self.alpha # Set boundary conditions # self.g_t = lambda t : [(Constant(0.0), "near(x[0],0)")] self.g = Constant(0.0) # self.g_t = lambda t : self.u_t(t) self.gamma_star = [ Constant((self.mu - self.r) / (self.sigmax**2 * (1 - self.alpha))) ] self.loc = conditional(x > 0.5, conditional(x < 1.5, 1, 0), 0)
def W_4(self, I_4, diff=0, *args, **kwargs): r""" Anisotropic contribution. If `diff = 0`, return .. math:: \frac{a_f}{2 b_f} \left( e^{ b_f (I_{4f_0} - 1)_+^2} -1 \right) If `diff = 1`, return .. math:: a_f (I_{4f_0} - 1)_+ e^{ b_f (I_{4f_0} - 1)^2} If `diff = 2`, return .. math:: a_f h(I_{4f_0} - 1) (1 + 2b(I_{4f_0} - 1)) e^{ b_f (I_{4f_0} - 1)_+^2} where .. math:: h(x) = \frac{\mathrm{d}}{\mathrm{d}x} \max\{x,0\} is the Heaviside function. """ a = self.a_f b = self.b_f if I_4 == 0: return 0 if diff == 0: return (a / (2.0 * b) * heaviside(I_4 - 1) * (dolfin.exp(b * pow(I_4 - 1, 2)) - 1)) elif diff == 1: return a * subplus(I_4 - 1) * dolfin.exp(b * pow(I_4 - 1, 2)) elif diff == 2: return (a * heaviside(I_4 - 1) * (1 + 2.0 * b * pow(I_4 - 1, 2)) * dolfin.exp(b * pow(I_4 - 1, 2)))
def main(): fsr = FunctionSubspaceRegistry() deg = 2 mesh = dolfin.UnitSquareMesh(100, 3) muc = mesh.ufl_cell() el_w = dolfin.FiniteElement('DG', muc, deg - 1) el_j = dolfin.FiniteElement('BDM', muc, deg) el_DG0 = dolfin.FiniteElement('DG', muc, 0) el = dolfin.MixedElement([el_w, el_j]) space = dolfin.FunctionSpace(mesh, el) DG0 = dolfin.FunctionSpace(mesh, el_DG0) fsr.register(space) facet_normal = dolfin.FacetNormal(mesh) xyz = dolfin.SpatialCoordinate(mesh) trial = dolfin.Function(space) test = dolfin.TestFunction(space) w, c = dolfin.split(trial) v, phi = dolfin.split(test) sympy_exprs = derive_exprs() exprs = { k: sympy_dolfin_printer.to_ufl(sympy_exprs['R'], mesh, v) for k, v in sympy_exprs['quantities'].items() } f = exprs['f'] w0 = dolfin.project(dolfin.conditional(dolfin.gt(xyz[0], 0.5), 1.0, 0.3), DG0) w_BC = exprs['w'] dx = dolfin.dx() form = (+v * dolfin.div(c) * dx - v * f * dx + dolfin.exp(w + w0) * dolfin.dot(phi, c) * dx + dolfin.div(phi) * w * dx - (w_BC - w0) * dolfin.dot(phi, facet_normal) * dolfin.ds() - (w0('-') - w0('+')) * dolfin.dot(phi('+'), facet_normal('+')) * dolfin.dS()) solver = NewtonSolver(form, trial, [], parameters=dict(relaxation_parameter=1.0, maximum_iterations=15, extra_iterations=10, relative_tolerance=1e-6, absolute_tolerance=1e-7)) solver.solve() with closing(XdmfPlot("out/qflop_test.xdmf", fsr)) as X: CG1 = dolfin.FunctionSpace(mesh, dolfin.FiniteElement('CG', muc, 1)) X.add('w0', 1, w0, CG1) X.add('w_c', 1, w + w0, CG1) X.add('w_e', 1, exprs['w'], CG1) X.add('f', 1, f, CG1) X.add('cx_c', 1, c[0], CG1) X.add('cx_e', 1, exprs['c'][0], CG1)
def W_8(self, I8, *args, **kwargs): """ Cross fiber-sheet contribution. """ a = self.a_fs b = self.b_fs try: if float(a) > dolfin.DOLFIN_EPS: if float(b) > dolfin.DOLFIN_EPS: return a / (2.0 * b) * (dolfin.exp(b * I8**2) - 1.0) else: return a / 2.0 * I8**2 else: return 0.0 except Exception: return a / (2.0 * b) * (dolfin.exp(b * I8**2) - 1.0)
def updateCoefficients(self): # Init coefficient matrix x, y = SpatialCoordinate(self.mesh) self.a = as_matrix([[1.0, 0.0], [0.0, 1.0]]) self.b = 100 * as_vector([1.0, -1.0]) self.c = -0.1 self.u_ = x * y * (1 - exp(1 - abs(x))) * (1 - exp(1 - abs(y))) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) \ + inner(self.b, grad(self.u_)) \ + self.c * self.u_ # Set boundary conditions to exact solution self.g = self.u_
def strain_energy(self, F_): """ UFL form of the strain energy. """ params = self.parameters # Elastic part of deformation gradient F = self.Fe(F_) E = kinematics.GreenLagrangeStrain(F, isochoric=self.isochoric) CC = Constant(params["C"], name="C") e1 = self.f0 e2 = self.s0 e3 = self.n0 if any(e is None for e in (e1, e2, e3)): msg = ("Need to provide the full orthotropic basis " "for the Guccione model got \ne1 = {e1}\n" "e2 = {e2}\ne3 = {e3}").format(e1=e1, e2=e2, e3=e3) raise ValueError(msg) if self.is_isotropic(): # isotropic case Q = dolfin.inner(E, E) else: # fully anisotropic bt = Constant(params["bt"], name="bt") bf = Constant(params["bf"], name="bf") bfs = Constant(params["bfs"], name="bfs") E11, E12, E13 = ( dolfin.inner(E * e1, e1), dolfin.inner(E * e1, e2), dolfin.inner(E * e1, e3), ) _, E22, E23 = ( dolfin.inner(E * e2, e1), dolfin.inner(E * e2, e2), dolfin.inner(E * e2, e3), ) _, _, E33 = ( dolfin.inner(E * e3, e1), dolfin.inner(E * e3, e2), dolfin.inner(E * e3, e3), ) Q = (bf * E11**2 + bt * (E22**2 + E33**2 + 2 * E23**2) + bfs * (2 * E12**2 + 2 * E13**2)) # passive strain energy Wpassive = CC / 2.0 * (dolfin.exp(Q) - 1) Wactive = self.Wactive(F, diff=0) return Wpassive + Wactive
def plot_prior_sample(self, exp=False): samp = self.sample(exp) s = dl.Function(self.V) s.vector()[:] = samp[:] if exp == False: p = dl.plot(s) plt.colorbar(p) else: p = dl.plot(dl.exp(s)) plt.colorbar(p)
def plot_prior(self, samp, exp=False, cmap='Spectral'): s = dl.Function(self.V) s.vector()[:] = samp[:] if exp == False: p = dl.plot(s, cmap=cmap) plt.colorbar(p) else: p = dl.plot(dl.exp(s)) plt.colorbar(p) return p
def jacobian_solver(self, u, lmbda, rhs): t = TrialFunction(self.V) v = TestFunction(self.V) ufun = Function(self.V) ufun.vector()[:] = u a = (self.a - 10 * assemble(t * v * dx) + 10 * lmbda * assemble(exp(ufun) * t * v * dx)) x = Function(self.V) solve(a, x.vector(), rhs) return x.vector()
def W_1(self, I1, diff=0, *args, **kwargs): r""" Isotropic contribution. If `diff = 0`, return .. math:: \frac{a}{2 b} \left( e^{ b (I_1 - 3)} -1 \right) If `diff = 1`, return .. math:: \frac{a}{b} e^{ b (I_1 - 3)} If `diff = 2`, return .. math:: \frac{a b}{2} e^{ b (I_1 - 3)} """ a = self.a b = self.b if diff == 0: try: if float(a) > dolfin.DOLFIN_EPS: if float(b) > dolfin.DOLFIN_EPS: return a / (2.0 * b) * (dolfin.exp(b * (I1 - 3)) - 1.0) else: return a / 2.0 * (I1 - 3) else: return 0.0 except Exception: return a / (2.0 * b) * (dolfin.exp(b * (I1 - 3)) - 1) elif diff == 1: return a / 2.0 * dolfin.exp(b * (I1 - 3)) elif diff == 2: return a * b / 2.0 * dolfin.exp(b * (I1 - 3))
def eval(self,values,x): ''' :param values: value 1d array of length 1 with value ~0.69 in one case :param x: :return: ''' # L = mesh_max-mesh_min # values[0] = 2.0 - (x[0]-mesh_min) / L * 6.0 values[0] = 8.7/(1 + 200*exp(0.05e-3*(x[0]-300.e3))) - 8.0
def assembleWmm(self, x): """ Assemble the derivative of the parameter equation with respect to the parameter (Newton method) """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[PARAMETER]) u = vector2Function(x[STATE], self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) varf = dl.inner(dl.grad(p),dl.exp(m)*dl.grad(u))*trial*test*dl.dx return dl.assemble(varf)
def assembleRaa(self, x): """ Assemble the derivative of the parameter equation with respect to the parameter (Newton method) """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[PARAMETER]) s = vector2Function(x[STATE], Vh[STATE]) c = vector2Function(x[PARAMETER], Vh[PARAMETER]) a = vector2Function(x[ADJOINT], Vh[ADJOINT]) varf = dl.inner(dl.nabla_grad(a), dl.exp(c) * dl.nabla_grad(s)) * trial * test * dl.dx return dl.assemble(varf)
def assembleC(self, x): """ Assemble the derivative of the forward problem with respect to the parameter """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[STATE]) u = vector2Function(x[STATE], Vh[STATE]) m = vector2Function(x[PARAMETER], Vh[PARAMETER]) Cvarf = dl.inner(dl.exp(m) * trial * dl.grad(u), dl.grad(test)) * dl.dx C = dl.assemble(Cvarf) # print ( "||m||", x[PARAMETER].norm("l2"), "||u||", x[STATE].norm("l2"), "||C||", C.norm("linf") ) self.bc0.zero(C) return C
def assembleWmu(self, x): """ Assemble the derivative of the parameter equation with respect to the state """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[PARAMETER]) p = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) varf = dl.inner(dl.exp(m)*dl.grad(trial),dl.grad(p))*test*dl.dx Wmu = dl.assemble(varf) Wmu_t = Transpose(Wmu) self.bc0.zero(Wmu_t) Wmu = Transpose(Wmu_t) return Wmu
def assembleA(self,x, assemble_adjoint = False, assemble_rhs = False): """ Assemble the matrices and rhs for the forward/adjoint problems """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) Avarf = dl.inner(dl.exp(m)*dl.grad(trial), dl.grad(test))*dl.dx if not assemble_adjoint: bform = dl.inner(self.f, test)*dl.dx Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc) else: # Assemble the adjoint of A (i.e. the transpose of A) u = vector2Function(x[STATE], self.Vh[STATE]) obs = vector2Function(self.u_o, self.Vh[STATE]) bform = dl.inner(obs - u, test)*dl.dx Matrix, rhs = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0) if assemble_rhs: return Matrix, rhs else: return Matrix
def RunJob(Tb, mu_value, path): runtimeInit = clock() tfile = File(path + '/t6t.pvd') mufile = File(path + "/mu.pvd") ufile = File(path + '/velocity.pvd') gradpfile = File(path + '/gradp.pvd') pfile = File(path + '/pstar.pvd') parameters = open(path + '/parameters', 'w', 0) vmeltfile = File(path + '/vmelt.pvd') rhofile = File(path + '/rhosolid.pvd') for name in dir(): ev = str(eval(name)) if name[0] != '_' and ev[0] != '<': parameters.write(name + ' = ' + ev + '\n') temp_values = [27. + 273, Tb + 273, 1300. + 273, 1305. + 273] dTemp = temp_values[3] - temp_values[0] temp_values = [x / dTemp for x in temp_values] # non dimensionalising temp mu_a = mu_value # this was taken from the blankenbach paper, can change.. Ep = b / dTemp mu_bot = exp(-Ep * (temp_values[3] * dTemp - 1573) + cc) * mu_a Ra = rho_0 * alpha * g * dTemp * h**3 / (kappa_0 * mu_a) w0 = rho_0 * alpha * g * dTemp * h**2 / mu_a tau = h / w0 p0 = mu_a * w0 / h print(mu_a, mu_bot, Ra, w0, p0) vslipx = 1.6e-09 / w0 vslip = Constant((vslipx, 0.0)) # nondimensional noslip = Constant((0.0, 0.0)) dt = 3.E11 / tau tEnd = 3.E13 / tau # non-dimensionalising times class PeriodicBoundary(SubDomain): def inside(self, x, on_boundary): return left(x, on_boundary) def map(self, x, y): y[0] = x[0] - MeshWidth y[1] = x[1] pbc = PeriodicBoundary() class TempExp(Expression): def eval(self, value, x): if x[1] >= LAB(x): value[0] = temp_values[0] + (temp_values[1] - temp_values[0]) * (MeshHeight - x[1]) / (MeshHeight - LAB(x)) else: value[0] = temp_values[3] - (temp_values[3] - temp_values[2]) * (x[1]) / (LAB(x)) class FluidTemp(Expression): def eval(self, value, x): if value[0] < 1295: value[0] = 1295 mesh = RectangleMesh(Point(0.0, 0.0), Point(MeshWidth, MeshHeight), nx, ny) Svel = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc) Spre = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) Stemp = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) Smu = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) Sgradp = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc) Srho = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc) S0 = MixedFunctionSpace([Svel, Spre, Stemp]) u = Function(S0) v, p, T = split(u) v_t, p_t, T_t = TestFunctions(S0) T0 = interpolate(TempExp(), Stemp) muExp = Expression('exp(-Ep * (T_val * dTemp - 1573) + cc * x[2] / meshHeight)', Smu.ufl_element(), Ep=Ep, dTemp=dTemp, cc=cc, meshHeight=MeshHeight, T_val=T0) mu = interpolate(muExp, Smu) rhosolid = Function(Srho) deltarho = Function(Srho) v0 = Function(Svel) vmelt = Function(Svel) v_theta = (1. - theta)*v0 + theta*v T_theta = (1. - theta)*T + theta*T0 r_v = (inner(sym(grad(v_t)), 2.*mu*sym(grad(v))) \ - div(v_t)*p \ - T*v_t[1] )*dx r_p = p_t*div(v)*dx r_T = (T_t*((T - T0) \ + dt*inner(v_theta, grad(T_theta))) \ + (dt/Ra)*inner(grad(T_t), grad(T_theta)) )*dx # + k_s*(Tf-T_theta)*dt Tf = T0.interpolate(FluidTemp()) # Tf = T0.interpolate(Expression('value[0] >= 1295.0 ? value[0] : 1295.0')) # Tf.interpolate(Expression('value[0] >= 1295 ? value[0] : 1295')) # project(Expression('value[0] >= 1295 ? value[0] : 1295'), Tf) # Alex, a question for you: # can you see if there is a way to set Tf = T in regions where T >=1295 celsius # # 1295 celsius is my arbitrary choice for the LAB isotherm. In regions # where T < 1295 C, set Tf to be some constant for now, such as 1295 C. # Once we do this, then we can add in a term like that last line above where # it will only be non-zero when the solid temperature, T, is cooler than 1295 # can you do this? After this is done, we will then worry about a calculation # where we solve for Tf as a function of time in the regions cooler than 1295 C # Makes sense? If not, we can skype soon -- email me with questions # 3/19/16 r = r_v + r_p + r_T bcv0 = DirichletBC(S0.sub(0), noslip, top) bcv1 = DirichletBC(S0.sub(0), vslip, bottom) bcp0 = DirichletBC(S0.sub(1), Constant(0.0), bottom) bct0 = DirichletBC(S0.sub(2), Constant(temp_values[0]), top) bct1 = DirichletBC(S0.sub(2), Constant(temp_values[3]), bottom) bcs = [bcv0, bcv1, bcp0, bct0, bct1] t = 0 count = 0 while (t < tEnd): solve(r == 0, u, bcs) t += dt nV, nP, nT = u.split() gp = grad(nP) rhosolid = rho_0 * (1 - alpha * (nT * dTemp - 1573)) deltarho = rhosolid - rhomelt yvec = Constant((0.0, 1.0)) vmelt = nV * w0 - darcy * (gp * p0 / h - deltarho * yvec * g) if (count % 100 == 0): pfile << nP ufile << nV tfile << nT mufile << mu gradpfile << project(grad(nP), Sgradp) mufile << project(mu * mu_a, Smu) rhofile << project(rhosolid, Srho) vmeltfile << project(vmelt, Svel) count += 1 assign(T0, nT) assign(v0, nV) mu.interpolate(muExp) print('Case mu=%g, Tb=%g complete.' % (mu_a, Tb), ' Run time =', clock() - runtimeInit, 's')
else: print ("\nNot Converged") print ("Termination reason: ", solver.termination_reasons[solver.reason]) print ("Final gradient norm: ", solver.final_grad_norm) print ("Final cost: ", solver.final_cost) model.setPointForHessianEvaluations(x, gauss_newton_approx=False) Hmisfit = ReducedHessian(model, solver.parameters["inner_rel_tolerance"], misfit_only=True) p = 20 k = 50 Omega = MultiVector(x[PARAMETER], k+p) parRandom.normal(1., Omega) d, U = doublePassG(Hmisfit, Prior.R, Prior.Rsolver, Omega, k, s=1, check=False) if rank == 0: plt.figure() plt.plot(range(0,k), d, 'b*',range(0,k), np.ones(k), '-r') plt.yscale('log') plt.show() if nproc == 1: xx = [vector2Function(x[i], Vh[i]) for i in range(len(Vh))] dl.plot(xx[STATE], title = "State") dl.plot(dl.exp(xx[PARAMETER]), title = "exp(Parameter)") dl.plot(xx[ADJOINT], title = "Adjoint") dl.plot(vector2Function(model.u_o, Vh[STATE]), title = "Observation") dl.interactive()
def eval(self, values, x): y_0 = -H + a0 * (exp(-((x[0]-L/2.)**2 + (x[1]-L/2.)**2) / sigma**2)) values[0] = sin(theta)/cos(theta) * (x[0] + sin(theta)*y_0) \ + cos(theta)*y_0
m4 = 4.49 m5 = 4.49 m6 = 12.02 m = (m0,m1,m2,m3,m4,m5,m6) parameters = dl.interpolate(dl.Constant(m),parameterV) #Model d = len(u) I = dl.Identity(d) # Identity tensor F = I + dl.grad(u) # Deformation gradient C = F.T*F # Right Cauchy-Green tensor J = dl.det(F) # Jacobian of deformation gradient Cbar = C*(J**(-2.0/3.0)) # Deviatoric Right Cauchy-Green tensor E = dl.Constant(0.5)*(Cbar-I) # Deviatoric Green strain c0,c1,c2,c3,c4,c5,c6 = dl.split(parameters) Q = c1*(E[0,0]**2)+c2*(E[1,1]**2)+c3*(E[2,2]**2) + c4*(dl.Constant(4.0)*(E[1,2]**2)) #+c5*(dl.Constant(4.0)*(E[0,1]**2))#)#+c6*(dl.Constant(4.0)*(E[0,2]**2)) Energy = dl.Constant(0.5)*c0*(dl.exp(Q)-dl.Constant(1.0)) IncompressibilityConstraint = (J-dl.Constant(1.0)) Lagrangian = p*IncompressibilityConstraint*dl.dx + Energy*dl.dx yhat = dl.interpolate(dl.Constant((1,1,1,1)),TaylorHoodV) residual_form = dl.derivative(Lagrangian,y,yhat) residual_form_a = dl.derivative(residual_form, a,atest) residual_form_y = dl.derivative(residual_form, y,ytest) residual_form_ya = dl.assemble(dl.derivative(residual_form_y, a,atrial)) residual_form_ay = dl.assemble(dl.derivative(residual_form_a, y,ytrial)) residual_form_aa = dl.assemble(dl.derivative(residual_form_a, a,atrial)) residual_form_yy = dl.assemble(dl.derivative(residual_form_y, y,ytrial))
def run_with_params(Tb, mu_value, k_s, path): run_time_init = clock() mesh = BoxMesh(Point(0.0, 0.0, 0.0), Point(mesh_width, mesh_width, mesh_height), nx, ny, nz) pbc = PeriodicBoundary() WE = VectorElement('CG', mesh.ufl_cell(), 2) SE = FiniteElement('CG', mesh.ufl_cell(), 1) WSSS = FunctionSpace(mesh, MixedElement(WE, SE, SE, SE), constrained_domain=pbc) # W = FunctionSpace(mesh, WE, constrained_domain=pbc) # S = FunctionSpace(mesh, SE, constrained_domain=pbc) W = WSSS.sub(0).collapse() S = WSSS.sub(1).collapse() temperature_vals = [27.0 + 273, Tb + 273, 1300.0 + 273, 1305.0 + 273] temp_prof = TemperatureProfile(temperature_vals, element=S.ufl_element()) mu_a = mu_value # this was taken from the Blankenbach paper, can change Ep = b / temp_prof.delta mu_bot = exp(-Ep * (temp_prof.bottom * temp_prof.delta - 1573.0) + cc) * mu_a # TODO: verify exponentiation Ra = rho_0 * alpha * g * temp_prof.delta * h ** 3 / (kappa_0 * mu_a) w0 = rho_0 * alpha * g * temp_prof.delta * h ** 2 / mu_a tau = h / w0 p0 = mu_a * w0 / h log(mu_a, mu_bot, Ra, w0, p0) slip_vx = 1.6E-09 / w0 # Non-dimensional slip_velocity = Constant((slip_vx, 0.0, 0.0)) zero_slip = Constant((0.0, 0.0, 0.0)) time_step = 3.0E11 / tau * 2 dt = Constant(time_step) t_end = 3.0E15 / tau / 5.0 # Non-dimensional times u = Function(WSSS) # Instead of TrialFunctions, we use split(u) for our non-linear problem v, p, T, Tf = split(u) v_t, p_t, T_t, Tf_t = TestFunctions(WSSS) T0 = interpolate(temp_prof, S) mu_exp = Expression('exp(-Ep * (T_val * dTemp - 1573.0) + cc * x[2] / mesh_height)', Ep=Ep, dTemp=temp_prof.delta, cc=cc, mesh_height=mesh_height, T_val=T0, element=S.ufl_element()) Tf0 = interpolate(temp_prof, S) mu = Function(S) v0 = Function(W) v_theta = (1.0 - theta) * v0 + theta * v T_theta = (1.0 - theta) * T0 + theta * T Tf_theta = (1.0 - theta) * Tf0 + theta * Tf # TODO: Verify forms r_v = (inner(sym(grad(v_t)), 2.0 * mu * sym(grad(v))) - div(v_t) * p - T * v_t[2]) * dx r_p = p_t * div(v) * dx heat_transfer = Constant(k_s) * (Tf_theta - T_theta) * dt r_T = (T_t * ((T - T0) + dt * inner(v_theta, grad(T_theta))) # TODO: Inner vs dot + (dt / Ra) * inner(grad(T_t), grad(T_theta)) - T_t * heat_transfer) * dx v_melt = Function(W) z_hat = Constant((0.0, 0.0, 1.0)) # TODO: inner -> dot, take out Tf_t r_Tf = (Tf_t * ((Tf - Tf0) + dt * inner(v_melt, grad(Tf_theta))) + Tf_t * heat_transfer) * dx r = r_v + r_p + r_T + r_Tf bcv0 = DirichletBC(WSSS.sub(0), zero_slip, top) bcv1 = DirichletBC(WSSS.sub(0), slip_velocity, bottom) bcv2 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), back) bcv3 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), front) bcp0 = DirichletBC(WSSS.sub(1), Constant(0.0), bottom) bct0 = DirichletBC(WSSS.sub(2), Constant(temp_prof.surface), top) bct1 = DirichletBC(WSSS.sub(2), Constant(temp_prof.bottom), bottom) bctf1 = DirichletBC(WSSS.sub(3), Constant(temp_prof.bottom), bottom) bcs = [bcv0, bcv1, bcv2, bcv3, bcp0, bct0, bct1, bctf1] t = 0 count = 0 files = DefaultDictByKey(partial(create_xdmf, path)) while t < t_end: mu.interpolate(mu_exp) rhosolid = rho_0 * (1.0 - alpha * (T0 * temp_prof.delta - 1573.0)) deltarho = rhosolid - rho_melt # TODO: project (accuracy) vs interpolate assign(v_melt, project(v0 - darcy * (grad(p) * p0 / h - deltarho * z_hat * g) / w0, W)) # TODO: Written out one step later? # v_melt.assign(v0 - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0) # TODO: use nP after to avoid projection? solve(r == 0, u, bcs) nV, nP, nT, nTf = u.split() # TODO: write with Tf, ... etc if count % output_every == 0: time_left(count, t_end / time_step, run_time_init) # TODO: timestep vs dt # TODO: Make sure all writes are to the same function for each time step files['T_fluid'].write(nTf, t) files['p'].write(nP, t) files['v_solid'].write(nV, t) files['T_solid'].write(nT, t) files['mu'].write(mu, t) files['v_melt'].write(v_melt, t) files['gradp'].write(project(grad(nP), W), t) files['rho'].write(project(rhosolid, S), t) files['Tf_grad'].write(project(grad(Tf), W), t) files['advect'].write(project(dt * dot(v_melt, grad(nTf))), t) files['ht'].write(project(heat_transfer, S), t) assign(T0, nT) assign(v0, nV) assign(Tf0, nTf) t += time_step count += 1 log('Case mu={}, Tb={}, k={} complete. Run time = {:.2f} minutes'.format(mu_a, Tb, k_s, (clock() - run_time_init) / 60.0))