-
Notifications
You must be signed in to change notification settings - Fork 261
Tutorial: Creating the Python Solver file
miguelmaso edited this page Dec 20, 2017
·
19 revisions
The porpouse of this file is to act as an interface between your problem's script (also in python) file and the Kratos functions. We will create a class and functions already customized for our type of problem, so that the calls required in the .py from the problem become simpler. We must also create a strategy file (.py too) that will include the 'recipe' to solve the problem but we will only focus on the first one. Both files must be in the folder /python_scripts.
#importing the Kratos Library
from KratosMultiphysics import *
from KratosMultiphysics.PureDiffusionApplication import *
def AddVariables(model_part): #this way er only need one command to add all the variables to our problem
model_part.AddNodalSolutionStepVariable(TEMPERATURE);
model_part.AddNodalSolutionStepVariable(POINT_HEAT_SOURCE);
def AddDofs(model_part):
for node in model_part.Nodes:
#adding dofs
node.AddDof(TEMPERATURE);
print ("variables for the Poisson solver added correctly")
class StaticPoissonSolver:
#######################################################################
def __init__(self,model_part,domain_size): #constructor of the class
self.model_part = model_part
self.time_scheme = ResidualBasedIncrementalUpdateStaticScheme()
#definition of the solvers
self.poisson_linear_solver = SkylineLUFactorizationSolver() #we set the type of solver that we want
#definition of the convergence criteria
self.conv_criteria = DisplacementCriteria(1e-6,1e-9) #tolerance for the solver
#######################################################################
def Initialize(self):
#creating the solution strategy
CalculateReactionFlag = False
ReformDofSetAtEachStep = False
MoveMeshFlag = False
import strategy_python
self.solver = strategy_python.SolvingStrategyPython(self.model_part,self.time_scheme,self.poisson_linear_solver,self.conv_criteria,CalculateReactionFlag,ReformDofSetAtEachStep,MoveMeshFlag)
#######################################################################
def Solve(self):
(self.solver).Solve()
#######################################################################
def SetEchoLevel(self,level):
(self.solver).SetEchoLevel(level)
#importing the Kratos Library
from KratosMultiphysics import *
class SolvingStrategyPython:
#######################################################################
def __init__(self,model_part,time_scheme,linear_solver,convergence_criteria,CalculateReactionsFlag,ReformDofSetAtEachStep,MoveMeshFlag):
#save the input parameters
self.model_part = model_part
self.scheme = time_scheme
self.linear_solver = linear_solver
self.convergence_criteria = convergence_criteria
self.CalculateReactionsFlag = CalculateReactionsFlag
self.ReformDofSetAtEachStep = ReformDofSetAtEachStep
self.MoveMeshFlag = MoveMeshFlag
self.space_utils = UblasSparseSpace()
#default values for some variables
self.max_iter = 30
self.rebuild_level = 1 #rebuild at each solution step
self.echo_level = 1
self.builder_and_solver = ResidualBasedEliminationBuilderAndSolver(self.linear_solver)
#local matrices and vectors
self.pA = self.space_utils.CreateEmptyMatrixPointer()
self.pDx = self.space_utils.CreateEmptyVectorPointer()
self.pb = self.space_utils.CreateEmptyVectorPointer()
self.A = (self.pA).GetReference()
self.Dx = (self.pDx).GetReference()
self.b = (self.pb).GetReference()
#initialize flags
self.SolutionStepIsInitialized = False
self.InitializeWasPerformed = False
self.StiffnessMatrixIsBuilt = False
#provide settings to the builder and solver
(self.builder_and_solver).SetCalculateReactionsFlag(self.CalculateReactionsFlag);
(self.builder_and_solver).SetReshapeMatrixFlag(self.ReformDofSetAtEachStep);
#######################################################################
def Initialize(self):
if(self.scheme.SchemeIsInitialized() == False):
self.scheme.Initialize(self.model_part)
if (self.scheme.ElementsAreInitialized() == False):
self.scheme.InitializeElements(self.model_part)
#######################################################################
#######################################################################
def Solve(self):
#perform the operations to be performed ONCE and ensure they will not be repeated
# elemental function "Initialize" is called here
if(self.InitializeWasPerformed == False):
self.Initialize()
self.InitializeWasPerformed = True
#perform initializations for the current step
#this operation implies:
#identifying the set of DOFs that will be solved during this step
#organizing the DOFs so to identify the dirichlet conditions
#resizing the matrix preallocating the "structure"
if (self.SolutionStepIsInitialized == False):
if(self.builder_and_solver.GetDofSetIsInitializedFlag() == False or self.ReformDofSetAtEachStep == True):
reform_dofs = True
else:
reform_dofs = False
self.InitializeSolutionStep(reform_dofs);
self.SolutionStepIsInitialized = True;
#perform prediction
self.Predict()
#execute iteration - first iteration is ALWAYS executed
calculate_norm = False
normDx = self.ExecuteIteration(self.echo_level,self.MoveMeshFlag,calculate_norm)
it = 1
print ("fist iteration is done")
#non linear loop
converged = False
while(it < self.max_iter and converged == False):
#verify convergence
converged = self.convergence_criteria.PreCriteria(self.model_part,self.builder_and_solver.GetDofSet(),self.A,self.Dx,self.b)
#calculate iteration
# - system is built and solved
# - database is updated depending on the solution
# - nodal coordinates are updated if required
normDx = self.ExecuteIteration(self.echo_level,self.MoveMeshFlag,calculate_norm)
#verify convergence
converged = self.convergence_criteria.PostCriteria(self.model_part,self.builder_and_solver.GetDofSet(),self.A,self.Dx,self.b)
#update iteration count
it = it + 1
#finalize the solution step
self.FinalizeSolutionStep(self.CalculateReactionsFlag)
self.SolutionStepIsInitialized = False
#clear if needed - deallocates memory
if(self.ReformDofSetAtEachStep == True):
self.Clear();
#######################################################################
#######################################################################
#######################################################################
def Predict(self):
self.scheme.Predict(self.model_part,self.builder_and_solver.GetDofSet(),self.A,self.Dx,self.b);
#######################################################################
def InitializeSolutionStep(self,reform_dofs):
if(self.builder_and_solver.GetDofSetIsInitializedFlag() == False or self.ReformDofSetAtEachStep == True):
#initialize the list of degrees of freedom to be used
self.builder_and_solver.SetUpDofSet(self.scheme,self.model_part);
#reorder the list of degrees of freedom to identify fixity and system size
self.builder_and_solver.SetUpSystem(self.model_part)
#allocate memory for the system and preallocate the structure of the matrix
self.builder_and_solver.ResizeAndInitializeVectors(self.pA,self.pDx,self.pb,self.model_part.Elements,self.model_part.Conditions,self.model_part.ProcessInfo);
#updating references
self.A = (self.pA).GetReference()
self.Dx = (self.pDx).GetReference()
self.b = (self.pb).GetReference()
self.builder_and_solver.InitializeSolutionStep(self.model_part,self.A,self.Dx,self.b)
self.scheme.InitializeSolutionStep(self.model_part,self.A,self.Dx,self.b)
#######################################################################
def ExecuteIteration(self,echo_level,MoveMeshFlag,CalculateNormDxFlag):
#reset system matrices and vectors prior to rebuild
self.space_utils.SetToZeroMatrix(self.A)
self.space_utils.SetToZeroVector(self.Dx)
self.space_utils.SetToZeroVector(self.b)
self.scheme.InitializeNonLinIteration(self.model_part,self.A,self.Dx,self.b)
#build and solve the problem
self.builder_and_solver.BuildAndSolve(self.scheme,self.model_part,self.A,self.Dx,self.b)
#full output if needed
if(echo_level == 3):
print ("SystemMatrix = ", self.A )
print ("solution obtained = ", self.Dx )
print ("RHS = ", self.b )
elif(echo_level == 4):
filename = str("A_t_") + str(self.model_part.ProcessInfo[TIME]) + str(".mm");
WriteMatrixMarket(filename, self.A, False);
## bname = str("b_t_") + str(self.model_part.ProcessInfo[TIME]) + str(".mm");
## print ("solution obtained = ", self.Dx )
## print ("RHS = ", self.b )
#perform update
self.scheme.Update(self.model_part,self.builder_and_solver.GetDofSet(),self.A,self.Dx,self.b);
#move the mesh as needed
if(MoveMeshFlag == True):
self.scheme.MoveMesh(self.model_part.Nodes);
self.scheme.FinalizeNonLinIteration(self.model_part,self.A,self.Dx,self.b)
#calculate the norm of the "correction" Dx
if(CalculateNormDxFlag == True):
normDx = self.space_utils.TwoNorm(self.Dx)
else:
normDx = 0.0
return normDx
#######################################################################
def FinalizeSolutionStep(self,CalculateReactionsFlag):
if(CalculateReactionsFlag == True):
self.builder_and_solver.CalculateReactions(self.scheme,self.model_part,self.A,self.Dx,self.b)
#Finalisation of the solution step,
self.scheme.FinalizeSolutionStep(self.model_part,self.A,self.Dx,self.b)
self.builder_and_solver.FinalizeSolutionStep(self.model_part,self.A,self.Dx,self.b)
self.scheme.Clean()
#reset flags for the next step
self.mSolutionStepIsInitialized = False
#######################################################################
def Clear(self):
self.space_utils.ClearMatrix(self.pA)
self.space_utils.ResizeMatrix(self.A,0,0)
self.space_utils.ClearVector(self.pDx)
self.space_utils.ResizeVector(self.Dx,0)
self.space_utils.ClearVector(self.pb)
self.space_utils.ResizeVector(self.b,0)
#updating references
self.A = (self.pA).GetReference()
self.Dx = (self.pDx).GetReference()
self.b = (self.pb).GetReference()
self.builder_and_solver.SetDofSetIsInitializedFlag(False)
self.builder_and_solver.Clear()
#######################################################################
def SetEchoLevel(self,level):
self.echo_level = level
self.builder_and_solver.SetEchoLevel(level)
- Getting Kratos (Last compiled Release)
- Compiling Kratos
- Running an example from GiD
- Kratos input files and I/O
- Data management
- Solving strategies
- Manipulating solution values
- Multiphysics
- Video tutorials
- Style Guide
- Authorship of Kratos files
- Configure .gitignore
- How to configure clang-format
- How to use smart pointer in Kratos
- How to define adjoint elements and response functions
- Visibility and Exposure
- Namespaces and Static Classes
Kratos structure
Conventions
Solvers
Debugging, profiling and testing
- Compiling Kratos in debug mode
- Debugging Kratos using GDB
- Cross-debugging Kratos under Windows
- Debugging Kratos C++ under Windows
- Checking memory usage with Valgind
- Profiling Kratos with MAQAO
- Creating unitary tests
- Using ThreadSanitizer to detect OMP data race bugs
- Debugging Memory with ASAN
HOW TOs
- How to create applications
- Python Tutorials
- Kratos For Dummies (I)
- List of classes and variables accessible via python
- How to use Logger
- How to Create a New Application using cmake
- How to write a JSON configuration file
- How to Access DataBase
- How to use quaternions in Kratos
- How to do Mapping between nonmatching meshes
- How to use Clang-Tidy to automatically correct code
- How to use the Constitutive Law class
- How to use Serialization
- How to use GlobalPointerCommunicator
- How to use PointerMapCommunicator
- How to use the Geometry
- How to use processes for BCs
- How to use Parallel Utilities in futureproofing the code
- Porting to Pybind11 (LEGACY CODE)
- Porting to AMatrix
- How to use Cotire
- Applications: Python-modules
- How to run multiple cases using PyCOMPSs
- How to apply a function to a list of variables
- How to use Kratos Native sparse linear algebra
Utilities
Kratos API
Kratos Structural Mechanics API