Esempio n. 1
0
    def linearstep(self, subprobctxt, linsys, time, unknowns, endtime):
        dt = endtime - time
        ## The matrix equation to be solved (for alpha) is A*alpha=x,
        ## where
        ## A = M + theta1 dt C + 1/2 theta2 dt^2 K
        ## x = -(C + theta1 dt K) adot - K a + rhs

        ## Note that   rhs = -f.
        ## We work with   M (d2/dt2) u + C (d/dt) u + K u = rhs
        ## instead of     M (d2/dt2) u + C (d/dt) u + K u + f = 0

        ## a is the known vector of dofs, adot is its known first time
        ## derivative.  rhs is a weighted average of the right hand sides
        ## over the time interval:
        ## rhs = (1-theta1) rhs(t) + theta1 rhs(t+dt)

        ## Values at t+dt are
        ##    a    <- a + dt adot + 1/2 dt^2 alpha
        ##    adot <- adot + dt alpha

        K = linsys.K_MCK()
        C = linsys.C_MCK()
        M = linsys.M_MCK()

        ## This relies on the Fields and their time derivative Fields
        ## having the same global dof ordering!
        A = M.clone()
        A.add(self.theta1*dt, C)
        A.add(0.5*self.theta2*dt*dt, K)
        A.consolidate()

        x  = linsys.rhs_MCK() # x = rhs(t_n)
        x *= (1.0 - self.theta1)        # x = (1-theta1) rhs(t_n)
        ## Compute the rhs at t = endtime.
        linsys1 = subprobctxt.make_linear_system(endtime, linsys)
        # x = (1-theta1) rhs(t_n) + theta1  rhs(t_{n+1})
        x.axpy(self.theta1, linsys1.rhs_MCK())

        # Separate the field and deriv parts of unknowns
        a    = linsys.get_fields_MCKd(unknowns)
        adot = linsys.get_derivs_MCKd(unknowns)

        K.axpy(-1.0, a, x)               # x = - K a + rhs
        C.axpy(-1.0, adot, x)            # x = -C adot - K a + rhs
        K.axpy(-self.theta1*dt, adot, x) # ... -theta1 dt K adot

        alpha = doublevec.DoubleVec(len(a))
        subprobctxt.matrix_method(_asymmetric, subprobctxt).solve(A, x, alpha)
        
        ## update a and adot, then copy them into endValues
        a.axpy(dt, adot)
        a.axpy(0.5*dt*dt, alpha)
        adot.axpy(dt, alpha)

        endValues = doublevec.DoubleVec(unknowns.size())
        linsys.set_fields_MCKd(a, endValues)
        linsys.set_derivs_MCKd(adot, endValues)

        return timestepper.StepResult(endTime=endtime, nextStep=dt,
                                      endValues=endValues, linsys=linsys)
Esempio n. 2
0
    def linearstep(self, subproblem, linsys, time, unknowns, endtime):
        # C du/dt + K u = f
        # C, K, and f might depend on time explicitly, but not on u
        #
        # Write du/dt = (u_{n+1}-u_n)/dt,  K u = K_{n+1} u_{n+1},  f = f_{n+1}
        #
        # (C + dt K_{n+1}) u_{n+1} = C u_{n} + dt f_{n+1}

        dt = endtime - time

        # Evaluate quantities at endtime.
        linsys1 = subproblem.make_linear_system(endtime, linsys)
        K1 = linsys1.K_MCKa()  # K_{n+1}
        f1 = linsys1.rhs_MCKa()  # f_{n+1}
        C = linsys1.C_MCKa()

        # Construct  A = C + dt K_{n+1}, which is the matrix to be inverted.
        A = C.clone()
        A.add(dt, K1)

        # Compute the rhs of the matrix equation.
        v = dt * f1
        C.axpy(1.0, unknowns, v)

        # Solve the linear system.  unknowns is updated in-place.
        subproblem.matrix_method(_asymmetricGE,
                                 subproblem).solve(A, v, unknowns)

        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=unknowns,
                                      linsys=linsys)
