コード例 #1
0
ファイル: ESDIRK.py プロジェクト: ayonge3/gryphon-project
    def getLinearVariationalForms(self, B, X):
        # Get the number of stage values
        s = B.shape[0]
        # Generate copies of time dependent functions
        self.tdfButcher = [[] for i in range(len(self.tdf))]
        for j in range(0, len(self.tdf)):
            for i in range(0, s):
                if self.tdf[j].__class__.__name__ == "CompiledExpression":
                    self.tdfButcher[j].append(Expression(self.tdf[j].cppcode, t=self.tstart))
                else:
                    self.tdfButcher[j].append(self.tdf[j])

        if self.n == 1:
            # Add differential equation
            L = [self.U * self.Q * dx - self.u * self.Q * dx for j in range(s - 1)]
            for j in range(0, s - 1):
                R = {}
                for k in range(0, len(self.tdf)):
                    R[self.tdf[k]] = self.tdfButcher[k][j + 1]
                L[j] -= self.DT * B[1, 1] * replace(self.f[0], R)

            for i in range(0, s - 1):
                for j in range(0, i + 1):
                    R = {}
                    for k in range(0, len(self.tdf)):
                        R[self.tdf[k]] = self.tdfButcher[k][j]
                    L[i] -= self.DT * B[i + 1, j] * action(replace(self.f[0], R), X[j])
        else:
            # Add differential equations
            L = [reduce((lambda x, y: x + y),
                        [self.U[alpha] * self.Q[alpha] * dx - self.u[alpha] * self.Q[alpha] * dx for alpha in
                         range(self.n - self.m)]) for i in range(s - 1)]
            for alpha in range(0, self.n - self.m):
                for i in range(s - 1):
                    R = {}
                    for k in range(0, len(self.tdf)):
                        R[self.tdf[k]] = self.tdfButcher[k][i + 1]
                    L[i] -= self.DT * B[1, 1] * replace(self.f[alpha], R)
                    for j in range(i + 1):
                        R = {}
                        for k in range(0, len(self.tdf)):
                            R[self.tdf[k]] = self.tdfButcher[k][j]
                        L[i] -= self.DT * B[i + 1, j] * action(replace(self.f[alpha], R), X[j])

            # Add algebraic equations
            for beta in range(self.m):
                for i in range(s - 1):
                    R = {}
                    for k in range(len(self.tdf)):
                        R[self.tdf[k]] = self.tdfButcher[k][i + 1]
                    L[i] += replace(self.g[beta], R)

        return L
コード例 #2
0
def adjoint_genericmatrix_mul(self, other):
    out = dolfin_genericmatrix_mul(self, other)
    if hasattr(self, 'form') and isinstance(other, dolfin.GenericVector):
        if hasattr(other, 'form'):
            out.form = dolfin.action(self.form, other.form)
        elif hasattr(other, 'function'):
            if hasattr(other, 'function_factor'):
                out.form = dolfin.action(other.function_factor*self.form, other.function)
            else:
                out.form = dolfin.action(self.form, other.function)

    return out
コード例 #3
0
def adjoint_genericmatrix_mul(self, other):
  out = dolfin_genericmatrix_mul(self, other)
  if hasattr(self, 'form') and isinstance(other, dolfin.GenericVector):
    if hasattr(other, 'form'):
      out.form = dolfin.action(self.form, other.form)
    elif hasattr(other, 'function'):
      if hasattr(other, 'function_factor'):
        out.form = dolfin.action(other.function_factor*self.form, other.function)
      else:
        out.form = dolfin.action(self.form, other.function)

  return out
コード例 #4
0
ファイル: pdemodel.py プロジェクト: codeants2012/NLP.py
    def jtprod(self, x, v, apply_bcs=True, **kwargs):
        """Transposed-Jacobian-vector product.

        Evaluate matrix-vector product between the transposed of the constraint
        Jacobian at x and v.

        :parameters:
            :x: NumPy ``array`` or Dolfin ``Expression``
            :v: Numpy ``array`` to multiply with
            :apply_bcs: apply boundary conditions to ``x`` prior to evaluation.

        If ``x`` is an ``Expression``, it must defined on the appropriate
        function space, by, e.g., declaring it as::

          v = Expression('x[0]*sin(x[1])',
                         element=pdenlp.function_space.ufl_element())

        where ``pdenlp`` is a ``PDENPLModel`` instance.
        """
        if self.__adjoint_jacobian is None:
            self.compile_adjoint_jacobian()

        self.assign_vector(x, apply_bcs=apply_bcs)

        w = Function(self.dual_function_space)
        w.vector()[:] = v
        JTop = action(self.__adjoint_jacobian, w)
        jtv = assemble(JTop)
        return jtv.array()
コード例 #5
0
    def derivative(self, parameter):
        """
        Return the derivative of the residual with respect to the supplied Constant
        or Function.
        """

        if not isinstance(parameter, (dolfin.Constant, dolfin.Function)):
            raise InvalidArgumentException(
                "parameter must be a Constant or Function")

        if self.is_linear():
            if form_rank(self.__eq.lhs) == 1:
                if parameter is self.__x:
                    form = self.__eq.lhs
                elif parameter in ufl.algorithms.extract_coefficients(
                        self.__eq.lhs):
                    raise NotImplementedException(
                        "General derivative for linear variational problem with rank 1 LHS not implemented"
                    )
                else:
                    form = ufl.form.Form([])
            else:
                form = dolfin.action(self.__eq.lhs, self.__x)
        else:
            form = self.__eq.lhs
        if not is_zero_rhs(self.__eq.rhs):
            form -= self.__eq.rhs

        return derivative(form, parameter)
コード例 #6
0
ファイル: state.py プロジェクト: micromagnetics/magnum.fe
  def M_inv_diag(self, domain = "all"):
    """
    Returns the inverse lumped mass matrix for the vector function space.
    The result ist cached.

    .. note:: This method requires the PETSc Backend to be enabled.

    *Returns*
      :class:`dolfin.Matrix`
        the matrix
    """
    if not self._M_inv_diag.has_key(domain):
      v = TestFunction(self.VectorFunctionSpace())
      u = TrialFunction(self.VectorFunctionSpace())

      mass_form = inner(v, u) * self.dx(domain)
      mass_action_form = action(mass_form, Constant((1.0, 1.0, 1.0)))
      diag = assemble(mass_action_form)
      as_backend_type(diag).vec().reciprocal()

      result = assemble(inner(v, u) * dP)
      result.zero()
      result.set_diagonal(diag)
      self._M_inv_diag[domain] = result

    return self._M_inv_diag[domain]
コード例 #7
0
    def test_unconstrained_newton_solver(self):
        L, nelem = 1, 201

        mesh = dl.IntervalMesh(nelem, -L, L)
        Vh = dl.FunctionSpace(mesh, "CG", 2)

        forcing = dl.Constant(1)

        dirichlet_bcs = [dl.DirichletBC(Vh, dl.Constant(0.0), on_any_boundary)]
        bc0 = dl.DirichletBC(Vh, dl.Constant(0.0), on_any_boundary)

        uh = dl.TrialFunction(Vh)
        vh = dl.TestFunction(Vh)
        F = dl.inner((1 + uh**2) * dl.grad(uh),
                     dl.grad(vh)) * dl.dx - forcing * vh * dl.dx
        u = dl.Function(Vh)
        F = dl.action(F, u)
        parameters = {
            "symmetric": True,
            "newton_solver": {
                # "relative_tolerance": 1e-8,
                "report": True,
                "linear_solver": "cg",
                "preconditioner": "petsc_amg"
            }
        }
        dl.solve(F == 0, u, dirichlet_bcs, solver_parameters=parameters)
        # dl.plot(uh)
        # plt.show()

        u_newton = dl.Function(Vh)
        F = dl.inner((1 + uh**2) * dl.grad(uh),
                     dl.grad(vh)) * dl.dx - forcing * vh * dl.dx
        F = dl.action(F, u_newton)
        # Compute Jacobian
        J = dl.derivative(F, u_newton, uh)
        unconstrained_newton_solve(
            F,
            J,
            u_newton,
            dirichlet_bcs=dirichlet_bcs,
            bc0=bc0,
            # linear_solver='PETScLU',opts=dict())
            linear_solver=None,
            opts=dict())
        error = dl.errornorm(u, u_newton, mesh=mesh)
        assert error < 1e-15
