def les_setup(u_, mesh, KineticEnergySGS, assemble_matrix, CG1Function, nut_krylov_solver, bcs, **NS_namespace): """ Set up for solving the Kinetic Energy SGS-model. """ DG = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) dim = mesh.geometry().dim() delta = Function(DG) delta.vector().zero() delta.vector().axpy(1.0, assemble(TestFunction(DG) * dx)) delta.vector().set_local(delta.vector().array()**(1. / dim)) delta.vector().apply('insert') Ck = KineticEnergySGS["Ck"] ksgs = interpolate(Constant(1E-7), CG1) bc_ksgs = DirichletBC(CG1, 0, "on_boundary") A_mass = assemble_matrix(TrialFunction(CG1) * TestFunction(CG1) * dx) nut_form = Ck * delta * sqrt(ksgs) bcs_nut = derived_bcs(CG1, bcs['u0'], u_) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, bounded=True, name="nut") At = Matrix() bt = Vector(nut_.vector()) ksgs_sol = KrylovSolver("bicgstab", "additive_schwarz") #ksgs_sol.parameters["preconditioner"]["structure"] = "same_nonzero_pattern" ksgs_sol.parameters["error_on_nonconvergence"] = False ksgs_sol.parameters["monitor_convergence"] = False ksgs_sol.parameters["report"] = False del NS_namespace return locals()
def solver_setup(F_fluid_linear, F_fluid_nonlinear, F_solid_linear, F_solid_nonlinear, DVP, dvp_, up_sol, compiler_parameters, **namespace): """ Pre-assemble the system of equations for the Jacobian matrix for the Newton solver """ F_lin = F_fluid_linear + F_solid_linear F_nonlin = F_solid_nonlinear + F_fluid_nonlinear F = F_lin + F_nonlin chi = TrialFunction(DVP) J_linear = derivative(F_lin, dvp_["n"], chi) J_nonlinear = derivative(F_nonlin, dvp_["n"], chi) A_pre = assemble(J_linear, form_compiler_parameters=compiler_parameters, keep_diagonal=True) A = Matrix(A_pre) b = None # Option not available in FEniCS 2018.1.0 # up_sol.parameters['reuse_factorization'] = True return dict(F=F, J_nonlinear=J_nonlinear, A_pre=A_pre, A=A, b=b, up_sol=up_sol)
def weighted_gradient_matrix(mesh, i, family='CG', degree=1, constrained_domain=None): """Compute weighted gradient matrix The matrix allows you to compute the gradient of a P1 Function through a simple matrix vector product CG family: p_ is the pressure solution on CG1 dPdX = weighted_gradient_matrix(mesh, 0, 'CG', degree) V = FunctionSpace(mesh, 'CG', degree) dpdx = Function(V) dpdx.vector()[:] = dPdX * p_.vector() The space for dpdx must be continuous Lagrange of some order CR family: p_ is the pressure solution on CR dPdX = weighted_gradient_matrix(mesh, 0, 'CR', 1) V = FunctionSpace(mesh, 'CR', 1) dpdx = Function(V) dpdx.vector()[:] = dPdX * p_.vector() """ DG = FunctionSpace(mesh, 'DG', 0) if family == 'CG': # Source and Target spaces are CG_1 and CG_degree S = FunctionSpace(mesh, 'CG', 1, constrained_domain=constrained_domain) T = FunctionSpace(mesh, 'CG', degree, constrained_domain=constrained_domain) elif family == 'CR': if degree != 1: print('\033[1;37;34m%s\033[0m' % 'Ignoring degree') # Source and Target spaces are CR S = FunctionSpace(mesh, 'CR', 1, constrained_domain=constrained_domain) T = S else: raise ValueError('Only CG and CR families are allowed.') G = assemble(TrialFunction(DG)*TestFunction(T)*dx) dg = Function(DG) if isinstance(i, (tuple, list)): CC = [] for ii in i: dP = assemble(TrialFunction(S).dx(ii)*TestFunction(DG)*dx) A = Matrix(G) Cp = compiled_gradient_module.compute_weighted_gradient_matrix(A, dP, dg) CC.append(Cp) return CC else: dP = assemble(TrialFunction(S).dx(i)*TestFunction(DG)*dx) Cp = compiled_gradient_module.compute_weighted_gradient_matrix(G, dP, dg) #info(G, True) #info(dP, True) return Cp
def assemble(a): """ Assemles a _DofForm_. *Arguments* a _DofForm_ to assemble. """ A = 0 if a.rank() == 2: A = Matrix() elif a.rank() == 1: A = Vector() cpp.DofAssembler.assemble(A, a, True) return A
def gaussian_distribution(mb, mu, sigma, function=None, lumping=True, nsteps=100): "Gaussian distribution via heat equation" tend = 0.5 * sigma**2 dt = Constant(tend / nsteps, name="smooth") # prepare the problem P1e = FiniteElement("CG", mb.ufl_cell(), 1) Ve = FunctionSpace(mb, P1e) u, v = TrialFunction(Ve), TestFunction(Ve) uold = Function(Ve) if lumping: # diffusion K = assemble(dt * inner(grad(u), grad(v)) * dx) # we use mass lumping to avoid negative values Md = assemble(action(u * v * dx, Constant(1.0))) # full matrix (divide my mass) M = Matrix(K) M.zero() M.set_diagonal(Md) A = M + K else: a = u * v * dx + dt * inner(grad(u), grad(v)) * dx L = uold * v * dx A = assemble(a) # initial conditions dist = function or Function(Ve) dist.vector().zero() PointSource(Ve, mu, 1.0).apply(dist.vector()) # iterations for t in range(nsteps): uold.assign(dist) if lumping: solve(A, dist.vector(), M * uold.vector()) else: b = assemble(L) solve(A, dist.vector(), b) # normalize area = assemble(dist * dx) dist.vector()[:] /= area if function is None: return dist
def __init__(self, u_, Space, bcs=[], name="div", method={}): solver_type = method.get('solver_type', 'cg') preconditioner_type = method.get('preconditioner_type', 'default') solver_method = method.get('method', 'default') low_memory_version = method.get('low_memory_version', False) OasisFunction.__init__(self, div(u_), Space, bcs=bcs, name=name, method=solver_method, solver_type=solver_type, preconditioner_type=preconditioner_type) Source = u_[0].function_space() if not low_memory_version: self.matvec = [[ A_cache[(self.test * TrialFunction(Source).dx(i) * dx, ())], u_[i] ] for i in range(Space.mesh().geometry().dim())] if solver_method.lower() == "gradient_matrix": from fenicstools import compiled_gradient_module DG = FunctionSpace(Space.mesh(), 'DG', 0) G = assemble(TrialFunction(DG) * self.test * dx()) dg = Function(DG) self.WGM = [] st = TrialFunction(Source) for i in range(Space.mesh().geometry().dim()): dP = assemble(st.dx(i) * TestFunction(DG) * dx) A = Matrix(G) self.WGM.append( compiled_gradient_module.compute_weighted_gradient_matrix( A, dP, dg))
np.set_printoptions(formatter={'all': lambda x: '%.5E' % x}) def copy_to_vector(U, U_array): assert U.size() == len(U_array) U.set_local(U_array) U.apply('') # Get the forms # a, L, V, bc, Z = neumann_poisson_data() a, L, V, bc, Z = neumann_elasticity_data() # Turn to dolfin.la objects parameters.linear_algebra_backend = 'uBLAS' # this one provides Matrix.data A, b = Matrix(), Vector() assemble_system(a, L, A_tensor=A, b_tensor=b) # Turn to scipy objects rows, cols, values = A.data() AA = csr_matrix((values, cols, rows)) bb = np.array(b.array()) # Okay, first claim is that CG solver can't solve the problem Ax=b if the # rhs is not perpendicular to the nullspace ZZ = [np.array(Zi.array()) for Zi in Z] for ZZi in ZZ: print '<b, Zi> =', ZZi.dot(bb) x, info = la.cg(AA, bb)