Esempio n. 3
0
    def nonlinearstep(self, subproblem, linsys, time, unknowns, endtime,
                      nonlinearMethod):
        # M d2u/dt2 + C du/dt + F(u,t) = 0
        # F might depend on time and u explicitly
        # M and C might depend on time

        dt = endtime - time

        data = NLDataSS22(subproblem, linsys, endtime, dt, unknowns,
                          self.theta1, self.theta2)

        alpha = doublevec.DoubleVec(linsys.n_unknowns_MCK())  # not MCKd

        nonlinearMethod.solve(
            subproblem.matrix_method(_asymmetric, subproblem),
            self.precomputeNL, self.compute_residual, self.compute_jacobian,
            self.compute_linear_coef_mtx, data, alpha)

        # Update a and adot, reusing the storage in data.a0 and data.a0dot.
        data.a0.axpy(dt, data.a0dot)
        data.a0.axpy(0.5 * dt * dt, alpha)
        data.a0dot.axpy(dt, alpha)
        endValues = doublevec.DoubleVec(unknowns.size())
        linsys.set_fields_MCKd(data.a0, endValues)
        linsys.set_derivs_MCKd(data.a0dot, endValues)
        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=endValues,
                                      linsys=linsys)
Esempio n. 4
0
 def nonlinearstep(self, subproblem, linsys, time, unknowns, endtime,
                   nonlinearMethod):
     data = timestepper.NLData(subproblem, linsys, endtime)
     endValues = unknowns.clone()
     nonlinearMethod.solve(subproblem.matrix_method(subproblem.asymmetricK),
                           self.precomputeNL, self.compute_residual,
                           self.compute_jacobian,
                           self.compute_linear_coef_mtx, data, endValues)
     return timestepper.StepResult(endTime=endtime,
                                   endValues=endValues,
                                   linsys=linsys)
Esempio n. 5
0
    def linearstep(self, subproblem, linsys, time, unknowns, endtime):
        # This function is called only when solving quasi-static
        # problems.  Fully static problems are solved by
        # SubProblemContext.initializeStaticFields.

        # Use unknowns as an initial guess for the solution.  The
        # calculation is done in place. (evolve.py created the
        # unknowns vector by calling SubProblemContext.get_unknowns,
        # which copied them out of the subproblem's dof list, so we're
        # already working with a copy here.)
        linsys = subproblem.make_linear_system(endtime, linsys)
        self.staticSolve(subproblem, linsys, unknowns)
        return timestepper.StepResult(endTime=endtime, endValues=unknowns,
                                      linsys=linsys)
Esempio n. 6
0
    def linearstep(self, subproblem, linsys, time, unknowns, endtime):
        # C du/dt + K u = f
        # C, K, and f might have explicit time dependence, but don't
        # depend on u.

        # Write du/dt = (u_{n+1}-u_n)/dt,
        # K u = (1-theta) K_n u_n + theta K_{n+1} u_{n+1}
        # f = (1-theta) f_n + theta f_{n+1}

        # (C + dt theta K_{n+1}) u_{n+1} =
        #   (C - dt (1-theta) K_n) u_n + (1-theta) dt f_n + theta dt f_{n+1}

        # Because GeneralizedEuler mixes C and K in the matrix to be
        # solved, it doesn't have to worry that C can be singular,
        # unlike ForwardEuler.  It can work with the full MCKa matrix,
        # and doesn't have to explicitly solve the static equations.

        dt = endtime - time

        # Evaluate quantities at start time.
        K0 = linsys.K_MCKa()  # K_n
        f0 = linsys.rhs_MCKa()  # f_n
        C = linsys.C_MCKa()

        # Evaluate quantities at endtime, in case of explicit time
        # dependence of rhs_ind or K_eff.
        linsys1 = subproblem.make_linear_system(endtime, linsys)
        K1 = linsys1.K_MCKa()  # K_{n+1}
        f1 = linsys1.rhs_MCKa()  # f_{n+1}

        # Compute C + dt theta K_{n+1}, which is the matrix to be solved.
        A = C.clone()
        A.add(self.theta * dt, K1)

        # Compute the rhs of the matrix equation.

        v = (dt * (1.0 - self.theta)) * f0
        v.axpy(self.theta * dt, f1)  # v = (1-theta) dt f_n + theta dt f_{n+1}
        K0.axpy(-dt * (1 - self.theta), unknowns,
                v)  # ... - dt (1-theta) K_n u_n
        C.axpy(1.0, unknowns, v)  # ... + C u_n

        subproblem.matrix_method(_asymmetricGE,
                                 subproblem).solve(A, v, unknowns)
        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=unknowns,
                                      linsys=linsys1)
