Example #1
0
    def _init_forms(self):

        u = self.state
        v = self.state_test

        F = dolfin.variable(DeformationGradient(u))
        J = Jacobian(F)

        dx = self.geometry.dx

        # Add penalty term
        internal_energy = self.material.strain_energy(F) \
            + self.kappa * (J * dolfin.ln(J) - J + 1)

        self._virtual_work \
            = dolfin.derivative(internal_energy * dx,
                                self.state, self.state_test)

        self._virtual_work += self._external_work(u, v)

        self._jacobian \
            = dolfin.derivative(self._virtual_work, self.state,
                                dolfin.TrialFunction(self.state_space))

        self._set_dirichlet_bc()
Example #2
0
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)
Example #3
0
    def define_ufl_stress_work_diff(self):
        """
        Define the UFL object corresponding to the Gateaux derivative of
        the stress tensor term in the weak form. The function exits if it
        has already been defined.


        """

        if hasattr(self, 'ufl_stress_work_diff'):
            return None

        if self.displacement != 0:
            # Derivative of stress term w.r.t. to displacement.
            self.ufl_stress_work_du = dlf.derivative(self.ufl_stress_work,
                                                     self.displacement,
                                                     self.trial_vector)
        else:
            self.ufl_stress_work_du = 0

        if self.velocity != 0:
            self.ufl_stress_work_dv = dlf.derivative(self.ufl_stress_work,
                                                     self.velocity,
                                                     self.trial_vector)
        else:
            self.ufl_stress_work_dv = 0

        if self.pressure != 0:
            self.ufl_stress_work_dp = dlf.derivative(self.ufl_stress_work,
                                                     self.pressure,
                                                     self.trial_scalar)
        else:
            self.ufl_stress_work_dp = 0

        return None
Example #4
0
 def Jacobian(self,
              x,
              x_test,
              x_trial,
              sigma,
              m,
              x0,
              xl,
              true_derivative=False):
     """
     Returns the weak form of the Jacobian matrix.
     
     INPUTS:
     - x: the state at which evaluate the Jacobian
     - x_test: the test function
     - x_trial: the trial function
     - sigma: the inverse of the time-step
     - m: the uncertain parameter
     - x0: the state at the previous time step
     - xl: the auxiliary state to compute the Picard Jacobian (if None then xl is a copy of x)
     - true_derivative: if true compute the true Jacobian, if false compute the Picard Jacobian
     """
     if x0 is None:
         x0 = vector2Function(x.vector(), self.Vh)
     if xl is None:
         xl = vector2Function(x.vector(), self.Vh)
     r = self.residual(x, x_test, sigma, m, x0, xl, true_derivative)
     if true_derivative:
         return dl.derivative(r, x, x_trial) + dl.derivative(r, xl, x_trial)
     else:
         return dl.derivative(r, x, x_trial)
    def _init_forms(self):

        logger.debug("Initialize forms mechanics problem")
        # Displacement and hydrostatic_pressure
        u, p = dolfin.split(self.state)
        v, q = dolfin.split(self.state_test)

        # Some mechanical quantities
        F = dolfin.variable(kinematics.DeformationGradient(u))
        J = kinematics.Jacobian(F)
        dx = self.geometry.dx

        internal_energy = (self.material.strain_energy(F, ) +
                           self.material.compressibility(p, J))

        self._virtual_work = dolfin.derivative(
            internal_energy * dx,
            self.state,
            self.state_test,
        )

        external_work = self._external_work(u, v)
        if external_work is not None:
            self._virtual_work += external_work

        self._set_dirichlet_bc()
        self._jacobian = dolfin.derivative(
            self._virtual_work,
            self.state,
            dolfin.TrialFunction(self.state_space),
        )
        self._init_solver()
    def stab(self, x, x_test, m, true_derivative):
        """
        The G-LS stabilization
        """
        r_s = self.strong_residual(x, m)

        r_s_prime = [None, None]

        if true_derivative:
            for i in range(2):
                r_s_prime[i] = dl.derivative(r_s[i], x, x_test)

            tau = self.all_tau(x, m)
        else:
            xl = vector2Function(x.vector(), self.Vh)
            r_sl = self.strong_residual(xl, m)
            for i in range(2):
                r_s_prime[i] = dl.derivative(r_sl[i], xl, x_test)

            tau = self.all_tau(xl, m)

        res_stab = ( tau[0]*dl.inner(r_s[0], r_s_prime[0]) + \
                     tau[1]*dl.inner(r_s[1], r_s_prime[1]) )*dl.dx

        return res_stab
Example #7
0
    def _init_forms(self):

        u, p, pinn = dolfin.split(self.state)
        v, q, qinn = dolfin.split(self.state_test)

        F = dolfin.variable(DeformationGradient(u))
        J = Jacobian(F)

        ds = self.geometry.ds
        dsendo = ds(self.geometry.markers['ENDO'])
        dx = self.geometry.dx

        endoarea = dolfin.assemble(dolfin.Constant(1.0) * dsendo)

        internal_energy = self.material.strain_energy(F) * dx \
            + self.material.compressibility(p, J) * dx \
            + (pinn * (self._V0/endoarea - self._Vu)) * dsendo

        self._virtual_work \
            = dolfin.derivative(internal_energy,
                                self.state, self.state_test)

        self._virtual_work += self._external_work(u, v)

        self._jacobian \
            = dolfin.derivative(self._virtual_work, self.state,
                                dolfin.TrialFunction(self.state_space))

        self._set_dirichlet_bc()
Example #8
0
    def _solveTangentProblem(self, dstate, m_hat, x):
        """
        The predictor step for the parameter continuation algorithm.
        """
        state_fun = vector2Function(x[STATE], self.Vh[STATE])
        statel_fun = vector2Function(x[STATE], self.Vh[STATE])
        param_fun = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
        param_hat_fun = vector2Function(m_hat, self.Vh[PARAMETER])
        x_test = [
            dl.TestFunction(self.Vh[STATE]),
            dl.TestFunction(self.Vh[PARAMETER])
        ]
        x_trial = [
            dl.TrialFunction(self.Vh[STATE]),
            dl.TrialFunction(self.Vh[PARAMETER])
        ]

        res = self.model.residual(state_fun, x_test[STATE], dl.Constant(0.),
                                  param_fun, None, statel_fun, True)
        Aform = dl.derivative(res, state_fun, x_trial[STATE]) + dl.derivative(
            res, statel_fun, x_trial[STATE])
        b_form = dl.derivative(res, param_fun, param_hat_fun)

        A, b = dl.assemble_system(Aform,
                                  b_form,
                                  self.bcs0,
                                  form_compiler_parameters=self.fcp)
        solver = dl.PETScLUSolver()
        solver.set_operator(A)
        solver.solve(dstate, -b)
