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) self.wrapper.SetModelImportSettingsInputType("use_input_model_part") materials_filename = self.wrapper.GetMaterialsFilename() self.wrapper.SetMaterialsFilename("") serialized_project_parameters = KratosMultiphysics.StreamSerializer() serialized_project_parameters.Save("ParametersSerialization",parameters) self.serialized_project_parameters = serialized_project_parameters # reset to read the model part self.wrapper.SetModelImportSettingsInputType("mdpa") self.wrapper.SetMaterialsFilename(materials_filename) # 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. 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)