Beispiel #1
0
def evolve_to(meshctxt,
              subprobctxts,
              time,
              endtime,
              delta,
              prog,
              linsysDict=None):
    ## debug.fmsg("--------------- time=%g endtime=%g delta=%s"
    ##            % (time, endtime, delta))
    # subprobctxts is a list of SubProblemContexts.
    # delta is an initial suggested stepsize.
    # prog is a Progress object.
    assert endtime > time
    mindelta = None
    if linsysDict is None:
        linsysDict = {}
    starttime = time
    startdelta = delta
    truncated_step = False

    try:
        # Main loop.  There is no explicit limit to the number of
        # iterations of this loop.  Instead, the adaptive stepper's
        # nextStepEstimate function raises an ErrTimeStepTooSmall
        # exception if the step size is too small.
        while time < endtime and not prog.stopped():

            # Choose the time step.  If no delta is provide, just to
            # up to endtime.  If delta is provided, go up to the
            # smaller of time+delta and endtime, unless time+delta is
            # within epsilon of endtime, in which case go up to
            # endtime anyway.  This prevents roundoff errors from
            # requiring an extra infinitesimal step to reach endtime.
            #
            # truncated_step indicates whether we're trying to take a
            # step with the full delta or not. If we're not trying,
            # then the suggested time step for the next step may be
            # too small, because the stepper will make a suggestion
            # based on the delta it has (not the delta it wants or the
            # delta it might have at some future time).
            if delta > 0:
                if time + delta > endtime:
                    targettime = endtime
                    truncated_step = True
                else:  # time + delta <= endtime
                    targettime = time + delta
                    if (endtime - targettime <=
                            3 * endtime * utils.machine_epsilon):
                        targettime = endtime
                    truncated_step = False
            else:  # delta == 0
                targettime = endtime
                truncated_step = False

            for subprob in subprobctxts:
                # Build or update the linearized system at the current
                # time, even if the stepper is fully implicit.  The
                # maps have to be constructed, and they depend on the
                # matrices.
                lsys = subprob.make_linear_system(
                    time, linsysDict.get(subprob, None))
                linsysDict[subprob] = lsys
                subprob.startStep(lsys, time)  # sets subprob.startValues
                subprob.cacheConstraints(lsys, time)

            # Iterate over subprobctxts repeatedly until answers are
            # consistent.
            stepno = 0
            prevresults = {}
            newlinsys = {}
            stepTaken = False
            while (stepno < maxconsistencysteps
                   and not (stepTaken or prog.stopped())):
                stepno += 1
                mintime = None  # lowest time attained by any subproblem
                mindelta = None  # smallest recommended delta for any subp.
                for subproblem in subprobctxts:
                    newconstraints = True
                    # Take the step from time to targettime and add in
                    # any new constraints encountered.  Do this
                    # repeatedly until there are no changes in the
                    # constraints.
                    while newconstraints and not prog.stopped():
                        # subproblem.nonlinear_solver is a
                        # nonlinearsolver.NonlinearSolverBase
                        # object, whose job it is to call the
                        # appropriate (linear or nonlinear) method of
                        # the subproblem's "time_stepper" object.

                        # subproblem.time_stepper is a StepDriver
                        # object, containing a TimeStepper object.
                        # The StepDriver's [non]linearstep method
                        # calls the TimeStepper's [non]linearstep
                        # method.

                        # The LinearizedSystem must be cloned because
                        # we may need to repeat the step, and stepper
                        # might re-evaluate the LinearizedSystem at an
                        # intermediate or end time.
                        ## TODO TDEP OPT: The cost of the clone can be
                        ## reduced if the LinearizedSystem *doesn't*
                        ## store K_indfree_, etc, or uses
                        ## SparseSubMats for them.
                        lsClone = linsysDict[subproblem].clone()
                        unknowns = subproblem.get_unknowns(lsClone)
                        # Take a timestep.  The return value is a
                        # timestepper.StepResult object.
                        # debug.fmsg("taking step from %g to %g (%g)" %
                        #            (time, targettime, targettime-time))
                        stepResult = subproblem.nonlinear_solver.step(
                            subproblem,
                            linsys=lsClone,
                            time=time,
                            unknowns=unknowns,
                            endtime=targettime)
                        # debug.fmsg("endValues=", stepResult.endValues)
                        if stepResult.ok:
                            # endStep() sets subproblem.endValues
                            assert stepResult.linsys is not None
                            newlinsys[subproblem] = stepResult.linsys
                            subproblem.endStep(linsysDict[subproblem],
                                               stepResult)
                            newconstraints = subproblem.applyConstraints(
                                subproblem.endValues, stepResult.endTime)
                        else:
                            # Don't bother checking constraints if the
                            # step is going to be repeated anyway.
                            newconstraints = False
                    ## End 'while newconstraints' loop.

                    # Keep track of the minimum time achieved and
                    # minimum recommended next step size for all
                    # subproblems.
                    if mintime is None or mintime > stepResult.endTime:
                        mintime = stepResult.endTime
                    if mindelta is None or (stepResult.nextStep is not None and
                                            mindelta > stepResult.nextStep):
                        mindelta = stepResult.nextStep
                ## End loop over subproblems.

                # Check that all subproblems made it to the target
                # time.  If not, try again with a smaller target time.
                if mintime != targettime:
                    assert mindelta is not None
                    targettime = time + mindelta
                    for subproblem in subprobctxts:
                        subproblem.restoreConstraints()
                    continue  # goto "while stepno < maxconsistencysteps...

                # All subproblems reached the target time.  Did each
                # get the same answer it got last time?
                consistent = True
                if len(subprobctxts) > 1:
                    for subproblem in subprobctxts:
                        prev = prevresults.get(subproblem, None)
                        consistent = (consistent and (prev is not None)
                                      and subproblem.cmpDoF(
                                          prev, subproblem.endValues))
                        prevresults[subproblem] = subproblem.endValues.clone()
                if not consistent:
                    for subproblem in subprobctxts:
                        subproblem.restoreConstraints()
                    continue  # goto "while stepno < maxconsistencysteps...

                # All subproblems are consistent. Go on to the next time.
                time = targettime
                delta = mindelta
                stepTaken = True
                prog.time(time, delta=mindelta)
                for subproblem in subprobctxts:
                    linsysDict[subproblem] = newlinsys[subproblem]
                    del newlinsys[subproblem]
                    subproblem.solverStats.stepTaken(mindelta, truncated_step)
                    # Copy values at targettime into DoFs.  Set
                    # startValues to current endValues.  Set
                    # subproblem.startTime to current time, and unset
                    # subproblem.endTime.
                    subproblem.moveOn()
                    subproblem.finalizeConstraints(time)
                if truncated_step:
                    meshctxt.setCurrentTime(time, None)
                else:
                    meshctxt.setCurrentTime(time, mindelta)

            ## End of consistency loop.

            if not stepTaken and not prog.stopped():
                raise ooferror2.ErrConvergenceFailure(
                    "Self-consistency loop at t=%s" % time,
                    maxconsistencysteps)
            if meshctxt.outputSchedule.isConditional():
                _do_output(meshctxt, time)

        ## End main loop.

        if prog.stopped():
            raise ooferror2.ErrInterrupted()

    except ooferror2.ErrInterrupted:
        debug.fmsg("Interrupted!")
        meshctxt.setStatus(meshstatus.Failed("Solution interrupted."))
        raise
    except ooferror2.ErrInstabilityError, err:
        debug.fmsg("Instability detected: ", err)
        meshctxt.setStatus(
            meshstatus.Failed("Solution diverged? " + err.summary()))
        raise