Example #9
0
    def linearize(self, inputs, outputs, partials):
        pde_problem = self.options['pde_problem']
        state_name = self.options['state_name']
        state_function = pde_problem.states_dict[state_name]['function']
        residual_form = pde_problem.states_dict[state_name]['residual_form']

        self._set_values(inputs, outputs)
        derivative_form = df.derivative(residual_form, state_function)
        derivative_assembled = df.assemble(derivative_form)
        for bc in pde_problem.bcs_list:
            bc.apply(derivative_assembled)
        derivative_petsc_sparse = df.as_backend_type(
            derivative_assembled).mat()
        derivative_csr = csr_matrix(
            derivative_petsc_sparse.getValuesCSR()[::-1],
            shape=derivative_petsc_sparse.size)

        partials[state_name, state_name] = derivative_csr.tocoo().data

        for argument_name, argument_function in iteritems(
                self.argument_functions_dict):
            derivative_form_arg = df.derivative(residual_form,
                                                argument_function)
            derivative_form_arg_assembled = df.assemble(derivative_form_arg)
            for bc in pde_problem.bcs_list:
                bc.apply(derivative_form_arg_assembled)
            derivative_petsc_sparse_arg = df.as_backend_type(
                derivative_form_arg_assembled).mat()
            derivative_csr_arg = csr_matrix(
                derivative_petsc_sparse_arg.getValuesCSR()[::-1],
                shape=derivative_petsc_sparse_arg.size)
            partials[state_name,
                     argument_name] = derivative_csr_arg.tocoo().data
Example #10
0
 def setLinearizationPoint(self, x):
     u = vector2Function(x[STATE], self.Vh[STATE])
     m = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
     x = [u, m]
     for i in range(2):
         di_form = dl.derivative(self.qoi_varf(*x), x[i])
         for j in range(i, 2):
             dij_form = dl.derivative(di_form, x[j])
             self.L[i, j] = dl.assemble(dij_form)
Example #11
0
 def setLinearizationPoint(self, x):
     self.u = vector2Function(x[STATE], self.Vh[STATE])
     self.m = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
     x = [self.u,self.m]
     form = self.form(x)
     for i in range(2):
         di_form = dl.derivative(form, x[i])
         for j in range(2):
             dij_form = dl.derivative(di_form,x[j] )
             self.L[i,j] = dl.assemble(dij_form)
Example #12
0
    def define_ufl_equations_diff(self):
        """
        Differentiate all of the variational forms with respect to appropriate
        fields variables and add as member data.


        """

        # Derivatives of velocity integration equation.
        if self.f1 != 0:
            self.df1_du = dlf.derivative(self.f1, self.displacement,
                                         self.trial_vector)
            self.df1_dv = dlf.derivative(self.f1, self.velocity,
                                         self.trial_vector)
        else:
            self.df1_du = 0
            self.df1_dv = 0
        self.df1_dp = 0  # This is always zero.

        # Derivatives of momentum equation.
        if self.displacement != 0:
            self.df2_du = dlf.derivative(self.f2, self.displacement,
                                         self.trial_vector)
        else:
            self.df2_du = 0

        if self.velocity != 0:
            self.df2_dv = dlf.derivative(self.f2, self.velocity,
                                         self.trial_vector)
        else:
            self.df2_dv = 0

        if self.pressure != 0:
            self.df2_dp = dlf.derivative(self.f2, self.pressure,
                                         self.trial_scalar)
        else:
            self.df2_dp = 0

        # Derivatives of incompressibility equation.
        if self.f3 != 0:
            if self.displacement != 0:
                self.df3_du = dlf.derivative(self.f3, self.displacement,
                                             self.trial_vector)
            else:
                self.df3_du = 0

            if self.velocity != 0:
                self.df3_dv = dlf.derivative(self.f3, self.velocity,
                                             self.trial_vector)
            else:
                self.df3_dv = 0

            self.df3_dp = dlf.derivative(self.f3, self.pressure,
                                         self.trial_scalar)
        else:
            self.df3_du = 0
            self.df3_dv = 0
            self.df3_dp = 0

        return None
def solve_adjoint():
    a = a1 + a2 + a3 + a4 + a5
    a = derivative(a, T, TestFunction(V))
    a = replace(a, {lmb: TrialFunction(V)})
    l = derivative(-J1, T, TestFunction(V))
    a = assemble_multimesh(a)
    L = assemble_multimesh(l)
    bcs = [
        MultiMeshDirichletBC(V, Constant(0), mfs[0], 1, 0),
        MultiMeshDirichletBC(V, Constant(0), mfs[1], 2, 1)
    ]
    [bc.apply(a, L) for bc in bcs]
    V.lock_inactive_dofs(a, L)
    solve(a, lmb.vector(), L)
    def __init__(self, mesh, parameters=[], isprint=False):
        self.parameters = {}
        self.parameters['eps'] = 0.0
        self.parameters['k'] = 1.0
        self.parameters['correctcost'] = True
        self.parameters.update(parameters)
        eps = self.parameters['eps']
        k = self.parameters['k']

        self.V = FunctionSpace(mesh, 'CG', 1)
        self.tmp1, self.tmp2 = Function(self.V), Function(self.V)

        self.VV = VectorFunctionSpace(mesh, 'CG', 1, 2)
        self.m = Function(self.VV)
        self.mtest = TestFunction(self.VV)
        self.mtrial = TrialFunction(self.VV)
        self.m1, self.m2 = split(self.m)
        self.mh = Function(self.VV)

        normg1 = inner(nabla_grad(self.m1), nabla_grad(self.m1))
        normg2 = inner(nabla_grad(self.m2), nabla_grad(self.m2))
        if self.parameters['correctcost']:
            meshtmp = UnitSquareMesh(mesh.mpi_comm(), 10, 10)
            Vtmp = FunctionSpace(meshtmp, 'CG', 1)
            x = SpatialCoordinate(meshtmp)
            self.correctioncost = 1. / assemble(sqrt(4.0 * x[0] * x[0]) * dx)
            print '[NuclearNormformula] Correction cost with factor={}'.format(
                self.correctioncost)
        else:
            self.correctioncost = 1.0
        self.cost = 1./np.sqrt(2.0) * Constant(k) * (\
        sqrt(normg1 + normg2 + Constant(np.sqrt(eps)) +
        sqrt((normg1 - normg2)**2 + Constant(eps) +
        4.0*inner(nabla_grad(self.m1), nabla_grad(self.m2))**2))
        + sqrt(normg1 + normg2 + Constant(np.sqrt(eps)*(1.0+1e-15)) -
        sqrt((normg1 - normg2)**2 + Constant(eps) +
        4.0*inner(nabla_grad(self.m1), nabla_grad(self.m2))**2)))*dx

        self.grad = derivative(self.cost, self.m, self.mtest)

        self.hessian = derivative(self.grad, self.m, self.mtrial)

        M = assemble(inner(self.mtest, self.mtrial) * dx)
        factM = 1e-2 * k
        self.sMass = M * factM

        if isprint:
            print '[NuclearNormformula] eps={}, k={}'.format(eps, k)

        self.amgprecond = amg_solver()