コード例 #8
0
    def solve_molecular(self,rho_solute=const.rhom):
        """
        Solve the molecular diffusion problem
        if 'solve_sol_mol' is not in the flags list this will be an instantaneous mixing problem.
        """

        # Solve solution concentration
        # Diffusivity
        ramp = dolfin.Expression('x[0] > minR ? 100. : 1.',minR=np.log(self.Rstar)-0.5,degree=1)
        self.Dstar = dolfin.project(dolfin.Expression('ramp*diff_ratio*exp(-2.*x[0])',degree=1,ramp=ramp,diff_ratio=self.astar_i/self.Lewis),self.sol_V)
        # calculate solute flux (this is like the Stefan condition for the molecular diffusion problem
        Dwall = self.Dstar(self.sol_coords[self.sol_idx_wall])
        self.solFlux = -(self.C_wall/Dwall)*(self.dR/self.dt)
        # Set the concentration for points that moved out of the grid to match the solute flux
        u0_c_hold = self.u0_c.vector()[:].copy()
        u0_c_hold[~self.sol_idx_extrapolate] = self.C_wall+self.solFlux*(np.exp(self.sol_coords[~self.sol_idx_extrapolate,0])-self.Rstar)
        u0_c_hold[u0_c_hold<0.]=0.
        self.u0_c.vector()[:] = u0_c_hold[:]
        # Variational Problem
        F_c = (self.u_s-self.u0_c)*self.v_s*dolfin.dx + \
                self.dt*dolfin.inner(dolfin.grad(self.u_s), dolfin.grad(self.Dstar*self.v_s))*dolfin.dx - \
                self.dt*self.solFlux*self.v_s*self.sds(1)
        F_c = dolfin.action(F_c,self.C)
        # First derivative
        J = dolfin.derivative(F_c, self.C, self.u_s)
        # handle the bounds
        lower = dolfin.project(dolfin.Constant(0.0),self.sol_V)
        upper = dolfin.project(dolfin.Constant(rho_solute),self.sol_V)
        # set bounds and solve
        snes_solver_parameters = {"nonlinear_solver": "snes",
                                  "snes_solver": {"linear_solver": "lu",
                                                  "maximum_iterations": 20,
                                                  "report": True,
                                                  "error_on_nonconvergence": False}}
        problem = dolfin.NonlinearVariationalProblem(F_c, self.C, J=J)
        problem.set_bounds(lower, upper)
        solver = dolfin.NonlinearVariationalSolver(problem)
        solver.parameters.update(snes_solver_parameters)
        dolfin.info(solver.parameters, True)
        (iter, converged) = solver.solve()
        self.u0_c.assign(self.C)

        # Recalculate the freezing temperature
        self.Tf_last = self.Tf
        self.Tf = Tf_depression(self.C.vector()[self.sol_idx_wall,0],linear=True)
        # Get the updated solution properties
        self.rhos = dolfin.project(dolfin.Expression('C + rhow*(1.-C/rho_solute)',
            degree=1,C=self.C,rhow=const.rhow,rho_solute=rho_solute),self.sol_V)
        self.cs = dolfin.project(dolfin.Expression('ce*(C/rho_solute) + cw*(1.-C/rho_solute)',
            degree=1,C=self.C,cw=const.cw,ce=const.ce,rho_solute=rho_solute),self.sol_V)
        self.ks = dolfin.project(dolfin.Expression('ke*(C/rho_solute) + kw*(1.-C/rho_solute)',
            degree=1,C=self.C,kw=const.kw,ke=const.ke,rho_solute=rho_solute),self.sol_V)
        self.rhos_wall = self.rhos.vector()[self.sol_idx_wall]
        self.cs_wall = self.cs.vector()[self.sol_idx_wall]
        self.ks_wall = self.ks.vector()[self.sol_idx_wall]
コード例 #9
0
ファイル: utils.py プロジェクト: pezzus/fimh2021
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
コード例 #10
0
ファイル: isaacs.py プロジェクト: BartoszJaroszkowski/FEISol
    def assemble_lumpedmm(self):
        """ Assembly lumped mass matrix - plays role of identity matrix
        """
        print("Assembling lumped mass matrix")
        mass_form = self.w * self.u * dx
        self.mass_matrix = assemble(mass_form)

        mass_action_form = action(mass_form, Constant(1))
        self.MM_terms = assemble(mass_action_form)

        self.mass_matrix.zero()
        self.mass_matrix.set_diagonal(self.MM_terms)
        self.scipy_mass_matrix = toscipy(self.mass_matrix)
コード例 #11
0
def action(form, coefficient):
    """
    Wrapper for the DOLFIN action function. Correctly handles QForm s.
    """

    if not isinstance(form, ufl.form.Form):
        raise InvalidArgumentException("form must be a Form")
    if not isinstance(coefficient, dolfin.Function):
        raise InvalidArgumentException("coefficient must be a Function")

    nform = dolfin.action(form, coefficient)
    if isinstance(form, QForm):
        return QForm(nform, quadrature_degree = form_quadrature_degree(form))
    else:
        return nform
コード例 #12
0
    def J(self):
        """
        Return the derivative of the residual with respect to x (the Jacobian).
        """

        if self.__J is None:
            if self.is_linear():
                form = dolfin.action(self.__eq.lhs, self.__x)
            else:
                form = self.__eq.lhs
            if not is_zero_rhs(self.__eq.rhs):
                form -= self.__eq.rhs
            self.__J = derivative(form, self.__x)

        return self.__J
コード例 #13
0
def run_dolfin():

    import dolfin as df

    x_array = np.linspace(-49.5, 49.5, 100)

    mesh = df.IntervalMesh(100, -50, 50)

    Delta = np.sqrt(A / K)
    xi = 2 * A / D

    Delta_s = Delta * 1e9

    V = df.FunctionSpace(mesh, "Lagrange", 1)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    u_ = df.Function(V)
    F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \
        (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx
    F = df.action(F, u_)

    J = df.derivative(F, u_, u)

    # the boundary condition is from equation (8)
    theta0 = np.arcsin(Delta / xi)
    ss = 'x[0]<0? %g: %g ' % (-theta0, theta0)

    u0 = df.Expression(ss)

    def u0_boundary(x, on_boundary):
        return on_boundary

    bc = df.DirichletBC(V, u0, u0_boundary)

    problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J)
    solver = df.NonlinearVariationalSolver(problem)
    solver.solve()

    u_array = u_.vector().array()

    mx_df = []
    for x in x_array:
        mx_df.append(u_(x))

    return mx_df
コード例 #14
0
ファイル: pdemodel.py プロジェクト: codeants2012/NLP.py
    def hprod(self, x, y, v, apply_bcs=True, **kwargs):
        """Hessian-vector product.

        Evaluate matrix-vector product between the Hessian of the Lagrangian at
        (x, z) and v.

        :parameters:
            :x: NumPy ``array`` or Dolfin ``Expression``
            :y: Numpy ``array`` or Dolfin ``Expression`` for multipliers
            :v: Numpy ``array`` to multiply with
            :apply_bcs: apply boundary conditions to ``x`` prior to evaluation.

        If ``x`` is an ``Expression``, it must defined on the appropriate
        function space, by, e.g., declaring it as::

          v = Expression('x[0]*sin(x[1])',
                         element=pdenlp.function_space.ufl_element())

        where ``pdenlp`` is a ``PDENPLModel`` instance.
        """
        obj_weight = kwargs.get('obj_weight', 1.0)

        if self.__objective_hessian is None:
            self.compile_objective_hessian()

        self.assign_vector(x, apply_bcs=apply_bcs)

        w = Function(self.function_space)
        w.vector()[:] = v
        Hop = action(self.__objective_hessian, w)
        hv = obj_weight * assemble(Hop).array()

        if self.ncon > 0 and y is not None:
            if self.__constraint_jacobian is None:
                self.compile_constraint_jacobian()

            z = Function(self.__dual_function_space)
            z.vector()[:] = -y

            # ∑ⱼ yⱼ Hⱼ(u) may be viewed as the directional derivative
            # of J(.) with respect to u in the direction y.
            Hc = derivative(self.__constraint_jacobian, self.__u, z)
            hv += Hc * v

        return hv
コード例 #15
0
ファイル: test_prb88_184422.py プロジェクト: fangohr/fidimag
def run_dolfin():

    import dolfin as df

    x_array = np.linspace(-49.5, 49.5, 100)

    mesh = df.IntervalMesh(100, -50, 50)

    Delta = np.sqrt(A / K)
    xi = 2 * A / D

    Delta_s = Delta * 1e9

    V = df.FunctionSpace(mesh, "Lagrange", 1)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    u_ = df.Function(V)
    F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \
        (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx
    F = df.action(F, u_)

    J = df.derivative(F, u_, u)

    # the boundary condition is from equation (8)
    theta0 = np.arcsin(Delta / xi)
    ss = 'x[0]<0? %g: %g ' % (-theta0, theta0)

    u0 = df.Expression(ss)

    def u0_boundary(x, on_boundary):
        return on_boundary

    bc = df.DirichletBC(V, u0, u0_boundary)

    problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J)
    solver = df.NonlinearVariationalSolver(problem)
    solver.solve()

    u_array = u_.vector().array()

    mx_df = []
    for x in x_array:
        mx_df.append(u_(x))

    return mx_df