Esempio n. 7
0
    def _do_step(self, subproblem, linsys, time, unknowns, endtime, get_res):
        # Solve C(u_{n+1} - u_n) = dt*(f - K u_n)
        # C and K are effective matrices, coming from the reduction of
        # a second order problem to a system of first order problems.

        # If C has empty rows, the static solution of those rows has
        # already been computed by initializeStaticFields() or by a
        # previous Euler step, and we only have to solve the remaining
        # nonempty rows here.  Unlike GeneralizedEuler, here we're
        # solving an unmodified C, so it can't contain empty rows.
        staticEqns = linsys.n_unknowns_part('K') > 0

        dt = endtime - time
        # v = dt * linsys.rhs_MCa() # v = dt*f

        # # K_MCa is really (MCa)x(MCKa), so we can multiply by
        # # unknowns, which includes the K part.
        # K = linsys.K_MCa()
        # K.axpy(-dt, unknowns, v) # v = dt*(f - K u)
        v = get_res(linsys, dt, unknowns)

        C = linsys.C_MCa()
        # solve() stores u_{n+1}-u_n in endValues.  Before calling
        # solve, set endValues to a good guess for u_{n+1}-u_n.
        # Assuming that the step size is small, a good guess is zero.
        endValues = doublevec.DoubleVec(unknowns.size())
        endValues.zero()

        x = linsys.extract_MCa_dofs(endValues)
        subproblem.matrix_method(_asymmetricFE, subproblem,
                                 linsys).solve(C, v, x)
        linsys.inject_MCa_dofs(x, endValues)

        endValues += unknowns

        if staticEqns:
            # Re-solve the static equations at endtime.
            subproblem.installValues(linsys, endValues, endtime)
            linsys = subproblem.make_linear_system(endtime, linsys)
            subproblem.computeStaticFields(linsys, endValues)

        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=endValues,
                                      linsys=linsys)
Esempio n. 8
0
    def _do_step(self, subprobctxt, linsys, time, unknowns, endtime, get_res):

        nK = linsys.n_unknowns_part('K')  # number of static DoFs
        staticEqns = nK > 0

        dt = endtime - time
        n = unknowns.size() - nK

        C = linsys.C_MCa()
        # K = linsys.K_MCa()
        # v = linsys.rhs_MCa() - K*unknowns
        v = get_res(linsys, unknowns)
        k1 = linsys.extract_MCa_dofs(unknowns)  # initial guess for k1
        subprobctxt.matrix_method(_asymmetric, subprobctxt,
                                  linsys).solve(C, v, k1)
        if staticEqns:
            linsys.expand_MCa_dofs(k1)

        y = unknowns + (0.5 * dt) * k1
        subprobctxt.installValues(linsys, y, time + 0.5 * dt)
        linsys = subprobctxt.make_linear_system(time + 0.5 * dt, linsys)
        if staticEqns:
            subprobctxt.computeStaticFields(linsys, y)
        C = linsys.C_MCa()
        # K = linsys.K_MCa()
        # v = linsys.rhs_MCa() - K*y
        v = get_res(linsys, y)
        k2 = linsys.extract_MCa_dofs(y)
        subprobctxt.matrix_method(_asymmetric, subprobctxt,
                                  linsys).solve(C, v, k2)
        if staticEqns:
            linsys.expand_MCa_dofs(k2)

        unknowns.axpy(dt, k2)
        if staticEqns:
            subprobctxt.installValues(linsys, unknowns, endtime)
            linsys = subprobctxt.make_linear_system(endtime, linsys)
            subprobctxt.computeStaticFields(linsys, unknowns)

        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=unknowns,
                                      linsys=linsys)
Esempio n. 9
0
    def nonlinearstep(self, subproblem, linsys, time, unknowns, endtime,
                      nonlinearMethod):
        # C du/dt + F(u,t) = 0
        # C (u_{n+1}-u_n)/dt + theta F(u_{n+1}, t+dt) + (1-theta)F(u_n, t) = 0
        #  or
        # C u_{n+1} + theta dt F(u_{n+1}, t+dt)
        #         - C u_n + (1-theta)dt F(u_n,t) = 0

        dt = endtime - time

        data = NLDataGE(subproblem, linsys, endtime, dt, unknowns, self.theta)
        endValues = unknowns.clone()
        nonlinearMethod.solve(
            subproblem.matrix_method(_asymmetricGE, subproblem),
            self.precomputeNL, self.compute_residual, self.compute_jacobian,
            self.compute_linear_coef_mtx, data, endValues)
        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=endValues,
                                      linsys=linsys)