Example #15
0
    def stab(self, x, x_test, m, x0, xl, true_derivative=False):
        """
        The G-LS stabilization
        """
        r_s = self.strong_residual(x, m, xl)

        r_s_prime = [None, None, None, None]

        #if true_derivative:
        #    for i in range(4):
        #        r_s_prime[i] = dl.derivative(r_s[i], x, x_test) + dl.derivative(r_s[i], xl, x_test)
        #else:
        #    for i in range(4):
        #        r_s_prime[i] = dl.derivative(r_s[i], x, x_test)

        for i in range(4):
            r_s_prime[i] = dl.derivative(r_s[i], x, x_test)

        tau = self.all_tau(xl, m)

        res_stab = ( tau[0]*dl.inner(r_s[0], r_s_prime[0]) + \
                     tau[1]*dl.inner(r_s[1], r_s_prime[1]) + \
                     tau[2]*dl.inner(r_s[2], r_s_prime[2]) + \
                     tau[3]*dl.inner(r_s[3], r_s_prime[3]) )*dl.dx

        return res_stab
Example #16
0
    def solve(self, dt):
        self.u = Function(self.V0)
        self.w = TestFunction(self.V0)
        self.du = TrialFunction(self.V0)

        x = SpatialCoordinate(self.mesh0)

        L = inner( self.S(), self.eps(self.w) )*dx(degree=4)\
        - inner( self.b, self.w )*dx(degree=4)\
        - inner( self.h, self.w )*ds(degree=4)\
        + inner( 1e-6*self.u, self.w )*ds(degree=4)\
        - inner( min_value(x[2]+self.ut[2]+self.u[2], 0) * Constant((0,0,-1.0)), self.w )*ds(degree=4)

        a = derivative(L, self.u, self.du)

        problem = NonlinearVariationalProblem(L, self.u, bcs=[], J=a)
        solver = NonlinearVariationalSolver(problem)

        solver.solve()

        self.ut.vector()[:] = self.ut.vector()[:] + self.u.vector()[:]

        ALE.move(self.mesh, Function(self.V, self.u.vector()))

        self.v.vector()[:] = self.u.vector()[:] / dt
        self.n = FacetNormal(self.mesh)
Example #17
0
    def apply_ijk(self, i, j, k, x, jdir, kdir, out):
        x_fun = [vector2Function(x[ii], self.Vh[ii]) for ii in range(3)]
        idir_fun = dl.TestFunction(self.Vh[i])
        jdir_fun = vector2Function(jdir, self.Vh[j])
        kdir_fun = vector2Function(kdir, self.Vh[k])

        res_form = self.varf_handler(*x_fun)
        form = dl.derivative(
            dl.derivative(dl.derivative(res_form, x_fun[i], idir_fun),
                          x_fun[j], jdir_fun), x_fun[k], kdir_fun)

        out.zero()
        dl.assemble(form, tensor=out)

        if i in [STATE, ADJOINT]:
            [bc.apply(out) for bc in self.bc0]
Example #18
0
    def custom_newton_solver(self):
        V = self.my_function_space_cls.V
        F = self.my_var_prob_cls.F
        #self.u = my_function_space_cls.u
        du = df.TrialFunction(V)  #TrialFunctions --> wrong, without 's'
        Jac = df.derivative(F, self.u, du)

        absolute_tol = 1E-5
        relative_tol = 9E-2
        u_inc = df.Function(V)
        nIter = 0
        relative_residual = 1
        CONVERGED = True
        MAX_ITER = 5000
        while relative_residual > relative_tol and nIter < MAX_ITER and CONVERGED:
            nIter += 1
            A, b = df.assemble_system(Jac, -(F), [])
            df.solve(A, u_inc.vector(), b)
            #df.solve(F == 0, u_inc.vector(), [], J=Jac,  solver_parameters={'newton_solver' : {'linear_solver' : 'mumps'}})
            relative_residual = u_inc.vector().norm('l2')
            #a = df.assemble(F)
            residual = b.norm('l2')
            lmbda = 0.8
            self.u.vector()[:] += lmbda * u_inc.vector()
            if residual > 1000:
                CONVERGED = False
                print("Did not converge after {} Iterations".format(nIter))
            elif residual < absolute_tol:
                CONVERGED = False
                print("converged after {} Iterations".format(nIter))
            print('{0:2d}  {1:3.2E}  {2:5e}'.format(nIter, relative_residual,
                                                    residual))
Example #19
0
def equilibrium_EC(w_, test_functions,
                   solutes,
                   permittivity,
                   dx, ds, normal,
                   dirichlet_bcs, neumann_bcs, boundary_to_mark,
                   use_iterative_solvers,
                   V_lagrange,
                   **namespace):
    """ Electrochemistry equilibrium solver. Nonlinear! """
    num_solutes = len(solutes)

    cV = df.split(w_["EC"])
    c, V = cV[:num_solutes], cV[num_solutes]
    if V_lagrange:
        V0 = cV[-1]

    b = test_functions["EC"][:num_solutes]
    U = test_functions["EC"][num_solutes]
    if V_lagrange:
        U0 = test_functions["EC"][-1]

    z = []  # Charge z[species]
    K = []  # Diffusivity K[species]

    for solute in solutes:
        z.append(solute[1])
        K.append(solute[2])

    rho_e = sum([c_e*z_e for c_e, z_e in zip(c, z)])

    veps = permittivity[0]

    F_c = []
    for ci, bi, Ki, zi in zip(c, b, K, z):
        grad_g_ci = df.grad(alpha_c(ci) + zi*V)
        F_ci = Ki*max_value(ci, 0.)*df.dot(grad_g_ci, df.grad(bi))*dx
        F_c.append(F_ci)

    F_V = veps*df.dot(df.grad(V), df.grad(U))*dx
    for boundary_name, sigma_e in neumann_bcs["V"].iteritems():
        F_V += -sigma_e*U*ds(boundary_to_mark[boundary_name])
    if rho_e != 0:
        F_V += -rho_e*U*dx
    if V_lagrange:
        F_V += veps*V0*U*dx + veps*V*U0*dx

    F = sum(F_c) + F_V
    J = df.derivative(F, w_["EC"])

    problem = df.NonlinearVariationalProblem(F, w_["EC"],
                                             dirichlet_bcs["EC"], J)
    solver = df.NonlinearVariationalSolver(problem)

    solver.parameters["newton_solver"]["relative_tolerance"] = 1e-7
    if use_iterative_solvers:
        solver.parameters["newton_solver"]["linear_solver"] = "bicgstab"
        if not V_lagrange:
            solver.parameters["newton_solver"]["preconditioner"] = "hypre_amg"

    solver.solve()