コード例 #16
0
    def assemble_lumpedmm(self):
        """ Assembly lumped mass matrix - equal to 0 on robin boundary since
            there is no time derivative there.
        """
        print("Assembling lumped mass matrix")
        mass_form = self.w * self.u * dx
        mass_action_form = action(mass_form, Constant(1))
        self.MM_terms = assemble(mass_action_form)

        for n in self.robint_nodes_list:
            self.MM_terms[n] = 1.0
        for n in self.robin_nodes_list:
            self.MM_terms[n] = 0.0

        self.mass_matrix = assemble(mass_form)
        self.mass_matrix.zero()
        self.mass_matrix.set_diagonal(self.MM_terms)
        self.scipy_mass_matrix = toscipy(self.mass_matrix)
コード例 #17
0
 def setSolverParams(self, step=None):
     if self.eqn == "poisboltz":
         print("PoisBoltz")
         self.F = dolfin.action(self.F, self.u_s)
         J = dolfin.derivative(self.F, self.u_s, self.u)
         problem = dolfin.NonlinearVariationalProblem(
             self.F, self.u_s, self.bcs, J)
         self.solver = dolfin.NonlinearVariationalSolver(problem)
         prm = self.solver.parameters
         prm['newton_solver']['absolute_tolerance'] = self.max_abs_error
         prm['newton_solver']['relative_tolerance'] = self.max_rel_error
         prm['newton_solver']['maximum_iterations'] = 10000
         prm['newton_solver']['relaxation_parameter'] = 0.1
         prm['newton_solver']['report'] = True
         prm['newton_solver']['linear_solver'] = self.method
         prm['newton_solver']['preconditioner'] = self.preconditioner
         prm['newton_solver']['krylov_solver']['maximum_iterations'] = 10000
         prm['newton_solver']['krylov_solver'][
             'absolute_tolerance'] = self.max_abs_error
         prm['newton_solver']['krylov_solver'][
             'relative_tolerance'] = self.max_rel_error
         prm['newton_solver']['krylov_solver']['monitor_convergence'] = True
     else:
         print("Separating LHS and RHS...")
         # Separate left and right hand sides of equation
         self.a, self.L = dolfin.lhs(self.F), dolfin.rhs(self.F)
         self.problem = dolfin.LinearVariationalProblem(
             self.a, self.L, self.u_s, self.bcs)
         self.solver = dolfin.LinearVariationalSolver(self.problem)
         dolfin.parameters['form_compiler']['optimize'] = True
         self.solver.parameters['linear_solver'] = self.method
         self.solver.parameters['preconditioner'] = self.preconditioner
         spec_param = self.solver.parameters['krylov_solver']
         #These only accessible after spec_param available.
         if self.init_guess == "prev":
             if step == 0:
                 spec_param['nonzero_initial_guess'] = False
             else:
                 spec_param['nonzero_initial_guess'] = True
         elif self.init_guess == "zero":
             spec_param['nonzero_initial_guess'] = False
         spec_param['absolute_tolerance'] = self.max_abs_error
         spec_param['relative_tolerance'] = self.max_rel_error
         spec_param['maximum_iterations'] = self.max_linear_iters
コード例 #18
0
    def set_forms(self, unknown, geom_ord=[0]):
        """
        Set up weak forms of elliptic PDE.
        """
        if any(s >= 0 for s in geom_ord):
            ## forms for forward equation ##
            # 4. Define variational problem
            # functions
            if not hasattr(self, 'states_fwd'):
                self.states_fwd = df.Function(self.W)
            # u, l = df.split(self.states_fwd)
            u, l = df.TrialFunctions(self.W)
            v, m = df.TestFunctions(self.W)
            f = self._source_term(degree=2)
            # variational forms
            if 'true' in str(type(unknown)):
                unknown = df.interpolate(unknown, self.V)
            self.F = df.exp(unknown) * df.inner(
                df.grad(u), df.grad(v)) * df.dx + (
                    u * m + v *
                    l) * self.ds - f * v * df.dx + self.nugg * l * m * df.dx
#             self.dFdstates = df.derivative(self.F, self.states_fwd) # Jacobian
#             self.a = unknown*df.inner(df.grad(u), df.grad(v))*df.dx + (u*m + v*l)*self.ds + self.nugg*l*m*df.dx
#             self.L = f*v*df.dx
        if any(s >= 1 for s in geom_ord):
            ## forms for adjoint equation ##
            # Set up the objective functional J
            #             u,_,_ = df.split(self.states_fwd)
            #             J_form = obj.form(u)
            # Compute adjoint of forward operator
            F2 = df.action(self.F, self.states_fwd)
            self.dFdstates = df.derivative(
                F2, self.states_fwd)  # linearized forward operator
            args = ufl.algorithms.extract_arguments(
                self.dFdstates)  # arguments for bookkeeping
            self.adj_dFdstates = df.adjoint(
                self.dFdstates, reordered_arguments=args
            )  # adjoint linearized forward operator
            #             self.dJdstates = df.derivative(J_form, self.states_fwd, df.TestFunction(self.W)) # derivative of functional with respect to solution
            #             self.dirac_1 = obj.ptsrc(u,1) # dirac_1 cannot be initialized here because it involves evaluation
            ## forms for gradient ##
            self.dFdunknown = df.derivative(F2, unknown)
            self.adj_dFdunknown = df.adjoint(self.dFdunknown)
コード例 #19
0
ファイル: pfibs_adjoint.py プロジェクト: NREL/pfibs
    def _assemble_and_solve_adj_eq(self, dFdu_form, dJdu):
        dJdu_copy = dJdu.copy()
        bcs = self._homogenize_bcs()

        solver = self.block_helper.adjoint_solver
        if solver is None:

            adj_sol = df.Function(self.function_space)

            adjoint_problem = pf.BlockProblem(dFdu_form,
                                              dJdu,
                                              adj_sol,
                                              bcs=bcs)
            for key, value in self.block_field.items():
                adjoint_problem.field(key, value[1], solver=value[2])
            for key, value in self.block_split.items():
                adjoint_problem.split(key, value[0], solver=value[1])
            solver = pf.LinearBlockSolver(adjoint_problem)
            self.block_helper.adjoint_solver = solver

            ############
            ## Assemble ##
            rhs_bcs_form = df.inner(df.Function(self.function_space),
                                    dFdu_form.arguments()[0]) * df.dx
            A_, _ = df.assemble_system(dFdu_form, rhs_bcs_form, bcs)
            A = df.as_backend_type(A_)

            solver.linear_solver.set_operators(A, A)
            solver.linear_solver.init_solver_options()

        [bc.apply(dJdu) for bc in bcs]
        b = df.as_backend_type(dJdu)
        ## Actual solve ##
        its = solver.linear_solver.solve(adj_sol.vector(), b)
        ###########

        adj_sol_bdy = dfa.compat.function_from_vector(
            self.function_space, dJdu_copy -
            dfa.compat.assemble_adjoint_value(df.action(dFdu_form, adj_sol)))
        return adj_sol, adj_sol_bdy
コード例 #20
0
    def test_constrained_newton_energy_solver(self):
        L, nelem = 1, 201

        mesh = dl.IntervalMesh(nelem, -L, L)
        Vh = dl.FunctionSpace(mesh, "CG", 2)

        forcing = dl.Constant(1)

        dirichlet_bcs = [dl.DirichletBC(Vh, dl.Constant(0.0), on_any_boundary)]
        bc0 = dl.DirichletBC(Vh, dl.Constant(0.0), on_any_boundary)

        uh = dl.TrialFunction(Vh)
        vh = dl.TestFunction(Vh)
        F = dl.inner((1 + uh**2) * dl.grad(uh),
                     dl.grad(vh)) * dl.dx - forcing * vh * dl.dx
        F += uh * vh * dl.inner(dl.nabla_grad(uh), dl.nabla_grad(uh)) * dl.dx
        u = dl.Function(Vh)
        F = dl.action(F, u)
        parameters = {
            "symmetric": True,
            "newton_solver": {
                "relative_tolerance": 1e-12,
                "report": True,
                "linear_solver": "cg",
                "preconditioner": "petsc_amg"
            }
        }
        dl.solve(F == 0, u, dirichlet_bcs, solver_parameters=parameters)
        # dl.plot(uh)
        # plt.show()

        F = 0.5 * (1 + uh**2) * dl.inner(dl.nabla_grad(uh), dl.nabla_grad(
            uh)) * dl.dx - forcing * uh * dl.dx
        #F = dl.inner((1+uh**2)*dl.grad(uh),dl.grad(vh))*dl.dx-forcing*vh*dl.dx
        u_newton = dl.Function(Vh)
        F = dl.action(F, u_newton)
        constrained_newton_energy_solve(F,
                                        u_newton,
                                        dirichlet_bcs=dirichlet_bcs,
                                        bc0=bc0,
                                        linear_solver='PETScLU',
                                        opts=dict())

        F = 0.5 * (1 + uh**2) * dl.inner(dl.nabla_grad(uh), dl.nabla_grad(
            uh)) * dl.dx - forcing * uh * dl.dx
        u_grad = dl.Function(Vh)
        F = dl.action(F, u_grad)
        grad = dl.derivative(F, u_grad)
        print(F)
        print(grad)
        parameters = {
            "symmetric": True,
            "newton_solver": {
                "relative_tolerance": 1e-12,
                "report": True,
                "linear_solver": "cg",
                "preconditioner": "petsc_amg"
            }
        }
        dl.solve(grad == 0,
                 u_grad,
                 dirichlet_bcs,
                 solver_parameters=parameters)
        error1 = dl.errornorm(u_grad, u_newton, mesh=mesh)
        # print(error)
        error2 = dl.errornorm(u, u_newton, mesh=mesh)
        # print(error)
        # dl.plot(u)
        # dl.plot(u_newton)
        # dl.plot(u_grad)
        # plt.show()
        assert error1 < 1e-15
        assert error2 < 1e-15