Esempio n. 10
0
    def nonlinearstep(self, subproblem, linsys, time, unknowns, endtime,
                      nonlinearMethod):
        # C du/dt + F = 0
        # K, and f might depend on time and u explicitly

        # Write du/dt = (u_{n+1}-u_n)/dt,
        # F(u,t) = F( u_{n+1}, t_{n+1} )

        # So we need to solve the following nonlinear eqn for v
        # to obtain u_{n+1}

        # C v + dt F(v,t+dt) - C u_{n} = 0
        dt = endtime - time

        data = NLDataBE(subproblem, linsys, endtime, dt, unknowns)
        endValues = unknowns.clone()
        nonlinearMethod.solve(
            subproblem.matrix_method(_asymmetricGE, subproblem),
            self.precomputeNL, self.compute_residual, self.compute_jacobian,
            self.compute_linear_coef_mtx, data, endValues)
        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=endValues,
                                      linsys=linsys)
Esempio n. 11
0
    def _do_step(self, subprobctxt, linsys, time, unknowns, endtime, get_res):
        nK = linsys.n_unknowns_part('K')  # number of static DoFs
        staticEqns = nK > 0

        dt = endtime - time
        n = unknowns.size() - nK
        halftime = time + 0.5 * dt

        C = linsys.C_MCa()
        v = get_res(linsys, unknowns)
        # K = linsys.K_MCa()                     # really (MCa)x(MCKa)
        # v = linsys.rhs_MCa() - K*unknowns      # (f - K u)
        k1 = linsys.extract_MCa_dofs(unknowns)  # initial guess for k1
        assert k1.size() == n
        subprobctxt.matrix_method(_asymmetric, subprobctxt,
                                  linsys).solve(C, v, k1)
        if staticEqns:
            linsys.expand_MCa_dofs(k1)
            # include room for static dofs in k1

        y = unknowns + (0.5 * dt) * k1
        subprobctxt.installValues(linsys, y, halftime)
        linsys = subprobctxt.make_linear_system(halftime, linsys)
        if staticEqns:
            subprobctxt.computeStaticFields(linsys, y)
        C = linsys.C_MCa()
        # K = linsys.K_MCa()
        # v = linsys.rhs_MCa() - K*y
        v = get_res(linsys, y)
        k2 = linsys.extract_MCa_dofs(y)
        subprobctxt.matrix_method(_asymmetric, subprobctxt,
                                  linsys).solve(C, v, k2)
        if staticEqns:
            linsys.expand_MCa_dofs(k2)

        y = unknowns + (0.5 * dt) * k2
        subprobctxt.installValues(linsys, y, halftime)
        linsys = subprobctxt.make_linear_system(halftime, linsys)
        if staticEqns:
            subprobctxt.computeStaticFields(linsys, y)
        C = linsys.C_MCa()
        # K = linsys.K_MCa()
        # v = linsys.rhs_MCa() - K*y
        v = get_res(linsys, y)
        k3 = linsys.extract_MCa_dofs(y)
        subprobctxt.matrix_method(_asymmetric, subprobctxt,
                                  linsys).solve(C, v, k3)
        if staticEqns:
            linsys.expand_MCa_dofs(k3)

        y = unknowns + dt * k3
        subprobctxt.installValues(linsys, y, endtime)
        linsys = subprobctxt.make_linear_system(endtime, linsys)
        if staticEqns:
            subprobctxt.computeStaticFields(linsys, y)
        C = linsys.C_MCa()
        # K = linsys.K_MCa()
        # v = linsys.rhs_MCa() - K*y
        v = get_res(linsys, y)
        k4 = linsys.extract_MCa_dofs(y)
        subprobctxt.matrix_method(_asymmetric, subprobctxt,
                                  linsys).solve(C, v, k4)
        if staticEqns:
            linsys.expand_MCa_dofs(k4)

        unknowns.axpy(dt / 6., k1)
        unknowns.axpy(dt / 3., k2)
        unknowns.axpy(dt / 3., k3)
        unknowns.axpy(dt / 6., k4)
        if staticEqns:
            subprobctxt.installValues(linsys, unknowns, endtime)
            linsys = subprobctxt.make_linear_system(endtime, linsys)
            subprobctxt.computeStaticFields(linsys, unknowns)

        return timestepper.StepResult(endTime=endtime,
                                      nextStep=dt,
                                      endValues=unknowns,
                                      linsys=linsys)