def block_derivative(F, u, du):
    assert isinstance(F, (array, list, BlockForm1))
    if isinstance(F, (array, list)):
        input_type = array
        (F, block_V, block_form_rank) = _block_form_preprocessing(F)
        assert block_form_rank == 1
    else:
        input_type = BlockForm1
        block_V = F.block_function_spaces()
    assert len(block_V) == 1
    block_V = block_V[0]
    
    # Compute the derivative
    assert len(F) == len(u) == len(du)
    J = empty((len(F), len(u)), dtype=object)
    for i in range(len(F)):
        if not _is_zero(F[i]):
            for j in range(len(u)):
                J[i, j] = derivative(F[i], u[j], du[j])
        else:
            J[i, :] = 0
    if input_type is array:
        return J
    elif input_type is BlockForm1:
        return BlockForm2(J, block_function_space=[du.block_function_space(), block_V])
Example #21
0
    def define_ufl_convec_accel_diff(self):
        """
        Define the UFL object corresponding to the Gateaux derivative of
        the convective acceleration term in the weak form. The function
        exits if it has already been defined.


        """

        if hasattr(self, 'ufl_convec_accel_dv'):
            return None

        # Exit if problem is formulated with respect to Eulerian
        # coordinates and is not an elastic material.
        eulerian = self.config['formulation']['domain'] == 'eulerian'
        lin_elastic = self.config['material']['const_eqn'] == 'lin_elastic'
        stokes = self.config['material']['const_eqn'] == 'stokes'
        if (not eulerian) or lin_elastic or stokes:
            self.ufl_convec_accel_dv = 0
            return None

        self.ufl_convec_accel_dv = dlf.derivative(self.ufl_convec_accel,
                                                  self.velocity,
                                                  self.trial_vector)

        return None
Example #22
0
def setup_NSPFEC(w_NSPFEC, w_1NSPFEC, bcs_NSPFEC, trial_func_NSPFEC, v, q, psi,
                 h, b, U, u_, p_, phi_, g_, c_, V_, u_1, p_1, phi_1, g_1, c_1,
                 V_1, M_, nu_, veps_, rho_, K_, rho_e_, M_1, nu_1, veps_1,
                 rho_1, K_1, rho_e_1, dbeta, dveps, drho, per_tau, sigma_bar,
                 eps, grav, z, enable_NS, enable_PF, enable_EC,
                 use_iterative_solvers):
    """ The full problem of electrohydrodynamics in two pahase.
    Note that it is possioble to trun off the dirffent parts at will.
    """

    F_imp = NSPFEC_action(u_, u_1, phi_, phi_1, c_, c_1, u_, p_, phi_, g_, c_,
                          V_, v, q, psi, h, b, U, rho_, M_, nu_, rho_e_, K_,
                          veps_, drho, grav, sigma_bar, eps, dveps, dbeta, z,
                          per_tau, enable_NS, enable_PF, enable_EC)
    F_exp = NSPFEC_action(u_, u_1, phi_, phi_1, c_, c_1, u_1, p_1, phi_1, g_1,
                          c_1, V_1, v, q, psi, h, b, U, rho_1, M_1, nu_1,
                          rho_e_1, K_1, veps_1, drho, grav, sigma_bar, eps,
                          dveps, dbeta, z, per_tau, enable_NS, enable_PF,
                          enable_EC)
    F = 0.5 * (F_imp + F_exp)
    J = df.derivative(F, w_NSPFEC)

    problem_NSPFEC = df.NonlinearVariationalProblem(F, w_NSPFEC, bcs_NSPFEC, J)
    solver_NSPFEC = df.NonlinearVariationalSolver(problem_NSPFEC)
    if use_iterative_solvers:
        solver_NSPFEC.parameters['newton_solver']['linear_solver'] = 'gmres'
        solver_NSPFEC.parameters['newton_solver']['preconditioner'] = 'ilu'

    return solver_NSPFEC
 def assemble_operator_for_derivative_decorator_impl(self, term):
     residual_term = jacobian_term_to_residual_term.get(term)
     if residual_term is None: # term was not a jacobian_term
         return assemble_operator(self, term)
     else:
         trial = TrialFunction(self.V)
         return tuple(derivative(op, self._solution, trial) for op in assemble_operator(self, residual_term))
def derivative(form, u, du = None, expand = True):
    """
    Wrapper for the DOLFIN derivative function. This attempts to select an
    appropriate du if one is not supplied. Correctly handles QForm s. By default
    the returned Form is first expanded using ufl.algorithms.expand_derivatives.
    This can be disabled if the optional expand argument is False.
    """

    if du is None:
        if isinstance(u, dolfin.Constant):
            du = dolfin.Constant(1.0)
        elif isinstance(u, dolfin.Function):
            rank = form_rank(form)
            if rank == 0:
                du = dolfin.TestFunction(u.function_space())
            elif rank == 1:
                du = dolfin.TrialFunction(u.function_space())

    der = dolfin.derivative(form, u, du = du)
    if expand:
        der = ufl.algorithms.expand_derivatives(der)

    if isinstance(form, QForm):
        return QForm(der, quadrature_degree = form.quadrature_degree())
    else:
        return der
Example #25
0
 def solveAdj(self, adj, x, adj_rhs, tol):
     """ Solve the linear Adj Problem: 
         Given a, u; find p such that
         \delta_u F(u,a,p;\hat_u) = 0 \for all \hat_u
     """
     u = vector2Function(x[STATE], self.Vh[STATE])
     a = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
     p = dl.Function(self.Vh[ADJOINT])
     du = dl.TestFunction(self.Vh[STATE])
     dp = dl.TrialFunction(self.Vh[ADJOINT])
     varf = self.varf_handler(u,a,p)
     adj_form = dl.derivative( dl.derivative(varf, u, du), p, dp )
     Aadj, dummy = dl.assemble_system(adj_form, dl.Constant(0.)*dl.inner(u,du)*dl.dx, self.bc0)
     solver = dl.PETScLUSolver()
     solver.set_operator(Aadj)
     solver.solve(adj, adj_rhs)