コード例 #21
0
    def assembleSystem(self):
        """Assemble the FEM system. This is only run a single time before time-stepping. The values of the coefficient
        fields need to be updated between time-steps
        """
        # Loop through the entire model and composite the system of equations
        self.diffusors = []  # [[compartment, species, diffusivity of species],[ ...],[...]]
        """
           Diffusors have source terms
        """
        self.electrostatic_compartments = [] # (compartment) where electrostatic equations reside
        """
           Has source term
        """
        self.potentials = [] # (membrane)
        """
            No spatial derivatives, just construct ODE
        """
        self.channelvars = [] #(membrane, channel, ...)

        for compartment in self.compartments:
            s = 0
            for species in compartment.species:
                if compartment.diffusivities[species] < 1e-10: continue
                self.diffusors.extend([ [compartment,species,compartment.diffusivities[species]] ])
                s+=compartment.diffusivities[species]*abs(species.z)
            if s>0:
                self.electrostatic_compartments.extend([compartment])
                # Otherwise, there are no mobile charges in the compartment


        # the number of potentials is the number of spatial potentials + number of membrane potentials
        self.numdiffusers = len(self.diffusors)
        self.numpoisson = len(self.electrostatic_compartments)

        # Functions
        # Reaction-diffusion type
        #   Diffusers    :numdiffusers
        #
        # Coefficient
        #   Diffusivities
        self.V_np = dolfin.MixedFunctionSpace([self.v]*(self.numdiffusers))
        self.V_poisson = dolfin.MixedFunctionSpace([self.v]*self.numpoisson)
        #self.V = self.V_diff*self.V_electro
        self.V = dolfin.MixedFunctionSpace([self.v]*(self.numdiffusers+self.numpoisson))

        self.dofs_is = [self.V.sub(j).dofmap().dofs() for j in range(self.numdiffusers+self.numpoisson)]
        self.N = len(self.dofs_is[0])

        self.diffusivities = [dolfin.Function(self.v) for j in range(self.numdiffusers)]

        self.trialfunctions = dolfin.TrialFunctions(self.V)  # Trial function
        self.testfunctions = dolfin.TestFunctions(self.V) # test functions, one for each field

        self.sourcefunctions = [dolfin.Function(self.v) for j in range(self.numpoisson+self.numdiffusers)]

        self.permitivities = [dolfin.Function(self.v) for j in range(self.numpoisson)]

        # index the compartments!

        self.functions__ = dolfin.Function(self.V)

        self.np_assigner = dolfin.FunctionAssigner(self.V_np,[self.v]*self.numdiffusers)
        self.poisson_assigner = dolfin.FunctionAssigner(self.V_poisson,[self.v]*self.numpoisson)
        self.full_assigner = dolfin.FunctionAssigner(self.V,[self.v]*(self.numdiffusers+self.numpoisson))

        self.prev_value__ = dolfin.Function(self.V)
        self.prev_value_ = dolfin.split(self.prev_value__)
        self.prev_value = [dolfin.Function(self.v) for j in range(self.numdiffusers+self.numpoisson)]

        self.vfractionfunctions = [dolfin.Function(self.v) for j in range(len(self.compartments))]
        # Each reaction diffusion eqn should be indexed to a single volume fraction function
        # Each reaction diffusion eqn should be indexed to a single potential function
        # Each reaction diffusion eqn should be indexed to a single valence
        self.dt = dolfin.Constant(0.1)
        self.eqs = []
        self.phi = dolfin.Constant(phi)

        for membrane in self.membranes:
            self.potentials.extend([membrane])
            membrane.phi_m = np.ones(self.N)*membrane.phi_m
        self.num_membrane_potentials = len(self.potentials) # improve this

        """
            Assemble the equations for the system
            Order of equations:
            for compartment in compartments:
                for species in compartment.species
                    diffusion (in order)
                volume
                potential for electrodiffusion
            Membrane potentials


        """
        for j,compartment in enumerate(self.compartments):
            self.vfractionfunctions[j].vector()[:] = self.volfrac[compartment]

        # Set the reaction-diffusion equations
        for j,(trial,old,test,source,D,diffusor) in enumerate(zip(self.trialfunctions[:self.numdiffusers],self.prev_value_[:self.numdiffusers] \
                ,self.testfunctions[:self.numdiffusers], self.sourcefunctions[:self.numdiffusers]\
                ,self.diffusivities,self.diffusors)):
            """
            This instance of the loop corresponds to a diffusion species in self.diffusors
            """
            compartment_index = self.compartments.index(diffusor[0]) # we are in this compartment

            try:
                phi_index = self.electrostatic_compartments.index(diffusor[0]) + self.numdiffusers
                self.eqs.extend([ trial*test*dx-test*old*dx+ \
                        self.dt*(inner(D*nabla_grad(trial),nabla_grad(test)) + \
                        dolfin.Constant(diffusor[1].z/phi)*inner(D*trial*nabla_grad(self.prev_value[phi_index]),nabla_grad(test)))*dx   ])

                """
                self.eqs.extend([ trial*test*dx-test*old*dx+ \
                        self.dt*(inner(D*nabla_grad(trial),nabla_grad(test)) + \
                        dolfin.Constant(diffusor[1].z/phi)*inner(D*trial*nabla_grad(self.prev_value[phi_index]),nabla_grad(test)) - source*test)*dx   ])
                """
                # electrodiffusion here

            except ValueError:
                # No electrodiffusion for this species
                self.eqs.extend([trial*test*dx-old*test*dx+self.dt*(inner(D*nabla_grad(trial),nabla_grad(test))- source*test)*dx ])

            self.prev_value[j].vector()[:] = diffusor[0].value(diffusor[1])
            self.diffusivities[j].vector()[:] = diffusor[2]
            #diffusor[0].setValue(diffusor[1],self.prev_value[j].vector().array()) # do this below instead


        self.full_assigner.assign(self.prev_value__,self.prev_value)
        self.full_assigner.assign(self.functions__,self.prev_value)  # Initial guess for Newton

        """
        Vectorize the values that aren't already vectorized
        """
        for compartment in self.compartments:
            for j,(species, val) in enumerate(compartment.values.items()):
                try:
                    length = len(val)
                    compartment.internalVars.extend([(species,self.N,j*self.N)])
                    compartment.species_internal_lookup[species] = j*self.N
                except:
                    compartment.values[species]= np.ones(self.N)*val
                    #compartment.internalVars.extend([(species,self.N,j*self.N)])
                    compartment.species_internal_lookup[species] = j*self.N


        # Set the electrostatic eqns
        # Each equation is associated with a single compartment as defined in

        for j,(trial, test, source, eps, compartment) in enumerate(zip(self.trialfunctions[self.numdiffusers:],self.testfunctions[self.numdiffusers:], \
                self.sourcefunctions[self.numdiffusers:], self.permitivities, self.electrostatic_compartments)):
            # set the permitivity for this equation
            eps.vector()[:] = F**2*self.volfrac[compartment]/R/T \
                *sum([compartment.diffusivities[species]*species.z**2*compartment.value(species)  for species in compartment.species],axis=0)
            self.eqs.extend( [inner(eps*nabla_grad(trial),nabla_grad(test))*dx - source*test*dx] )

        compartmentfluxes = self.updateSources()

        #


        """
        Set indices for the "internal variables"
        List of tuples
        (compartment/membrane, num of variables)

        Each compartment or membrane has method
        getInternalVars()
        get_dot_InternalVars(t,values)
        get_jacobian_InternalVars(t,values)
        setInternalVars(values)

        The internal variables for each object are stored starting in
        y[obj.system_state_offset]
        """
        self.internalVars = []
        index = 0
        for membrane in self.membranes:
            index2 = 0
            for channel in membrane.channels:
                channeltmp = channel.getInternalVars()
                if channeltmp is not None:
                    self.internalVars.extend([ (channel, len(channeltmp),index2)])
                    channel.system_state_offset = index+index2
                    channel.internalLength = len(channeltmp)
                    index2+=len(channeltmp)
            tmp = membrane.getInternalVars()
            if tmp is not None:
                self.internalVars.extend( [(membrane,len(tmp),index)] )
                membrane.system_state_offset = index
                index += len(tmp)
                membrane.points = self.N
        """
        Compartments at the end, so we may reuse some computations
        """

        for compartment in self.compartments:
            index2 = 0
            compartment.system_state_offset = index  # offset for this object in the overall state
            for species, value in compartment.values.items():
                compartment.internalVars.extend([(species,len(compartment.value(species)),index2)])
                index2 += len(value)
            tmp = compartment.getInternalVars()
            self.internalVars.extend( [(compartment,len(tmp),index)] )
            index += len(tmp)
            compartment.points = self.N

        for key, val in self.volfrac.items():
            self.volfrac[key] = val*np.ones(self.N)

        """
        Solver setup below
        self.pdewolver is the FEM solver for the concentrations
        self.ode is the ODE solver for the membrane and volume fraction
        The ODE solve uses LSODA
        """
        # Define the problem and the solver
        self.equation = sum(self.eqs)
        self.equation_ = dolfin.action(self.equation, self.functions__)
        self.J = dolfin.derivative(self.equation_,self.functions__)
        ffc_options = {"optimize": True, \
            "eliminate_zeros": True, \
            "precompute_basis_const": True, \
            "precompute_ip_const": True, \
            "quadrature_degree": 2}
        self.problem = dolfin.NonlinearVariationalProblem(self.equation_, self.functions__, None, self.J, form_compiler_parameters=ffc_options)
        self.pdesolver  = dolfin.NonlinearVariationalSolver(self.problem)
        self.pdesolver.parameters['newton_solver']['absolute_tolerance'] = 1e-9
        self.pdesolver.parameters['newton_solver']['relative_tolerance'] = 1e-9

        """
        ODE integrator here. Add ability to customize the parameters in the future
        """
        self.t = 0.0
        self.odesolver = ode(self.ode_rhs) #
        self.odesolver.set_integrator('lsoda', nsteps=3000, first_step=1e-6, max_step=5e-3 )
        self.odesolver.set_initial_value(self.getInternalVars(),self.t)

        self.isAssembled = True