Beispiel #2
0
def evolve(meshctxt, endtime):
    global linsys_dict
    starttime = meshctxt.getObject().latestTime()

    # We're solving a static problem if endtime is the same as the
    # current time, or if there are no non-static steppers and output
    # is requested at at single time.
    staticProblem = (starttime == endtime
                     or (not meshctxt.timeDependent()
                         and meshctxt.outputSchedule.isSingleTime()))
    # "continuing" is true if we're continuing an earlier time
    # evolution, in which case we can assume that all Fields have
    # their correct initial values. "continuing" is never true for
    # static problems.
    continuing = (not staticProblem
                  and isinstance(meshctxt.status, meshstatus.Solved))

    targettime = endtime

    if starttime > endtime:
        raise ooferror2.ErrSetupError(
            "End time must not precede current time.")

    meshctxt.solver_precompute(solving=True)

    meshctxt.setStatus(meshstatus.Solving())
    meshctxt.timeDiff = endtime - starttime  # used to get next endtime in GUI

    # Make sure that the starting point has been cached.
    ## TODO OPT: Is it necessary to call cacheCurrentData here?
    meshctxt.restoreLatestData()
    meshctxt.cacheCurrentData()
    meshctxt.releaseLatestData()

    meshctxt.outputSchedule.reset(starttime, continuing)
    prog = ProgressData(starttime, endtime,
                        progress.getProgress("Solving", progress.DEFINITE))
    try:
        # Get an ordered list of subproblems to be solved.  First,
        # create tuples containing a subproblem and its solveOrder.
        subprobctxts = [(s.solveOrder, s) for s in meshctxt.subproblems()
                        if s.time_stepper is not None and s.solveFlag]
        subprobctxts.sort()  # sort by solveOrder
        subprobctxts = [s[1] for s in subprobctxts]  # strip solveOrder

        # Initialize statistics.
        for subp in subprobctxts:
            subp.resetStats()

        if not continuing:
            # Initialize static fields in all subproblems.  For static
            # problems, this computes the actual solution.
            try:
                linsys_dict = initializeStaticFields(subprobctxts, starttime,
                                                     prog)
                # Initial output comes *after* solving static fields.
                # For fully static problems, this is the only output.
                _do_output(meshctxt, starttime)
            except ooferror2.ErrInterrupted:
                raise
            except ooferror2.ErrError, exc:
                meshctxt.setStatus(meshstatus.Failed(exc.summary()))
                raise
            except Exception, exc:
                meshctxt.setStatus(meshstatus.Failed( ` exc `))
                raise
Beispiel #3
0
         for subp in subprobctxts
     ])
 try:
     time, delta, linsys_dict = evolve_to(
         meshctxt,
         subprobctxts,
         time=time,
         endtime=t1,
         delta=delta,
         prog=prog,
         linsysDict=linsys_dict)
 except ooferror2.ErrInterrupted:
     # Interruptions shouldn't raise an error dialog
     debug.fmsg("Interrupted!")
     meshctxt.setStatus(
         meshstatus.Failed("Solution interrupted."))
     break
 meshctxt.solverDelta = delta
 if time < t1:
     meshctxt.setStatus(
         meshstatus.Failed(
             "Solver failed to reach the target time."))
     raise ooferror2.ErrSetupError(
         "Failed to reach target time. target=%s, actual=%s" %
         (t1, time))
 if not meshctxt.outputSchedule.isConditional():
     # If there are conditional outputs, _do_output was
     # already called by evolve_to().
     _do_output(meshctxt, t1)
 if t1 == endtime:
     meshctxt.setStatus(meshstatus.Solved())