Example #26
0
        def __init__(self, ui, time_step_method, rho, mu, u, p0, dt, bcs, f, my_dx):
            super(TentativeVelocityProblem, self).__init__()

            W = ui.function_space()
            v = TestFunction(W)

            self.bcs = bcs

            r = SpatialCoordinate(ui.function_space().mesh())[0]

            def me(uu, ff):
                return _momentum_equation(uu, v, p0, ff, rho, mu, my_dx)

            self.F0 = rho * dot(ui - u[0], v) / dt * 2 * pi * r * my_dx
            if time_step_method == "forward euler":
                self.F0 += me(u[0], f[0])
            elif time_step_method == "backward euler":
                self.F0 += me(ui, f[1])
            else:
                assert (
                    time_step_method == "crank-nicolson"
                ), "Unknown time stepper '{}'".format(
                    time_step_method
                )
                self.F0 += 0.5 * (me(u[0], f[0]) + me(ui, f[1]))

            self.jacobian = derivative(self.F0, ui)
            self.reset_sparsity = True
            return
    def __init__(self, Th, callback_type):
        # Create mesh and define function space
        mesh = UnitSquareMesh(Th, Th)
        self.V = FunctionSpace(mesh, "Lagrange", 1)
        # Define variational problem
        du = TrialFunction(self.V)
        v = TestFunction(self.V)
        self.u = Function(self.V)
        self.r = lambda u, g: inner(grad(u), grad(v)) * dx + inner(
            u + u**3, v) * dx - g * v * dx
        self.j = lambda u, r: derivative(r, u, du)
        # Define initial guess
        self.initial_guess_expression = Expression(
            "0.1 + 0.9*x[0]*x[1]", element=self.V.ufl_element())
        # Define callback function depending on callback type
        assert callback_type in ("form callbacks", "tensor callbacks")
        if callback_type == "form callbacks":

            def callback(arg):
                return arg
        elif callback_type == "tensor callbacks":

            def callback(arg):
                return assemble(arg)

        self.callback_type = callback_type
        self.callback = callback
Example #28
0
def get_residual_form(u, v, rho_e, method='RAMP'):

    df.dx = df.dx(metadata={"quadrature_degree": 4})
    # stiffness = rho_e/(1 + 8. * (1. - rho_e))

    if method == 'SIMP':
        stiffness = rho_e**3
    else:  #RAMP
        stiffness = rho_e / (1 + 8. * (1. - rho_e))

    # print('the value of stiffness is:', rho_e.vector().get_local())
    # Kinematics
    k = 3e1
    E = k * stiffness
    nu = 0.3
    mu, lmbda = (E / (2 * (1 + nu))), (E * nu / ((1 + nu) * (1 - 2 * nu)))

    d = len(u)
    I = df.Identity(d)  # Identity tensor
    F = I + df.grad(u)  # Deformation gradient
    C = F.T * F  # Right Cauchy-Green tensor

    E_ = 0.5 * (C - I)  # Green--Lagrange strain
    S = 2.0 * mu * E_ + lmbda * df.tr(E_) * df.Identity(
        d)  # stress tensor (C:eps)
    psi = 0.5 * df.inner(S, E_)  # 0.5*eps:C:eps

    # Total potential energy
    Pi = psi * df.dx
    # Solve weak problem obtained by differentiating Pi:
    res = df.derivative(Pi, u, v)
    return res
    def _external_work(self, u, v):

        F = dolfin.variable(kinematics.DeformationGradient(u))

        N = self.geometry.facet_normal
        ds = self.geometry.ds
        dx = self.geometry.dx

        external_work = []

        for neumann in self.bcs.neumann:

            n = neumann.traction * ufl.cofac(F) * N
            external_work.append(dolfin.inner(v, n) * ds(neumann.marker))

        for robin in self.bcs.robin:

            external_work.append(
                dolfin.inner(robin.value * u, v) * ds(robin.marker))

        for body_force in self.bcs.body_force:

            external_work.append(
                -dolfin.derivative(dolfin.inner(body_force, u) * dx, u, v), )

        if len(external_work) > 0:
            return list_sum(external_work)

        return None
Example #30
0
 def grad_param(self, x, g):
     """Evaluate the gradient with respect to the state.
     Only the state u and (possibly) the parameter m are accessed. """
     u = vector2Function(x[STATE], self.Vh[STATE])
     m = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
     g.zero()
     dl.assemble(dl.derivative(self.qoi_varf(u, m), m), tensor=g)
    def __init__(self, ui, theta,
                 rho, mu,
                 u, p0, dt,
                 bcs,
                 f0, f1,
                 stabilization=False,
                 dx=dx
                 ):
        super(TentativeVelocityProblem, self).__init__()

        W = ui.function_space()
        v = TestFunction(W)

        self.bcs = bcs

        r = Expression('x[0]', degree=1, domain=ui.function_space().mesh())

        #self.F0 = rho * dot(3*ui - 4*u[-1] + u[-2], v) / (2*Constant(dt)) \
        #    * 2*pi*r*dx
        #self.F0 += momentum_equation(ui, v,
        #                             p0,
        #                             f1,
        #                             rho, mu,
        #                             stabilization=stabilization,
        #                             dx=dx
        #                             )

        self.F0 = rho * dot(ui - u[-1], v) / Constant(dt) \
            * 2*pi*r*dx
        if abs(theta) > DOLFIN_EPS:
            # Implicit terms.
            if f1 is None:
                raise RuntimeError('Implicit schemes need right-hand side '
                                   'at target step (f1).')
            self.F0 += theta \
                * momentum_equation(ui, v,
                                    p0,
                                    f1,
                                    rho, mu,
                                    stabilization=stabilization,
                                    dx=dx
                                    )
        if abs(1.0 - theta) > DOLFIN_EPS:
            # Explicit terms.
            if f0 is None:
                raise RuntimeError('Explicit schemes need right-hand side '
                                   'at current step (f0).')
            self.F0 += (1.0 - theta) \
                * momentum_equation(u[-1], v,
                                    p0,
                                    f0,
                                    rho, mu,
                                    stabilization=stabilization,
                                    dx=dx
                                    )
        self.jacobian = derivative(self.F0, ui)
        self.reset_sparsity = True
        return