コード例 #22
0
def Res(du):
    return L(du) - rho * omega**2 * r**2


# Galerkin Least Square stabilization term
stb_gls = L(tu) * tau * Res(du) * df.dx

# Weak form
dres = r * sigma_r(du) * epsilon_r(tu) * df.dx
dres = dres + sigma_theta(du) * tu * df.dx
dres = dres - Fc * tu * df.dx
dres = dres + 1e9 * stb_gls

# residual
res = df.action(dres, u)

# solve
df.solve(res == 0, u, bc)

# displacement
df.File(save_path + 'displacement.pvd') << u

# compute stresses
sigma_r_pro = df.project(sigma_r(u), V)
sigma_r_pro.rename('sigma_r [Pa]', 'sigma_r [Pa]')
df.File(save_path + 'sigma_r.pvd') << sigma_r_pro

sigma_theta_pro = df.project(sigma_theta(u), V)
sigma_theta_pro.rename('sigma_theta [Pa]', 'sigma_theta [Pa]')
df.File(save_path + 'sigma_theta.pvd') << sigma_theta_pro
コード例 #23
0
 def add_lhs_dep(form, dep, x):
     add_rhs_dep(dolfin.action(-form, x), dep, x)
     return
コード例 #24
0
def comp_axisymmetric_dirichlet(mat_obj, mesh_obj, bc, omega, save_path):
    E = mat_obj.E
    rho = mat_obj.rho
    nu = mat_obj.nu

    mesh = mesh_obj.create()
    Rext = mesh_obj.Rext
    Rint = mesh_obj.Rint

    cell_markers, facet_markers = define_markers(mesh, Rext, Rint)

    # rename x[0], x[1] by x, y
    x, y = df.SpatialCoordinate(mesh)

    dim = mesh.topology().dim()

    coord = mesh.coordinates()

    # Create mesh and define function space
    V = df.FunctionSpace(mesh, "CG", 1)

    # Define boundary condition (homogeneous BC)
    u0 = df.Constant(0.0)

    if bc == 'CC':
        bc = [df.DirichletBC(V, u0, facet_markers, i) for i in [1, 2]]
    elif bc == 'CF':
        bc = df.DirichletBC(V, u0, facet_markers, 2)

    # Define variational problem
    du = df.TrialFunction(V)
    tu = df.TestFunction(V)
    # displacement in radial direction u(x,y)
    u = df.Function(V, name='displacement')

    class THETA(df.UserExpression):
        def eval(self, values, x):
            values[0] = math.atan2(x[1], x[0])

        def value_shape(self):
            #return (1,) # vector
            return ()  # scalar

    theta = THETA(degree=1)

    #theta_int = df.interpolate(theta, df.FunctionSpace(mesh, "DG", 0))
    #df.File(save_path + 'theta.pvd') << theta_int

    class RADIUS(df.UserExpression):
        def eval(self, values, x):
            values[0] = df.sqrt(x[0] * x[0] + x[1] * x[1])

        def value_shape(self):
            return ()  # scalar

    r = RADIUS(degree=1)

    # strain radial
    def epsilon_r(du):
        return 1.0 / r * (x * df.Dx(du, 0) + y * df.Dx(du, 1))

    # strain circumferential
    def epsilon_theta(du):
        return du / df.sqrt(x**2 + y**2)

    # radial stress # train-stress relation
    def sigma_r(du):
        return E / (1.0 - nu**2) * (epsilon_r(du) + nu * epsilon_theta(du))

    # circumferential stress
    def sigma_theta(du):
        return E / (1.0 - nu**2) * (nu * epsilon_r(du) + epsilon_theta(du))

    #define centrifugal force vector form
    Fc = rho * omega**2 * r**2

    # Weak form
    dres = r * sigma_r(du) * epsilon_r(tu) * df.dx
    dres = dres + sigma_theta(du) * tu * df.dx
    dres = dres - Fc * tu * df.dx

    # residual
    res = df.action(dres, u)

    # solve
    df.solve(res == 0, u, bc)

    # displacement
    df.File(save_path + 'displacement.pvd') << u

    # compute stresses
    sigma_r_pro = df.project(sigma_r(u), V)
    sigma_r_pro.rename('sigma_r [Pa]', 'sigma_r [Pa]')
    df.File(save_path + 'sigma_r.pvd') << sigma_r_pro

    sigma_theta_pro = df.project(sigma_theta(u), V)
    sigma_theta_pro.rename('sigma_theta [Pa]', 'sigma_theta [Pa]')
    df.File(save_path + 'sigma_theta.pvd') << sigma_theta_pro

    # compute von Mises stress
    def von_mises_stress(sigma_r, sigma_theta):
        return df.sqrt(sigma_r**2 + sigma_theta**2 - sigma_r * sigma_theta)

    von_stress_pro = df.project(von_mises_stress(sigma_r(u), sigma_theta(u)),
                                V)
    von_stress_pro.rename('von Mises Stress [Pa]', 'von Mises Stress [Pa]')
    df.File(save_path + 'von_mises_stress.pvd') << von_stress_pro

    # save results to h5
    rfile = df.HDF5File(mesh.mpi_comm(), save_path + 'results.h5', "w")
    rfile.write(u, "u")
    rfile.write(sigma_r_pro, "sigma_r")
    rfile.write(sigma_theta_pro, "sigma_theta")
    rfile.write(von_stress_pro, "von_mises_stress")
    rfile.close()
    '''
    # Load solution
    U = df.Function(V)
    Sig_r = df.Function(V)
    Sig_theta = df.Function(V)
    Vm_stress = df.Function(V)
    input_file = df.HDF5File(mesh.mpi_comm(), save_path + 'results.h5', "r")
    input_file.read(U, "u")
    input_file.read(Sig_r, "sigma_r")
    input_file.read(Sig_theta, "sigma_theta")
    input_file.read(Vm_stress, "von_mises_stress")
    input_file.close()
    '''

    return
