def ConstructStationarityTool(self): self.stationarity = False self.stationarity_counter = self.GetStationarityCounter() self.stationarity_tool = SDP.StationarityAssessmentTool( self.project_parameters["stationarity"] ["max_pressure_variation_rate_tol"].GetDouble(), SDP.FunctionsCalculator())
elif spheres_model_part.NumberOfElements(0) == 0: DEM_parameters.meso_scale_length = 1.0 projection_module = CFD_DEM_coupling.ProjectionModule(fluid_model_part, spheres_model_part, rigid_face_model_part, domain_size, pp) projection_module.UpdateDatabase(h_min) # creating a custom functions calculator for the implementation of additional custom functions custom_functions_tool = swim_proc.FunctionsCalculator(pp) # creating a basset_force tool to perform the operations associated with the calculation of this force along the path of each particle if pp.CFD_DEM.basset_force_type > 0: basset_force_tool = swim_proc.BassetForceTools() # creating a stationarity assessment tool stationarity_tool = swim_proc.StationarityAssessmentTool(DEM_parameters.max_pressure_variation_rate_tol , custom_functions_tool) # creating a debug tool dem_volume_tool = swim_proc.ProjectionDebugUtils(DEM_parameters.fluid_domain_volume, fluid_model_part, spheres_model_part, custom_functions_tool) # creating a distance calculation process for the embedded technology # (used to calculate elemental distances defining the structure embedded in the fluid mesh) if (DEM_parameters.embedded_option): calculate_distance_process = CalculateSignedDistanceTo3DSkinProcess(rigid_face_model_part, fluid_model_part) calculate_distance_process.Execute() # constructing a model part for the DEM inlet. it contains the DEM elements to be released during the simulation if (DEM_parameters.dem_inlet_option): max_DEM_node_Id = creator_destructor.FindMaxNodeIdInModelPart(spheres_model_part) max_elem_Id = creator_destructor.FindMaxElementIdInModelPart(spheres_model_part)
def Initialize(self): Say('Initializing Problem...\n') self.run_code = self.GetRunCode() # Moving to the recently created folder os.chdir(self.main_path) [self.post_path, data_and_results, self.graphs_path, MPI_results] = \ self.procedures.CreateDirectories(str(self.main_path), str(self.pp.CFD_DEM["problem_name"].GetString()), self.run_code) SDP.CopyInputFilesIntoFolder(self.main_path, self.post_path) self.MPI_results = MPI_results #self.mixed_model_part = self.all_model_parts.Get('MixedPart') vars_man.ConstructListsOfVariables(self.pp) self.FluidInitialize() self.DispersePhaseInitialize() self.SetAllModelParts() self.SetCutsOutput() self.swimming_DEM_gid_io = \ swimming_DEM_gid_output.SwimmingDEMGiDOutput( self.pp.CFD_DEM["problem_name"].GetString(), self.pp.VolumeOutput, self.pp.GiDPostMode, self.pp.GiDMultiFileFlag, self.pp.GiDWriteMeshFlag, self.pp.GiDWriteConditionsFlag ) self.swimming_DEM_gid_io.initialize_swimming_DEM_results( self.spheres_model_part, self.cluster_model_part, self.rigid_face_model_part, self.mixed_model_part) self.SetDragOutput() self.SetPointGraphPrinter() self.TransferGravityFromDisperseToFluid() self.AssignKinematicViscosityFromDynamicViscosity() # coarse-graining: applying changes to the physical properties of the model to adjust for # the similarity transformation if required (fluid effects only). SDP.ApplySimilarityTransformations( self.fluid_model_part, self.pp.CFD_DEM["similarity_transformation_type"].GetInt(), self.pp.CFD_DEM["model_over_real_diameter_factor"].GetDouble()) self.SetPostUtils() # creating an IOTools object to perform other printing tasks self.io_tools = SDP.IOTools(self.pp) # creating a projection module for the fluid-DEM coupling self.h_min = 0.01 n_balls = 1 fluid_volume = 10 # the variable n_particles_in_depth is only relevant in 2D problems self.pp.CFD_DEM.AddEmptyValue("n_particles_in_depth").SetInt( int(math.sqrt(n_balls / fluid_volume))) # creating a physical calculations module to analyse the DEM model_part dem_physics_calculator = SphericElementGlobalPhysicsCalculator( self.spheres_model_part) if self.pp.CFD_DEM["coupling_level_type"].GetInt(): default_meso_scale_length_needed = ( self.pp.CFD_DEM["meso_scale_length"].GetDouble() <= 0.0 and self.spheres_model_part.NumberOfElements(0) > 0) if default_meso_scale_length_needed: biggest_size = ( 2 * dem_physics_calculator.CalculateMaxNodalVariable( self.spheres_model_part, RADIUS)) self.pp.CFD_DEM["meso_scale_length"].SetDouble(20 * biggest_size) elif self.spheres_model_part.NumberOfElements(0) == 0: self.pp.CFD_DEM["meso_scale_length"].SetDouble(1.0) self.projection_module = CFD_DEM_coupling.ProjectionModule( self.fluid_model_part, self.spheres_model_part, self.rigid_face_model_part, self.pp, flow_field=self.GetFieldUtility()) self.projection_module.UpdateDatabase(self.h_min) # creating a custom functions calculator for the implementation of # additional custom functions self.custom_functions_tool = SDP.FunctionsCalculator(self.pp) # creating a stationarity assessment tool self.stationarity_tool = SDP.StationarityAssessmentTool( self.pp.CFD_DEM["max_pressure_variation_rate_tol"].GetDouble(), self.custom_functions_tool) # creating a debug tool self.dem_volume_tool = self.GetVolumeDebugTool() #self.SetEmbeddedTools() Say('Initialization Complete\n') self.report.Prepare(self.timer, self.pp.CFD_DEM["ControlTime"].GetDouble()) #first_print = True; index_5 = 1; index_10 = 1; index_50 = 1; control = 0.0 if self.pp.CFD_DEM["ModelDataInfo"].GetBool(): os.chdir(data_and_results) if self.pp.CFD_DEM.ContactMeshOption == "ON": coordination_number = self.procedures.ModelData( self.spheres_model_part, self.solver) Say('Coordination Number: ' + str(coordination_number) + '\n') os.chdir(self.main_path) else: Say('Activate Contact Mesh for ModelData information\n') if self.pp.CFD_DEM["flow_in_porous_medium_option"].GetBool(): fluid_frac_util = SDP.FluidFractionFieldUtility( self.fluid_model_part, self.pp.CFD_DEM.min_fluid_fraction) for field in self.pp.fluid_fraction_fields: fluid_frac_util.AppendLinearField(field) fluid_frac_util.AddFluidFractionField() if self.pp.CFD_DEM["flow_in_porous_DEM_medium_option"].GetBool(): SDP.FixModelPart(self.spheres_model_part) # choosing the directory in which we want to work (print to) os.chdir(self.post_path) ################################################## # I N I T I A L I Z I N G T I M E L O O P ################################################## self.step = 0 self.time = self.pp.Start_time self.Dt = self.pp.Dt self.final_time = self.pp.CFD_DEM["FinalTime"].GetDouble() self.DEM_step = 0 self.time_dem = 0.0 self.Dt_DEM = self.spheres_model_part.ProcessInfo.GetValue(DELTA_TIME) self.rigid_face_model_part.ProcessInfo[DELTA_TIME] = self.Dt_DEM self.cluster_model_part.ProcessInfo[DELTA_TIME] = self.Dt_DEM self.stationarity = False # setting up loop counters: self.fluid_solve_counter = self.GetFluidSolveCounter() self.DEM_to_fluid_counter = self.GetBackwardCouplingCounter() self.derivative_recovery_counter = self.GetRecoveryCounter() self.stationarity_counter = self.GetStationarityCounter() self.print_counter_updated_DEM = self.GetPrintCounterUpdatedDEM() self.print_counter_updated_fluid = self.GetPrintCounterUpdatedFluid() self.debug_info_counter = self.GetDebugInfo() self.particles_results_counter = self.GetParticlesResultsCounter() self.quadrature_counter = self.GetHistoryForceQuadratureCounter() #Phantom self.analytic_data_counter = self.ProcessAnalyticDataCounter() self.mat_deriv_averager = SDP.Averager(1, 3) self.laplacian_averager = SDP.Averager(1, 3) self.report.total_steps_expected = int(self.final_time / self.Dt_DEM) Say(self.report.BeginReport(self.timer)) # creating a Post Utils object that executes several post-related tasks self.post_utils_DEM = DEM_procedures.PostUtils(self.pp.CFD_DEM, self.spheres_model_part) SDP.InitializeVariablesWithNonZeroValues( self.fluid_model_part, self.spheres_model_part, self.pp) # otherwise variables are set to 0 by default self.SetUpResultsDatabase() # ANALYTICS BEGIN self.pp.CFD_DEM.AddEmptyValue("perform_analytics_option").SetBool( False) if self.pp.CFD_DEM["perform_analytics_option"].GetBool(): import analytics variables_to_measure = [PRESSURE] steps_between_measurements = 100 gauge = analytics.Gauge(self.fluid_model_part, self.Dt, self.final_time, variables_to_measure, steps_between_measurements) point_coors = [0.0, 0.0, 0.01] target_node = SDP.FindClosestNode(self.fluid_model_part, point_coors) target_id = target_node.Id Say(target_node.X, target_node.Y, target_node.Z) Say(target_id) def condition(node): return node.Id == target_id gauge.ConstructArrayOfNodes(condition) Say(gauge.variables) # ANALYTICS END import derivative_recovery.derivative_recovery_strategy as derivative_recoverer self.recovery = derivative_recoverer.DerivativeRecoveryStrategy( self.pp, self.fluid_model_part, self.custom_functions_tool) self.FillHistoryForcePrecalculatedVectors() self.PerformZeroStepInitializations() self.post_utils.Writeresults(self.time)
def Initialize(self): print("\nInitializing Problem...") sys.stdout.flush() self.run_code = self.GetRunCode() # Moving to the recently created folder os.chdir(self.main_path) [self.post_path, data_and_results, self.graphs_path, MPI_results] = self.procedures.CreateDirectories( str(self.main_path), str(self.pp.CFD_DEM.problem_name), self.run_code) SDP.CopyInputFilesIntoFolder(self.main_path, self.post_path) #self.mixed_model_part = self.all_model_parts.Get('MixedPart') self.vars_man = vars_man self.vars_man.ConstructListsOfVariables(self.pp) self.FluidInitialize() self.DispersePhaseInitialize() self.SetAllModelParts() self.SetCutsOutput() self.swimming_DEM_gid_io = swimming_DEM_gid_output.SwimmingDEMGiDOutput( self.pp.problem_name, self.pp.VolumeOutput, self.pp.GiDPostMode, self.pp.GiDMultiFileFlag, self.pp.GiDWriteMeshFlag, self.pp.GiDWriteConditionsFlag) self.swimming_DEM_gid_io.initialize_swimming_DEM_results( self.disperse_phase_algorithm.spheres_model_part, self.disperse_phase_algorithm.cluster_model_part, self.disperse_phase_algorithm.rigid_face_model_part, self.mixed_model_part) self.SetDragOutput() self.SetPointGraphPrinter() self.TransferGravityFromDisperseToFluid() # coarse-graining: applying changes to the physical properties of the model to adjust for # the similarity transformation if required (fluid effects only). SDP.ApplySimilarityTransformations( self.fluid_model_part, self.pp.CFD_DEM.similarity_transformation_type, self.pp.CFD_DEM.model_over_real_diameter_factor) # creating a Post Utils object that executes several post-related tasks self.post_utils = SDP.PostUtils( self.swimming_DEM_gid_io, self.pp, self.fluid_model_part, self.disperse_phase_algorithm.spheres_model_part, self.disperse_phase_algorithm.cluster_model_part, self.disperse_phase_algorithm.rigid_face_model_part, self.mixed_model_part) # creating an IOTools object to perform other printing tasks self.io_tools = SDP.IOTools(self.pp) # creating a projection module for the fluid-DEM coupling self.h_min = 0.01 n_balls = 1 fluid_volume = 10 self.pp.CFD_DEM.n_particles_in_depth = int( math.sqrt(n_balls / fluid_volume)) # only relevant in 2D problems # creating a physical calculations module to analyse the DEM model_part dem_physics_calculator = SphericElementGlobalPhysicsCalculator( self.disperse_phase_algorithm.spheres_model_part) if self.pp.CFD_DEM.coupling_level_type: if self.pp.CFD_DEM.meso_scale_length <= 0.0 and self.disperse_phase_algorithm.spheres_model_part.NumberOfElements( 0) > 0: biggest_size = 2 * dem_physics_calculator.CalculateMaxNodalVariable( self.disperse_phase_algorithm.spheres_model_part, RADIUS) self.pp.CFD_DEM.meso_scale_length = 20 * biggest_size elif self.disperse_phase_algorithm.spheres_model_part.NumberOfElements( 0) == 0: self.pp.CFD_DEM.meso_scale_length = 1.0 field_utility = self.GetFieldUtility() self.projection_module = CFD_DEM_coupling.ProjectionModule( self.fluid_model_part, self.disperse_phase_algorithm.spheres_model_part, self.disperse_phase_algorithm.rigid_face_model_part, self.pp.domain_size, self.pp, field_utility) self.projection_module.UpdateDatabase(self.h_min) # creating a custom functions calculator for the implementation of additional custom functions self.custom_functions_tool = SDP.FunctionsCalculator(self.pp) # creating a derivative recovery tool to calculate the necessary derivatives from the fluid solution (gradient, laplacian, material acceleration...) self.derivative_recovery_tool = DerivativeRecoveryTool3D( self.fluid_model_part) # creating a stationarity assessment tool self.stationarity_tool = SDP.StationarityAssessmentTool( self.pp.CFD_DEM.max_pressure_variation_rate_tol, self.custom_functions_tool) # creating a debug tool self.dem_volume_tool = self.GetVolumeDebugTool() self.SetEmbeddedTools() self.KRATOSprint("Initialization Complete" + "\n") sys.stdout.flush() self.step = 0 self.time = self.pp.Start_time self.Dt = self.pp.Dt self.out = self.Dt self.final_time = self.pp.CFD_DEM.FinalTime self.output_time = self.pp.CFD_DEM.OutputTimeStep self.report.Prepare(self.timer, self.pp.CFD_DEM.ControlTime) #first_print = True; index_5 = 1; index_10 = 1; index_50 = 1; control = 0.0 if self.pp.CFD_DEM.ModelDataInfo == "ON": os.chdir(data_and_results) if self.pp.CFD_DEM.ContactMeshOption == "ON": (coordination_number) = self.procedures.ModelData( self.disperse_phase_algorithm.spheres_model_part, self.solver ) # Calculates the mean number of neighbours the mean radius, etc.. self.KRATOSprint("Coordination Number: " + str(coordination_number) + "\n") os.chdir(self.main_path) else: self.KRATOSprint( "Activate Contact Mesh for ModelData information") if self.pp.CFD_DEM.flow_in_porous_medium_option: fluid_frac_util = SDP.FluidFractionFieldUtility( self.fluid_model_part, self.pp.CFD_DEM.min_fluid_fraction) for field in self.pp.fluid_fraction_fields: fluid_frac_util.AppendLinearField(field) fluid_frac_util.AddFluidFractionField() if self.pp.CFD_DEM.flow_in_porous_DEM_medium_option: SDP.FixModelPart(self.disperse_phase_algorithm.spheres_model_part) # choosing the directory in which we want to work (print to) os.chdir(self.post_path) ###################################################################################################################################### # I N I T I A L I Z I N G T I M E L O O P ... ( M I X E D F L U I D / D E M B L O C K ) ###################################################################################################################################### # setting up loop counters: Counter(steps_per_tick_step, initial_step, active_or_inactive_boolean, dead_or_not) self.fluid_solve_counter = self.GetFluidSolveCounter() self.embedded_counter = self.GetEmbeddedCounter() self.DEM_to_fluid_counter = self.GetBackwardCouplingCounter() self.derivative_recovery_counter = self.GetRecoveryCounter() self.stationarity_counter = self.GetStationarityCounter() self.print_counter = self.GetPrintCounter() self.debug_info_counter = self.GetDebugInfo() self.particles_results_counter = self.GetParticlesResultsCounter() self.quadrature_counter = self.HistoryForceQuadratureCounter() self.mat_deriv_averager = SDP.Averager(1, 3) self.laplacian_averager = SDP.Averager(1, 3) ############################################################################## # # # MAIN LOOP # # # ############################################################################## self.DEM_step = 0 # necessary to get a good random insertion of particles # relevant to the stationarity assessment tool self.time_dem = 0.0 self.Dt_DEM = self.disperse_phase_algorithm.spheres_model_part.ProcessInfo.GetValue( DELTA_TIME) self.disperse_phase_algorithm.rigid_face_model_part.ProcessInfo[ DELTA_TIME] = self.Dt_DEM self.disperse_phase_algorithm.cluster_model_part.ProcessInfo[ DELTA_TIME] = self.Dt_DEM self.stationarity = False self.report.total_steps_expected = int(self.pp.CFD_DEM.FinalTime / self.Dt_DEM) self.KRATOSprint(self.report.BeginReport(self.timer)) # creating a Post Utils object that executes several post-related tasks self.post_utils_DEM = DEM_procedures.PostUtils( self.pp.CFD_DEM, self.disperse_phase_algorithm.spheres_model_part) SDP.InitializeVariablesWithNonZeroValues( self.fluid_model_part, self.disperse_phase_algorithm.spheres_model_part, self.pp) # otherwise variables are set to 0 by default self.SetUpResultsDatabase() # ANALYTICS BEGIN self.pp.CFD_DEM.perform_analytics_option = False if self.pp.CFD_DEM.perform_analytics_option: import analytics variables_to_measure = [PRESSURE] steps_between_measurements = 100 gauge = analytics.Gauge(self.fluid_model_part, self.Dt, self.final_time, variables_to_measure, steps_between_measurements) point_coors = [0.0, 0.0, 0.01] target_node = SDP.FindClosestNode(self.fluid_model_part, point_coors) target_id = target_node.Id print(target_node.X, target_node.Y, target_node.Z) print(target_id) def condition(node): return node.Id == target_id gauge.ConstructArrayOfNodes(condition) print(gauge.variables) #print_analytics_counter = SDP.Counter( 5 * steps_between_measurements, 1, 1) # MA: not used anywhere? # ANALYTICS END import derivative_recovery.derivative_recovery_strategy as derivative_recoverer self.recovery = derivative_recoverer.DerivativeRecoveryStrategy( self.pp, self.fluid_model_part, self.derivative_recovery_tool, self.custom_functions_tool) self.FillHistoryForcePrecalculatedVectors() self.PerformZeroStepInitializations() self.post_utils.Writeresults(self.time)
def Initialize(self): Say('Initializing simulation...\n') self.run_code = self.GetRunCode() # Moving to the recently created folder os.chdir(self.main_path) if self.do_print_results: [self.post_path, data_and_results, self.graphs_path, MPI_results] = \ self.procedures.CreateDirectories(str(self.main_path), str(self.project_parameters["problem_data"]["problem_name"].GetString()), self.run_code) SDP.CopyInputFilesIntoFolder(self.main_path, self.post_path) self.MPI_results = MPI_results self.FluidInitialize() self.DispersePhaseInitialize() self.SetAllModelParts() if self.project_parameters.Has( 'sdem_output_processes') and self.do_print_results: gid_output_options = self.project_parameters[ "sdem_output_processes"]["gid_output"][0]["Parameters"] result_file_configuration = gid_output_options[ "postprocess_parameters"]["result_file_configuration"] write_conditions_option = result_file_configuration[ "gidpost_flags"]["WriteConditionsFlag"].GetString( ) == "WriteConditions" deformed_mesh_option = result_file_configuration["gidpost_flags"][ "WriteDeformedMeshFlag"].GetString() == "WriteDeformed" old_gid_output_post_options_dict = { 'GiD_PostAscii': 'Ascii', 'GiD_PostBinary': 'Binary', 'GiD_PostAsciiZipped': 'AsciiZipped' } old_gid_output_multiple_file_option_dict = { 'SingleFile': 'Single', 'MultipleFiles': 'Multiples' } post_mode_key = result_file_configuration["gidpost_flags"][ "GiDPostMode"].GetString() multiple_files_option_key = result_file_configuration[ "gidpost_flags"]["MultiFileFlag"].GetString() self.swimming_DEM_gid_io = \ swimming_DEM_gid_output.SwimmingDEMGiDOutput( file_name = self.project_parameters["problem_data"]["problem_name"].GetString(), vol_output = result_file_configuration["body_output"].GetBool(), post_mode = old_gid_output_post_options_dict[post_mode_key], multifile = old_gid_output_multiple_file_option_dict[multiple_files_option_key], deformed_mesh = deformed_mesh_option, write_conditions = write_conditions_option) self.swimming_DEM_gid_io.initialize_swimming_DEM_results( self.spheres_model_part, self.cluster_model_part, self.rigid_face_model_part, self.mixed_model_part) self.SetPointGraphPrinter() self.AssignKinematicViscosityFromDynamicViscosity() super(SwimmingDEMAnalysis, self).Initialize() # coarse-graining: applying changes to the physical properties of the model to adjust for # the similarity transformation if required (fluid effects only). SDP.ApplySimilarityTransformations( self.fluid_model_part, self.project_parameters["similarity"] ["similarity_transformation_type"].GetInt(), self.project_parameters["similarity"] ["model_over_real_diameter_factor"].GetDouble()) if self.do_print_results: self.SetPostUtils() # creating an IOTools object to perform other printing tasks self.io_tools = SDP.IOTools(self.project_parameters) dem_physics_calculator = DEM.SphericElementGlobalPhysicsCalculator( self.spheres_model_part) if self.project_parameters["coupling"]["coupling_level_type"].GetInt(): default_meso_scale_length_needed = ( self.project_parameters["coupling"]["backward_coupling"] ["meso_scale_length"].GetDouble() <= 0.0 and self.spheres_model_part.NumberOfElements(0) > 0) if default_meso_scale_length_needed: biggest_size = ( 2 * dem_physics_calculator.CalculateMaxNodalVariable( self.spheres_model_part, Kratos.RADIUS)) self.project_parameters["coupling"]["backward_coupling"][ "meso_scale_length"].SetDouble(20 * biggest_size) elif self.spheres_model_part.NumberOfElements(0) == 0: self.project_parameters["coupling"]["backward_coupling"][ "meso_scale_length"].SetDouble(1.0) # creating a custom functions calculator for the implementation of # additional custom functions fluid_domain_dimension = self.project_parameters["fluid_parameters"][ "solver_settings"]["domain_size"].GetInt() self.custom_functions_tool = SDP.FunctionsCalculator( fluid_domain_dimension) # creating a stationarity assessment tool self.stationarity_tool = SDP.StationarityAssessmentTool( self.project_parameters["stationarity"] ["max_pressure_variation_rate_tol"].GetDouble(), self.custom_functions_tool) # creating a debug tool self.dem_volume_tool = self.GetVolumeDebugTool() #self.SetEmbeddedTools() Say('Initialization Complete\n') if self.project_parameters["custom_fluid"][ "flow_in_porous_DEM_medium_option"].GetBool(): SDP.FixModelPart(self.spheres_model_part) ################################################## # I N I T I A L I Z I N G T I M E L O O P ################################################## self.step = 0 self.time = self.fluid_parameters["problem_data"][ "start_time"].GetDouble() self.fluid_time_step = self._GetFluidAnalysis()._GetSolver( )._ComputeDeltaTime() self.time_step = self.spheres_model_part.ProcessInfo.GetValue( Kratos.DELTA_TIME) self.rigid_face_model_part.ProcessInfo[ Kratos.DELTA_TIME] = self.time_step self.cluster_model_part.ProcessInfo[Kratos.DELTA_TIME] = self.time_step self.stationarity = False # setting up loop counters: self.DEM_to_fluid_counter = self.GetBackwardCouplingCounter() self.stationarity_counter = self.GetStationarityCounter() self.print_counter = self.GetPrintCounter() self.debug_info_counter = self.GetDebugInfo() self.particles_results_counter = self.GetParticlesResultsCounter() self.quadrature_counter = self.GetHistoryForceQuadratureCounter() # Phantom self._GetDEMAnalysis( ).analytic_data_counter = self.ProcessAnalyticDataCounter() self.mat_deriv_averager = SDP.Averager(1, 3) self.laplacian_averager = SDP.Averager(1, 3) self.report.total_steps_expected = int(self.end_time / self.time_step) Say(self.report.BeginReport(self.timer)) # creating a Post Utils object that executes several post-related tasks self.post_utils_DEM = DP.PostUtils( self.project_parameters['dem_parameters'], self.spheres_model_part) # otherwise variables are set to 0 by default: SDP.InitializeVariablesWithNonZeroValues(self.project_parameters, self.fluid_model_part, self.spheres_model_part) if self.do_print_results: self.SetUpResultsDatabase() # ANALYTICS BEGIN self.project_parameters.AddEmptyValue( "perform_analytics_option").SetBool(False) if self.project_parameters["perform_analytics_option"].GetBool(): import analytics variables_to_measure = [Kratos.PRESSURE] steps_between_measurements = 100 gauge = analytics.Gauge(self.fluid_model_part, self.fluid_time_step, self.end_time, variables_to_measure, steps_between_measurements) point_coors = [0.0, 0.0, 0.01] target_node = SDP.FindClosestNode(self.fluid_model_part, point_coors) target_id = target_node.Id Say(target_node.X, target_node.Y, target_node.Z) Say(target_id) def condition(node): return node.Id == target_id gauge.ConstructArrayOfNodes(condition) Say(gauge.variables) # ANALYTICS END import derivative_recovery.derivative_recovery_strategy as derivative_recoverer self.recovery = derivative_recoverer.DerivativeRecoveryStrategy( self.project_parameters, self.fluid_model_part, self.custom_functions_tool) self.FillHistoryForcePrecalculatedVectors() self.PerformZeroStepInitializations() if self.do_print_results: self._Print()
def Run(self): import math import swimming_DEM_procedures as swim_proc import CFD_DEM_coupling import embedded import swimming_DEM_algorithm # import the configuration data as read from the GiD import define_output run_code = self.alg.GetRunCode() # Moving to the recently created folder os.chdir(self.main_path) [post_path, data_and_results, graphs_path, MPI_results] = self.alg.procedures.CreateDirectories( str(self.main_path), str(self.pp.CFD_DEM.problem_name)) swim_proc.CopyInputFilesIntoFolder(self.main_path, post_path) self.alg.AddExtraVariables() [post_path, data_and_results, graphs_path, MPI_results] = self.alg.procedures.CreateDirectories( str(self.main_path), str(self.pp.CFD_DEM.problem_name)) os.chdir(self.main_path) # Initialize GiD-IO self.demio = DEM_procedures.DEMIo(self.pp.CFD_DEM, post_path) self.demio.AddGlobalVariables() self.demio.AddSpheresVariables() self.demio.AddFEMBoundaryVariables() self.demio.AddClusterVariables() self.demio.AddContactVariables() # MPI self.demio.AddMpiVariables() self.demio.Configure(self.pp.CFD_DEM.problem_name, self.pp.CFD_DEM.OutputFileType, self.pp.CFD_DEM.Multifile, self.pp.CFD_DEM.ContactMeshOption) self.demio.SetOutputName(self.pp.CFD_DEM.problem_name) os.chdir(post_path) self.demio.InitializeMesh(self.alg.all_model_parts) #Setting up the BoundingBox bounding_box_time_limits = [] if self.pp.CFD_DEM.BoundingBoxOption == "ON": self.alg.procedures.SetBoundingBox(self.alg.spheres_model_part, self.alg.cluster_model_part, self.alg.rigid_face_model_part, self.alg.creator_destructor) bounding_box_time_limits = [ self.alg.solver.bounding_box_start_time, self.alg.solver.bounding_box_stop_time ] # Creating the fluid solver SolverSettings = self.pp.FluidSolverConfiguration # solver_module = import_solver(SolverSettings) fluid_model_part = self.alg.all_model_parts.Get('FluidPart') mixed_model_part = self.alg.all_model_parts.Get('MixedPart') Dt_DEM = self.pp.CFD_DEM.MaxTimeStep # reading the fluid part self.alg.Initialize() self.alg.SetFluidBufferSizeAndAddAdditionalDofs() self.alg.fluid_solver = self.alg.solver_module.CreateSolver( fluid_model_part, SolverSettings) self.alg.FluidInitialize() # activate turbulence model self.alg.ActivateTurbulenceModel() # constructing a model part for the DEM inlet. it contains the DEM elements to be released during the simulation # Initializing the DEM solver must be done before creating the DEM Inlet, because the Inlet configures itself according to some options of the DEM model part if not self.pp.VolumeOutput: cut_list = define_output.DefineCutPlanes() gid_io.define_cuts(fluid_model_part, cut_list) # gid_io.initialize_results(fluid_model_part) # MOD. import swimming_DEM_gid_output swimming_DEM_gid_io = swimming_DEM_gid_output.SwimmingDEMGiDOutput( self.pp.problem_name, self.pp.VolumeOutput, self.pp.GiDPostMode, self.pp.GiDMultiFileFlag, self.pp.GiDWriteMeshFlag, self.pp.GiDWriteConditionsFlag) swimming_DEM_gid_io.initialize_swimming_DEM_results( self.alg.spheres_model_part, self.alg.cluster_model_part, self.alg.rigid_face_model_part, mixed_model_part) # define the drag computation list drag_list = define_output.DefineDragList() drag_file_output_list = [] for it in drag_list: f = open(it[1], 'w') drag_file_output_list.append(f) tmp = "#Drag for group " + it[1] + "\n" f.write(tmp) tmp = "time RX RY RZ" f.write(tmp) f.flush() print(drag_file_output_list) def PrintDrag(drag_list, drag_file_output_list, fluid_model_part, time): i = 0 for it in drag_list: print(it[0]) nodes = fluid_model_part.GetNodes(it[0]) drag = Vector(3) drag[0] = 0.0 drag[1] = 0.0 drag[2] = 0.0 for node in nodes: reaction = node.GetSolutionStepValue(REACTION, 0) drag[0] += reaction[0] drag[1] += reaction[1] drag[2] += reaction[2] output = str(time) + " " + str(drag[0]) + " " + str( drag[1]) + " " + str(drag[2]) + "\n" # print drag_file_output_list[i] # print output drag_file_output_list[i].write(output) drag_file_output_list[i].flush() i = i + 1 # preparing output of point graphs #import point_graph_printer #output_nodes_list = define_output.DefineOutputPoints() #graph_printer = point_graph_printer.PrintGraphPrinter( #output_nodes_list, #fluid_model_part, #variables_dictionary, #domain_size) # setting fluid's body force to the same as DEM's if self.pp.CFD_DEM.body_force_on_fluid_option: for node in fluid_model_part.Nodes: node.SetSolutionStepValue(BODY_FORCE_X, 0, self.pp.CFD_DEM.GravityX) node.SetSolutionStepValue(BODY_FORCE_Y, 0, self.pp.CFD_DEM.GravityY) node.SetSolutionStepValue(BODY_FORCE_Z, 0, self.pp.CFD_DEM.GravityZ) # coarse-graining: applying changes to the physical properties of the model to adjust for # the similarity transformation if required (fluid effects only). swim_proc.ApplySimilarityTransformations( fluid_model_part, self.pp.CFD_DEM.similarity_transformation_type, self.pp.CFD_DEM.model_over_real_diameter_factor) # creating a Post Utils object that executes several post-related tasks post_utils = swim_proc.PostUtils(swimming_DEM_gid_io, self.pp, fluid_model_part, self.alg.spheres_model_part, self.alg.cluster_model_part, self.alg.rigid_face_model_part, mixed_model_part) # creating an IOTools object to perform other printing tasks io_tools = swim_proc.IOTools(self.pp) # creating a projection module for the fluid-DEM coupling h_min = 0.01 n_balls = 1 fluid_volume = 10 self.pp.CFD_DEM.n_particles_in_depth = int( math.sqrt(n_balls / fluid_volume)) # only relevant in 2D problems # creating a physical calculations module to analyse the DEM model_part dem_physics_calculator = SphericElementGlobalPhysicsCalculator( self.alg.spheres_model_part) if self.pp.CFD_DEM.coupling_level_type: if self.pp.CFD_DEM.meso_scale_length <= 0.0 and self.alg.spheres_model_part.NumberOfElements( 0) > 0: biggest_size = 2 * dem_physics_calculator.CalculateMaxNodalVariable( self.alg.spheres_model_part, RADIUS) self.pp.CFD_DEM.meso_scale_length = 20 * biggest_size elif self.alg.spheres_model_part.NumberOfElements(0) == 0: self.pp.CFD_DEM.meso_scale_length = 1.0 field_utility = self.alg.GetFieldUtility() self.alg.projection_module = CFD_DEM_coupling.ProjectionModule( fluid_model_part, self.alg.spheres_model_part, self.alg.rigid_face_model_part, self.pp.domain_size, self.pp, field_utility) self.alg.projection_module.UpdateDatabase(h_min) # creating a custom functions calculator for the implementation of additional custom functions custom_functions_tool = swim_proc.FunctionsCalculator(self.pp) # creating a derivative recovery tool to calculate the necessary derivatives from the fluid solution (gradient, laplacian, material acceleration...) derivative_recovery_tool = DerivativeRecoveryTool3D(fluid_model_part) # creating a stationarity assessment tool stationarity_tool = swim_proc.StationarityAssessmentTool( self.pp.CFD_DEM.max_pressure_variation_rate_tol, custom_functions_tool) # creating a debug tool dem_volume_tool = swim_proc.ProjectionDebugUtils( self.pp.CFD_DEM.fluid_domain_volume, fluid_model_part, self.alg.spheres_model_part, custom_functions_tool) # creating a distance calculation process for the embedded technology # (used to calculate elemental distances defining the structure embedded in the fluid mesh) if self.pp.CFD_DEM.embedded_option: calculate_distance_process = CalculateSignedDistanceTo3DSkinProcess( self.alg.rigid_face_model_part, fluid_model_part) calculate_distance_process.Execute() self.alg.KRATOSprint("Initialization Complete" + "\n") step = 0 time = self.pp.Start_time Dt = self.pp.Dt out = Dt Nsteps = self.pp.nsteps final_time = self.pp.CFD_DEM.FinalTime output_time = self.pp.CFD_DEM.OutputTimeStep self.alg.report.Prepare(self.alg.timer, self.pp.CFD_DEM.ControlTime) first_print = True index_5 = 1 index_10 = 1 index_50 = 1 control = 0.0 if (self.pp.CFD_DEM.ModelDataInfo == "ON"): os.chdir(data_and_results) if (self.pp.CFD_DEM.ContactMeshOption == "ON"): (coordination_number) = self.alg.procedures.ModelData( self.alg.spheres_model_part, self.alg.solver ) # Calculates the mean number of neighbours the mean radius, etc.. self.alg.KRATOSprint("Coordination Number: " + str(coordination_number) + "\n") os.chdir(self.main_path) else: self.alg.KRATOSprint( "Activate Contact Mesh for ModelData information") if self.pp.CFD_DEM.flow_in_porous_medium_option: fluid_frac_util = swim_proc.FluidFractionFieldUtility( fluid_model_part, self.pp.CFD_DEM.min_fluid_fraction) for field in self.pp.fluid_fraction_fields: fluid_frac_util.AppendLinearField(field) fluid_frac_util.AddFluidFractionField() if self.pp.CFD_DEM.flow_in_porous_DEM_medium_option: swim_proc.FixModelPart(self.alg.spheres_model_part) # choosing the directory in which we want to work (print to) os.chdir(post_path) def yield_DEM_time(current_time, current_time_plus_increment, delta_time): current_time += delta_time tolerance = 0.0001 while current_time < (current_time_plus_increment - tolerance * delta_time): yield current_time current_time += delta_time current_time = current_time_plus_increment yield current_time ###################################################################################################################################### # I N I T I A L I Z I N G T I M E L O O P ... ( M I X E D F L U I D / D E M B L O C K ) ###################################################################################################################################### # setting up loop counters: Counter(steps_per_tick_step, initial_step, active_or_inactive_boolean, dead_or_not) fluid_solve_counter = self.alg.GetFluidSolveCounter() embedded_counter = self.alg.GetEmbeddedCounter() DEM_to_fluid_counter = self.alg.GetBackwardCouplingCounter() derivative_recovery_counter = self.alg.GetRecoveryCounter() stationarity_counter = self.alg.GetStationarityCounter() print_counter = self.alg.GetPrintCounter() debug_info_counter = self.alg.GetDebugInfo() particles_results_counter = self.alg.GetParticlesResultsCounter() quadrature_counter = self.alg.HistoryForceQuadratureCounter() mat_deriv_averager = swim_proc.Averager(1, 3) laplacian_averager = swim_proc.Averager(1, 3) ############################################################################## # # # MAIN LOOP # # # ############################################################################## DEM_step = 0 # necessary to get a good random insertion of particles # relevant to the stationarity assessment tool time_dem = 0.0 Dt_DEM = self.alg.spheres_model_part.ProcessInfo.GetValue(DELTA_TIME) self.alg.rigid_face_model_part.ProcessInfo[DELTA_TIME] = Dt_DEM self.alg.cluster_model_part.ProcessInfo[DELTA_TIME] = Dt_DEM stationarity = False self.alg.report.total_steps_expected = int(self.pp.CFD_DEM.FinalTime / Dt_DEM) self.alg.KRATOSprint(self.alg.report.BeginReport(self.alg.timer)) mesh_motion = DEMFEMUtilities() # creating a Post Utils object that executes several post-related tasks post_utils_DEM = DEM_procedures.PostUtils(self.pp.CFD_DEM, self.alg.spheres_model_part) swim_proc.InitializeVariablesWithNonZeroValues( fluid_model_part, self.alg.spheres_model_part, self.pp) # otherwise variables are set to 0 by default self.alg.SetUpResultsDatabase() # ANALYTICS BEGIN self.pp.CFD_DEM.perform_analytics_option = False if self.pp.CFD_DEM.perform_analytics_option: import analytics variables_to_measure = [PRESSURE] steps_between_measurements = 100 gauge = analytics.Gauge(fluid_model_part, Dt, final_time, variables_to_measure, steps_between_measurements) point_coors = [0.0, 0.0, 0.01] target_node = swim_proc.FindClosestNode(fluid_model_part, point_coors) target_id = target_node.Id print(target_node.X, target_node.Y, target_node.Z) print(target_id) def condition(node): return node.Id == target_id gauge.ConstructArrayOfNodes(condition) print(gauge.variables) print_analytics_counter = swim_proc.Counter( 5 * steps_between_measurements, 1, 1) # ANALYTICS END import derivative_recovery.derivative_recovery_strategy as derivative_recoverer recovery = derivative_recoverer.DerivativeRecoveryStrategy( self.pp, fluid_model_part, derivative_recovery_tool, custom_functions_tool) self.alg.FillHistoryForcePrecalculatedVectors() self.alg.PerformZeroStepInitializations() post_utils.Writeresults(time) while time <= final_time: time = time + Dt step += 1 fluid_model_part.CloneTimeStep(time) self.alg.TellTime(time) if self.pp.CFD_DEM.coupling_scheme_type == "UpdatedDEM": time_final_DEM_substepping = time + Dt else: time_final_DEM_substepping = time # calculating elemental distances defining the structure embedded in the fluid mesh if self.pp.CFD_DEM.embedded_option: calculate_distance_process.Execute() if embedded_counter.Tick(): embedded.ApplyEmbeddedBCsToFluid(fluid_model_part) embedded.ApplyEmbeddedBCsToBalls(self.alg.spheres_model_part, self.pp.CFD_DEM) # solving the fluid part if step >= 3 and not stationarity: print("Solving Fluid... (", fluid_model_part.NumberOfElements(0), "elements )") sys.stdout.flush() if fluid_solve_counter.Tick(): self.alg.FluidSolve(time) # assessing stationarity if stationarity_counter.Tick(): print("Assessing Stationarity...") stationarity = stationarity_tool.Assess(fluid_model_part) sys.stdout.flush() # printing if required if particles_results_counter.Tick(): # eliminating remote balls #if self.pp.dem.BoundingBoxOption == "ON": # self.alg.creator_destructor.DestroyParticlesOutsideBoundingBox(self.alg.spheres_model_part) io_tools.PrintParticlesResults( self.alg.pp.variables_to_print_in_file, time, self.alg.spheres_model_part) graph_printer.PrintGraphs(time) PrintDrag(drag_list, drag_file_output_list, fluid_model_part, time) if output_time <= out and self.alg.pp.CFD_DEM.coupling_scheme_type == "UpdatedDEM": if self.pp.CFD_DEM.coupling_level_type > 0: self.alg.projection_module.ComputePostProcessResults( self.alg.spheres_model_part.ProcessInfo) post_utils.Writeresults(time) out = 0 # solving the DEM part derivative_recovery_counter.Switch( time > self.pp.CFD_DEM.interaction_start_time) if derivative_recovery_counter.Tick(): recovery.Recover() print("Solving DEM... (", self.alg.spheres_model_part.NumberOfElements(0), "elements )") sys.stdout.flush() first_dem_iter = True for time_dem in yield_DEM_time(time_dem, time_final_DEM_substepping, Dt_DEM): DEM_step += 1 # this variable is necessary to get a good random insertion of particles self.alg.spheres_model_part.ProcessInfo[TIME_STEPS] = DEM_step self.alg.rigid_face_model_part.ProcessInfo[ TIME_STEPS] = DEM_step self.alg.cluster_model_part.ProcessInfo[TIME_STEPS] = DEM_step self.alg.PerformInitialDEMStepOperations(time_dem) if time >= self.pp.CFD_DEM.interaction_start_time and self.pp.CFD_DEM.coupling_level_type and ( self.pp.CFD_DEM.project_at_every_substep_option or first_dem_iter): if self.pp.CFD_DEM.coupling_scheme_type == "UpdatedDEM": self.alg.ApplyForwardCoupling() else: self.alg.ApplyForwardCoupling( (time_final_DEM_substepping - time_dem) / Dt) if self.alg.pp.CFD_DEM.IntegrationScheme in { 'Hybrid_Bashforth', 'TerminalVelocityScheme' }: self.alg.solver.Solve() # only advance in space self.alg.ApplyForwardCouplingOfVelocityOnly( time_dem) else: if self.alg.pp.CFD_DEM.basset_force_type > 0: node.SetSolutionStepValue(SLIP_VELOCITY_X, vx) node.SetSolutionStepValue(SLIP_VELOCITY_Y, vy) if quadrature_counter.Tick(): self.alg.AppendValuesForTheHistoryForce() # performing the time integration of the DEM part self.alg.spheres_model_part.ProcessInfo[TIME] = time_dem self.alg.rigid_face_model_part.ProcessInfo[TIME] = time_dem self.alg.cluster_model_part.ProcessInfo[TIME] = time_dem if self.alg.pp.do_solve_dem: self.alg.DEMSolve(time_dem) # Walls movement: mesh_motion.MoveAllMeshes(self.alg.rigid_face_model_part, time, Dt) mesh_motion.MoveAllMeshes(self.alg.spheres_model_part, time, Dt) mesh_motion.MoveAllMeshes(self.alg.DEM_inlet_model_part, time, Dt) #### TIME CONTROL ################################## # adding DEM elements by the inlet: if self.pp.CFD_DEM.dem_inlet_option: self.alg.DEM_inlet.CreateElementsFromInletMesh( self.alg.spheres_model_part, self.alg.cluster_model_part, self.alg.creator_destructor ) # After solving, to make sure that neighbours are already set. if output_time <= out and self.pp.CFD_DEM.coupling_scheme_type == "UpdatedFluid": if self.pp.CFD_DEM.coupling_level_type: self.alg.projection_module.ComputePostProcessResults( self.alg.spheres_model_part.ProcessInfo) post_utils.Writeresults(time_dem) out = 0 out = out + Dt_DEM first_dem_iter = False # applying DEM-to-fluid coupling if DEM_to_fluid_counter.Tick( ) and time >= self.pp.CFD_DEM.interaction_start_time: self.alg.projection_module.ProjectFromParticles() #### PRINTING GRAPHS #### os.chdir(graphs_path) # measuring mean velocities in a certain control volume (the 'velocity trap') if self.pp.CFD_DEM.VelocityTrapOption: post_utils_DEM.ComputeMeanVelocitiesinTrap( "Average_Velocity.txt", time) os.chdir(post_path) # coupling checks (debugging) if debug_info_counter.Tick(): dem_volume_tool.UpdateDataAndPrint( self.pp.CFD_DEM.fluid_domain_volume) # printing if required if particles_results_counter.Tick(): io_tools.PrintParticlesResults( self.pp.variables_to_print_in_file, time, self.alg.spheres_model_part) graph_printer.PrintGraphs(time) PrintDrag(drag_list, drag_file_output_list, fluid_model_part, time) swimming_DEM_gid_io.finalize_results() self.alg.PerformFinalOperations(time_dem) for i in drag_file_output_list: i.close() self.alg.TellFinalSummary(step, time, DEM_step) return self.alg.GetReturnValue()