Example #32
0
    def setLinearizationPoint(self, x):
        """ Set the values of the state and parameter
            for the incremental Fwd and Adj solvers """
        u = vector2Function(x[STATE], self.Vh[STATE])
        a = vector2Function(x[PARAMETER], self.Vh[PARAMETER])
        p = vector2Function(x[ADJOINT], self.Vh[ADJOINT])
        x_fun = [u, a, p]

        f_form = self.varf_handler(u, a, p)

        g_form = [None, None, None]
        for i in range(3):
            g_form[i] = dl.derivative(f_form, x_fun[i])

        self.A, dummy = dl.assemble_system(dl.derivative(g_form[ADJOINT], u),
                                           g_form[ADJOINT], self.bc0)
        self.At, dummy = dl.assemble_system(dl.derivative(g_form[STATE], p),
                                            g_form[STATE], self.bc0)
        self.C = dl.assemble(dl.derivative(g_form[ADJOINT], a))
        self.bc0.zero(self.C)
        self.Wau = dl.assemble(dl.derivative(g_form[PARAMETER], u))
        Wau_t = Transpose(self.Wau)
        self.bc0.zero(Wau_t)
        self.Wau = Transpose(Wau_t)

        self.Wuu = dl.assemble(dl.derivative(g_form[STATE], u))
        self.bc0.zero(self.Wuu)
        Wuu_t = Transpose(self.Wuu)
        self.bc0.zero(Wuu_t)
        self.Wuu = Transpose(Wuu_t)

        self.Waa = dl.assemble(dl.derivative(g_form[PARAMETER], a))

        self.solver_fwd_inc.set_operator(self.A)
        self.solver_adj_inc.set_operator(self.At)
Example #33
0
    def __init__(
            self, WPQ,
            kappa, rho, rho_const, mu, cp,
            g, extra_force,
            heat_source,
            u_bcs, p_bcs,
            theta_dirichlet_bcs=None,
            theta_neumann_bcs=None,
            theta_robin_bcs=None,
            my_dx=dx,
            my_ds=ds
            ):
        super(StokesHeat, self).__init__()

        theta_dirichlet_bcs = theta_dirichlet_bcs or {}
        theta_neumann_bcs = theta_neumann_bcs or {}
        theta_robin_bcs = theta_robin_bcs or {}

        # Translate the Dirichlet boundary conditions into the product space.
        self.dirichlet_bcs = helpers.dbcs_to_productspace(
            WPQ,
            [u_bcs, p_bcs, theta_dirichlet_bcs]
            )

        self.uptheta = Function(WPQ)
        u, p, theta = split(self.uptheta)
        v, q, zeta = TestFunctions(WPQ)

        mesh = WPQ.mesh()
        r = SpatialCoordinate(mesh)[0]

        # Right-hand side for momentum equation.
        f = rho(theta) * g  # coupling
        if extra_force is not None:
            f += as_vector((extra_force[0], extra_force[1], 0.0))
        self.stokes_F = stokes.F(
            u, p, v, q, f, r, mu, my_dx
            )

        self.heat_F = heat.F(
                theta, zeta,
                kappa=kappa, rho=rho_const, cp=cp,
                convection=u,  # coupling
                source=heat_source,
                r=r,
                neumann_bcs=theta_neumann_bcs,
                robin_bcs=theta_robin_bcs,
                my_dx=my_dx,
                my_ds=my_ds
                )

        self.F0 = self.stokes_F + self.heat_F
        self.jacobian = derivative(self.F0, self.uptheta)
        return
Example #34
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
Example #35
0
    def solve_system(self,rhs,factor,u0,t):
        """
        Dolfin's linear solver for (M-dtA)u = rhs

        Args:
            rhs: right-hand side for the nonlinear system
            factor: abbrev. for the node-to-node stepsize (or any other factor required)
            u0: initial guess for the iterative solver (not used here so far)

        Returns:
            solution as mesh
        """

        sol = fenics_mesh(self.V)

        # self.g.t = t
        self.w.assign(sol.values)

        q1,q2 = df.TestFunctions(self.V)
        w1,w2 = df.split(self.w)
        r1,r2 = df.split(rhs.values)
        F1 = w1*q1*df.dx - factor*self.F1 - r1*q1*df.dx
        F2 = w2*q2*df.dx - factor*self.F2 - r2*q2*df.dx
        F = F1+F2
        du = df.TrialFunction(self.V)
        J  = df.derivative(F, self.w, du)

        problem = df.NonlinearVariationalProblem(F, self.w, [], J)
        solver  = df.NonlinearVariationalSolver(problem)

        prm = solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-09
        prm['newton_solver']['relative_tolerance'] = 1E-08
        prm['newton_solver']['maximum_iterations'] = 100
        prm['newton_solver']['relaxation_parameter'] = 1.0

        # df.set_log_level(df.PROGRESS)

        solver.solve()

        sol.values.assign(self.w)

        return sol
    def __init__(self, WP, rho, mu, f, u_bcs, p_bcs, dx, stabilization=None):
        super(NavierStokesCylindrical, self).__init__()
        #
        self.WP = WP
        # Translate the boundary conditions into the product space.
        self.bcs = []
        for k, bcs in enumerate([u_bcs, p_bcs]):
            for bc in bcs:
                space = bc.function_space()
                C = space.component()
                if len(C) == 0:
                    self.bcs.append(DirichletBC(self.WP.sub(k),
                                                bc.value(),
                                                bc.domain_args[0]))
                elif len(C) == 1:
                    self.bcs.append(DirichletBC(self.WP.sub(k).sub(int(C[0])),
                                                bc.value(),
                                                bc.domain_args[0]))
                else:
                    raise RuntimeError('Illegal number of '
                                       'subspace components.'
                                       )
        #
        self.up = Function(self.WP)
        u, p = self.up.split()
        v, q = TestFunctions(self.WP)
        # Momentum equation.
        self.F0 = momentum_equation(u, v,
                                    p,
                                    f,
                                    rho, mu,
                                    stabilization=stabilization,
                                    dx=dx
                                    )
        # div_u = 1/r * div(r*u)
        r = Expression('x[0]', degree=1, domain=WP.mesh())
        self.F0 += (1.0 / r * (r * u[0]).dx(0) + u[1].dx(1)) * q \
            * 2 * pi * r * dx

        self.jacobian = derivative(self.F0, self.up)
        self.reset_sparsity = True
        return
Example #37
0
    def solve_system(self,rhs,factor,u0,t):
        """
        Dolfin's linear solver for (M-dtA)u = rhs

        Args:
            rhs: right-hand side for the nonlinear system
            factor: abbrev. for the node-to-node stepsize (or any other factor required)
            u0: initial guess for the iterative solver (not used here so far)

        Returns:
            solution as mesh
        """

        sol = fenics_mesh(self.V)

        self.g.t = t
        self.w.assign(sol.values)

        v = df.TestFunction(self.V)
        F = self.w*v*df.dx - factor*self.a_K - rhs.values*v*df.dx

        du = df.TrialFunction(self.V)
        J  = df.derivative(F, self.w, du)

        problem = df.NonlinearVariationalProblem(F, self.w, self.bc, J)
        solver  = df.NonlinearVariationalSolver(problem)

        prm = solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-8
        prm['newton_solver']['relative_tolerance'] = 1E-7
        prm['newton_solver']['maximum_iterations'] = 25
        prm['newton_solver']['relaxation_parameter'] = 1.0

        # df.set_log_level(df.PROGRESS)

        solver.solve()

        sol.values.assign(self.w)

        return sol