def comp_full_model_heat_dirichlet(mat_obj, mesh_obj, bc, omega, save_path):
    # ======
    # Parameters
    # ======
    E = mat_obj.E
    rho = mat_obj.rho
    nu = mat_obj.nu

    mesh = mesh_obj.create()
    Rext = mesh_obj.Rext
    Rint = mesh_obj.Rint
    G = 1  # FAKE

    # ======
    # Thermal load
    # ======
    alpha = 1
    T = 1

    # ======
    # Thickness profile
    # ======
    h = 1

    omega_velo = 1  #Fake

    # ======
    # markers
    # ======
    cell_markers, facet_markers = define_markers(mesh, Rext, Rint)

    # rename x[0], x[1] by x, y
    x, y = df.SpatialCoordinate(mesh)

    dim = mesh.topology().dim()

    coord = mesh.coordinates()

    # ======
    # Create function space
    # ======
    V = df.FunctionSpace(mesh, "CG", 1)
    degree = 1
    fi_ele = FiniteElement("CG", mesh.ufl_cell(),
                           degree)  # CG: Continuous Galerkin
    vec_ele = VectorElement("CG", mesh.ufl_cell(), degree)
    total_ele = MixedElement([fi_ele, fi_ele])
    W = df.FunctionSpace(mesh, total_ele)

    # ======
    # Define boundary condition
    # ======
    if bc == 'CC':
        u_Dbc = [
            df.DirichletBC(W.sub(0), df.Constant(0.0), facet_markers, bc)
            for bc in [1, 2]
        ]
        v_Dbc = [
            df.DirichletBC(W.sub(1), df.Constant(0.0), facet_markers, bc)
            for bc in [1, 2]
        ]
    elif bc == 'CF':
        u_Dbc = [
            df.DirichletBC(W.sub(0), df.Constant(0.0), facet_markers, bc)
            for bc in [2]
        ]
        v_Dbc = [
            df.DirichletBC(W.sub(1), df.Constant(0.0), facet_markers, bc)
            for bc in [2]
        ]
    Dbc = u_Dbc + v_Dbc

    # ======
    # Define functions
    # ======
    dunks = df.TrialFunction(W)
    tunks = df.TestFunction(W)
    unks = df.Function(W, name='displacement')

    # u(x,y): displacement in radial direction
    # v(x,y): displacement in tangential direction
    (du, dv) = df.split(dunks)
    (tu, tv) = df.split(tunks)
    (u, v) = df.split(unks)

    # ======
    # Define variable
    # ======
    class THETA(df.UserExpression):
        def eval(self, values, x):
            values[0] = math.atan2(x[1], x[0])

        def value_shape(self):
            #return (1,) # vector
            return ()  # scalar

    theta = THETA(degree=1)

    #theta_int = df.interpolate(theta, df.FunctionSpace(mesh, "DG", 0))
    #df.File(save_path + 'theta.pvd') << theta_int

    class RADIUS(df.UserExpression):
        def eval(self, values, x):
            values[0] = df.sqrt(x[0] * x[0] + x[1] * x[1])

        def value_shape(self):
            return ()  # scalar

    r = RADIUS(degree=1)

    # ======
    # Define week form
    # ======
    def d_dr(du):
        return 1.0 / r * (x * df.Dx(du, 0) + y * df.Dx(du, 1))

    def d_dtheta(du):
        return -y * df.Dx(du, 0) + x * df.Dx(du, 1)

    # strain radial
    def epsilon_r(du):
        return d_dr(du)

    # strain circumferential
    def epsilon_theta(du, dv):
        return du / r + 1.0 / r * d_dtheta(dv)

    # shear srain component
    def gamma_rtheta(du, dv):
        return d_dr(dv) - dv / r + 1.0 / r * d_dtheta(du)

    epsilon_r(du)
    epsilon_theta(du, dv)
    gamma_rtheta(du, dv)
    '''
    S = [[1.0/E, -nu/E, 0.0],
        [-nu/E, 1.0/E, 0.0],
        [0.0, 0.0, 1.0/G]]
    C = df.inv(df.as_matrix(S))
    eps_vector = df.as_vector([epsilon_r(du), epsilon_theta(du, dv), gamma_rtheta(du, dv)])
    sig_vector = dot(C, eps_vector)
    '''

    def sigma_r(du, dv):
        return E / (1.0 - nu**2) * ((epsilon_r(du) - alpha * T) + nu *
                                    (epsilon_theta(du, dv) - alpha * T))

    def sigma_theta(du, dv):
        return E / (1.0 - nu**2) * ((epsilon_theta(du, dv) - alpha * T) + nu *
                                    (epsilon_r(du) - alpha * T))

    def tau_rtheta(du, dv):
        return G * gamma_rtheta(du, dv)

    # week form
    dF_sigma = -sigma_r(du, dv) * h * r * d_dr(tu) * dx
    dF_sigma = dF_sigma - tau_rtheta(du, dv) * h * d_dtheta(tu) * dx
    dF_sigma = dF_sigma - sigma_theta(du, dv) * h * tu * dx
    dF_sigma = dF_sigma + rho * omega**2 * r**2 * h * tu * dx

    dF_tau = -tau_rtheta(du, dv) * h * r * d_dr(tv) * dx
    dF_tau = dF_tau - sigma_theta(du, dv) * h * d_dtheta(tv) * dx
    dF_tau = dF_tau + tau_rtheta(du, dv) * h * tv * dx
    dF_tau = dF_tau + rho * omega_velo * r**2 * h * tv * dx

    dF = dF_sigma + dF_tau

    # residual
    F = df.action(dF, unks)

    # solve
    df.solve(F == 0, unks, Dbc)

    # splits solution
    _u, _v = unks.split(True)

    # displacement
    df.File(save_path + 'u.pvd') << _u
    df.File(save_path + 'v.pvd') << _v

    # ======
    # Analyze
    # ======
    # compute stresses
    sigma_r_pro = df.project(sigma_r(_u, _v), V)
    sigma_r_pro.rename('sigma_r [Pa]', 'sigma_r [Pa]')
    df.File(save_path + 'sigma_r.pvd') << sigma_r_pro

    sigma_theta_pro = df.project(sigma_theta(_u, _v), V)
    sigma_theta_pro.rename('sigma_theta [Pa]', 'sigma_theta [Pa]')
    df.File(save_path + 'sigma_theta.pvd') << sigma_theta_pro

    # compute von Mises stress
    def von_mises_stress(sigma_r, sigma_theta):
        return df.sqrt(sigma_r**2 + sigma_theta**2 - sigma_r * sigma_theta)

    von_stress_pro = df.project(
        von_mises_stress(sigma_r(_u, _v), sigma_theta(_u, _v)), V)
    von_stress_pro.rename('von Mises Stress [Pa]', 'von Mises Stress [Pa]')
    df.File(save_path + 'von_mises_stress.pvd') << von_stress_pro

    tau_rtheta_pro = df.project(tau_rtheta(_u, _v), V)
    tau_rtheta_pro.rename('tau_rtheta [Pa]', 'tau_rtheta [Pa]')
    df.File(save_path + 'tau_rtheta.pvd') << tau_rtheta_pro

    # save results to h5
    rfile = df.HDF5File(mesh.mpi_comm(), save_path + 'results.h5', "w")
    rfile.write(_u, "u")
    rfile.write(_v, "v")
    rfile.write(sigma_r_pro, "sigma_r")
    rfile.write(sigma_theta_pro, "sigma_theta")
    rfile.write(von_stress_pro, "von_mises_stress")
    rfile.write(tau_rtheta_pro, "tau_rtheta_pro")
    rfile.close()
コード例 #26
0
ファイル: prb.py プロジェクト: computationalmodelling/fidimag
def test_prb88_184422():
    mu0 = 4 * np.pi * 1e-7

    Ms = 8.6e5
    A = 16e-12
    D = 3.6e-3
    K = 510e3

    mesh = CuboidMesh(nx=100, dx=1, unit_length=1e-9)

    sim = Sim(mesh)

    sim.driver.set_tols(rtol=1e-10, atol=1e-14)

    sim.driver.alpha = 0.5
    sim.driver.gamma = 2.211e5
    sim.Ms = Ms
    sim.do_precession = False

    sim.set_m((0, 0, 1))

    sim.add(UniformExchange(A))
    sim.add(DMI(-D, type='interfacial'))
    sim.add(UniaxialAnisotropy(K, axis=(0, 0, 1)))

    sim.relax(dt=1e-13, stopping_dmdt=0.01, max_steps=5000,
              save_m_steps=None, save_vtk_steps=50)

    m = sim.spin

    mx, my, mz = np.split(m, 3)

    x_array = np.linspace(-49.5, 49.5, 100)

    #plt.plot(x_array, mx)
    #plt.plot(x_array, my)
    #plt.plot(x_array, mz)

    mesh = df.IntervalMesh(100, -50, 50)

    Delta = np.sqrt(A / K)
    xi = 2 * A / D

    Delta_s = Delta * 1e9

    V = df.FunctionSpace(mesh, "Lagrange", 1)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    u_ = df.Function(V)
    F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \
        (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx
    F = df.action(F, u_)

    J = df.derivative(F, u_, u)

    # the boundary condition is from equation (8)
    theta0 = np.arcsin(Delta / xi)
    ss = 'x[0]<0? %g: %g ' % (-theta0, theta0)

    u0 = df.Expression(ss)

    def u0_boundary(x, on_boundary):
        return on_boundary

    bc = df.DirichletBC(V, u0, u0_boundary)

    problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J)
    solver = df.NonlinearVariationalSolver(problem)
    solver.solve()

    u_array = u_.vector().array()

    mx_df = []
    for x in x_array:
        mx_df.append(u_(x))

    #plt.plot(x_array, mx_df)

    assert abs(np.max(mx - mx_df)) < 0.05
