def SerializeModelParameters(self): with open(self.project_parameters_path,'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # save problem name self.problem_name = parameters["problem_data"]["problem_name"].GetString() # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType("use_input_model_part") serialized_project_parameters = KratosMultiphysics.StreamSerializer() serialized_project_parameters.Save("ParametersSerialization",parameters) self.serialized_project_parameters = serialized_project_parameters # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = generator.GenerateSample(self.problem_name) # only used to serialize simulation = self.analysis(model,parameters,fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart(main_model_part_name).ProcessInfo.SetValue(KratosMultiphysics.IS_RESTARTED,True) # serialize model serialized_model = KratosMultiphysics.StreamSerializer() serialized_model.Save("ModelSerialization",simulation.model) self.serialized_model = serialized_model # pickle model and parameters pickled_model = pickle.dumps(serialized_model, 2) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps(serialized_project_parameters, 2) self.pickled_model = pickled_model self.pickled_project_parameters = pickled_project_parameters self.is_project_parameters_pickled = True self.is_model_pickled = True print("\n","#"*50," SERIALIZATION COMPLETED ","#"*50,"\n")
def SerializeModelParametersReadingFromFile(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is reading_from_file. Inputs: """ current_index = 0 for parameters_path in self.project_parameters_path: with open(parameters_path, "r") as parameter_file: parameters = KratosMultiphysics.Parameters( parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize and pickle parmeters to serialize the model in MPI # it is not required to remove the materials, since the Kratos variable # IS_RESTARTED is set to True self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) # append to attributes self.serialized_project_parameters.append( serialized_project_parameters) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) self.pickled_project_parameters.append(pickled_project_parameters) # reset to read the model part self.wrapper.SetModelImportSettingsInputType("mdpa") # pickle and eventually serialize model if self.is_mpi: if not parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("XMC is set in MPI but Kratos is not!")) # self.serialized_model cannot be retrieved in MPI so only pickled model is returned # returns: [[model1_1,model_1_2, model_1_3, model_1_4], [model2_1,model_2_2, model_2_3, model_2_4]] pickled_model = mpi_mds.SerializeMPIModel_Wrapper( \ pickled_project_parameters, self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis, current_index) pickled_mapping_reference_model = mpi_mds.SerializeMPIModel_Wrapper( \ self.pickled_project_parameters[0], self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis, current_index) current_index += 1 else: if parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("Kratos is set in MPI but XMC is not!")) pickled_model = self.SerializeSerialModel(parameters) # append to attribute self.pickled_model.append(pickled_model) if self.is_mpi: self.pickled_mapping_reference_model.append( pickled_mapping_reference_model) else: self.pickled_mapping_reference_model.append( self.pickled_model[0])
def __init__(self,current_level,model_coarse,parameters_coarse,metric_param,remesh_param,metric_name="hessian"): self.model_coarse = model_coarse self.parameters_coarse = parameters_coarse self.metric_param = metric_param self.remesh_param = remesh_param self.problem_type = self.parameters_coarse["solver_settings"]["solver_type"].GetString() self.metric = metric_name self.current_level = current_level self.wrapper = ParametersWrapper(self.parameters_coarse)
def SerializeModelParametersReadingFromFile(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is reading_from_file. Inputs: - self: an instance of the class. """ for parameters_path in self.project_parameters_path: with open(parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters( parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters.append( serialized_project_parameters) # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = self.fake_sample_to_serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.MpiSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model.append(serialized_model) # pickle dataserialized_data pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2) self.pickled_model.append(pickled_model) self.pickled_project_parameters.append(pickled_project_parameters)
def SerializeModelParametersReadingFromFile(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is reading_from_file. Inputs: - self: an instance of the class. """ for parameters_path in self.project_parameters_path: with open(parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters( parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters.append( serialized_project_parameters) # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) if self.is_mpi: if not parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("XMC is set in MPI but Kratos is not!")) # self.serialized_model cannot be retrieved in MPI so only pickled model is returned # returns: [[model1_1,model_1_2, model_1_3, model_1_4], [model2_1,model_2_2, model_2_3, model_2_4]] pickled_model = mpi_mds.SerializeMPIModel( \ pickled_project_parameters, self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis) else: if parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("Kratos is set in MPI but XMC is not!")) pickled_model = self.SerializeSerialModel(parameters) self.pickled_model.append(pickled_model) self.pickled_project_parameters.append(pickled_project_parameters)
def SerializeModelParametersStochasticAdaptiveRefinement(self): with open(self.project_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.StreamSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters.append( serialized_project_parameters) # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = self.fake_sample_to_serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.StreamSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model.append(serialized_model) # pickle dataserialized_data pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2) self.pickled_model.append(pickled_model) self.pickled_project_parameters.append(pickled_project_parameters)
class MonteCarlo(object): """The base class for the MonteCarlo-classes""" def __init__(self, custom_parameters_path, project_parameters_path, custom_analysis): """ constructor of the MonteCarlo-Object Keyword arguments: self : an instance of the class custom_parameters_path : path of the Monte Carlo simulation project_parameters_path : path of the project parameters file custom_analysis : analysis stage of the problem """ # analysis: analysis stage of the current problem if (custom_analysis is not None): self.SetAnalysis(custom_analysis) else: raise Exception( "Please provide a Kratos specific application analysis stage for the current problem" ) # project_parameters_path: path to the project parameters json file if (project_parameters_path is not None): self.project_parameters_path = project_parameters_path else: raise Exception( "Please provide the path of the project parameters json file") # default settings of the Monte Carlo algorithm # run_monte_carlo : boolean setting if run or not the algorithm # tolerance : relative tolerance # tolerance_absolute : safety tolerance (absolute). Useful if expected value (qoi) is zero # confidence : confidence on tolerance # batch_size : number of samples per batch size # initial_number_batches : the starting number of batches # maximum_number_iterations : maximum number of iterations to run # convergence_criteria : convergence criteria to compute convergence default_settings = KratosMultiphysics.Parameters(""" { "run_monte_carlo" : true, "tolerance" : 1e-1, "tolerance_absolute" : 1e-6, "confidence" : 9e-1, "batch_size" : 25, "initial_number_batches" : 1, "maximum_number_iterations": 10, "convergence_criteria" : "MC_sample_variance_sequential_stopping_rule" } """) # set XMC parameters self.custom_parameters_path = custom_parameters_path self.SetXMCParameters() # validate and assign default parameters self.settings.ValidateAndAssignDefaults(default_settings) # convergence: boolean variable defining if MC algorithm has converged self.convergence = False # handle confidence = 1.0 if (self.settings["confidence"].GetDouble() == 1.0): self.settings["confidence"].SetDouble( 0.999 ) # reduce confidence to not get +inf for cphi_confidence (coefficient used in convergence criterias) # set error probability = 1.0 - confidence on given tolerance self.settings.AddEmptyValue("error_probability") self.settings["error_probability"].SetDouble( 1.0 - self.settings["confidence"].GetDouble()) # current_number_levels: number of levels of MC by default = 0 (we only have level 0) self.current_number_levels = 0 # current_level: current level of work, current_level = 0 for MC self.current_level = 0 # theta_i: splitting parameter \in (0,1), this affects bias and statistical error in the computation of the total error self.theta_i = None # TErr: total error of MC algorithm, the sum of bias and statistical error is an overestmation of the real total error # TErr := \abs(E^MC[QoI] - E[QoI])""" self.TErr = None # QoI: Quantity of Interest of the considered problem self.QoI = StatisticalVariable() # initialize all the variables of the StatisticalVariable class: MC has only one level, i.e. level 0 self.QoI.InitializeLists( self.current_number_levels + 1, self.settings["initial_number_batches"].GetInt()) # batches_number_samples: total number of samples, organized in level and batches # batches_number_samples = [ [ [level0_batch1] [level1_batch1] .. ] [ [level0_batch2] [level1_batch2] ..] .. ] # for MC: batches_number_samples = [ [ level0_batch1 ] [ level0_batch2 ] [ level0_batch3 ] .. ] self.batches_number_samples = [] # number_samples: total number of samples used for the computation of global power sums # number_samples = [total_level0 total_level1 ..] self.number_samples = [] # running_number_samples: total number of samples running self.running_number_samples = [] # batches_launched: boolean true or false if batch launched or not self.batches_launched = [] # batches_execution_finished: boolean true or false if batch finished or not self.batches_execution_finished = [] # batches_analysis_finished: boolean true or false if statistical analysis of batch is finished or not self.batches_analysis_finished = [] # batches_convergence_finished: boolean true or false if convergence computation of batch is finished or not self.batches_convergence_finished = [] # batch_size: number of iterations of each epoch self.batch_size = [] # current_convergence_batch: current batch for which convergence is computed self.current_convergence_batch = None # iteration counter self.iteration_counter = 0 # set convergence criteria self.SetConvergenceCriteria() # pickled_model: serialization of model Kratos object of the problem self.pickled_model = None # pickled_project_parameters: serialization of project parameters Kratos object of the problem self.pickled_project_parameters = None # construct the pickled model and pickled project parameters of the problem self.is_project_parameters_pickled = False self.is_model_pickled = False """ function executing the Monte Carlo algorithm input: self : an instance of the class """ def Run(self): if (self.settings["run_monte_carlo"].GetBool()): self.SerializeModelParameters() self.InitializeMCPhase() self.ScreeningInfoInitializeMCPhase() self.LaunchEpoch() self.FinalizeMCPhase() self.ScreeningInfoFinalizeMCPhase() while (self.convergence is not True): self.InitializeMCPhase() self.ScreeningInfoInitializeMCPhase() self.LaunchEpoch() self.FinalizeMCPhase() self.ScreeningInfoFinalizeMCPhase() #self.convergence = True else: print("\n", "#" * 50, "Not running Monte Carlo algorithm", "#" * 50) pass """ function running one Monte Carlo epoch input: self : an instance of the class """ def LaunchEpoch(self): for batch in range(len(self.batches_number_samples)): if (self.batches_launched[batch] is not True): self.batches_launched[batch] = True batch_results = [] for level in range(self.current_number_levels + 1): for instance in range( self.batches_number_samples[batch][level]): self.running_number_samples[ level] = self.running_number_samples[level] + 1 batch_results.append(self.ExecuteInstance()) self.running_number_samples[ level] = self.running_number_samples[level] - 1 self.AddResults(batch_results, batch) self.batches_execution_finished[batch] = True """ function executing an instance of the Monte Carlo algorithm requires: self.pickled_model : pickled model self.pickled_project_parameters : pickled parameters self.current_analysis_stage : analysis stage of the problem input: self: an instance of the class output: MonteCarloResults class : an instance og the MonteCarloResults class current_level : level of the current MC simulation (= 0) """ def ExecuteInstance(self): # ensure working level is level 0 current_level = self.current_level sample = generator.GenerateSample(self.problem_name) if (current_level != 0): raise Exception( "current work level must be = 0 in the Monte Carlo algorithm") return (ExecuteInstanceAux_Task(self.pickled_model, self.pickled_project_parameters, sample, self.GetAnalysis(), self.current_level), current_level) # return (ExecuteInstanceAux_Task(self.serialized_model,self.serialized_project_parameters,sample,self.GetAnalysis(),self.current_level),current_level) """ function initializing the MC phase input: self : an instance of the class """ def InitializeMCPhase(self): current_level = self.current_level if (current_level != 0): raise Exception( "current work level must be = 0 in the Monte Carlo algorithm") # update iteration counter self.iteration_counter = self.iteration_counter + 1 # update number of samples (MonteCarlo.batches_number_samples) and batch size if (self.iteration_counter == 1): self.batch_size = [ self.settings["batch_size"].GetInt() for _ in range(self.current_number_levels + 1) ] self.batches_number_samples = [[ self.settings["batch_size"].GetInt() for _ in range(self.current_number_levels + 1) ] for _ in range(self.settings["initial_number_batches"].GetInt())] self.number_samples = [ 0 for _ in range(self.current_number_levels + 1) ] self.running_number_samples = [ 0 for _ in range(self.current_number_levels + 1) ] self.batches_launched = [ False for _ in range( self.settings["initial_number_batches"].GetInt()) ] self.batches_execution_finished = [ False for _ in range( self.settings["initial_number_batches"].GetInt()) ] self.batches_analysis_finished = [ False for _ in range( self.settings["initial_number_batches"].GetInt()) ] self.batches_convergence_finished = [ False for _ in range( self.settings["initial_number_batches"].GetInt()) ] elif (self.iteration_counter > 1): # add new batches in case convergence = False if (self.convergence is not True): # estimate batches to append and batch size self.UpdateBatches() for batch in range(len(self.batches_launched)): if (self.batches_launched[batch] is False): self.batches_number_samples.append(self.batch_size) # append execution, analysis and convergence False booleans self.batches_execution_finished.append(False) self.batches_analysis_finished.append(False) self.batches_convergence_finished.append(False) # append new batch lists to self.QoI.values and self.QoI.power_sum_batches_* self.QoI.values.append( [[] for _ in range(self.current_number_levels + 1)]) self.QoI.power_sum_batches_1.append( [[] for _ in range(self.current_number_levels + 1)]) self.QoI.power_sum_batches_2.append( [[] for _ in range(self.current_number_levels + 1)]) self.QoI.power_sum_batches_3.append( [[] for _ in range(self.current_number_levels + 1)]) self.QoI.power_sum_batches_4.append( [[] for _ in range(self.current_number_levels + 1)]) self.QoI.batches_number_samples.append( [0 for _ in range(self.current_number_levels + 1)]) else: pass """ function updating number of batches and batch size input: self : an instance of the class """ def UpdateBatches(self): # set here number of batches to append if (len(self.batches_number_samples) >= self.settings["maximum_number_iterations"].GetInt()): new_number_batches = 0 else: new_number_batches = 1 # update batch size self.UpdateBatchSize() for _ in range(new_number_batches): self.batches_launched.append(False) """ function updating batch size input: self : an instance of the class TODO: for now batch_size = batch_size, in future flags can be added to have different behaviours """ def UpdateBatchSize(self): self.batch_size = copy.copy(self.batch_size) """ function finalizing the MC phase input: self : an instance of the class """ def FinalizeMCPhase(self): current_level = self.current_level if (current_level != 0): raise Exception( "current work level must be = 0 in the Monte Carlo algorithm") # update power sums batches for batch in range(len( self.batches_number_samples)): # i.e. total number of batches if (self.batches_execution_finished[batch] is True and self.batches_analysis_finished[batch] is not True ): # consider batches completed and not already analysed self.QoI.UpdateBatchesPassPowerSum(current_level, batch) self.batches_analysis_finished[batch] = True continue_iterating = True for batch in range(len(self.batches_number_samples)): if (self.batches_execution_finished[batch] is True and self.batches_analysis_finished[batch] is True and self.batches_convergence_finished[batch] is not True and continue_iterating ): # consider batches completed, analysed and # for which convergence has not been computed continue_iterating = False # update working convergence batch self.current_convergence_batch = batch # update global power sums from batches power sums self.QoI.UpdateGlobalPowerSums(current_level, batch) # update number of samples used to compute global power sums for level in range(self.current_level + 1): self.number_samples[level] = self.number_samples[ level] + self.batches_number_samples[batch][level] # compute the central moments we can't derive from the unbiased h statistics # compute from scratch the absolute central moment because we can't retrieve it from the power sums if (self.convergence_criteria == "MC_higher_moments_sequential_stopping_rule"): self.QoI.central_moment_from_scratch_3_absolute_to_compute = True self.QoI.ComputeSampleCentralMomentsFromScratch( current_level, self.number_samples[current_level] ) # not possible to use self.StatisticalVariable.number_samples[current_level] # inside the function because it is a pycompss.runtime.binding.Future object self.QoI.ComputeHStatistics(current_level) # self.QoI.ComputeSkewnessKurtosis(current_level) self.CheckConvergence(current_level) self.batches_convergence_finished[batch] = True # synchronization point needed to launch new tasks if convergence is false # put the synchronization point as in the end as possible self.convergence = get_value_from_remote(self.convergence) # bring to master what is needed to print self.QoI.h_statistics_1 = get_value_from_remote( self.QoI.h_statistics_1) self.QoI.h_statistics_2 = get_value_from_remote( self.QoI.h_statistics_2) break # break the for loop after the convergence of the first available batch is computed if (self.iteration_counter >= self.settings["maximum_number_iterations"].GetInt()): self.convergence = True """ function adding QoI values to the corresponding level input: self : an instance of the class simulation_results : tuple=(instance of MonteCarloResults class, working level) batch_number : number of working batch mini_batch_size : compute add result grouping results with this size """ def AddResults(self, simulation_results, batch_number, mini_batch_size=50): current_level = simulation_results[0][ 1] # not compss future object, it is working level if (current_level != 0): raise Exception( "current work level must be = 0 in the Monte Carlo algorithm") simulation_results = list(map(lambda x: x[0], simulation_results)) number_samples_batches_level = 0 while (len(simulation_results) >= 1): new_simulations = simulation_results[mini_batch_size:] current_simulations = simulation_results[:mini_batch_size] number_samples_batches_level += len(current_simulations) self.QoI.values[batch_number][current_level].append( AddResultsAux_Task(current_level, *current_simulations)) simulation_results = new_simulations self.QoI.batches_number_samples[batch_number][ current_level] = number_samples_batches_level """ function serializing and pickling the model and the project parameters of the problem the serialization-pickling process is the following: i) from Model/Parameters Kratos object to StreamSerializer Kratos object ii) from StreamSerializer Kratos object to pickle string iii) from pickle string to StreamSerializer Kratos object iv) from StreamSerializer Kratos object to Model/Parameters Kratos object requires: self.project_parameters_path: path of the Project Parameters file builds: self.pickled_model : pickled model self.pickled_project_parameters : pickled project parameters input: self : an instance of the class """ def SerializeModelParameters(self): with open(self.project_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # save problem name self.problem_name = parameters["problem_data"][ "problem_name"].GetString() # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.StreamSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters = serialized_project_parameters # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = generator.GenerateSample( self.problem_name) # only used to serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.StreamSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model = serialized_model # pickle model and parameters pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2) self.pickled_model = pickled_model self.pickled_project_parameters = pickled_project_parameters self.is_project_parameters_pickled = True self.is_model_pickled = True print("\n", "#" * 50, " SERIALIZATION COMPLETED ", "#" * 50, "\n") """ function reading the xmc parameters passed from json file input: self : an instance of the class """ def SetXMCParameters(self): with open(self.custom_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) self.settings = parameters["monte_carlo"] """ function defining the Kratos specific application analysis stage of the problem input: self : an instance of the class application_analysis_stage : working analysis stage Kratos class """ def SetAnalysis(self, application_analysis_stage): self.analysis = application_analysis_stage """ function returning the Kratos specific application analysis stage of the problem previously defined input: self : an instance of the class output: self.analysis : working analysis stage Kratos class """ def GetAnalysis(self): if (self.analysis is not None): return self.analysis else: print( "Provide a Kratos specific application analysis stage for the current problem." ) """ function checking the convergence of the MC algorithm, with respect to the selected convergence criteria input: self : an instance of the class level : working level """ def CheckConvergence(self, level): current_number_samples = self.QoI.number_samples[level] current_mean = self.QoI.h_statistics_1[level] current_h2 = self.QoI.h_statistics_2[level] current_h3 = self.QoI.h_statistics_3[level] current_sample_central_moment_3_absolute = self.QoI.central_moment_from_scratch_3_absolute[ level] current_h4 = self.QoI.h_statistics_4[level] current_tol = self.settings["tolerance"].GetDouble() current_tol_absolute = self.settings["tolerance_absolute"].GetDouble() current_error_probability = self.settings["error_probability"].GetDouble( ) # the "delta" in [3] in the convergence criteria is the error probability convergence_criteria = self.convergence_criteria convergence_boolean = CheckConvergenceAux_Task(current_number_samples,current_mean,current_h2,\ current_h3,current_sample_central_moment_3_absolute,current_h4,current_tol,current_tol_absolute,current_error_probability,convergence_criteria) self.convergence = convergence_boolean """ function printing informations about initializing MLMC phase input: self : an instance of the class """ def ScreeningInfoInitializeMCPhase(self): print("\n", "#" * 50, " MC iter = ", self.iteration_counter, "#" * 50, "\n") """ function printing informations about finalizing MC phase input: self : an instance of the class """ def ScreeningInfoFinalizeMCPhase(self): print("current convergence batch =", self.current_convergence_batch) # print("values computed of QoI = ",self.QoI.values) print("current batches", self.batches_number_samples) print("check number samples of batch statistical variable class", self.QoI.batches_number_samples) print("current number of samples = ", self.number_samples) print("monte carlo mean and variance QoI estimators = ", self.QoI.h_statistics_1, self.QoI.h_statistics_2) print("convergence = ", self.convergence) """ function setting the convergence criteria the algorithm will exploit input: self : an instance of the class """ def SetConvergenceCriteria(self): convergence_criteria = self.settings["convergence_criteria"].GetString( ) if (convergence_criteria != "MC_sample_variance_sequential_stopping_rule" and convergence_criteria != "MC_higher_moments_sequential_stopping_rule" and convergence_criteria != "total_error_stopping_rule" and convergence_criteria != "relative_total_error_stopping_rule"): raise Exception( "The selected convergence criteria is not yet implemented, plese select one of the following: \n i) MC_sample_variance_sequential_stopping_rule \n ii) MC_higher_moments_sequential_stopping_rule" ) self.convergence_criteria = convergence_criteria
class KratosSolverWrapper(sw.SolverWrapper): """ Solver wrapper class managing Kratos Multiphysics (Kratos) solver. Attributes: - analysis: Kratos analysis stage. The analysis stage class default name is SimulationScenario. The default file name is simulation_scenario. - adaptive_refinement_jump_to_finest_level: boolean. Used in multilevel algorithms when "stochastic_adaptive_refinement" strategy is selected. If true, intermediate refinement indices are skipped. Set by adaptiveRefinementJumpToFinestLevel key. - asynchronous: boolean. If true, the asynchronous algorithm should be run. If false, the standard synchronous algorithms should be run. Set by asynchronous key. - different_tasks: boolean. Used in multilevel algorithms when "stochastic_adaptive_refinement" strategy is selected. If true, different indices are run all together in the same task. If false, each index is run in a different task. Set by not TaskAllAtOnce key. - fake_sample_to_serialize: list. A variable which is used just to serialize the Kratos Model and the Kratos Parameters. The list should be of the same type of the random variable generated by the generator. Set by fakeRandomVariable key. - mapping_output_quantities: boolean. If true, the analysis stage is prepared to map the variables of interest to a reference Kratos Model. By default, such Kratos Model is the coarsest index. Set by mappingOutputQuantities key. - number_contributions_per_instance: integer. Defines the number of realization per each solve call. Useful if one wants to exploit ensemble average, together with hierarchical Monte Carlo methods. Set by numberContributionsPerInstance key. - number_qoi: integer. Defines the number of Quantities of Interest the user wants to return. Set by numberQoI key. - number_combined_qoi: integer. Defines the number of combined Quantities of Interest the user wants to return. Set by numberCombinedQoi key. - number_multi_qoi: integer. Defines the number of vector Quantities of Interest the user wants to return. Set by numberMultiQoI key. - number_multi_combined_qoi: integer. Defines the number of vector combined Quantities of Interest the user wants to return. Set by numberMultiCombinedQoi key. - outputBatchSize: integer. Defines the size of each sub-list of the Quantities of Interest list which is returned by the solve method. It is alternative to outputDimension, defined below. Set by OutputBatchSize. - outputDimension: integer or list of integers. If integer, equals to len(sample), where sample is the first output argument of self.solve(). If list of integers, then it means that samples are split in future lists, and outputDimension is [len(subSample) for subSample in sample]. Set by OutputDimension key. - print_to_file: boolean. If true, prepares the distributed environment programing model PyCOMPSs to write a file inside the solve task. Set by printToFile key. - project_parameters_path: string or list of strings. Defines the path to Kratos Project Parameters. Set by projectParametersPath key. - refinement_parameters_path: string. Define the path to the Kratos Adaptive Refinement Project Parameters. Set by refinementParametersPath key. - refinement_strategy: string. Options are: "reading_from_file", "deterministic_adaptive_refinement", "stochastic_adaptive_refinement". It defines the refinement strategy for multilevel algorithms. Set by refinementStrategy key. - size_multi_x_qoi: integer or list of integers. Defines the size of each vector quantity if interest. If integer, vector quantities of interest have the same size. If list, the list has the same length of numberMultiQoI+numberMultiCombinedQoI. It is required to set a priori this value only because of returnZeroQoiAndTime_Task, which needs to know how many 0s to return. Set by sizeMultiXQoI. Methods: - serialize: method serializing Kratos Model and Kratos Parameters. - solve: method running the problem. Other methods are called from the two methods defined above. """ # TODO: solverWrapperIndex will be removed from here and will have an indicator about the level we are at and not which algorithm we are using # TODO: are both outputBatchSize and outputBatchSize needed? Probably not. # TODO: integrate MultiXMomentEstimators with ensemble average. def __init__(self, **keywordArgs): super().__init__(**keywordArgs) self.analysis = SimulationScenario self.adaptive_refinement_jump_to_finest_level = keywordArgs.get( "adaptiveRefinementJumpToFinestLevel", False) self.asynchronous = keywordArgs.get("asynchronous", False) self.different_tasks = not keywordArgs.get('taskAllAtOnce', False) self.fake_sample_to_serialize = keywordArgs.get('fakeRandomVariable') self.mapping_output_quantities = keywordArgs.get( "mappingOutputQuantities", False) self.number_contributions_per_instance = keywordArgs.get( "numberContributionsPerInstance", 1) self.number_qoi = keywordArgs.get("numberQoI", 0) self.number_combined_qoi = keywordArgs.get("numberCombinedQoi", 0) self.number_multi_qoi = keywordArgs.get("numberMultiQoI", 0) self.number_multi_combined_qoi = keywordArgs.get( "numberMultiCombinedQoI", 0) self.outputBatchSize = keywordArgs.get('outputBatchSize', 1) self.print_to_file = keywordArgs.get("printToFile", False) self.project_parameters_path = keywordArgs.get('projectParametersPath') self.refinement_parameters_path = keywordArgs.get( 'refinementParametersPath') self.refinement_strategy = keywordArgs.get('refinementStrategy') self.size_multi_x_qoi = keywordArgs.get( 'sizeMultiXQoI', -1) # remove after returnZeroQoiAndTime_Task is removed # Set outputDimension self.outputDimension = keywordArgs.get('outputDimension', None) # If not given, compute from self.outputBatchSize for backward compatibility if self.outputDimension is None: outputNb = self._numberOfOutputs() # Total number of output splits, including (possibly) a last one of smaller size batchNb = int(math.ceil(outputNb / self.outputBatchSize)) # Assemble the list of sizes of each split # They are all equal to outputBatchSize, except perhaps the last one # E.g. outputBatchSize=2 and outputNb=5 gives [2,2,1] self.outputDimension = [ min(self.outputBatchSize, outputNb - i * self.outputBatchSize) for i in range(batchNb) ] # workaround for Monte Carlo if (self.solverWrapperIndex == []): self.solverWrapperIndex.append(0) if (self.solverWrapperIndex[0] >= 0): # for index < 0 not needed if (self.asynchronous is not True): # synchronous framework self.serialize() else: # asynchronous framework pass def serialize(self): """ Method serializing Kratos Model and Kratos Parameters. Inputs: - self: an instance of the class. """ if (self.refinement_strategy == "stochastic_adaptive_refinement"): # serialization self.is_project_parameters_pickled = False self.is_model_pickled = False self.is_custom_settings_metric_refinement_pickled = False self.is_custom_settings_remesh_refinement_pickled = False self.SetRefinementParameters() self.SerializeRefinementParameters() self.SerializeModelParameters() # estimate mesh size of current index self.ComputeMeshParameters() elif (self.refinement_strategy == "deterministic_adaptive_refinement"): # serialization self.is_project_parameters_pickled = False self.is_model_pickled = False self.is_custom_settings_metric_refinement_pickled = False self.is_custom_settings_remesh_refinement_pickled = False self.SetRefinementParameters() self.SerializeRefinementParameters() self.SerializeModelParameters() # estimate mesh size of current index self.ComputeMeshParameters() elif (self.refinement_strategy == "reading_from_file"): # serialization self.is_project_parameters_pickled = False self.is_model_pickled = False self.is_custom_settings_metric_refinement_pickled = False self.is_custom_settings_remesh_refinement_pickled = False self.SetRefinementParameters() self.SerializeRefinementParameters() self.SerializeModelParameters() # estimate mesh size of current index self.ComputeMeshParameters() else: raise Exception( "Select KratosMultiphysics refinement stategy.\nOptions:\ \n i) stochastic_adaptive_refinement\ \n ii) deterministic_adaptive_refinement\ \n iii) reading_from_file") def solve(self, random_variable): """ Method running the problem. Inputs: - self: an instance of the class - random_variable: random event in the form of list. Outputs: - qoi_list: list of structure respecting self.outputDimension. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ if all([component >= 0 for component in self.solverWrapperIndex]): aux_qoi_array = [] for contribution_counter in range( 0, self.number_contributions_per_instance): self.current_local_contribution = contribution_counter if (self.refinement_strategy == "stochastic_adaptive_refinement"): qoi, time_for_qoi = self.executeInstanceStochasticAdaptiveRefinement( random_variable) elif (self.refinement_strategy == "deterministic_adaptive_refinement"): qoi, time_for_qoi = self.executeInstanceDeterministicAdaptiveRefinement( random_variable) elif (self.refinement_strategy == "reading_from_file"): qoi, time_for_qoi = self.executeInstanceReadingFromFile( random_variable) # append components to aux array aux_qoi_array.append(qoi) # delete COMPSs future objects no longer needed delete_object(random_variable) # postprocess components if self.number_contributions_per_instance > 1: unm = mdu.UnfolderManager(self._numberOfOutputs(), self.outputBatchSize) if (self._numberOfOutputs() == self.outputBatchSize): qoi_list = [ unm.PostprocessContributionsPerInstance( aux_qoi_array, self.number_qoi, self.number_combined_qoi) ] elif (self._numberOfOutputs() > self.outputBatchSize): qoi_list = unm.PostprocessContributionsPerInstance( aux_qoi_array, self.number_qoi, self.number_combined_qoi) else: raise Exception( "_numberOfOutputs() returns a value smaller than self.outputBatchSize. Set outputBatchSize smaller or equal to the number of scalar outputs." ) delete_object(unm) else: # unfold qoi into its components of fixed size unm = mdu.UnfolderManager(self._numberOfOutputs(), self.outputBatchSize) if (self._numberOfOutputs() == self.outputBatchSize): qoi_list = [unm.UnfoldNValues_Task(aux_qoi_array[0])] elif (self._numberOfOutputs() > self.outputBatchSize): qoi_list = unm.UnfoldNValues_Task(aux_qoi_array[0]) else: raise Exception( "_numberOfOutputs() returns a value smaller than self.outputBatchSize. Set outputBatchSize smaller or equal to the number of scalar outputs." ) # delete COMPSs future objects no longer needed delete_object(unm) # delete COMPSs future objects no longer needed for contribution_counter in range( 0, self.number_contributions_per_instance): delete_object(aux_qoi_array[contribution_counter]) delete_object(qoi) del (aux_qoi_array) else: qoi, time_for_qoi = mds.returnZeroQoiAndTime_Task( self.number_qoi + self.number_combined_qoi, self.number_multi_qoi + self.number_multi_combined_qoi, self.size_multi_x_qoi) # unfold qoi into its components of fixed size unm = mdu.UnfolderManager(self._numberOfOutputs(), self.outputBatchSize) if (self._numberOfOutputs() == self.outputBatchSize): qoi_list = [unm.UnfoldNValues_Task(qoi)] elif (self._numberOfOutputs() > self.outputBatchSize): qoi_list = unm.UnfoldNValues_Task(qoi) else: raise Exception( "_numberOfOutputs() returns a value smaller than self.outputBatchSize. Set outputBatchSize smaller or equal to the number of scalar outputs." ) # delete COMPSs future objects no longer needed delete_object(unm) return qoi_list, time_for_qoi #################################################################################################### ######################################### EXECUTION TOOLS ########################################## #################################################################################################### def executeInstanceStochasticAdaptiveRefinement(self, random_variable): """ Method executing an instance of the UQ algorithm, i.e. a single MC realization and eventually the refinement (that occurs before the simulation run). To be called if the selected refinement strategy is stochastic_adaptive_refinement. Inputs: - self: an instance of the class. Outputs: - qoi: list. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ current_index = self.solverWrapperIndex[0] # local variables pickled_coarse_model = self.pickled_model[0] pickled_reference_model_mapping = pickled_coarse_model pickled_coarse_project_parameters = self.pickled_project_parameters[0] pickled_custom_metric_refinement_parameters = self.pickled_custom_metric_refinement_parameters pickled_custom_remesh_refinement_parameters = self.pickled_custom_remesh_refinement_parameters current_analysis = self.analysis different_tasks = self.different_tasks mapping_flag = self.mapping_output_quantities adaptive_refinement_jump_to_finest_level = self.adaptive_refinement_jump_to_finest_level print_to_file = self.print_to_file current_local_contribution = self.current_local_contribution time_for_qoi = 0.0 if (different_tasks is False): # tasks all at once qoi,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementAllAtOnce_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_analysis,time_for_qoi,mapping_flag,adaptive_refinement_jump_to_finest_level,print_to_file,current_local_contribution) elif (different_tasks is True): # multiple tasks if (current_index == 0): # index = 0 current_local_index = 0 qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution) delete_object(pickled_current_model) else: # index > 0 for current_local_index in range(current_index + 1): if ((adaptive_refinement_jump_to_finest_level is False) or (adaptive_refinement_jump_to_finest_level is True and (current_local_index == 0 or current_local_index == current_index))): if (mapping_flag is False): qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution) elif (mapping_flag is True): qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution,pickled_mapping_reference_model=pickled_reference_model_mapping) delete_object(pickled_coarse_model) del (pickled_coarse_model) pickled_coarse_model = pickled_current_model del (pickled_current_model) else: # not running since we jump from coarsest to finest level pass delete_object(pickled_coarse_model) else: raise Exception( "Boolean variable different task is not a boolean, instead is equal to", different_tasks) return qoi, time_for_qoi def executeInstanceDeterministicAdaptiveRefinement(self, random_variable): """ Method executing an instance of the UQ algorithm, i.e. a single MC realization and eventually the refinement (that occurs before the simulation run). To be called if the selected refinement strategy is deterministic_adaptive_refinement. Inputs: - self: an instance of the class. Outputs: - qoi: list. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ # local variables current_index = self.solverWrapperIndex[0] pickled_model = self.pickled_model[current_index] pickled_project_parameters = self.pickled_project_parameters[0] current_analysis = self.analysis time_for_qoi = 0.0 qoi, time_for_qoi = mds.executeInstanceDeterministicAdaptiveRefinement_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi) return qoi, time_for_qoi def executeInstanceReadingFromFile(self, random_variable): """ Method executing an instance of the UQ algorithm, i.e. a single MC realization and eventually the refinement (that occurs before the simulation run). To be called if the selected refinement strategy is reading_from_file. Inputs: - self: an instance of the class. Outputs: - qoi: list. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ # local variables current_index = self.solverWrapperIndex[0] pickled_model = self.pickled_model[current_index] pickled_mapping_reference_model = self.pickled_model[0] pickled_project_parameters = self.pickled_project_parameters[ current_index] mapping_flag = self.mapping_output_quantities print_to_file = self.print_to_file current_local_contribution = self.current_local_contribution current_analysis = self.analysis time_for_qoi = 0.0 qoi, time_for_qoi = mds.executeInstanceReadingFromFile_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi, mapping_flag, pickled_mapping_reference_model, print_to_file, current_local_contribution) return qoi, time_for_qoi #################################################################################################### ####################################### SERIALIZATION TOOLS ######################################## #################################################################################################### def SerializeModelParameters(self): """ Method managing the serialization and pickling of the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. The serialization-pickling process is the following: i) from Model/Parameters Kratos object to MpiSerializer Kratos object, ii) from MpiSerializer Kratos object to pickle string, iii) from pickle string to MpiSerializer Kratos object, iv) from MpiSerializer Kratos object to Model/Parameters Kratos object. Depending on the refinement strategy, three different methods may be called and are defined next. Inputs: - self: an instance of the class. """ self.serialized_model = [] self.serialized_project_parameters = [] self.pickled_model = [] self.pickled_project_parameters = [] if (self.refinement_strategy == "stochastic_adaptive_refinement"): self.SerializeModelParametersStochasticAdaptiveRefinement() elif (self.refinement_strategy == "deterministic_adaptive_refinement"): self.SerializeModelParametersDeterministicAdaptiveRefinement() elif (self.refinement_strategy == "reading_from_file"): self.SerializeModelParametersReadingFromFile() else: raise Exception( "Specify refinement_strategy: stochastic_adaptive_refinement or deterministic_adaptive_refinement or reading_from_file" ) self.is_project_parameters_pickled = True self.is_model_pickled = True print("\n", "#" * 50, " SERIALIZATION MODEL AND PROJECT PARAMETERS COMPLETED ", "#" * 50, "\n") def SerializeModelParametersStochasticAdaptiveRefinement(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is stochastic_adaptive_refinement. Inputs: - self: an instance of the class. """ with open(self.project_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters.append( serialized_project_parameters) # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = self.fake_sample_to_serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.MpiSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model.append(serialized_model) # pickle dataserialized_data pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2) self.pickled_model.append(pickled_model) self.pickled_project_parameters.append(pickled_project_parameters) def SerializeModelParametersDeterministicAdaptiveRefinement(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is deterministic_adaptive_refinement. Inputs: - self: an instance of the class. """ self.SerializeModelParametersStochasticAdaptiveRefinement( ) # to prepare parameters and model part of coarsest level number_levels_to_serialize = self.solverWrapperIndex[0] # same routine of ExecuteInstanceConcurrentAdaptiveRefinemnt() to build models and parameters, but here we save models and parameters pickled_coarse_model = self.pickled_model[0] pickled_coarse_project_parameters = self.pickled_project_parameters[0] pickled_custom_metric_refinement_parameters = self.pickled_custom_metric_refinement_parameters pickled_custom_remesh_refinement_parameters = self.pickled_custom_remesh_refinement_parameters current_analysis = self.analysis # generate the sample and prepare auxiliary variables we need fake_sample = self.fake_sample_to_serialize fake_computational_time = 0.0 if (number_levels_to_serialize > 0): for current_level in range(number_levels_to_serialize + 1): fake_qoi,pickled_current_model,fake_computational_time = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(number_levels_to_serialize,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,fake_sample,current_level,current_analysis,fake_computational_time,mapping_flag=False,print_to_file=False,current_contribution=0) del (pickled_coarse_model) pickled_coarse_model = pickled_current_model # save if current level > 0 (level = 0 has already been saved) if (current_level > 0): # save pickled and serialized model and parameters self.pickled_model.append(pickled_current_model) self.serialized_model.append( pickle.loads(pickled_current_model)) del (pickled_current_model) def SerializeModelParametersReadingFromFile(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is reading_from_file. Inputs: - self: an instance of the class. """ for parameters_path in self.project_parameters_path: with open(parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters( parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters.append( serialized_project_parameters) # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = self.fake_sample_to_serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.MpiSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model.append(serialized_model) # pickle dataserialized_data pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2) self.pickled_model.append(pickled_model) self.pickled_project_parameters.append(pickled_project_parameters) def SerializeRefinementParameters(self): """ Method serializing and pickling the custom setting metric and remeshing for the adaptive refinement. It requires self.custom_metric_refinement_parameters and self.custom_remesh_refinement_parameters. It builds self.pickled_custom_metric_refinement_parameters and self.pickled_custom_remesh_refinement_parameters. Inputs: - self: an instance of the class. """ metric_refinement_parameters = self.custom_metric_refinement_parameters remeshing_refinement_parameters = self.custom_remesh_refinement_parameters # save parameters as MpiSerializer Kratos objects serialized_metric_refinement_parameters = KratosMultiphysics.MpiSerializer( ) serialized_metric_refinement_parameters.Save( "MetricRefinementParametersSerialization", metric_refinement_parameters) serialized_remesh_refinement_parameters = KratosMultiphysics.MpiSerializer( ) serialized_remesh_refinement_parameters.Save( "RemeshRefinementParametersSerialization", remeshing_refinement_parameters) # pickle parameters pickled_metric_refinement_parameters = pickle.dumps( serialized_metric_refinement_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_remesh_refinement_parameters = pickle.dumps( serialized_remesh_refinement_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) self.pickled_custom_metric_refinement_parameters = pickled_metric_refinement_parameters self.pickled_custom_remesh_refinement_parameters = pickled_remesh_refinement_parameters self.is_custom_settings_metric_refinement_pickled = True self.is_custom_settings_remesh_refinement_pickled = True print("\n", "#" * 50, " SERIALIZATION REFINEMENT PARAMETERS COMPLETED ", "#" * 50, "\n") #################################################################################################### ######################################### AUXILIARY TOOLS ########################################## #################################################################################################### def SetRefinementParameters(self): """ Method reading the refinement parameters passed from json file. Inputs: - self: an instance of the class. """ with open(self.refinement_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) self.custom_metric_refinement_parameters = parameters["hessian_metric"] self.custom_remesh_refinement_parameters = parameters["refinement_mmg"] def ComputeMeshParameters(self): """ Method computing the mesh discretization parameter self.mesh_parameters and the mesh sizes self.mesh_sizes. The mesh parameter is the reciprocal of the minimum mesh size of the grid. Inputs: - self: an instance of the class. """ # unpickle and unserialize model and build Kratos Model object serialized_model = pickle.loads(self.pickled_model[0]) current_model = KratosMultiphysics.Model() serialized_model.Load("ModelSerialization", current_model) # unpickle and unserialize parameters and build Kratos Parameters object serialized_project_parameters = pickle.loads( self.pickled_project_parameters[0]) current_project_parameters = KratosMultiphysics.Parameters() serialized_project_parameters.Load("ParametersSerialization", current_project_parameters) # unpickle and unserialize metric refinement parameters and build Kratos Parameters objects serialized_custom_metric_refinement_parameters = pickle.loads( self.pickled_custom_metric_refinement_parameters) current_custom_metric_refinement_parameters = KratosMultiphysics.Parameters( ) serialized_custom_metric_refinement_parameters.Load( "MetricRefinementParametersSerialization", current_custom_metric_refinement_parameters) self.mesh_sizes = [] self.mesh_parameters = [] level = self.solverWrapperIndex[0] adaptive_refinement_manager = AdaptiveRefinement( level, current_model, current_project_parameters, current_custom_metric_refinement_parameters, None) adaptive_refinement_manager.EstimateMeshSizeCurrentLevel() h_current_level = adaptive_refinement_manager.mesh_size mesh_parameter_current_level = h_current_level**(-1) self.mesh_sizes.append(h_current_level) self.mesh_parameters.append(mesh_parameter_current_level) def _numberOfOutputs(self): """ Internal method returning the total number of outputs, regardless of how how many members vector quantities of interest have. Inputs: - self: an instance of the class. """ return self.number_qoi + self.number_combined_qoi + self.number_multi_qoi + self.number_multi_combined_qoi
class AdaptiveRefinement(object): """ Class managing the adaptive refinement process, called when executing Multilevel Monte Carlo algorithms. This class handles the call to the MeshingApplication, and to other applications, if needed along the process. Input: - model_coarse: Kratos model class before refinement - parameters_coarse: Kratos parameters class before refinement - minimal_size_value: minimal size after remeshing - maximal_size_value: maximal size after remeshing - metric_param: Kratos parameters class containing metric custom settings - remesh_param: Kratos parameters class containing remeshing custom settings - metric_name: string defining the metring which the class will use to build the metric """ def __init__(self, current_level, model_coarse, parameters_coarse, metric_param, remesh_param, metric_name="hessian"): self.model_coarse = model_coarse self.parameters_coarse = parameters_coarse self.metric_param = metric_param self.remesh_param = remesh_param self.problem_type = self.parameters_coarse["solver_settings"][ "solver_type"].GetString() self.metric = metric_name self.current_level = current_level self.wrapper = ParametersWrapper(self.parameters_coarse) def ComputeAdaptiveRefinement(self): """ Method computing the refinement of the model based on the solution on the coarse mesh, exploiting the hessian metric of the solution. Input: - self: an instance of the class Output: - current_model_refined : Kratos model class after refinement - current_parameters_refined : Kratos parameters class after refinement """ parameters_coarse = self.parameters_coarse model_coarse = self.model_coarse metric_param = self.metric_param remesh_param = self.remesh_param problem_type = self.problem_type current_level = self.current_level # check MeshingApplication is imported, # otherwise raise an error if not CheckIfApplicationsAvailable("MeshingApplication"): raise Exception( "[MultilevelMonteCarloApplication]: MeshingApplication cannot be imported, but it is necessary to perform adaptive refinement." ) if (self.metric is "hessian"): # initialize interpolation error original_interp_error = metric_param[ "hessian_strategy_parameters"][ "interpolation_error"].GetDouble() # set interpolation error for current level if current_level > 0: coefficient_interp_error = metric_param[ "hessian_strategy_parameters"][ "coefficient_interpolation_error"].GetDouble() metric_param["hessian_strategy_parameters"].RemoveValue( "coefficient_interpolation_error") interp_error = original_interp_error * ( coefficient_interp_error)**(-current_level) # interp_error = original_interp_error/(coefficient_interp_error*current_level) metric_param["hessian_strategy_parameters"][ "interpolation_error"].SetDouble(interp_error) # Setting metric tensor to 0 domain_size = self.wrapper.GetDomainSize() model_part_name = parameters_coarse["solver_settings"][ "model_part_name"].GetString() if domain_size == 2: KratosMultiphysics.VariableUtils( ).SetNonHistoricalVariableToZero( KratosMultiphysics.MeshingApplication.METRIC_TENSOR_2D, model_coarse.GetModelPart(model_part_name).Nodes) elif domain_size == 3: KratosMultiphysics.VariableUtils( ).SetNonHistoricalVariableToZero( KratosMultiphysics.MeshingApplication.METRIC_TENSOR_3D, model_coarse.GetModelPart(model_part_name).Nodes) else: err_msg = "Domain size is {}. Supported values are 2 and 3.\n".format( domain_size) # calculate NODAL_H find_nodal_h = KratosMultiphysics.FindNodalHNonHistoricalProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h.Execute() # build the metric if metric_param["hessian_strategy_parameters"].Has( "metric_variable"): metric_variables = self.__generate_variable_list_from_input( metric_param["hessian_strategy_parameters"] ["metric_variable"]) # remove metric value from settings, since we pass it directly in the constructor metric_param["hessian_strategy_parameters"].RemoveValue( "metric_variable") else: raise Exception( "A list of variable is expected under the key [\"hessian_strategy_parameters\"][\"metric_variable\"] of the \"metric\" dictionary." ) for mv in metric_variables: local_gradient = KratosMultiphysics.MeshingApplication.ComputeHessianSolMetricProcess( model_coarse.GetModelPart(model_part_name), mv, metric_param) local_gradient.Execute() # create the remeshing process and execute it if KratosMultiphysics.IsDistributedRun(): # MPI KratosMultiphysics.mpi.ParallelFillCommunicator( model_coarse.GetModelPart(model_part_name)).Execute() if domain_size == 3: if (hasattr(KratosMultiphysics.MeshingApplication, "ParMmgProcess3D")): pmmg_process = KratosMultiphysics.MeshingApplication.ParMmgProcess3D( model_coarse.GetModelPart(model_part_name), remesh_param) else: raise Exception( "[MultilevelMonteCarloApplication]: ParMmgProcess3D atrribute not found within MeshingApplcation. It is required to perform remeshing." ) else: err_msg = "Domain size is {}. Supported value is 3.\n".format( domain_size) raise Exception(err_msg) pmmg_process.Execute() else: # serial if domain_size == 2: if (hasattr(KratosMultiphysics.MeshingApplication, "MmgProcess2D")): mmg_process = KratosMultiphysics.MeshingApplication.MmgProcess2D( model_coarse.GetModelPart(model_part_name), remesh_param) else: raise Exception( "[MultilevelMonteCarloApplication]: MmgProcess2D atrribute not found within MeshingApplcation. It is required to perform remeshing." ) elif domain_size == 3: if (hasattr(KratosMultiphysics.MeshingApplication, "MmgProcess3D")): mmg_process = KratosMultiphysics.MeshingApplication.MmgProcess3D( model_coarse.GetModelPart(model_part_name), remesh_param) else: raise Exception( "[MultilevelMonteCarloApplication]: MmgProcess3D atrribute not found within MeshingApplcation. It is required to perform remeshing." ) else: err_msg = "Domain size is {}. Supported values are 2 and 3.\n".format( domain_size) raise Exception(err_msg) mmg_process.Execute() # reset variables if needed model_coarse.GetModelPart(model_part_name).ProcessInfo.SetValue( KratosMultiphysics.TIME, 0.0) model_coarse.GetModelPart(model_part_name).ProcessInfo.SetValue( KratosMultiphysics.STEP, 0) model_coarse.GetModelPart(model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, False) if (problem_type in ["monolithic", "FractionalStep", "potential_flow"]): model_coarse.GetModelPart(model_part_name).RemoveSubModelPart( "fluid_computational_model_part") # the refinement process empties the coarse model part object and fill it with the refined model part # the solution on the refined grid is obtained from the interpolation of the coarse solution # there are not other operations, therefore to build the new model we just need to take the updated coarse model current_model_refined = model_coarse current_parameters_refined = parameters_coarse return current_model_refined, current_parameters_refined else: err_msg = "Metric passed to the AdaptiveRefinement class is {}, but the only supported metric is \"hessian\".\n".format( self.metric) raise Exception(err_msg) def ComputeMeshSizeCoarsestLevel(self): """ Method computing the mesh size of coarsest level, estimated as minimum nodal_h. Input: - self: an instance of the class """ model_coarse = self.model_coarse model_part_name = self.wrapper.GetModelPartName() # set NODAL_AREA and NODAL_H as non historical variables KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( KratosMultiphysics.NODAL_AREA, 0.0, model_coarse.GetModelPart(model_part_name).Nodes) KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( KratosMultiphysics.NODAL_H, 0.0, model_coarse.GetModelPart(model_part_name).Nodes) # calculate NODAL_H find_nodal_h = KratosMultiphysics.FindNodalHProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h = KratosMultiphysics.FindNodalHNonHistoricalProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h.Execute() # compute average mesh size mesh_size = 10.0 for node in model_coarse.GetModelPart(model_part_name).Nodes: if (node.GetValue(KratosMultiphysics.NODAL_H) < mesh_size): mesh_size = node.GetValue(KratosMultiphysics.NODAL_H) self.mesh_size_coarsest_level = mesh_size def EstimateMeshSizeCurrentLevel(self): """ Method estimating the mesh size of current level. Input: - self: an instance of the class """ self.ComputeMeshSizeCoarsestLevel() current_level = self.current_level if (self.metric is "hessian"): original_interp_error = self.metric_param[ "hessian_strategy_parameters"][ "interpolation_error"].GetDouble() domain_size = self.wrapper.GetDomainSize() if (domain_size == 2): coefficient = 2 / 9 # 2d elif (domain_size == 3): coefficient = 9 / 32 # 3d # TODO: compute below interp error level more automatically coefficient_interp_error = self.metric_param[ "hessian_strategy_parameters"][ "coefficient_interpolation_error"].GetDouble() # interp_error_level = original_interp_error*(coefficient_interp_error)**(-current_level) if (current_level > 0): interp_error_level = original_interp_error / ( coefficient_interp_error * current_level) else: # current_level == 0 interp_error_level = original_interp_error mesh_size_level = self.mesh_size_coarsest_level * sqrt( interp_error_level / original_interp_error ) # relation from [Alauzet] eqs. pag 34 and 35 self.mesh_size = mesh_size_level def __generate_variable_list_from_input(self, param): """ Method taken and adapted from mmg_progess.py of MeshingApplication. Parse a list of variables from input. """ # At least verify that the input is a string if not param.IsArray(): raise Exception("{0} Error: Variable list is unreadable".format( self.__class__.__name__)) # Retrieve variable name from input (a string) and request the corresponding C++ object to the kernel variable_list = [] param_names = param.GetStringArray() for variable_name in param_names: varriable_type = KratosMultiphysics.KratosGlobals.GetVariableType( variable_name) if varriable_type == "Double" or varriable_type == "Component": variable_list.append( KratosMultiphysics.KratosGlobals.GetVariable( variable_name)) else: variable_list.append( KratosMultiphysics.KratosGlobals.GetVariable( variable_name + "_X")) variable_list.append( KratosMultiphysics.KratosGlobals.GetVariable( variable_name + "_Y")) if self.wrapper.GetDomainSize() == 3: variable_list.append( KratosMultiphysics.KratosGlobals.GetVariable( variable_name + "_Z")) return variable_list
class AdaptiveRefinement(object): """ input: model_coarse : Kratos model class before refinement parameters_coarse : Kratos parameters class before refinement minimal_size_value : minimal size after remeshing maximal_size_value : maximal size after remeshing metric_param : Kratos parameters class containing metric custom settings remesh_param : Kratos parameters class containing remeshing custom settings """ def __init__(self, current_level, model_coarse, parameters_coarse, metric_param, remesh_param, metric_name="hessian"): self.model_coarse = model_coarse self.parameters_coarse = parameters_coarse self.metric_param = metric_param self.remesh_param = remesh_param self.problem_type = self.parameters_coarse["solver_settings"][ "solver_type"].GetString() self.metric = metric_name self.current_level = current_level self.wrapper = ParametersWrapper(self.parameters_coarse) """ function computing the refinement of the model based on the solution on the coarse mesh, exploiting the hessian metric of the solution input: self: an instance of the class output: current_model_refined : Kratos model class after refinement current_parameters_refined : Kratos parameters class after refinement """ def ComputeAdaptiveRefinement(self): parameters_coarse = self.parameters_coarse model_coarse = self.model_coarse metric_param = self.metric_param remesh_param = self.remesh_param problem_type = self.problem_type current_level = self.current_level if (self.metric is "hessian"): original_interp_error = metric_param[ "hessian_strategy_parameters"][ "interpolation_error"].GetDouble() # problem dependent section if (problem_type == "potential_flow"): model_part_name = parameters_coarse["solver_settings"][ "model_part_name"].GetString() # set NODAL_AREA and NODAL_H as non historical variables KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( KratosMultiphysics.NODAL_AREA, 0.0, model_coarse.GetModelPart(model_part_name).Nodes) KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( KratosMultiphysics.NODAL_H, 0.0, model_coarse.GetModelPart(model_part_name).Nodes) # Setting Metric Tensor to 0 KratosMultiphysics.VariableUtils( ).SetNonHistoricalVariableToZero( KratosMultiphysics.MeshingApplication.METRIC_TENSOR_2D, model_coarse.GetModelPart(model_part_name).Nodes) # calculate NODAL_H find_nodal_h = KratosMultiphysics.FindNodalHProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h = KratosMultiphysics.FindNodalHNonHistoricalProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h.Execute() custom_gradient = KratosMultiphysics.CompressiblePotentialFlowApplication.ComputeCustomNodalGradientProcess( model_coarse.GetModelPart(model_part_name), KratosMultiphysics.VELOCITY, KratosMultiphysics.NODAL_AREA) custom_gradient.Execute() if metric_param.Has("local_gradient_variable"): metric_param.RemoveValue("local_gradient_variable") if current_level > 0: coefficient_interp_error = metric_param[ "hessian_strategy_parameters"][ "coefficient_interpolation_error"].GetDouble() metric_param["hessian_strategy_parameters"].RemoveValue( "coefficient_interpolation_error") # interp_error = original_interp_error*(coefficient_interp_error)**(-current_level) interp_error = original_interp_error / ( coefficient_interp_error * current_level) metric_param["hessian_strategy_parameters"][ "interpolation_error"].SetDouble(interp_error) local_gradient = KratosMeshing.ComputeHessianSolMetricProcess( model_coarse.GetModelPart(model_part_name), KratosMultiphysics.VELOCITY_X, metric_param) local_gradient.Execute() local_gradient = KratosMeshing.ComputeHessianSolMetricProcess( model_coarse.GetModelPart(model_part_name), KratosMultiphysics.VELOCITY_Y, metric_param) local_gradient.Execute() # #### OLD APPROACH # for node in model_coarse.GetModelPart(model_part_name).Nodes: # vector=node.GetValue(KratosMultiphysics.VELOCITY) # norm=np.linalg.norm(vector) # node.SetSolutionStepValue(KratosMultiphysics.TEMPERATURE,norm) # prepare parameters to calculate the gradient of the designed variable # local_gradient_variable_string = metric_param["local_gradient_variable"].GetString() # local_gradient_variable = KratosMultiphysics.KratosGlobals.GetVariable(metric_param["local_gradient_variable"].GetString()) # set interpolation error value (level dependent) # calculate the gradient of the variable # local_gradient = KratosMeshing.ComputeHessianSolMetricProcess(model_coarse.GetModelPart(model_part_name),local_gradient_variable,metric_param) # local_gradient.Execute() # # add again the removed variable parameter # metric_param.AddEmptyValue("local_gradient_variable") # metric_param["local_gradient_variable"].SetString(local_gradient_variable_string) #### OLD APPROACH elif (problem_type == "monolithic"): if metric_param.Has("local_gradient_variable"): metric_param.RemoveValue("local_gradient_variable") if current_level > 0: coefficient_interp_error = metric_param[ "hessian_strategy_parameters"][ "coefficient_interpolation_error"].GetDouble() metric_param["hessian_strategy_parameters"].RemoveValue( "coefficient_interpolation_error") # interp_error = original_interp_error*(coefficient_interp_error)**(-current_level) interp_error = original_interp_error / ( coefficient_interp_error * current_level) metric_param["hessian_strategy_parameters"][ "interpolation_error"].SetDouble(interp_error) model_part_name = parameters_coarse["solver_settings"][ "model_part_name"].GetString() # Setting Metric Tensor to 0 KratosMultiphysics.VariableUtils( ).SetNonHistoricalVariableToZero( KratosMultiphysics.MeshingApplication.METRIC_TENSOR_2D, model_coarse.GetModelPart(model_part_name).Nodes) # calculate NODAL_H find_nodal_h = KratosMultiphysics.FindNodalHNonHistoricalProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h.Execute() local_gradient = KratosMeshing.ComputeHessianSolMetricProcess( model_coarse.GetModelPart(model_part_name), KratosFluid.AVERAGE_VELOCITY_X, metric_param) local_gradient.Execute() local_gradient = KratosMeshing.ComputeHessianSolMetricProcess( model_coarse.GetModelPart(model_part_name), KratosFluid.AVERAGE_VELOCITY_Y, metric_param) local_gradient.Execute() elif (problem_type == "stationary"): if current_level > 0: coefficient_interp_error = metric_param[ "hessian_strategy_parameters"][ "coefficient_interpolation_error"].GetDouble() metric_param["hessian_strategy_parameters"].RemoveValue( "coefficient_interpolation_error") interp_error = original_interp_error * ( coefficient_interp_error)**(-current_level) metric_param["hessian_strategy_parameters"][ "interpolation_error"].SetDouble(interp_error) model_part_name = parameters_coarse["solver_settings"][ "model_part_name"].GetString() # Setting Metric Tensor to 0 KratosMultiphysics.VariableUtils( ).SetNonHistoricalVariableToZero( KratosMultiphysics.MeshingApplication.METRIC_TENSOR_2D, model_coarse.GetModelPart(model_part_name).Nodes) # calculate NODAL_H find_nodal_h = KratosMultiphysics.FindNodalHNonHistoricalProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h.Execute() local_gradient = KratosMeshing.ComputeHessianSolMetricProcess( model_coarse.GetModelPart(model_part_name), KratosMultiphysics.TEMPERATURE, metric_param) local_gradient.Execute() # create the remeshing process MmgProcess = KratosMeshing.MmgProcess2D( model_coarse.GetModelPart(model_part_name), remesh_param) MmgProcess.Execute() # reset variables if needed model_coarse.GetModelPart(model_part_name).ProcessInfo.SetValue( KratosMultiphysics.TIME, 0.0) model_coarse.GetModelPart(model_part_name).ProcessInfo.SetValue( KratosMultiphysics.STEP, 0) """ the refinement process empties the coarse model part object and fill it with the refined model part the solution on the refined grid is obtained from the interpolation of the coarse solution there are not other operations, therefore to build the new model we just need to take the updated coarse model """ current_model_refined = model_coarse current_parameters_refined = parameters_coarse return current_model_refined, current_parameters_refined """ method computing the mesh size of coarsest level, estimated as minimum nodal_h input: self : an instance of the class """ def ComputeMeshSizeCoarsestLevel(self): model_coarse = self.model_coarse parameters_coarse = self.parameters_coarse model_part_name = self.wrapper.GetModelPartName() # set NODAL_AREA and NODAL_H as non historical variables KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( KratosMultiphysics.NODAL_AREA, 0.0, model_coarse.GetModelPart(model_part_name).Nodes) KratosMultiphysics.VariableUtils().SetNonHistoricalVariable( KratosMultiphysics.NODAL_H, 0.0, model_coarse.GetModelPart(model_part_name).Nodes) # calculate NODAL_H find_nodal_h = KratosMultiphysics.FindNodalHProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h = KratosMultiphysics.FindNodalHNonHistoricalProcess( model_coarse.GetModelPart(model_part_name)) find_nodal_h.Execute() # compute average mesh size mesh_size = 10.0 for node in model_coarse.GetModelPart(model_part_name).Nodes: if (node.GetValue(KratosMultiphysics.NODAL_H) < mesh_size): mesh_size = node.GetValue(KratosMultiphysics.NODAL_H) self.mesh_size_coarsest_level = mesh_size """ method estimating the mesh size of current level input: self : an instance of the class """ def EstimateMeshSizeCurrentLevel(self): self.ComputeMeshSizeCoarsestLevel() current_level = self.current_level if (self.metric is "hessian"): original_interp_error = self.metric_param[ "hessian_strategy_parameters"][ "interpolation_error"].GetDouble() domain_size = self.wrapper.GetDomainSize() if (domain_size == 2): coefficient = 2 / 9 # 2d elif (domain_size == 3): coefficient = 9 / 32 # 3d # TODO: compute below interp error level more automatically coefficient_interp_error = self.metric_param[ "hessian_strategy_parameters"][ "coefficient_interpolation_error"].GetDouble() # interp_error_level = original_interp_error*(coefficient_interp_error)**(-current_level) if (current_level > 0): interp_error_level = original_interp_error / ( coefficient_interp_error * current_level) else: # current_level == 0 interp_error_level = original_interp_error mesh_size_level = self.mesh_size_coarsest_level * np.sqrt( interp_error_level / original_interp_error ) # relation from [Alauzet] eqs. pag 34 and 35 self.mesh_size = mesh_size_level
class KratosSolverWrapper(sw.SolverWrapper): # TODO: solverWrapperIndex will be removed from here and will have an indicator about the level we are at and not which algorithm we are using def __init__(self, **keywordArgs): super().__init__(**keywordArgs) self.analysis = SimulationScenario self.adaptive_refinement_jump_to_finest_level = keywordArgs.get( "adaptiveRefinementJumpToFinestLevel", False) self.asynchronous = keywordArgs.get("asynchronous", False) self.fake_sample_to_serialize = keywordArgs.get('fakeRandomVariable') self.mapping_output_quantities = keywordArgs.get( "mappingOutputQuantities", False) self.number_contributions_per_instance = keywordArgs.get( "numberContributionsPerInstance", 2) self.number_qoi = keywordArgs.get("numberQoI", 1) self.number_combined_qoi = keywordArgs.get("numberCombinedQoi", 0) self.print_to_file = keywordArgs.get("printToFile", False) self.project_parameters_path = keywordArgs.get('projectParametersPath') self.refinement_parameters_path = keywordArgs.get( 'refinementParametersPath') self.refinement_strategy = keywordArgs.get('refinementStrategy') self.different_tasks = not keywordArgs.get('taskAllAtOnce', False) # TODO: remove this hard code to run MC if (self.solverWrapperIndex == []): self.solverWrapperIndex.append(0) if (self.solverWrapperIndex[0] >= 0): # for index < 0 nothing is needed if (self.asynchronous is not True): # synchronous framework self.serialize() else: # asynchronous framework pass def serialize(self): if (self.refinement_strategy == "stochastic_adaptive_refinement"): # serialization self.is_project_parameters_pickled = False self.is_model_pickled = False self.is_custom_settings_metric_refinement_pickled = False self.is_custom_settings_remesh_refinement_pickled = False self.SetRefinementParameters() self.SerializeRefinementParameters() self.SerializeModelParameters() # estimate mesh size of current index self.ComputeMeshParameters() elif (self.refinement_strategy == "deterministic_adaptive_refinement"): # serialization self.is_project_parameters_pickled = False self.is_model_pickled = False self.is_custom_settings_metric_refinement_pickled = False self.is_custom_settings_remesh_refinement_pickled = False self.SetRefinementParameters() self.SerializeRefinementParameters() self.SerializeModelParameters() # estimate mesh size of current index self.ComputeMeshParameters() elif (self.refinement_strategy == "reading_from_file"): # TODO - Change this implementation for later # If solverWrapperIndex == [], then projectParametersPath should indicate the absolute file # Else, projectParametersPath should be a prefix such that (number).json will be appeneded if (self.solverWrapperIndex[0] >= 0): # reading of json file self.project_parameters_path = self.project_parameters_path + '_' + str( self.solverWrapperIndex[0]) + '.json' # serialization self.is_project_parameters_pickled = False self.is_model_pickled = False self.SerializeModelParameters() else: pass else: raise Exception( "Select KratosMultiphysics refinement stategy.\nOptions:\ \n i) stochastic_adaptive_refinement\ \n ii) deterministic_adaptive_refinement\ \n iii) reading_from_file") def solve(self, random_variable): if all([component >= 0 for component in self.solverWrapperIndex]): aux_qoi_array = [ [] for _ in range(0, self.number_qoi + self.number_combined_qoi) ] # to store each qoi for _ in range(0, self.number_contributions_per_instance): if (self.refinement_strategy == "stochastic_adaptive_refinement"): qoi, time_for_qoi = self.executeInstanceStochasticAdaptiveRefinement( random_variable) elif (self.refinement_strategy == "deterministic_adaptive_refinement"): qoi, time_for_qoi = self.executeInstanceDeterministicAdaptiveRefinement( random_variable) elif (self.refinement_strategy == "reading_from_file"): qoi, time_for_qoi = self.executeInstanceReadingFromFile( random_variable) # unfold qoi into its components if ((self.number_qoi + self.number_combined_qoi) == 1): qoi_list = mdu.unfoldVales_Wrapper(self.number_qoi, qoi) else: qoi_list = mdu.UnfolderManager( self.number_qoi + self.number_combined_qoi).UnfoldNValues_Task(qoi) # append components to aux array for qoi_counter in range( 0, self.number_qoi + self.number_combined_qoi): aux_qoi_array[qoi_counter].append(qoi_list[qoi_counter]) # postprocess components qoi_postprocessed = mdu.PostprocessContributionsPerInstance( aux_qoi_array, self.number_qoi, self.number_combined_qoi) # unfold qoi into its components if ((self.number_qoi + self.number_combined_qoi) == 1): qoi_list = mdu.unfoldVales_Wrapper(self.number_qoi, qoi_postprocessed) else: qoi_list = mdu.UnfolderManager( self.number_qoi + self.number_combined_qoi).UnfoldNValues_Task( qoi_postprocessed) else: qoi, time_for_qoi = mds.returnZeroQoIandTime_Task() qoi_list = [qoi] * (self.number_qoi + self.number_combined_qoi) return qoi_list, time_for_qoi #################################################################################################### ######################################### EXECUTION TOOLS ########################################## #################################################################################################### """ function executing an instance of the UQ algorithm, i.e. a single MC simulation and eventually the refinement (that occurs before the simulation run) input: self: an instance of the class output: qoi: quantity of interest value """ def executeInstanceStochasticAdaptiveRefinement(self, random_variable): current_index = self.solverWrapperIndex[0] # local variables pickled_coarse_model = self.pickled_model[0] pickled_reference_model_mapping = pickled_coarse_model pickled_coarse_project_parameters = self.pickled_project_parameters[0] pickled_custom_metric_refinement_parameters = self.pickled_custom_metric_refinement_parameters pickled_custom_remesh_refinement_parameters = self.pickled_custom_remesh_refinement_parameters current_analysis = self.analysis different_tasks = self.different_tasks mapping_flag = self.mapping_output_quantities adaptive_refinement_jump_to_finest_level = self.adaptive_refinement_jump_to_finest_level print_to_file = self.print_to_file time_for_qoi = 0.0 if (different_tasks is False): # tasks all at once qoi,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementAllAtOnce_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_analysis,time_for_qoi,mapping_flag,adaptive_refinement_jump_to_finest_level,print_to_file) elif (different_tasks is True): # multiple tasks if (current_index == 0): # index = 0 current_local_index = 0 qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file) else: # index > 0 for current_local_index in range(current_index + 1): if ((adaptive_refinement_jump_to_finest_level is False) or (adaptive_refinement_jump_to_finest_level is True and (current_local_index == 0 or current_local_index == current_index))): if (mapping_flag is False): qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file) elif (mapping_flag is True): qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,pickled_reference_model_mapping=pickled_mapping_reference_model) del (pickled_coarse_model) pickled_coarse_model = pickled_current_model del (pickled_current_model) else: # not running since we jump from coarsest to finest level pass else: raise Exception( "Boolean variable different task is not a boolean, instead is equal to", different_tasks) return qoi, time_for_qoi """ function executing an instance of the UQ algorithm, i.e. a single MC simulation and eventually the refinement (that occurs before the simulation run) input: self: an instance of the class output: qoi: quantity of interest value """ def executeInstanceDeterministicAdaptiveRefinement(self, random_variable): # local variables current_index = self.solverWrapperIndex[0] pickled_model = self.pickled_model[current_index] pickled_project_parameters = self.pickled_project_parameters[0] current_analysis = self.analysis time_for_qoi = 0.0 qoi, time_for_qoi = mds.executeInstanceDeterministicAdaptiveRefinement_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi) return qoi, time_for_qoi """ function executing an instance of the UQ algorithm, i.e. a single MC simulation and eventually the refinement (that occurs before the simulation run) input: self: an instance of the class output: qoi: quantity of interest value """ def executeInstanceReadingFromFile(self, random_variable): # local variables current_index = self.solverWrapperIndex[0] pickled_model = self.pickled_model[0] pickled_project_parameters = self.pickled_project_parameters[0] current_analysis = self.analysis time_for_qoi = 0.0 # TODO - Change this to be more general qoi, time_for_qoi = mds.executeInstanceReadingFromFile_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi) return qoi, time_for_qoi #################################################################################################### ####################################### SERIALIZATION TOOLS ######################################## #################################################################################################### """ function serializing and pickling the model and the project parameters of the problem the serialization-pickling process is the following: i) from Model/Parameters Kratos object to StreamSerializer Kratos object ii) from StreamSerializer Kratos object to pickle string iii) from pickle string to StreamSerializer Kratos object iv) from StreamSerializer Kratos object to Model/Parameters Kratos object requires: self.project_parameters_path: path of the Project Parameters file builds: self.pickled_model: pickled model self.pickled_project_parameters: pickled project parameters input: self: an instance of the class """ # def SerializeModelParameters(self): # with open(self.project_parameters_path,'r') as parameter_file: # parameters = KratosMultiphysics.Parameters(parameter_file.read()) # model = KratosMultiphysics.Model() # fake_sample = [1.0] # TODO: make application-indipendent # simulation = self.analysis(model,parameters,fake_sample) # simulation.Initialize() # serialized_model = KratosMultiphysics.StreamSerializer() # serialized_model.Save("ModelSerialization",simulation.model) # serialized_project_parameters = KratosMultiphysics.StreamSerializer() # serialized_project_parameters.Save("ParametersSerialization",simulation.project_parameters) # self.serialized_model = serialized_model # self.serialized_project_parameters = serialized_project_parameters # # pickle dataserialized_data # pickled_model = pickle.dumps(serialized_model, 2) # second argument is the protocol and is NECESSARY (according to pybind11 docs) # pickled_project_parameters = pickle.dumps(serialized_project_parameters, 2) # self.pickled_model = pickled_model # self.pickled_project_parameters = pickled_project_parameters # self.is_project_parameters_pickled = True # self.is_model_pickled = True # print("\n","#"*50," SERIALIZATION MODEL PART AND PARAMETERS COMPLETED ","#"*50,"\n") def SerializeModelParameters(self): self.serialized_model = [] self.serialized_project_parameters = [] self.pickled_model = [] self.pickled_project_parameters = [] if (self.refinement_strategy == "stochastic_adaptive_refinement" or self.refinement_strategy == "reading_from_file"): self.SerializeModelParametersStochasticAdaptiveRefinement() elif (self.refinement_strategy == "deterministic_adaptive_refinement"): self.SerializeModelParametersDeterministicAdaptiveRefinement() else: raise Exception( "Specify refinement_strategy: stochastic_adaptive_refinement or deterministic_adaptive_refinement" ) self.is_project_parameters_pickled = True self.is_model_pickled = True print("\n", "#" * 50, " SERIALIZATION MODEL AND PROJECT PARAMETERS COMPLETED ", "#" * 50, "\n") def SerializeModelParametersStochasticAdaptiveRefinement(self): with open(self.project_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize parmeters (to avoid adding new data dependent on the application) parameters = self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.StreamSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) self.serialized_project_parameters.append( serialized_project_parameters) # reset to read the model part parameters = self.wrapper.SetModelImportSettingsInputType("mdpa") # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = self.fake_sample_to_serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.StreamSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model.append(serialized_model) # pickle dataserialized_data pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2) self.pickled_model.append(pickled_model) self.pickled_project_parameters.append(pickled_project_parameters) def SerializeModelParametersDeterministicAdaptiveRefinement(self): self.SerializeModelParametersStochasticAdaptiveRefinement( ) # to prepare parameters and model part of coarsest level number_levels_to_serialize = self.solverWrapperIndex[0] # same routine of ExecuteInstanceConcurrentAdaptiveRefinemnt() to build models and parameters, but here we save models and parameters pickled_coarse_model = self.pickled_model[0] pickled_coarse_project_parameters = self.pickled_project_parameters[0] pickled_custom_metric_refinement_parameters = self.pickled_custom_metric_refinement_parameters pickled_custom_remesh_refinement_parameters = self.pickled_custom_remesh_refinement_parameters current_analysis = self.analysis # generate the sample and prepare auxiliary variables we need fake_sample = self.fake_sample_to_serialize fake_computational_time = 0.0 if (number_levels_to_serialize > 0): for current_level in range(number_levels_to_serialize + 1): if (current_level < number_levels_to_serialize): fake_qoi,pickled_current_model,fake_computational_time = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(number_levels_to_serialize,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,fake_sample,current_level,current_analysis,fake_computational_time) # mds.executeInstanceStochasticAdaptiveRefinementAux_Task(number_levels_to_serialize,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,fake_sample,current_level,current_analysis,fake_computational_time) del (pickled_coarse_model) pickled_coarse_model = pickled_current_model elif (current_level == number_levels_to_serialize): pickled_current_model, fake_computational_time = mds.executeInstanceOnlyAdaptiveRefinement_Wrapper( pickled_coarse_model, pickled_coarse_project_parameters, pickled_custom_metric_refinement_parameters, pickled_custom_remesh_refinement_parameters, fake_sample, current_level, current_analysis, fake_computational_time) # save if current level > 0 if (current_level > 0): # save pickled and serialized model and parameters self.pickled_model.append(pickled_current_model) self.serialized_model.append( pickle.loads(pickled_current_model)) del (pickled_current_model) """ function serializing and pickling the custom setting metric and remeshing for the refinement requires: self.custom_metric_refinement_parameters self.custom_remesh_refinement_parameters builds: self.pickled_custom_metric_refinement_parameters self.pickled_custom_remesh_refinement_parameters input: self: an instance of the class """ def SerializeRefinementParameters(self): metric_refinement_parameters = self.custom_metric_refinement_parameters remeshing_refinement_parameters = self.custom_remesh_refinement_parameters # save parameters as StreamSerializer Kratos objects serialized_metric_refinement_parameters = KratosMultiphysics.StreamSerializer( ) serialized_metric_refinement_parameters.Save( "MetricRefinementParametersSerialization", metric_refinement_parameters) serialized_remesh_refinement_parameters = KratosMultiphysics.StreamSerializer( ) serialized_remesh_refinement_parameters.Save( "RemeshRefinementParametersSerialization", remeshing_refinement_parameters) # pickle parameters pickled_metric_refinement_parameters = pickle.dumps( serialized_metric_refinement_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_remesh_refinement_parameters = pickle.dumps( serialized_remesh_refinement_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) self.pickled_custom_metric_refinement_parameters = pickled_metric_refinement_parameters self.pickled_custom_remesh_refinement_parameters = pickled_remesh_refinement_parameters self.is_custom_settings_metric_refinement_pickled = True self.is_custom_settings_remesh_refinement_pickled = True print("\n", "#" * 50, " SERIALIZATION REFINEMENT PARAMETERS COMPLETED ", "#" * 50, "\n") #################################################################################################### ######################################### AUXILIARY TOOLS ########################################## #################################################################################################### """ function reading the refinement parameters passed from json file input: self: an instance of the class """ def SetRefinementParameters(self): with open(self.refinement_parameters_path, 'r') as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) self.custom_metric_refinement_parameters = parameters["hessian_metric"] self.custom_remesh_refinement_parameters = parameters["refinement_mmg"] """ function giving as output the mesh discretization parameter the mesh parameter is the reciprocal of the minimum mesh size of the grid input: self: an instance of the class """ def ComputeMeshParameters(self): # unpickle and unserialize model and build Kratos Model object serialized_model = pickle.loads(self.pickled_model[0]) current_model = KratosMultiphysics.Model() serialized_model.Load("ModelSerialization", current_model) # unpickle and unserialize parameters and build Kratos Parameters object serialized_project_parameters = pickle.loads( self.pickled_project_parameters[0]) current_project_parameters = KratosMultiphysics.Parameters() serialized_project_parameters.Load("ParametersSerialization", current_project_parameters) # unpickle and unserialize metric refinement parameters and build Kratos Parameters objects serialized_custom_metric_refinement_parameters = pickle.loads( self.pickled_custom_metric_refinement_parameters) current_custom_metric_refinement_parameters = KratosMultiphysics.Parameters( ) serialized_custom_metric_refinement_parameters.Load( "MetricRefinementParametersSerialization", current_custom_metric_refinement_parameters) self.mesh_sizes = [] self.mesh_parameters = [] level = self.solverWrapperIndex[0] adaptive_refinement_manager = AdaptiveRefinement( level, current_model, current_project_parameters, current_custom_metric_refinement_parameters, None) adaptive_refinement_manager.EstimateMeshSizeCurrentLevel() h_current_level = adaptive_refinement_manager.mesh_size mesh_parameter_current_level = h_current_level**(-1) self.mesh_sizes.append(h_current_level) self.mesh_parameters.append(mesh_parameter_current_level)
def SerializeModelParametersStochasticAdaptiveRefinement(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is stochastic_adaptive_refinement. Inputs: - self: an instance of the class. """ with open(self.project_parameters_path, "r") as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize and pickle parmeters to serialize the model in MPI self.wrapper.SetModelImportSettingsInputType("use_input_model_part") serialized_project_parameters_tmp = KratosMultiphysics.MpiSerializer() serialized_project_parameters_tmp.Save("ParametersSerialization", parameters) pickled_project_parameters_tmp = pickle.dumps( serialized_project_parameters_tmp, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) # remove the materials filename to pickle the parameters # this is required to read the materials only once # finally, we restore the materials filename to read the materials # in the model serialization # it is important to serialize first the parameters and then the model # to avoid additional data which may be added to the parameters # remove materials filename from Kratos settings and revert model part type materials_filename = self.wrapper.GetMaterialsFilename() self.wrapper.SetMaterialsFilename("") # serialize and pickle Kratos project parameters serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) # append to attributes self.serialized_project_parameters.append( serialized_project_parameters) self.pickled_project_parameters.append(pickled_project_parameters) # reset to read the model part and materials filename self.wrapper.SetModelImportSettingsInputType("mdpa") self.wrapper.SetMaterialsFilename(materials_filename) # pickle and eventually serialize model if self.is_mpi: if not parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("XMC is set in MPI but Kratos is not!")) # self.serialized_model cannot be retrieved in MPI so only pickled model is returned # returns: [[model1_1,model_1_2, model_1_3, model_1_4], [model2_1,model_2_2, model_2_3, model_2_4]] # we need to pass the index to serialize with the correct number of MPI processors # however, since pickled_project_parameters is the same across levels, the same model part is considered current_index = self.solverWrapperIndex[0] pickled_model = mpi_mds.SerializeMPIModel_Wrapper( \ pickled_project_parameters_tmp, self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis, current_index=current_index) else: if parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("Kratos is set in MPI but XMC is not!")) pickled_model = self.SerializeSerialModel(parameters) # append to attribute self.pickled_model.append(pickled_model) # remove temporary objects created for MPI serialization del (serialized_project_parameters_tmp) del (pickled_project_parameters_tmp)
class KratosSolverWrapper(sw.SolverWrapper): """ Solver wrapper class managing Kratos Multiphysics (Kratos) solver. Attributes: - analysis: Kratos analysis stage. The analysis stage class default name is SimulationScenario. The default file name is simulation_scenario. It is imported with the "analysisStage" key. By default an example analysis stage is called. - adaptive_refinement_jump_to_finest_level: boolean. Used in multilevel algorithms when "stochastic_adaptive_refinement" strategy is selected. If true, intermediate refinement indices are skipped. Set by adaptiveRefinementJumpToFinestLevel key. - asynchronous: boolean. If true, the asynchronous algorithm should be run. If false, the standard synchronous algorithms should be run. Set by asynchronous key. - different_tasks: boolean. Used in multilevel algorithms when "stochastic_adaptive_refinement" strategy is selected. If true, different indices are run all together in the same task. If false, each index is run in a different task. Set by not TaskAllAtOnce key. - fake_sample_to_serialize: list. A variable which is used just to serialize the Kratos Model and the Kratos Parameters. The list should be of the same type of the random variable generated by the generator. Set by fakeRandomVariable key. - is_mpi: boolean stating if problem is run in MPI or in serial. - mapping_output_quantities: boolean. If true, the analysis stage is prepared to map the variables of interest to a reference Kratos Model. By default, such Kratos Model is the coarsest index. Set by mappingOutputQuantities key. - number_contributions_per_instance: integer. Defines the number of realization per each solve call. Useful if one wants to exploit ensemble average, together with hierarchical Monte Carlo methods. Set by numberContributionsPerInstance key. - outputBatchSize: integer. Defines the size of each sub-list of the Quantities of Interest list which is returned by the solve method. It is alternative to outputDimension, defined below. Set by OutputBatchSize. - outputDimension: integer or list of integers. If integer, equals to len(sample), where sample is the first output argument of self.solve(). If list of integers, then it means that samples are split in future lists, and outputDimension is [len(subSample) for subSample in sample]. Set by OutputDimension key. - print_to_file: boolean. If true, prepares the distributed environment programing model PyCOMPSs to write a file inside the solve task. Set by printToFile key. - project_parameters_path: string or list of strings. Defines the path to Kratos Project Parameters. Set by projectParametersPath key. - qoi_estimator: list of strings. Each string is the moment estimator name to which each quantity of interest is associated. - refinement_parameters_path: string. Define the path to the Kratos Adaptive Refinement Project Parameters. Set by refinementParametersPath key. - refinement_strategy: string. Options are: "reading_from_file", "deterministic_adaptive_refinement", "stochastic_adaptive_refinement". It defines the refinement strategy for multilevel algorithms. Set by refinementStrategy key. - size_multi_x_moment_estimator: integer. Defines the size of each vector quantity if interest. If integer, vector quantities of interest have the same size. It is required to set a priori this value only because of returnZeroQoiAndTime_Task, which needs to know how many 0s to return. Set by sizeMultiXMomentEstimator. Obs: in future, also a list will be supported. If list, the list has the same length of numberMultiMomentEstimator+numberMultiCombinedMomentEstimator. Methods: - serialize: method serializing Kratos Model and Kratos Parameters. - solve: method running the problem. Other methods are called from the two methods defined above. """ # TODO: are both outputBatchSize and outputBatchSize needed? Probably not. def __init__(self, **keywordArgs): super().__init__(**keywordArgs) self.analysis = dynamicImport( keywordArgs.get( "analysisStage", ("xmc.classDefs_solverWrapper.methodDefs_KratosSolverWrapper" ".simulation_definition.SimulationScenario"))) self.adaptive_refinement_jump_to_finest_level = keywordArgs.get( "adaptiveRefinementJumpToFinestLevel", False) self.asynchronous = keywordArgs.get("asynchronous", False) self.different_tasks = not keywordArgs.get("taskAllAtOnce", True) self.fake_sample_to_serialize = keywordArgs.get("fakeRandomVariable") self.mapping_output_quantities = keywordArgs.get( "mappingOutputQuantities", False) self.is_mpi = keywordArgs.get("isMpi", False) self.number_contributions_per_instance = keywordArgs.get( "numberContributionsPerInstance", 1) self.outputBatchSize = keywordArgs.get("outputBatchSize", 1) self.print_to_file = keywordArgs.get("printToFile", False) self.project_parameters_path = keywordArgs.get("projectParametersPath") self.qoi_estimator = keywordArgs.get("qoiEstimator") self.refinement_parameters_path = keywordArgs.get( "refinementParametersPath") self.refinement_strategy = keywordArgs.get("refinementStrategy") self.size_multi_x_moment_estimator = keywordArgs.get( "sizeMultiXMomentEstimator", -1) # remove after returnZeroQoiAndTime_Task is removed # Set outputDimension self.outputDimension = keywordArgs.get("outputDimension", None) # If not given, compute from self.outputBatchSize for backward compatibility if self.outputDimension is None: outputNb = self._numberOfOutputs() # Total number of output splits, including (possibly) a last one of smaller size batchNb = int(math.ceil(outputNb / self.outputBatchSize)) # Assemble the list of sizes of each split # They are all equal to outputBatchSize, except perhaps the last one # E.g. outputBatchSize=2 and outputNb=5 gives [2,2,1] self.outputDimension = [ min(self.outputBatchSize, outputNb - i * self.outputBatchSize) for i in range(batchNb) ] # workaround for Monte Carlo if (self.solverWrapperIndex == []): self.solverWrapperIndex.append(0) if (self.solverWrapperIndex[0] >= 0): # for index < 0 not needed if (self.asynchronous is not True): # synchronous framework self.serialize() else: # asynchronous framework pass def serialize(self): """ Method serializing Kratos Model and Kratos Parameters. Inputs: - self: an instance of the class. """ if self.refinement_strategy not in [ "stochastic_adaptive_refinement", "deterministic_adaptive_refinement", "reading_from_file" ]: raise Exception( "Select KratosMultiphysics refinement stategy.\nOptions:\ \n i) stochastic_adaptive_refinement\ \n ii) deterministic_adaptive_refinement\ \n iii) reading_from_file") self.is_project_parameters_pickled = False self.is_model_pickled = False self.is_custom_settings_metric_refinement_pickled = False self.is_custom_settings_remesh_refinement_pickled = False self.SetRefinementParameters() self.SerializeRefinementParameters() self.SerializeModelParameters() print(self.__class__.__name__, ": Model and parameters serialized correctly.") def solve(self, random_variable): """ Method running the problem. Inputs: - self: an instance of the class. - random_variable: random event in the form of list. Outputs: - qoi_list: list of structure respecting self.outputDimension. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ if all([component >= 0 for component in self.solverWrapperIndex]): aux_qoi_array = [] # loop over contributions (by default only one) for contribution_counter in range( 0, self.number_contributions_per_instance): self.current_local_contribution = contribution_counter # if multiple ensembles, append a seed to the random variable list # for example, this seed is used to generate different initial conditions if self.number_contributions_per_instance > 1: random_variable.append(int(np.random.uniform(0, 429496729))) # solve if (self.refinement_strategy == "stochastic_adaptive_refinement"): qoi, time_for_qoi = self.executeInstanceStochasticAdaptiveRefinement( random_variable) elif (self.refinement_strategy == "deterministic_adaptive_refinement"): qoi, time_for_qoi = self.executeInstanceDeterministicAdaptiveRefinement( random_variable) elif (self.refinement_strategy == "reading_from_file"): qoi, time_for_qoi = self.executeInstanceReadingFromFile( random_variable) # append components to aux array aux_qoi_array.append(qoi) # delete COMPSs future objects no longer needed delete_object(random_variable) # postprocess components if self.number_contributions_per_instance > 1: unm = mdu.UnfolderManager(self._numberOfOutputs(), self.outputBatchSize) if (self._numberOfOutputs() == self.outputBatchSize): qoi_list = [ unm.PostprocessContributionsPerInstance_Task( aux_qoi_array, self.qoi_estimator, returns=math.ceil(self._numberOfOutputs() / self.outputBatchSize)) ] elif (self._numberOfOutputs() > self.outputBatchSize): qoi_list = unm.PostprocessContributionsPerInstance_Task( aux_qoi_array, self.qoi_estimator, returns=math.ceil(self._numberOfOutputs() / self.outputBatchSize)) else: raise Exception( "_numberOfOutputs() returns a value smaller than self.outputBatchSize. Set outputBatchSize smaller or equal to the number of scalar outputs." ) delete_object(unm) else: # unfold qoi into its components of fixed size unm = mdu.UnfolderManager(self._numberOfOutputs(), self.outputBatchSize) if (self._numberOfOutputs() == self.outputBatchSize): qoi_list = [ unm.UnfoldNValues_Task( aux_qoi_array[0], returns=math.ceil(self._numberOfOutputs() / self.outputBatchSize)) ] elif (self._numberOfOutputs() > self.outputBatchSize): qoi_list = unm.UnfoldNValues_Task( aux_qoi_array[0], returns=math.ceil(self._numberOfOutputs() / self.outputBatchSize)) else: raise Exception( "_numberOfOutputs() returns a value smaller than self.outputBatchSize. Set outputBatchSize smaller or equal to the number of scalar outputs." ) # delete COMPSs future objects no longer needed delete_object(unm) # delete COMPSs future objects no longer needed for contribution_counter in range( 0, self.number_contributions_per_instance): delete_object(aux_qoi_array[contribution_counter]) #delete_object(qoi) del (aux_qoi_array) else: qoi, time_for_qoi = mds.returnZeroQoiAndTime_Task( self.qoi_estimator, self.size_multi_x_moment_estimator) # unfold qoi into its components of fixed size unm = mdu.UnfolderManager(self._numberOfOutputs(), self.outputBatchSize) if (self._numberOfOutputs() == self.outputBatchSize): qoi_list = [ unm.UnfoldNValues_Task( qoi, returns=math.ceil(self._numberOfOutputs() / self.outputBatchSize)) ] elif (self._numberOfOutputs() > self.outputBatchSize): qoi_list = unm.UnfoldNValues_Task( qoi, returns=math.ceil(self._numberOfOutputs() / self.outputBatchSize)) else: raise Exception( "_numberOfOutputs() returns a value smaller than self.outputBatchSize. Set outputBatchSize smaller or equal to the number of scalar outputs." ) # delete COMPSs future objects no longer needed delete_object(unm) delete_object(qoi) return qoi_list, time_for_qoi #################################################################################################### ######################################### EXECUTION TOOLS ########################################## #################################################################################################### def executeInstanceStochasticAdaptiveRefinement(self, random_variable): """ Method executing an instance of the UQ algorithm, i.e. a single MC realization and eventually the refinement (that occurs before the simulation run). To be called if the selected refinement strategy is stochastic_adaptive_refinement. Inputs: - self: an instance of the class. Outputs: - qoi: list. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ # local variables current_index = self.solverWrapperIndex[0] pickled_coarse_model = self.pickled_model[0] pickled_reference_model_mapping = pickled_coarse_model pickled_coarse_project_parameters = self.pickled_project_parameters[0] pickled_custom_metric_refinement_parameters = self.pickled_custom_metric_refinement_parameters pickled_custom_remesh_refinement_parameters = self.pickled_custom_remesh_refinement_parameters current_analysis = self.analysis different_tasks = self.different_tasks mapping_flag = self.mapping_output_quantities adaptive_refinement_jump_to_finest_level = self.adaptive_refinement_jump_to_finest_level print_to_file = self.print_to_file current_local_contribution = self.current_local_contribution time_for_qoi = 0.0 if (different_tasks is False): # single task if self.is_mpi: qoi,time_for_qoi = \ mpi_mds.executeInstanceStochasticAdaptiveRefinementAllAtOnce_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_analysis,time_for_qoi,mapping_flag,adaptive_refinement_jump_to_finest_level,print_to_file,current_local_contribution) else: qoi,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementAllAtOnce_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_analysis,time_for_qoi,mapping_flag,adaptive_refinement_jump_to_finest_level,print_to_file,current_local_contribution) elif (different_tasks is True): # multiple tasks if (current_index == 0): # index = 0 current_local_index = 0 if self.is_mpi: qoi,pickled_current_model,time_for_qoi = \ mpi_mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution) else: qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution) delete_object(pickled_current_model) else: # index > 0 for current_local_index in range(current_index + 1): if ((adaptive_refinement_jump_to_finest_level is False) or (adaptive_refinement_jump_to_finest_level is True and (current_local_index == 0 or current_local_index == current_index))): if (mapping_flag is False): qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution) elif (mapping_flag is True): qoi,pickled_current_model,time_for_qoi = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(current_index,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,random_variable,current_local_index,current_analysis,time_for_qoi,mapping_flag,print_to_file,current_local_contribution,pickled_mapping_reference_model=pickled_reference_model_mapping) delete_object(pickled_coarse_model) del (pickled_coarse_model) pickled_coarse_model = pickled_current_model del (pickled_current_model) else: # not running since we jump from coarsest to finest level pass delete_object(pickled_coarse_model) else: raise Exception( "Boolean variable different task is not a boolean, instead is equal to", different_tasks) return qoi, time_for_qoi def executeInstanceDeterministicAdaptiveRefinement(self, random_variable): """ Method executing an instance of the UQ algorithm, i.e. a single MC realization and eventually the refinement (that occurs before the simulation run). To be called if the selected refinement strategy is deterministic_adaptive_refinement. Inputs: - self: an instance of the class. Outputs: - qoi: list. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ # local variables current_index = self.solverWrapperIndex[0] pickled_model = self.pickled_model[current_index] pickled_mapping_reference_model = self.pickled_model[0] pickled_project_parameters = self.pickled_project_parameters[ current_index] mapping_flag = self.mapping_output_quantities print_to_file = self.print_to_file current_local_contribution = self.current_local_contribution current_analysis = self.analysis time_for_qoi = 0.0 if self.is_mpi: qoi, time_for_qoi = mpi_mds.executeInstanceDeterministicAdaptiveRefinement_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi, mapping_flag, pickled_mapping_reference_model, print_to_file, current_local_contribution) else: qoi, time_for_qoi = mds.executeInstanceDeterministicAdaptiveRefinement_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi, mapping_flag, pickled_mapping_reference_model, print_to_file, current_local_contribution) return qoi, time_for_qoi def executeInstanceReadingFromFile(self, random_variable): """ Method executing an instance of the UQ algorithm, i.e. a single MC realization and eventually the refinement (that occurs before the simulation run). To be called if the selected refinement strategy is reading_from_file. Inputs: - self: an instance of the class. Outputs: - qoi: list. It contains the quantities of interest. - time_for_qoi: float. Measure of time to generate the sample. """ # local variables current_index = self.solverWrapperIndex[0] pickled_model = self.pickled_model[current_index] pickled_mapping_reference_model = self.pickled_mapping_reference_model[ current_index] pickled_project_parameters = self.pickled_project_parameters[ current_index] mapping_flag = self.mapping_output_quantities print_to_file = self.print_to_file current_local_contribution = self.current_local_contribution current_analysis = self.analysis time_for_qoi = 0.0 if self.is_mpi: qoi, time_for_qoi = mpi_mds.executeInstanceReadingFromFile_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi, mapping_flag, pickled_mapping_reference_model, print_to_file, current_local_contribution) else: qoi, time_for_qoi = mds.executeInstanceReadingFromFile_Wrapper( current_index, pickled_model, pickled_project_parameters, current_analysis, random_variable, time_for_qoi, mapping_flag, pickled_mapping_reference_model, print_to_file, current_local_contribution) return qoi, time_for_qoi #################################################################################################### ####################################### SERIALIZATION TOOLS ######################################## #################################################################################################### def SerializeModelParameters(self): """ Method managing the serialization and pickling of the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. The serialization-pickling process is the following: i) from Model/Parameters Kratos object to MpiSerializer Kratos object, ii) from MpiSerializer Kratos object to pickle string, iii) from pickle string to MpiSerializer Kratos object, iv) from MpiSerializer Kratos object to Model/Parameters Kratos object. Depending on the refinement strategy, three different methods may be called and are defined next. We remark that creating the class member pickled_mapping_reference_model is required by MPI runs, since we need such coarse model to be serialized with the same number of processors of the MPI task. Inputs: - self: an instance of the class. """ self.serialized_model = [] self.serialized_project_parameters = [] self.pickled_model = [] self.pickled_project_parameters = [] self.pickled_mapping_reference_model = [] if (self.refinement_strategy == "stochastic_adaptive_refinement"): self.SerializeModelParametersStochasticAdaptiveRefinement() elif (self.refinement_strategy == "deterministic_adaptive_refinement"): self.SerializeModelParametersDeterministicAdaptiveRefinement() elif (self.refinement_strategy == "reading_from_file"): self.SerializeModelParametersReadingFromFile() else: raise Exception( "Specify refinement_strategy: stochastic_adaptive_refinement or deterministic_adaptive_refinement or reading_from_file" ) self.is_project_parameters_pickled = True self.is_model_pickled = True def SerializeSerialModel(self, parameters): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. It is called if we are not runnnig in MPI. Inputs: - self: an instance of the class. - parameters: KratosMultiphysics.ProjectParameters object. It contains the settings of the simulation. """ # prepare the model to serialize model = KratosMultiphysics.Model() fake_sample = self.fake_sample_to_serialize simulation = self.analysis(model, parameters, fake_sample) simulation.Initialize() # reset general flags main_model_part_name = self.wrapper.GetModelPartName() simulation.model.GetModelPart( main_model_part_name).ProcessInfo.SetValue( KratosMultiphysics.IS_RESTARTED, True) # serialize model serialized_model = KratosMultiphysics.MpiSerializer() serialized_model.Save("ModelSerialization", simulation.model) self.serialized_model.append(serialized_model) # pickle dataserialized_data pickled_model = pickle.dumps( serialized_model, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) return pickled_model def SerializeModelParametersStochasticAdaptiveRefinement(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is stochastic_adaptive_refinement. Inputs: - self: an instance of the class. """ with open(self.project_parameters_path, "r") as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize and pickle parmeters to serialize the model in MPI self.wrapper.SetModelImportSettingsInputType("use_input_model_part") serialized_project_parameters_tmp = KratosMultiphysics.MpiSerializer() serialized_project_parameters_tmp.Save("ParametersSerialization", parameters) pickled_project_parameters_tmp = pickle.dumps( serialized_project_parameters_tmp, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) # remove the materials filename to pickle the parameters # this is required to read the materials only once # finally, we restore the materials filename to read the materials # in the model serialization # it is important to serialize first the parameters and then the model # to avoid additional data which may be added to the parameters # remove materials filename from Kratos settings and revert model part type materials_filename = self.wrapper.GetMaterialsFilename() self.wrapper.SetMaterialsFilename("") # serialize and pickle Kratos project parameters serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) # append to attributes self.serialized_project_parameters.append( serialized_project_parameters) self.pickled_project_parameters.append(pickled_project_parameters) # reset to read the model part and materials filename self.wrapper.SetModelImportSettingsInputType("mdpa") self.wrapper.SetMaterialsFilename(materials_filename) # pickle and eventually serialize model if self.is_mpi: if not parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("XMC is set in MPI but Kratos is not!")) # self.serialized_model cannot be retrieved in MPI so only pickled model is returned # returns: [[model1_1,model_1_2, model_1_3, model_1_4], [model2_1,model_2_2, model_2_3, model_2_4]] # we need to pass the index to serialize with the correct number of MPI processors # however, since pickled_project_parameters is the same across levels, the same model part is considered current_index = self.solverWrapperIndex[0] pickled_model = mpi_mds.SerializeMPIModel_Wrapper( \ pickled_project_parameters_tmp, self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis, current_index=current_index) else: if parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("Kratos is set in MPI but XMC is not!")) pickled_model = self.SerializeSerialModel(parameters) # append to attribute self.pickled_model.append(pickled_model) # remove temporary objects created for MPI serialization del (serialized_project_parameters_tmp) del (pickled_project_parameters_tmp) def SerializeModelParametersDeterministicAdaptiveRefinement(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is deterministic_adaptive_refinement. Inputs: - self: an instance of the class. """ # Serialize model and parameters of coarsest level (level = 0). # If we are running with MPI parallel type, # the model is being serialized in a MPI task # with the same number of processes required by level = self.solverWrapperIndex[0]. # This strategy works in both cases the solverWrapper instance is solving level 0 # or if it is solving levels > 0. self.SerializeModelParametersStochasticAdaptiveRefinement() # now serialize levels > 0 number_levels_to_serialize = self.solverWrapperIndex[0] # same routine of executeInstanceStochasticAdaptiveRefinement() to build models and parameters, but here we save models and parameters pickled_coarse_model = self.pickled_model[0] pickled_coarse_project_parameters = self.pickled_project_parameters[0] pickled_custom_metric_refinement_parameters = self.pickled_custom_metric_refinement_parameters pickled_custom_remesh_refinement_parameters = self.pickled_custom_remesh_refinement_parameters current_analysis = self.analysis # generate the sample and prepare auxiliary variables we need fake_sample = self.fake_sample_to_serialize fake_computational_time = 0.0 if (number_levels_to_serialize > 0): for current_level in range(number_levels_to_serialize + 1): if not self.is_mpi: # serial fake_qoi,pickled_current_model,fake_computational_time = \ mds.executeInstanceStochasticAdaptiveRefinementMultipleTasks_Wrapper(number_levels_to_serialize,pickled_coarse_model,pickled_coarse_project_parameters,pickled_custom_metric_refinement_parameters,pickled_custom_remesh_refinement_parameters,fake_sample,current_level,current_analysis,fake_computational_time,mapping_flag=False,print_to_file=False,current_contribution=0) elif self.is_mpi and current_level == number_levels_to_serialize: # MPI and we serialize level of interest adaptive_refinement_jump_to_finest_level = self.adaptive_refinement_jump_to_finest_level pickled_current_model = mpi_mds.SerializeDeterministicAdaptiveRefinementMPIModel_Wrapper( current_level, pickled_coarse_model, pickled_coarse_project_parameters, pickled_custom_metric_refinement_parameters, pickled_custom_remesh_refinement_parameters, fake_sample, current_analysis, fake_computational_time, adaptive_refinement_jump_to_finest_level) else: # MPI parallel type and we do not serialize since it is not the level of interest # we set pickled model equal to coarsest model as workaround pickled_current_model = pickled_coarse_model del (pickled_coarse_model) pickled_coarse_model = pickled_current_model # save if current level > 0 (level = 0 has already been saved) if (current_level > 0): # save pickled and serialized model and parameters self.pickled_model.append(pickled_current_model) # self.serialized_model.append(pickle.loads(get_value_from_remote(pickled_current_model))) # commented since gives problem when solving with PyCOMPSs self.pickled_project_parameters.append( pickled_coarse_project_parameters) # self.serialized_project_parameters.append(pickle.loads(get_value_from_remote(pickled_coarse_project_parameters))) # commented since gives problem when solving with PyCOMPSs del (pickled_current_model) def SerializeModelParametersReadingFromFile(self): """ Method serializing and pickling the Kratos Model and the Kratos Parameters of the problem. It builds self.pickled_model and self.pickled_project_parameters. To be called if the selected refinement strategy is reading_from_file. Inputs: - self: an instance of the class. """ current_index = 0 for parameters_path in self.project_parameters_path: with open(parameters_path, "r") as parameter_file: parameters = KratosMultiphysics.Parameters( parameter_file.read()) # create wrapper instance to modify current project parameters self.wrapper = ParametersWrapper(parameters) # serialize and pickle parmeters to serialize the model in MPI # it is not required to remove the materials, since the Kratos variable # IS_RESTARTED is set to True self.wrapper.SetModelImportSettingsInputType( "use_input_model_part") serialized_project_parameters = KratosMultiphysics.MpiSerializer() serialized_project_parameters.Save("ParametersSerialization", parameters) # append to attributes self.serialized_project_parameters.append( serialized_project_parameters) pickled_project_parameters = pickle.dumps( serialized_project_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) self.pickled_project_parameters.append(pickled_project_parameters) # reset to read the model part self.wrapper.SetModelImportSettingsInputType("mdpa") # pickle and eventually serialize model if self.is_mpi: if not parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("XMC is set in MPI but Kratos is not!")) # self.serialized_model cannot be retrieved in MPI so only pickled model is returned # returns: [[model1_1,model_1_2, model_1_3, model_1_4], [model2_1,model_2_2, model_2_3, model_2_4]] pickled_model = mpi_mds.SerializeMPIModel_Wrapper( \ pickled_project_parameters, self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis, current_index) pickled_mapping_reference_model = mpi_mds.SerializeMPIModel_Wrapper( \ self.pickled_project_parameters[0], self.wrapper.GetModelPartName(), self.fake_sample_to_serialize, self.analysis, current_index) current_index += 1 else: if parameters["problem_data"]["parallel_type"].GetString( ) == "MPI": raise (Exception("Kratos is set in MPI but XMC is not!")) pickled_model = self.SerializeSerialModel(parameters) # append to attribute self.pickled_model.append(pickled_model) if self.is_mpi: self.pickled_mapping_reference_model.append( pickled_mapping_reference_model) else: self.pickled_mapping_reference_model.append( self.pickled_model[0]) def SerializeRefinementParameters(self): """ Method serializing and pickling the custom setting metric and remeshing for the adaptive refinement. It requires self.custom_metric_refinement_parameters and self.custom_remesh_refinement_parameters. It builds self.pickled_custom_metric_refinement_parameters and self.pickled_custom_remesh_refinement_parameters. Inputs: - self: an instance of the class. """ metric_refinement_parameters = self.custom_metric_refinement_parameters remeshing_refinement_parameters = self.custom_remesh_refinement_parameters # save parameters as MpiSerializer Kratos objects serialized_metric_refinement_parameters = KratosMultiphysics.MpiSerializer( ) serialized_metric_refinement_parameters.Save( "MetricRefinementParametersSerialization", metric_refinement_parameters) serialized_remesh_refinement_parameters = KratosMultiphysics.MpiSerializer( ) serialized_remesh_refinement_parameters.Save( "RemeshRefinementParametersSerialization", remeshing_refinement_parameters) # pickle parameters pickled_metric_refinement_parameters = pickle.dumps( serialized_metric_refinement_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) pickled_remesh_refinement_parameters = pickle.dumps( serialized_remesh_refinement_parameters, 2 ) # second argument is the protocol and is NECESSARY (according to pybind11 docs) self.pickled_custom_metric_refinement_parameters = pickled_metric_refinement_parameters self.pickled_custom_remesh_refinement_parameters = pickled_remesh_refinement_parameters self.is_custom_settings_metric_refinement_pickled = True self.is_custom_settings_remesh_refinement_pickled = True #################################################################################################### ######################################### AUXILIARY TOOLS ########################################## #################################################################################################### def SetRefinementParameters(self): """ Method reading the refinement parameters passed from json file. Inputs: - self: an instance of the class. """ with open(self.refinement_parameters_path, "r") as parameter_file: parameters = KratosMultiphysics.Parameters(parameter_file.read()) if parameters.Has("metric"): self.custom_metric_refinement_parameters = parameters["metric"] elif parameters.Has("hessian_metric"): self.custom_metric_refinement_parameters = parameters[ "hessian_metric"] warnings.warn( ("The metric settings are passed through the \"hessian_metric\" key." " This is deprecated and will be removed soon." " Instead, you should pass the metric settings using the \"metric\" key." ), FutureWarning, ) else: raise Exception( "Refinement parameters, set by refinement_parameters_path, does not contain the required key \"metric\"." ) if parameters.Has("remeshing"): self.custom_remesh_refinement_parameters = parameters["remeshing"] elif parameters.Has("refinement_mmg"): self.custom_remesh_refinement_parameters = parameters[ "refinement_mmg"] warnings.warn( ("The remeshing settings are passed through the \"refinement_mmg\" key." " This is deprecated and will be removed soon." " Instead, you should pass the metric settings using the \"remeshing\" key." ), FutureWarning, ) else: raise Exception( "Refinement parameters, set by refinement_parameters_path, does not contain the required key \"remeshing\"." ) def ComputeMeshParameters(self): """ Method computing the mesh discretization parameter self.mesh_parameters and the mesh sizes self.mesh_sizes. The mesh parameter is the reciprocal of the minimum mesh size of the grid. Inputs: - self: an instance of the class. """ # unpickle and unserialize model and build Kratos Model object serialized_model = pickle.loads(self.pickled_model[0]) current_model = KratosMultiphysics.Model() serialized_model.Load("ModelSerialization", current_model) # unpickle and unserialize parameters and build Kratos Parameters object serialized_project_parameters = pickle.loads( self.pickled_project_parameters[0]) current_project_parameters = KratosMultiphysics.Parameters() serialized_project_parameters.Load("ParametersSerialization", current_project_parameters) # unpickle and unserialize metric refinement parameters and build Kratos Parameters objects serialized_custom_metric_refinement_parameters = pickle.loads( self.pickled_custom_metric_refinement_parameters) current_custom_metric_refinement_parameters = KratosMultiphysics.Parameters( ) serialized_custom_metric_refinement_parameters.Load( "MetricRefinementParametersSerialization", current_custom_metric_refinement_parameters) self.mesh_sizes = [] self.mesh_parameters = [] level = self.solverWrapperIndex[0] adaptive_refinement_manager = AdaptiveRefinement( level, current_model, current_project_parameters, current_custom_metric_refinement_parameters, None) adaptive_refinement_manager.EstimateMeshSizeCurrentLevel() h_current_level = adaptive_refinement_manager.mesh_size mesh_parameter_current_level = h_current_level**(-1) self.mesh_sizes.append(h_current_level) self.mesh_parameters.append(mesh_parameter_current_level) def _numberOfOutputs(self): """ Internal method returning the total number of outputs, regardless of how how many members vector quantities of interest have. Inputs: - self: an instance of the class. """ return len(self.qoi_estimator)