Example #38
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))
Example #39
0
    # Nonlinear coefficient 1
    q1 = ufl.operators.exp(a * u1)

    # Nonlinear coefficient 2
    q2 = ufl.operators.exp(a * u2)

    for k in range(10):

        # Two parts of the weak form
        F1 = (u1.dx(0) * v1.dx(0) + a * u1.dx(0) * q2 * v1) * df.dx
        F2 = (u2.dx(0) * v2.dx(0) - a * q1 * u2.dx(0) * v2) * df.dx

        F = F1 + F2

        # Compute Jacobian
        dF = df.derivative(F, u, du)

        # Assemble matrix and load vector
        A, b = df.assemble_system(dF, -F, bch)

        # Compute Newton update
        df.solve(A, u_inc.vector(), b)

        # Update solution
        u.vector()[:] += u_inc.vector()

    # Evaluate solution
    ug = u.compute_vertex_values()

    # partition into u1 and u2
    U = np.reshape(ug, (2, nel + 1))
    def solve(self, F, u, grad = None, H = None):
        
        if grad is None:
            print "Using Automatic Differentiation to compute the gradient"
            grad = derivative(F,u)
            
        if H is None:
            print "Using Automatic Differentiation to compute the Hessian"
            H = derivative(grad, u)
        
        rtol = self.parameters["rel_tolerance"]
        atol = self.parameters["abs_tolerance"]
        gdu_tol = self.parameters["gdu_tolerance"]
        max_iter = self.parameters["max_iter"]
        c_armijo = self.parameters["c_armijo"] 
        max_backtrack = self.parameters["max_backtracking_iter"]
        prt_level =  self.parameters["print_level"]
        cg_coarsest_tol = self.parameters["cg_coarse_tolerance"]
        
        Fn = assemble(F)
        gn = assemble(grad)
        g0_norm = gn.norm("l2")
        gn_norm = g0_norm
        tol = max(g0_norm*rtol, atol)
        du = Vector()
        
        self.converged = False
        self.reason = 0
        
        if prt_level > 0:
            print "{0:3} {1:15} {2:15} {3:15} {4:15} {5:15} {6:5}".format(
                "It", "Energy", "||g||", "(g,du)", "alpha", "tol_cg", "cg_it")
        
        for self.it in range(max_iter):
            Hn = assemble(H)
            
            Hn.init_vector(du,1)
            solver = PETScKrylovSolver("cg", "petsc_amg")
            solver.set_operator(Hn)
            solver.parameters["nonzero_initial_guess"] = False
            cg_tol = min(cg_coarsest_tol, math.sqrt( gn_norm/g0_norm) )
            solver.parameters["relative_tolerance"] = cg_tol
            lin_it = solver.solve(du,gn)
            
            self.total_cg_iter += lin_it
            

            du_gn = -du.inner(gn)
            
            if(-du_gn < gdu_tol):
                self.converged=True
                self.reason = 3
                break
             
            u_backtrack = u.copy(deepcopy=True)
            alpha = 1.   
            bk_converged = False
            
            #Backtrack
            for j in range(max_backtrack):
                u.assign(u_backtrack)
                u.vector().axpy(-alpha, du)
                Fnext = assemble(F)
                if Fnext < Fn + alpha*c_armijo*du_gn:
                    Fn = Fnext
                    bk_converged = True
                    break
                
                alpha = alpha/2.
                
            if not bk_converged:
                self.reason = 2
                break
                   
            gn = assemble(grad)
            gn_norm = gn.norm("l2")
            
            if prt_level > 0:
                print "{0:3d} {1:15f} {2:15f} {3:15f} {4:15f} {5:15f} {6:5d}".format(
                        self.it, Fn, gn_norm, du_gn, alpha, cg_tol, lin_it)
                
            if gn_norm < tol:
                self.converged = True
                self.reason = 1
                break
            
        self.final_grad_norm = gn_norm
        
        if prt_level > -1:
            print self.termination_reasons[self.reason]
            if self.converged:
                print "Inexact Newton CG converged in ", self.it, \
                "nonlinear iterations and ", self.total_cg_iter, "linear iterations."
            else:
                print "Inexact Newton CG did NOT converge after ", self.it, \
                "nonlinear iterations and ", self.total_cg_iter, "linear iterations."
            print "Final norm of the gradient", self.final_grad_norm
            print "Value of the cost functional", Fn
    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
a = (H_n - H_o) / dt * w
b = D(H_n) * dfn.dot(dfn.grad(H_n), dfn.grad(w))
c = M * w
F = (a + b - c) * dfn.dx

# <codecell>

# F = dfn.action(F, H_coef)

# <markdowncell>

# Compute the Jacobian matrix. 

# <codecell>

J = dfn.derivative(F, H_n, dH)

# <markdowncell>

# Setup the boundaries to contain a constant value (we do not want any Von Neuman boundaries)

# <codecell>

def boundary(h, on_boundary):
    return on_boundary

bc = dfn.DirichletBC(V, dfn.Constant(0.0), boundary)
# bc = dfn.DirichletBC(V, M, boundary)