コード例 #27
0
    def steepest_descent():
        o_u = [File("output/u_mesh%d.pvd" % i) for i in range(solver.N)]
        search = moola.linesearch.ArmijoLineSearch(start_stp=1)
        outmesh = File("output/steepest.pvd")
        extra_opts = 0
        r_step = 8
        max_it = 3 * r_step

        opts = 0
        rel_tol = 1e-4
        solver.solve()
        solver.eval_J()
        plot(solver.multimesh.part(1),
             color=colors[0],
             linewidth=0.75,
             zorder=0)
        b_mesh = BoundaryMesh(solver.multimesh.part(1), "exterior", True)
        plot(b_mesh,
             color=colors[0],
             linestyle="None",
             markersize=1,
             marker=markers[0],
             label="Iteration {}".format(0),
             zorder=1)

        J_it = [solver.J]
        J_i = J_it[0]
        i = 1
        while i <= max_it:
            outmesh << solver.multimesh.part(1)
            for k in range(solver.N):
                o_u[k] << solver.u.part(k)
            print("-" * 10)
            print("It: {0:1d}, J: {1:.5f}".format(i, J_it[-1]))
            solver.recompute_dJ()
            solver.generate_mesh_deformation()
            #solver.generate_H1_deformation()

            dJ_i = 0
            for j in range(1, solver.N):
                dJ_i += assemble(
                    action(solver.dJ_form[j - 1], solver.deformation[j - 1]))
            print("Gradient at current iteration {0:.2e}".format(dJ_i))

            def J_steepest(step):
                solver.update_multimesh(step)
                solver.solve()
                solver.eval_J()
                solver.get_checkpoint()
                return float(solver.J)

            def dJ0_steepest():
                return float(J_it[-1]), dJ_i

            def increase_opt_number():
                solver.vfac *= 2
                solver.bfac *= 2
                if opts < extra_opts:
                    return True
                else:
                    print("{0:d} optimizations done, exiting".format(opts + 1))
                    return False

            try:
                step_a = search.search(J_steepest, None, dJ0_steepest())
                print(
                    "Linesearch found decreasing step: {0:.2e}".format(step_a))
                # Backup in case step is too large
                backup_coordinates = [
                    solver.multimesh.part(k).coordinates().copy()
                    for k in range(1, solver.N)
                ]
                solver.update_multimesh(step_a)
                solver.set_checkpoint()
                solver.solve()

                solver.eval_J()
                J_it.append(solver.J)
                J_i = J_it[-1]
                if J_i > 0:
                    if i % r_step == 0:
                        print("Increasing volume and barycenter penalty")
                        solver.vfac *= 2
                        solver.bfac *= 2
                        solver.eval_J()
                        J_it.append(solver.J)
                    if i % r_step == 0:
                        b_mesh = BoundaryMesh(solver.multimesh.part(1),
                                              "exterior", True)
                        plot(b_mesh,
                             color=colors[i // r_step],
                             linestyle="None",
                             markersize=1,
                             marker=markers[i // r_step],
                             label="Iteration {}".format(i),
                             zorder=i // r_step + 2)

                    i += 1
                    search.start_stp = 1
                else:
                    # If Armjio linesearch returns an unfeasible
                    # functional value, literally deforming too much.
                    # We know that J in our problem has to be positive
                    # Decrease initial stepsize and retry
                    search.start_stp = 0.5 * step_a
                    for k in range(1, solver.N):
                        solver.multimesh.part(
                            k).coordinates()[:] = backup_coordinates[k - 1]
                    solver.multimesh.build()
                    for key in solver.cover_points.keys():
                        solver.multimesh.auto_cover(key,
                                                    solver.cover_points[key])
                    solver.set_checkpoint()
                    solver.solve()
                    solver.eval_J()
                    J_it[-1] = solver.J
                rel_reduction = abs(J_it[-1] - J_it[-2]) / abs(J_it[-2])
                if rel_reduction < rel_tol and solver.move_norm < rel_tol:
                    raise ValueError(
                        "Relative reduction less than {0:1e1}".format(rel_tol))
            except Warning:
                print("Linesearch could not find descent direction")
                print("Restart with stricter penalty")
                print("*" * 15)
                if not increase_opt_number():
                    break
                else:
                    # Reset linesearch
                    opts += 1
                    # In new optimization run, the deformed geometry
                    # should not have a higher functional value than the first
                    # iteration
                    J_i = J_it[0]
            except ValueError:
                print("Stopping criteria met")
                print("abs((J_k-J_k-1)/J_k)={0:.2e}<{1:.2e}".format(
                    rel_reduction, rel_tol))
                print("L^2(Gamma)(s)={0:.2e}<{1:.2e}".format(
                    solver.move_norm, rel_tol))
                print("Increase volume and barycenter penalty")
                print("*" * 15)
                if not increase_opt_number():
                    break
                else:
                    opts += 1
                    solver.solve()
                    solver.eval_J()
                    print("V_r {0:.2e}, Bx_r {1:.2e}, By_r {2:.2e}".format(
                        float(solver.Voloff / solver.Vol0),
                        float(solver.bxoff / solver.bx0),
                        float(solver.byoff / solver.by0)))
                    J_i = solver.J  # Old solution with new penalization
        print("V_r {0:.2e}, Bx_r {1:.2e}, By_r {2:.2e}".format(
            float(solver.Voloff / solver.Vol0) * 100,
            float(solver.bxoff / solver.bx0) * 100,
            float(solver.byoff / solver.by0) * 100))
        plot(solver.multimesh.part(1),
             zorder=2,
             color=colors[i // r_step],
             linewidth=1)
        plt.legend(prop={'size': 10}, markerscale=2)
        manager = plt.get_current_fig_manager()
        plt.tight_layout()
        manager.resize(*manager.window.maxsize())
        plt.axis("off")
        plt.savefig("StokesRugbyMeshes.png", dpi=300)
        import os
        os.system("convert StokesRugbyMeshes.png -trim StokesRugbyMeshes.png")
コード例 #28
0
ファイル: prb.py プロジェクト: writergirish/fidimag
def test_prb88_184422():
    mu0 = 4 * np.pi * 1e-7

    Ms = 8.6e5
    A = 16e-12
    D = 3.6e-3
    K = 510e3

    mesh = CuboidMesh(nx=100, dx=1, unit_length=1e-9)

    sim = Sim(mesh)

    sim.driver.set_tols(rtol=1e-10, atol=1e-14)

    sim.driver.alpha = 0.5
    sim.driver.gamma = 2.211e5
    sim.Ms = Ms
    sim.do_precession = False

    sim.set_m((0, 0, 1))

    sim.add(UniformExchange(A=A))
    sim.add(DMI(-D, type='interfacial'))
    sim.add(UniaxialAnisotropy(K, axis=(0, 0, 1)))

    sim.relax(dt=1e-13,
              stopping_dmdt=0.01,
              max_steps=5000,
              save_m_steps=None,
              save_vtk_steps=50)

    m = sim.spin

    mx, my, mz = np.split(m, 3)

    x_array = np.linspace(-49.5, 49.5, 100)

    #plt.plot(x_array, mx)
    #plt.plot(x_array, my)
    #plt.plot(x_array, mz)

    mesh = df.IntervalMesh(100, -50, 50)

    Delta = np.sqrt(A / K)
    xi = 2 * A / D

    Delta_s = Delta * 1e9

    V = df.FunctionSpace(mesh, "Lagrange", 1)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    u_ = df.Function(V)
    F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \
        (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx
    F = df.action(F, u_)

    J = df.derivative(F, u_, u)

    # the boundary condition is from equation (8)
    theta0 = np.arcsin(Delta / xi)
    ss = 'x[0]<0? %g: %g ' % (-theta0, theta0)

    u0 = df.Expression(ss)

    def u0_boundary(x, on_boundary):
        return on_boundary

    bc = df.DirichletBC(V, u0, u0_boundary)

    problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J)
    solver = df.NonlinearVariationalSolver(problem)
    solver.solve()

    u_array = u_.vector().array()

    mx_df = []
    for x in x_array:
        mx_df.append(u_(x))

    #plt.plot(x_array, mx_df)

    assert abs(np.max(mx - mx_df)) < 0.05
コード例 #29
0
    def __init__(self, f_solves_a, f_solves_b, a_map):
        if not isinstance(f_solves_a, list):
            raise InvalidArgumentException("f_solves_a must be a list of AssignmentSolver s or EquationSolver s")
        for f_solve in f_solves_a:
            if not isinstance(f_solve, (AssignmentSolver, EquationSolver)):
                raise InvalidArgumentException("f_solves_a must be a list of AssignmentSolver s or EquationSolver s")
        if not isinstance(f_solves_b, list):
            raise InvalidArgumentException("f_solves_b must be a list of AssignmentSolver s or EquationSolver s")
        for f_solve in f_solves_b:
            if not isinstance(f_solve, (AssignmentSolver, EquationSolver)):
                raise InvalidArgumentException("f_solves_b must be a list of AssignmentSolver s or EquationSolver s")
        if not isinstance(a_map, AdjointVariableMap):
            raise InvalidArgumentException("a_map must be an AdjointVariableMap")

        # Reverse causality
        f_solves_a = copy.copy(f_solves_a);  f_solves_a.reverse()
        f_solves_b = copy.copy(f_solves_b);  f_solves_b.reverse()

        la_a_forms = []
        la_x = []
        la_L_forms = []
        la_L_as = []
        la_bcs = []
        la_solver_parameters = []
        la_pre_assembly_parameters = []
        la_keys = {}

        # Create an adjoint solve for each forward solve in f_solves_a, and add
        # the adjoint LHS
        for f_solve in f_solves_a:
            f_x = f_solve.x()
            a_x = a_map[f_x]
            a_space = a_x.function_space()
            assert(not a_x in la_keys)
            if isinstance(f_solve, AssignmentSolver):
                la_a_forms.append(None)
                la_bcs.append([])
                la_solver_parameters.append(None)
                la_pre_assembly_parameters.append(dolfin.parameters["timestepping"]["pre_assembly"].copy())
            else:
                assert(isinstance(f_solve, EquationSolver))
                f_a = f_solve.tangent_linear()[0]
                f_a_rank = form_rank(f_a)
                if f_a_rank == 2:
                    a_test, a_trial = dolfin.TestFunction(a_space), dolfin.TrialFunction(a_space)
                    a_a = adjoint(f_a, adjoint_arguments = (a_test, a_trial))
                    la_a_forms.append(a_a)
                    la_bcs.append(f_solve.hbcs())
                    la_solver_parameters.append(copy.deepcopy(f_solve.adjoint_solver_parameters()))
                else:
                    assert(f_a_rank == 1)
                    a_a = f_a
                    la_a_forms.append(a_a)
                    la_bcs.append(f_solve.hbcs())
                    la_solver_parameters.append(None)
                la_pre_assembly_parameters.append(f_solve.pre_assembly_parameters().copy())
            la_x.append(a_x)
            la_L_forms.append(None)
            la_L_as.append([])
            la_keys[a_x] = len(la_x) - 1

        # Add adjoint RHS terms corresponding to terms in each forward solve in
        # f_solves_a and f_solves_b
        for f_solve in f_solves_a + f_solves_b:
            f_x = f_solve.x()
            a_dep = a_map[f_x]
            if isinstance(f_solve, AssignmentSolver):
                f_rhs = f_solve.rhs()
                if isinstance(f_rhs, ufl.core.expr.Expr):
                    # Adjoin an expression assignment RHS
                    for f_dep in ufl.algorithms.extract_coefficients(f_rhs):
                        if isinstance(f_dep, dolfin.Function):
                            a_x = a_map[f_dep]
                            a_rhs = differentiate_expr(f_rhs, f_dep) * a_dep
                            if a_x in la_keys and not isinstance(a_rhs, ufl.constantvalue.Zero):
                                la_L_as[la_keys[a_x]].append(a_rhs)
                else:
                    # Adjoin a linear combination assignment RHS
                    for alpha, f_dep in f_rhs:
                        a_x = a_map[f_dep]
                        if a_x in la_keys:
                            la_L_as[la_keys[a_x]].append((alpha, a_dep))
            else:
                # Adjoin an equation RHS
                assert(isinstance(f_solve, EquationSolver))
                a_trial = dolfin.TrialFunction(a_dep.function_space())
                f_a_od = f_solve.tangent_linear()[1]
                for f_dep in f_a_od:
                    a_x = a_map[f_dep]
                    if a_x in la_keys:
                        a_test = dolfin.TestFunction(a_x.function_space())
                        a_key = la_keys[a_x]
                        a_form = -dolfin.action(adjoint(f_a_od[f_dep], adjoint_arguments = (a_test, a_trial)), a_dep)
                        if la_L_forms[a_key] is None:
                            la_L_forms[a_key] = a_form
                        else:
                            la_L_forms[a_key] += a_form

        self.__a_map = a_map
        self.__a_a_forms = la_a_forms
        self.__a_x = la_x
        self.__a_L_forms = la_L_forms
        self.__a_L_as = la_L_as
        self.__a_bcs = la_bcs
        self.__a_solver_parameters = la_solver_parameters
        self.__a_pre_assembly_parameters = la_pre_assembly_parameters
        self.__a_keys = la_keys

        self.__functional = None
        self.reassemble()

        return
def comp_axisymmetric_heat_dirichlet(mat_obj, mesh_obj, bc, omega, save_path):
    E = mat_obj.E
    rho = mat_obj.rho
    nu = mat_obj.nu

    mesh = mesh_obj.create()
    Rext = mesh_obj.Rext
    Rint = mesh_obj.Rint
    G = 1  # FAKE

    # ======
    # Thermal load
    # ======
    alpha = 1
    T = 1

    # ======
    # Thickness profile
    # ======
    h = 1

    # ======
    # markers
    # ======
    cell_markers, facet_markers = define_markers(mesh, Rext, Rint)

    # rename x[0], x[1] by x, y
    x, y = df.SpatialCoordinate(mesh)
    dim = mesh.topology().dim()
    coord = mesh.coordinates()

    # ======
    # Create function space
    # ======
    # Create mesh and define function space
    V = df.FunctionSpace(mesh, "CG", 1)

    # Define boundary condition (homogeneous BC)
    u0 = df.Constant(0.0)

    if bc == 'CC':
        bc = [df.DirichletBC(V, u0, facet_markers, i) for i in [1, 2]]
    elif bc == 'CF':
        bc = df.DirichletBC(V, u0, facet_markers, 2)

    # Define variational problem
    du = df.TrialFunction(V)
    tu = df.TestFunction(V)
    # displacement in radial direction u(x,y)
    u = df.Function(V, name='displacement')

    class THETA(df.UserExpression):
        def eval(self, values, x):
            values[0] = math.atan2(x[1], x[0])

        def value_shape(self):
            #return (1,) # vector
            return ()  # scalar

    theta = THETA(degree=1)

    #theta_int = df.interpolate(theta, df.FunctionSpace(mesh, "DG", 0))
    #df.File(save_path + 'theta.pvd') << theta_int

    class RADIUS(df.UserExpression):
        def eval(self, values, x):
            values[0] = df.sqrt(x[0] * x[0] + x[1] * x[1])

        def value_shape(self):
            return ()  # scalar

    r = RADIUS(degree=1)

    # ======
    # Define week form
    # ======
    def d_dr(du):
        return 1.0 / r * (x * df.Dx(du, 0) + y * df.Dx(du, 1))

    def d_dtheta(du):
        return -y * df.Dx(du, 0) + x * df.Dx(du, 1)

    # strain radial
    def epsilon_r(du):
        return d_dr(du)

    # strain circumferential
    def epsilon_theta(du):
        return du / r

    def sigma_r(du):
        return E / (1.0 - nu**2) * ((epsilon_r(du) - alpha * T) + nu *
                                    (epsilon_theta(du) - alpha * T))

    def sigma_theta(du):
        return E / (1.0 - nu**2) * ((epsilon_theta(du) - alpha * T) + nu *
                                    (epsilon_r(du) - alpha * T))

    # week form
    dF = -sigma_r(du) * r * h * epsilon_r(tu) * df.dx
    dF = -dF + sigma_theta(du) * h * tu * df.dx
    dF = dF + rho * omega**2 * r**2 * h * tu * df.dx

    # residual
    F = df.action(dF, u)

    # solve
    df.solve(F == 0, u, bc)

    # displacement
    df.File(save_path + 'u.pvd') << _u

    # ======
    # Analyze
    # ======
    # compute stresses
    sigma_r_pro = df.project(sigma_r(u), V)
    sigma_r_pro.rename('sigma_r [Pa]', 'sigma_r [Pa]')
    df.File(save_path + 'sigma_r.pvd') << sigma_r_pro

    sigma_theta_pro = df.project(sigma_theta(u), V)
    sigma_theta_pro.rename('sigma_theta [Pa]', 'sigma_theta [Pa]')
    df.File(save_path + 'sigma_theta.pvd') << sigma_theta_pro

    # compute von Mises stress
    def von_mises_stress(sigma_r, sigma_theta):
        return df.sqrt(sigma_r**2 + sigma_theta**2 - sigma_r * sigma_theta)

    von_stress_pro = df.project(von_mises_stress(sigma_r(u), sigma_theta(u)),
                                V)
    von_stress_pro.rename('von Mises Stress [Pa]', 'von Mises Stress [Pa]')
    df.File(save_path + 'von_mises_stress.pvd') << von_stress_pro

    # save results to h5
    rfile = df.HDF5File(mesh.mpi_comm(), save_path + 'results.h5', "w")
    rfile.write(u, "u")
    rfile.write(sigma_r_pro, "sigma_r")
    rfile.write(sigma_theta_pro, "sigma_theta")
    rfile.write(von_stress_pro, "von_mises_stress")
    rfile.close()