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)
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)
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()
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
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
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
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()