Example #1
0
    def solve(self, nonLinearIterate=None, **kwargs):
        """ Solve the sle using provided solver.
        """
        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        self._setup_options(**kwargs)
        petsc.OptionsClear() # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)

        #self._heatSLE._cself.solver=self._cself 
        libUnderworld.StgFEM.Energy_SLE_Solver_SetSolver(self._cself, self._heatSLE._cself) # this sets solver on SLE struct.
        # check for non-linearity
        nonLinear = False
        message = "Nonlinearity detected."
        if self._temperatureField in self._heatSLE.fn_diffusivity._underlyingDataItems:
            nonLinear = True
            message += "\nDiffusivity function depends on the temperature field provided to the system."
        if self._temperatureField in self._heatSLE.fn_heating._underlyingDataItems:
            nonLinear = True
            message += "\nHeating function depends on the temperature field provided to the system."

        message += "\nPlease set the 'nonLinearIterate' solve parameter to 'True' or 'False' to continue."
        if nonLinear and (nonLinearIterate==None):
            raise RuntimeError(message)
        
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(self._heatSLE._cself, True )
        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(self._heatSLE._cself, False )

        if self._heatSLE._PICSwarm:
            self._heatSLE._PICSwarm.repopulate()

        libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(self._heatSLE._cself, None)
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(self._heatSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(self._heatSLE._cself, None)

        libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(self._heatSLE._cself, None)
Example #2
0
    def solve(self, nonLinearIterate=None, nonLinearTolerance=1.0e-2, **kwargs):
        """ Solve the sle using provided solver.
        """

        if not isinstance(nonLinearTolerance, float) or nonLinearTolerance < 0.0:
            raise ValueError("'nonLinearTolerance' option must be of type 'float' and greater than 0.0")

        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        self._setup_options(**kwargs)
        petsc.OptionsClear() # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)

        libUnderworld.StgFEM.Energy_SLE_Solver_SetSolver(self._cself, self._heatSLE._cself) # this sets solver on SLE struct.

        # check for non-linearity
        nonLinear = self._check_linearity(nonLinearIterate)

        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_SetNonLinearTolerance(self._heatSLE._cself, nonLinearTolerance)
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(self._heatSLE._cself, True )
        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(self._heatSLE._cself, False )

        if self._heatSLE._swarm:
            self._heatSLE._swarm._voronoi_swarm.repopulate()

        libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(self._heatSLE._cself, None)
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(self._heatSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(self._heatSLE._cself, None)

        libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(self._heatSLE._cself, None)
Example #3
0
    def solve(self,
              nonLinearIterate=None,
              nonLinearTolerance=1.0e-2,
              nonLinearMaxIterations=500,
              callback_post_solve=None,
              **kwargs):
        """ 
        Solve the HeatEq system
        
        Parameters
        ----------
        nonLinearIterate: bool
            True will perform non linear iterations iterations, False (or 0) will not
        
        nonLinearTolerance: float, Default=1.0e-2
            Relative tolerance criterion for the change in the velocity field
            
        nonLinearMaxIterations: int, Default=500
            Maximum number of non linear iteration to perform
            
        callback_post_sovle: func, Default=None
            Optional callback function to be performed at the end of a linear solve iteration.
            Commonly this will be used to perform operations between non linear iterations, for example,
            calibrating the solution or removing the system null space.
        """

        # error check callback_post_solve
        if callback_post_solve is not None:
            if not callable(callback_post_solve):
                raise RuntimeError(
                    "The 'callback_post_solve' parameter is not 'None' and isn't callable"
                )

        # in this c function we handle callback_post_solve=None
        uw.libUnderworld.StgFEM.SystemLinearEquations_SetCallback(
            self._heatSLE._cself, callback_post_solve)

        if not isinstance(nonLinearTolerance,
                          float) or nonLinearTolerance < 0.0:
            raise ValueError(
                "'nonLinearTolerance' option must be of type 'float' and greater than 0.0"
            )

        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        self._setup_options(**kwargs)
        petsc.OptionsClear()  # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)

        libUnderworld.StgFEM.Energy_SLE_Solver_SetSolver(
            self._cself,
            self._heatSLE._cself)  # this sets solver on SLE struct.

        # check for non-linearity
        nonLinear = self._check_linearity(nonLinearIterate)

        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_SetNonLinearTolerance(
                self._heatSLE._cself, nonLinearTolerance)
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._heatSLE._cself, True)
            self._heatSLE._cself.nonLinearMaxIterations = nonLinearMaxIterations
        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._heatSLE._cself, False)

        if self._heatSLE._swarm:
            self._heatSLE._swarm._voronoi_swarm.repopulate()

        libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(
            self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(
            self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(
            self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(
            self._heatSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(
            self._heatSLE._cself, None)
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(
                self._heatSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(
                self._heatSLE._cself, None)

        libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(
            self._heatSLE._cself, None)

        if isinstance(self._heatSLE, (uw.systems.SteadyStateDarcyFlow)):
            self._heatSLE.solve_velocityField()
Example #4
0
    def solve(self, nonLinearIterate=None, nonLinearTolerance=1.0e-2,
              nonLinearKillNonConvergent=False,
              nonLinearMaxIterations=500,
              print_stats=False, reinitialise=True, **kwargs):
        """ solve the Stokes system
        """
        Solvers.SBKSP_SetSolver(self._cself, self._stokesSLE._cself)
        if isinstance(self.options.main.penalty,float) and self.options.main.penalty > 0.0:
            Solvers.SBKSP_SetPenalty(self._cself, self.options.main.penalty)
            if self.options.main.ksp_k2_type == "NULL":
                self.options.main.ksp_k2_type = "GMG"

        if not isinstance(nonLinearTolerance, float) or nonLinearTolerance < 0.0:
            raise ValueError("'nonLinearTolerance' option must be of type 'float' and greater than 0.0")

        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        # self.options.A11._mg_active is True by default but can be changed before here via
        # functions like set_lu

        self._setup_options(**kwargs)
        petsc.OptionsClear() # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)

        # set up MG
        if self.options.mg.active == True:
            self._setup_mg()

        # check for non-linearity
        nonLinear=self._check_linearity(nonLinearIterate)

        if nonLinear and nonLinearIterate:
            # self._stokesSLE._cself.nonLinearTolerance = nonLinearTolerance # set via python
            libUnderworld.StgFEM.SystemLinearEquations_SetNonLinearTolerance(self._stokesSLE._cself, nonLinearTolerance)
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(self._stokesSLE._cself, True, )
            self._stokesSLE._cself.nonLinearMaxIterations = nonLinearMaxIterations
            self._stokesSLE._cself.killNonConvergent = nonLinearKillNonConvergent

        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(self._stokesSLE._cself, False )



        if self._stokesSLE._swarm and reinitialise:
            self._stokesSLE._swarm._voronoi_swarm.repopulate()

        # set up objects on SLE

        if reinitialise:
            libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(self._stokesSLE._cself, None)

            # setup penalty specific objects
            if isinstance(self.options.main.penalty, float) and self.options.main.penalty > 0.0:
                self._create_penalty_objects()
                self._setup_penalty_objects()

        # solve
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(self._stokesSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(self._stokesSLE._cself, None)

        libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(self._stokesSLE._cself, None)

        if print_stats:
            self.print_stats()
            if nonLinear and nonLinearIterate:
                if uw.rank()==0:
                    purple = "\033[0;35m"
                    endcol = "\033[00m"
                    boldpurple = "\033[1;35m"
                    print boldpurple
                    print( "Non linear iterations: %3d of 500 " % (self._stokesSLE._cself.nonLinearIteration_I) )
                    print endcol
                    print

        return
Example #5
0
    def solve(self,
              nonLinearIterate=None,
              nonLinearTolerance=1.0e-2,
              nonLinearKillNonConvergent=False,
              nonLinearMaxIterations=500,
              callback_post_solve=None,
              print_stats=False,
              reinitialise=True,
              fpwarning=True,
              petscwarning=True,
              **kwargs):
        """
        Solve the stokes system

        Parameters
        ----------
        nonLinearIterate: bool
            True will perform non linear iterations iterations, False (or 0) will not

        nonLinearTolerance: float, Default=1.0e-2
            Relative tolerance criterion for the change in the velocity field

        nonLinearMaxIterations: int, Default=500
            Maximum number of non linear iteration to perform

        callback_post_sovle: func, Default=None
            Optional callback function to be performed at the end of a linear solve iteration.
            Commonly this will be used to perform operations between non linear iterations, for example,
            calibrating the pressure solution or removing the system null space.

        print_stats: bool, Default=False
            Print out solver iteration and timing counts per solver

        reinitialise: bool, Default=True,
            Rebuild the system discretisation storage (location matrix/petsc mats & vecs) and repopulate, if available,
            the stokes voronio swarm before the system is solved.
        """

        # clear the floating-point env registers. Should return 0
        rubbish = uw.libUnderworld.Underworld.Underworld_feclearexcept()

        Solvers.SBKSP_SetSolver(self._cself, self._stokesSLE._cself)
        if isinstance(self.options.main.penalty,
                      float) and self.options.main.penalty > 0.0:
            Solvers.SBKSP_SetPenalty(self._cself, self.options.main.penalty)
            if self.options.main.ksp_k2_type == "NULL":
                self.options.main.ksp_k2_type = "GMG"

        # error check callback_post_solve
        if callback_post_solve is not None:
            if not callable(callback_post_solve):
                raise RuntimeError(
                    "The 'callback_post_solve' parameter is not 'None' and isn't callable"
                )

        # in this c function we handle callback_post_solve=None
        uw.libUnderworld.StgFEM.SystemLinearEquations_SetCallback(
            self._stokesSLE._cself, callback_post_solve)

        if not isinstance(nonLinearTolerance,
                          float) or nonLinearTolerance < 0.0:
            raise ValueError(
                "'nonLinearTolerance' option must be of type 'float' and greater than 0.0"
            )

        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        # self.options.A11._mg_active is True by default but can be changed before here via
        # functions like set_lu

        self._setup_options(**kwargs)
        petsc.OptionsClear()  # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)

        # set up MG
        if self.options.mg.active == True:
            self._setup_mg()

        # check for non-linearity
        nonLinear = self._check_linearity(nonLinearIterate)

        if nonLinear and nonLinearIterate:
            # self._stokesSLE._cself.nonLinearTolerance = nonLinearTolerance # set via python
            libUnderworld.StgFEM.SystemLinearEquations_SetNonLinearTolerance(
                self._stokesSLE._cself, nonLinearTolerance)
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._stokesSLE._cself,
                True,
            )
            self._stokesSLE._cself.nonLinearMaxIterations = nonLinearMaxIterations
            self._stokesSLE._cself.killNonConvergent = nonLinearKillNonConvergent

        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._stokesSLE._cself, False)

        if self._stokesSLE._swarm and reinitialise:
            self._stokesSLE._swarm._voronoi_swarm.repopulate()

        # set up objects on SLE
        if reinitialise:
            libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(
                self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(
                self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(
                self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(
                self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(
                self._stokesSLE._cself, None)

            # setup penalty specific objects
            if isinstance(self.options.main.penalty,
                          float) and self.options.main.penalty > 0.0:
                self._create_penalty_objects()
                self._setup_penalty_objects()

        # solve
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(
                self._stokesSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(
                self._stokesSLE._cself, None)

        libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(
            self._stokesSLE._cself, None)

        if print_stats:
            self.print_stats()
            if nonLinear and nonLinearIterate:
                if uw.rank() == 0:
                    purple = "\033[0;35m"
                    endcol = "\033[00m"
                    boldpurple = "\033[1;35m"
                    print boldpurple
                    print("Non linear iterations: %3d of 500 " %
                          (self._stokesSLE._cself.nonLinearIteration_I))
                    print endcol
                    print

        # check the petsc convergence reasons, see StokesBlockKSPInterface.h
        if petscwarning and (self._cself.fhat_reason < 0  or \
            self._cself.outer_reason < 0 or \
            self._cself.backsolve_reason < 0 ):
            import warnings

            estring = "A petsc error has been detected during the solve.\n" + \
            "The resultant solution fields are most likely erroneous, check them thoroughly.\n"+ \
            "This is possibly due to many things, for example solar flares or insufficient boundary conditions.\n"+ \
            "The resultant KSPConvergedReasons are (f_hat, outer, backsolve) ({},{},{}).".format(
                self._cself.fhat_reason,self._cself.outer_reason, self._cself.backsolve_reason)
            if uw.rank() == 0:
                warnings.warn(estring)

        # check if fp error was detected and 'reduce' result to proc 0
        import numpy as np
        lres, gres = np.zeros(1), np.zeros(1)

        lres[:] = uw.libUnderworld.Underworld.Underworld_fetestexcept()
        comm = MPI.COMM_WORLD
        comm.Allreduce(lres, gres, op=MPI.SUM)

        if gres[0] > 0 and fpwarning:
            import warnings
            estring = "A floating-point operation error has been detected during the solve.\n" + \
            "The resultant solution fields are most likely erroneous, check them thoroughly.\n"+ \
            "This is likely due to large number variations in the linear algrebra or fragile solver configurations.\n"+ \
            "Consider rescaling the fn_viscosity or fn_bodyforce inputs to avoid this problem.\n"+ \
            "This warning can be supressed with the argument 'fpwarning=False'."
            if uw.rank() == 0:
                warnings.warn(estring)
        return
Example #6
0
    def solve(self,
              nonLinearIterate=None,
              nonLinearTolerance=1.0e-2,
              nonLinearKillNonConvergent=False,
              nonLinearMinIterations=1,
              nonLinearMaxIterations=500,
              callback_post_solve=None,
              print_stats=False,
              reinitialise=True,
              **kwargs):
        """
        Solve the stokes system

        Parameters
        ----------
        nonLinearIterate: bool
            True will perform non linear iterations iterations, False (or 0) will not

        nonLinearTolerance: float, Default=1.0e-2
            Relative tolerance criterion for the change in the velocity field

        nonLinearMaxIterations: int, Default=500
            Maximum number of non linear iteration to perform

        callback_post_sovle: func, Default=None
            Optional callback function to be performed at the end of a linear solve iteration.
            Commonly this will be used to perform operations between non linear iterations, for example,
            calibrating the pressure solution or removing the system null space.

        print_stats: bool, Default=False
            Print out solver iteration and timing counts per solver

        reinitialise: bool, Default=True,
            Rebuild the system discretisation storage (location matrix/petsc mats & vecs) and repopulate, if available,
            the stokes voronio swarm before the system is solved.
        """

        # clear the floating-point env registers. Should return 0
        rubbish = uw.libUnderworld.Underworld.Underworld_feclearexcept()

        Solvers.SBKSP_SetSolver(self._cself, self._stokesSLE._cself)
        if isinstance(self.options.main.penalty,
                      float) and self.options.main.penalty > 0.0:
            Solvers.SBKSP_SetPenalty(self._cself, self.options.main.penalty)
            if self.options.main.ksp_k2_type == "NULL":
                self.options.main.ksp_k2_type = "GMG"

        # if user provided callback_post_solve then use it, else use stokes system
        if callback_post_solve is not None:
            if not callable(callback_post_solve):
                raise RuntimeError(
                    "The 'callback_post_solve' parameter is not 'None' and isn't callable"
                )
        else:
            callback_post_solve = self._stokesSLE.callback_post_solve

        # in this c function we handle callback_post_solve=None
        uw.libUnderworld.StgFEM.SystemLinearEquations_SetCallback(
            self._stokesSLE._cself, callback_post_solve)

        if not isinstance(nonLinearTolerance,
                          float) or nonLinearTolerance < 0.0:
            raise ValueError(
                "'nonLinearTolerance' option must be of type 'float' and greater than 0.0"
            )

        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        # self.options.A11._mg_active is True by default but can be changed before here via
        # functions like set_lu

        self._setup_options(**kwargs)
        petsc.OptionsClear()  # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)

        # set up MG
        if self.options.mg.active == True:
            self._setup_mg()

        # check for non-linearity
        nonLinear = self._check_linearity(nonLinearIterate)

        if nonLinear and nonLinearIterate:
            # self._stokesSLE._cself.nonLinearTolerance = nonLinearTolerance # set via python
            libUnderworld.StgFEM.SystemLinearEquations_SetNonLinearTolerance(
                self._stokesSLE._cself, nonLinearTolerance)
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._stokesSLE._cself,
                True,
            )
            self._stokesSLE._cself.nonLinearMinIterations = nonLinearMinIterations
            self._stokesSLE._cself.nonLinearMaxIterations = nonLinearMaxIterations
            self._stokesSLE._cself.killNonConvergent = nonLinearKillNonConvergent

        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._stokesSLE._cself, False)

        if self._stokesSLE._swarm and reinitialise:
            self._stokesSLE._swarm._voronoi_swarm.repopulate()

        # set up objects on SLE
        if reinitialise:
            import mpi4py

            wtime = mpi4py.MPI.Wtime()
            libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(
                self._stokesSLE._cself, None)
            if uw.mpi.rank == 0 and print_stats:
                print("Setup - BCs        {:.4} s".format(mpi4py.MPI.Wtime() -
                                                          wtime))

            wtime = mpi4py.MPI.Wtime()
            libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(
                self._stokesSLE._cself, None)
            if uw.mpi.rank == 0 and print_stats:
                print("Setup - Eq numbers {:.4} s".format(mpi4py.MPI.Wtime() -
                                                          wtime))

            wtime = mpi4py.MPI.Wtime()
            libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(
                self._stokesSLE._cself, None)
            if uw.mpi.rank == 0 and print_stats:
                print("Setup - Zero vecs  {:.4} s".format(mpi4py.MPI.Wtime() -
                                                          wtime))

            wtime = mpi4py.MPI.Wtime()
            libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(
                self._stokesSLE._cself, None)
            if uw.mpi.rank == 0 and print_stats:
                print("Setup - Matrices   {:.4} s".format(mpi4py.MPI.Wtime() -
                                                          wtime))

            wtime = mpi4py.MPI.Wtime()
            libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(
                self._stokesSLE._cself, None)
            if uw.mpi.rank == 0 and print_stats:
                print("Setup - Vectors    {:.4} s".format(mpi4py.MPI.Wtime() -
                                                          wtime))

            # setup penalty specific objects
            if isinstance(self.options.main.penalty,
                          float) and self.options.main.penalty > 0.0:
                self._create_penalty_objects()
                self._setup_penalty_objects()

        # solve
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(
                self._stokesSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(
                self._stokesSLE._cself, None)
            libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(
                self._stokesSLE._cself, None)

        if print_stats:
            self.print_stats()
            if nonLinear and nonLinearIterate:
                if uw.mpi.rank == 0:
                    purple = "\033[0;35m"
                    endcol = "\033[00m"
                    boldpurple = "\033[1;35m"
                    print(boldpurple)
                    print("Non linear iterations: %3d of 500 " %
                          (self._stokesSLE._cself.nonLinearIteration_I))
                    print(endcol)
                    print

        # check the petsc convergence reasons, see StokesBlockKSPInterface.h
        if (self._cself.fhat_reason      < 0  or \
            self._cself.outer_reason     < 0  or \
            self._cself.backsolve_reason < 0 ):
            import warnings
            estring = \
                "A PETSc error has been encountered during the solve. " \
                "Solution fields are possibly erroneous. \n\n" \
                "This error is probably due to an incorrectly constructed linear system. " \
                "Please check that your boundary conditions are consistent " \
                "and sufficient and that your viscosity is positive everywhere. " \
                "If you are deforming the mesh, ensure that it has not become " \
                "tangled. \n\n" \
                "The resultant KSPConvergedReasons are (f_hat, outer, backsolve) ({},{},{}).\n\n".format(
                self._cself.fhat_reason,self._cself.outer_reason, self._cself.backsolve_reason)
            if uw.mpi.rank == 0:
                warnings.warn(estring)

        # check if fp error was detected and 'reduce' result to proc 0

        lres, gres = np.zeros(1), np.zeros(1)

        lres[:] = uw.libUnderworld.Underworld.Underworld_fetestexcept()
        comm = MPI.COMM_WORLD
        comm.Allreduce(lres, gres, op=MPI.SUM)

        if gres[0] > 0:
            import warnings
            estring = "A floating-point error has been detected during the solve. " + \
            "Solution fields are possibly erroneous. \n\n"+ \
            "This is likely due to overly large value variations within your linear system, " \
            "or a fragile (or incorrect) solver configuration. " \
            "If your inputs are constructed using real world physical units, you may " \
            "need to rescale them for solver amenability. \n\n"
            if uw.mpi.rank == 0:
                warnings.warn(estring)
        return
Example #7
0
    def solve(self, nonLinearIterate=None, print_stats=False, **kwargs):
        """ solve the Stokes system
        """
        Solvers.SBKSP_SetSolver(self._cself, self._stokesSLE._cself)
        if isinstance(self.options.main.penalty,
                      float) and self.options.main.penalty > 0.0:
            Solvers.SBKSP_SetPenalty(self._cself, self.options.main.penalty)
            if self.options.main.ksp_k2_type == "NULL":
                self.options.main.ksp_k2_type = "GMG"

        # Set up options string from dictionaries.
        # We set up here so that we can set/change terms on the dictionaries before we run solve
        self._setup_options(**kwargs)
        petsc.OptionsClear()  # reset the petsc options
        petsc.OptionsInsertString(self._optionsStr)
        # set up MG
        if self.options.mg.active == True:
            self._setup_mg()
        # check for non-linearity
        nonLinear = self._check_linearity(nonLinearIterate)
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._stokesSLE._cself, True)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_SetToNonLinear(
                self._stokesSLE._cself, False)

        if self._stokesSLE._PICSwarm:
            self._stokesSLE._PICSwarm.repopulate()

        # set up objects on SLE
        libUnderworld.StgFEM.SystemLinearEquations_BC_Setup(
            self._stokesSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_LM_Setup(
            self._stokesSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_ZeroAllVectors(
            self._stokesSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_MatrixSetup(
            self._stokesSLE._cself, None)
        libUnderworld.StgFEM.SystemLinearEquations_VectorSetup(
            self._stokesSLE._cself, None)

        # setup penalty specific objects
        if isinstance(self.options.main.penalty,
                      float) and self.options.main.penalty > 0.0:
            self._create_penalty_objects()
            self._setup_penalty_objects()

        # solve
        if nonLinear and nonLinearIterate:
            libUnderworld.StgFEM.SystemLinearEquations_NonLinearExecute(
                self._stokesSLE._cself, None)
        else:
            libUnderworld.StgFEM.SystemLinearEquations_ExecuteSolver(
                self._stokesSLE._cself, None)

        libUnderworld.StgFEM.SystemLinearEquations_UpdateSolutionOntoNodes(
            self._stokesSLE._cself, None)

        if print_stats:
            self.print_stats()