# <markdowncell>
    def step(self,
             dt,
             u1, p1,
             u, p0,
             u_bcs, p_bcs,
             f0=None, f1=None,
             verbose=True,
             tol=1.0e-10
             ):
        # Some initial sanity checkups.
        assert dt > 0.0
        # Define trial and test functions
        ui = Function(self.W)
        v = TestFunction(self.W)
        # Create functions
        # Define coefficients
        k = Constant(dt)

        # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        # Compute tentative velocity step:
        #
        #     F(u) = 0,
        #     F(u) := rho (U0 + (u.\nabla)u) - mu \div(\nabla u) - f = 0.
        #
        with Message('Computing tentative velocity'):
            # TODO higher-order scheme for time integration
            #
            # For higher-order schemes, see
            #
            #     A comparison of time-discretization/linearization approaches
            #     for the incompressible Navier-Stokes equations;
            #     Volker John, Gunar Matthies, Joachim Rang;
            #     Comput. Methods Appl. Mech. Engrg. 195 (2006) 5995-6010;
            #     <http://www.wias-berlin.de/people/john/ELECTRONIC_PAPERS/JMR06.CMAME.pdf>.
            #
            F1 = self.rho * inner((ui - u[0])/k, v) * dx

            if abs(self.theta) > DOLFIN_EPS:
                # Implicit terms.
                if f1 is None:
                    raise RuntimeError('Implicit schemes need right-hand side '
                                       'at target step (f1).')
                F1 -= self.theta * _rhs_weak(ui, v, f1, self.rho, self.mu)
            if abs(1.0 - self.theta) > DOLFIN_EPS:
                # Explicit terms.
                if f0 is None:
                    raise RuntimeError('Explicit schemes need right-hand side '
                                       'at current step (f0).')
                F1 -= (1.0 - self.theta) \
                    * _rhs_weak(u[0], v, f0, self.rho, self.mu)

            if p0:
                F1 += dot(grad(p0), v) * dx

            #if stabilization:
            #    tau = stab.supg2(V.mesh(),
            #                     u_1,
            #                     mu/rho,
            #                     V.ufl_element().degree()
            #                     )
            #    R = rho*(ui - u_1)/k
            #    if abs(theta) > DOLFIN_EPS:
            #        R -= theta * _rhs_strong(ui, f1, rho, mu)
            #    if abs(1.0-theta) > DOLFIN_EPS:
            #        R -= (1.0-theta) * _rhs_strong(u_1, f0, rho, mu)
            #    if p_1:
            #        R += grad(p_1)
            #    # TODO use u_1 or ui here?
            #    F1 += tau * dot(R, grad(v)*u_1) * dx

            # Get linearization and solve nonlinear system.
            # If the scheme is fully explicit (theta=0.0), then the system is
            # actually linear and only one Newton iteration is performed.
            J = derivative(F1, ui)

            # What is a good initial guess for the Newton solve?
            # Three choices come to mind:
            #
            #    (1) the previous solution u_1,
            #    (2) the intermediate solution from the previous step ui_1,
            #    (3) the solution of the semilinear system
            #        (u.\nabla(u) -> u_1.\nabla(u)).
            #
            # Numerical experiments with the Karman vortex street show that the
            # order of accuracy is (1), (3), (2). Typical norms would look like
            #
            #     ||u - u_1 || = 1.726432e-02
            #     ||u - ui_1|| = 2.720805e+00
            #     ||u - u_e || = 5.921522e-02
            #
            # Hence, use u_1 as initial guess.
            ui.assign(u[0])

            # Wrap the solution in a try-catch block to make sure we call end()
            # if necessary.
            #problem = NonlinearVariationalProblem(F1, ui, u_bcs, J)
            #solver  = NonlinearVariationalSolver(problem)
            solve(
                F1 == 0, ui,
                bcs=u_bcs,
                J=J,
                solver_parameters={
                    #'nonlinear_solver': 'snes',
                    'nonlinear_solver': 'newton',
                    'newton_solver': {
                        'maximum_iterations': 5,
                        'report': True,
                        'absolute_tolerance': tol,
                        'relative_tolerance': 0.0,
                        'linear_solver': 'iterative',
                        ## The nonlinear term makes the problem generally
                        ## nonsymmetric.
                        #'symmetric': False,
                        # If the nonsymmetry is too strong, e.g., if u_1 is
                        # large, then AMG preconditioning might not work very
                        # well.
                        'preconditioner': 'ilu',
                        #'preconditioner': 'hypre_amg',
                        'krylov_solver': {'relative_tolerance': tol,
                                          'absolute_tolerance': 0.0,
                                          'maximum_iterations': 1000,
                                          'monitor_convergence': verbose}
                        }})
        # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        with Message('Computing pressure correction'):
            #
            # The following is based on the update formula
            #
            #     rho/dt (u_{n+1}-u*) + \nabla phi = 0
            #
            # with
            #
            #     phi = (p_{n+1} - p*) + chi*mu*div(u*)
            #
            # and div(u_{n+1})=0. One derives
            #
            #   - \nabla^2 phi = rho/dt div(u_{n+1} - u*),
            #   - n.\nabla phi = rho/dt  n.(u_{n+1} - u*),
            #
            # In its weak form, this is
            #
            #     \int \grad(phi).\grad(q)
            #   = - rho/dt \int div(u*) q - rho/dt \int_Gamma n.(u_{n+1}-u*) q.
            #
            # If Dirichlet boundary conditions are applied to both u* and
            # u_{n+1} (the latter in the final step), the boundary integral
            # vanishes.
            #
            # Assume that on the boundary
            #   L2 -= inner(n, rho/k (u_bcs - ui)) * q * ds
            # is zero. This requires the boundary conditions to be set for
            # ui as well as u_final.
            # This creates some problems if the boundary conditions are
            # supposed to remain 'free' for the velocity, i.e., no Dirichlet
            # conditions in normal direction. In that case, one needs to
            # specify Dirichlet pressure conditions.
            #
            rotational_form = False
            self._pressure_poisson(p1, p0,
                                   self.mu, ui,
                                   divu=Constant(self.rho/dt)*div(ui),
                                   p_bcs=p_bcs,
                                   rotational_form=rotational_form,
                                   tol=tol,
                                   verbose=verbose
                                   )
            #plot(p - phi, title='p-phi')
            #plot(ui, title='u intermediate')
            #plot(f, title='f')
            ##plot(ui[1], title='u intermediate[1]')
            #plot(div(ui), title='div(u intermediate)')
            #plot(phi, title='phi')
            #interactive()
        # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        # Velocity correction.
        #   U = U0 - dt/rho \nabla p.
        with Message('Computing velocity correction'):
            u2 = TrialFunction(self.W)
            a3 = inner(u2, v) * dx
            if p0:
                phi = Function(self.P)
                phi.assign(p1)
                phi -= p0
            else:
                phi = p1
            if rotational_form:
                phi += self.mu * div(ui)
            L3 = inner(ui,  v) * dx \
                - k/self.rho * inner(grad(phi), v) * dx
            solve(a3 == L3, u1,
                  bcs=u_bcs,
                  solver_parameters={
                      'linear_solver': 'iterative',
                      'symmetric': True,
                      'preconditioner': 'jacobi',
                      'krylov_solver': {'relative_tolerance': tol,
                                        'absolute_tolerance': 0.0,
                                        'maximum_iterations': 100,
                                        'monitor_convergence': verbose}
                      })
        #u = project(ui - k/rho * grad(phi), V)
        #print '||u||_div = %e' % norm(u, 'Hdiv0')
        #uu = TrialFunction(Q)
        #vv = TestFunction(Q)
        #div_u = Function(Q)
        #solve(uu*vv*dx == div(u)*vv*dx, div_u,
        #      #bcs=DirichletBC(Q, 0.0, 'on_boundary')
        #      )
        #plot(div_u, title='div(u)')
        #interactive()
        return
Example #44
0
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