Python Script Tutorial: Going for a unified script

From KratosWiki
Revision as of 19:10, 2 June 2016 by Rrossi (Talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The final step needed to solve an example is to run the "Main" script.

In the previous section we described how a simple script can be mounted using the Kratos building blocks. In the practice it is convenient to have a "unified" script that looks essentially the same for problems of different sort. This is achieved by making use of the ProjectParameters mechanism in the configuration

The main we currently employ is as follows

from __future__ import print_function, absolute_import, division #makes KratosMultiphysics backward compatible with python 2.6 and 2.7

   #import kratos core and applications
   from KratosMultiphysics import *
   from KratosMultiphysics.SolidMechanicsApplication import *
   from KratosMultiphysics.StructuralMechanicsApplication import *
   from KratosMultiphysics.ExternalSolversApplication import *
   #### PARSING THE PARAMETERS ####
   parameter_file = open("ProjectParameters.json",'r')
   ProjectParameters = Parameters( parameter_file.read())
   #defining the model_part
   main_model_part = ModelPart(ProjectParameters["problem_data"]["model_part_name"].GetString())
   main_model_part.ProcessInfo.SetValue(DOMAIN_SIZE, ProjectParameters["problem_data"]["domain_size"].GetInt())
   ###TODO replace this "model" for real one once available in kratos core
   Model = {ProjectParameters["problem_data"]["model_part_name"].GetString() : main_model_part}
   #construct the solver (main setting methods are located in the solver_module)
   solver_module = __import__(ProjectParameters["solver_settings"]["solver_type"].GetString())
   solver = solver_module.CreateSolver(main_model_part, ProjectParameters["solver_settings"])
   solver.AddVariables() #here we allocate the variables in the nodes
   solver.ImportModelPart() #here we import the data to the model part
   solver.AddDofs()
   #build sub_model_parts or submeshes (rearrange parts for the application of custom processes)
   ##TODO: replace MODEL for the Kratos one ASAP
   ##get the list of the submodel part in the object Model
   for i in range(ProjectParameters["solver_settings"]["processes_sub_model_part_list"].size()):
       part_name = ProjectParameters["solver_settings"]["processes_sub_model_part_list"][i].GetString()
       Model.update({part_name: main_model_part.GetSubModelPart(part_name)})
   #obtain the list of the processes to be applied
   import process_factory
   list_of_processes = process_factory.KratosProcessFactory(Model).ConstructListOfProcesses( ProjectParameters["constraints_process_list"] )
   list_of_processes += process_factory.KratosProcessFactory(Model).ConstructListOfProcesses( ProjectParameters["loads_process_list"] )
   #TODO: decide which is the correct place to initialize the processes 
   for process in list_of_processes:
       process.ExecuteInitialize()
   computing_model_part = solver.GetComputeModelPart()
   # initialize GiD  I/O (gid outputs, file_lists)
   from gid_output_process import GiDOutputProcess 
   gid_output = GiDOutputProcess(computing_model_part,
                                 ProjectParameters["problem_data"]["problem_name"].GetString(),
                                 ProjectParameters["output_configuration"])
   gid_output.ExecuteInitialize()
   solver.Initialize()
   for process in list_of_processes:
       process.ExecuteBeforeSolutionLoop()
       
   gid_output.ExecuteBeforeSolutionLoop()
   delta_time = ProjectParameters["problem_data"]["time_step"].GetDouble()
   step       = 0
   time       = ProjectParameters["problem_data"]["start_time"].GetDouble()
   end_time   = ProjectParameters["problem_data"]["end_time"].GetDouble()
   while(time <= end_time):
       time = time + delta_time
       step = step + 1
       main_model_part.CloneTimeStep(time)
       for process in list_of_processes:
           process.ExecuteInitializeSolutionStep()
       gid_output.ExecuteInitializeSolutionStep()
       #here the solution is actually done
       solver.Solve()
          
       for process in list_of_processes:
           process.ExecuteFinalizeSolutionStep()
       
       gid_output.ExecuteFinalizeSolutionStep()
       for process in list_of_processes:
           process.ExecuteBeforeOutputStep()
       
       # write results 
       if gid_output.IsOutputStep():
           gid_output.PrintOutput()
                         
       for process in list_of_processes:
           process.ExecuteAfterOutputStep()
   for process in list_of_processes:
       process.ExecuteFinalize()
       
   # ending the problem (time integration finished)
   gid_output.ExecuteFinalize()

This constitutes a working script that can be used for example to solve problems in structural mechanics.

The script shown, which we consider as the "modern" way to solve the problem, presents two main differences with respect to a script that can be constructed by simply combining the building blocks: 1 - The "solver" is put in charge of Importing the model part (read it from a file, from a restart file, or generate it from an existing model_part) 2 - The idea of "process" is employed heavily in order to introduce standardized entry points to perform "operations".

The idea of "Processes"

The idea behind the design of the Kratos processes is to standardize the application of "operations" over parts of the model, to be intended as groups of geometrical entitites. In this sense a "Process" shall thus be intended as the implementation of an "operation" (intended in a very broad sense) to be applied on a group of entities within the model (typically defined in kratos as a SubModelPart). The Process provides some standardized calls, to be performed in well defined positions within the simulation loop (think for example "ExecuteBeforeSolutionLoop"). Internally a process could be easily implemented using the python scripting capabilities shown before, the advantage over the direct approach is that a catalogue of Processes can be developed over time, so that one can provide a list of operations to be executed during the simulation. Some of them can be for example implemented in c++ to achieve a higher efficiency.

The list of processes to be performed is described in the "ProjectParameters.json" as a list. The order of execution of the processes will match the order within the construction list.

The Process API is given by the class "Process" defined in c++ by the header "includes/process.h". It is expected that all processes are derived from such base class so that they inherit its public API.

The process API is :

  • ExecuteInitialize()
  • ExecuteBeforeSolutionLoop()
  • ExecuteInitializeSolutionStep()
  • ExecuteFinalizeSolutionStep()
  • ExecuteBeforeOutputStep()
  • ExecuteAfterOutputStep()
  • ExecuteFinalize()

additionally a function

  • Execute()

is defined as a place to implement specific operations

Personal tools
Categories