Exemple #1
0
        node.SetSolutionStepValue(BODY_FORCE_Y, 0, DEM_parameters.GravityY)
        node.SetSolutionStepValue(BODY_FORCE_Z, 0, DEM_parameters.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, DEM_parameters.similarity_transformation_type,
    DEM_parameters.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, pp, fluid_model_part,
                                 spheres_model_part, cluster_model_part,
                                 rigid_face_model_part, mixed_model_part)

# creating an IOTools object to perform other printing tasks
io_tools = swim_proc.IOTools(pp)

# creating a projection module for the fluid-DEM coupling
h_min = 0.01
n_balls = 1
fluid_volume = 10
DEM_parameters.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(
    spheres_model_part)

if DEM_parameters["coupling_level_type"].GetInt():

    if DEM_parameters.meso_scale_length <= 0.0 and spheres_model_part.NumberOfElements(
            0) > 0:
    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.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.CFD_DEM,
                self.pp.coupling_dem_vars,
                self.pp.coupling_fluid_vars,
                self.pp.time_filtered_vars,
                flow_field=self.GetFieldUtility(),
                domain_size=self.domain_size)

            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.domain_size)

        # 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.end_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.end_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.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.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"].GetString()), 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"].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
        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)

        field_utility = self.GetFieldUtility()

        if self.pp.CFD_DEM["coupling_level_type"].GetInt():

            if self.pp.CFD_DEM["meso_scale_length"].GetDouble() <= 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

            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"].GetDouble() , 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"].GetDouble()
        self.output_time    = self.pp.CFD_DEM["OutputTimeStep"].GetDouble()

        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.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"].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.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.GetHistoryForceQuadratureCounter()
        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"].GetDouble() / 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()
                                  ProjectParameters.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, ProjectParameters.similarity_transformation_type,
    ProjectParameters.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, ProjectParameters,
                                 fluid_model_part, balls_model_part,
                                 clusters_model_part, rigid_faces_model_part,
                                 mixed_model_part)

# creating an IOTools object to perform other printing tasks
io_tools = swim_proc.IOTools(ProjectParameters)

# creating a projection module for the fluid-DEM coupling
h_min = 0.01
n_balls = 1
fluid_volume = 10
ProjectParameters.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(
    balls_model_part)

if (ProjectParameters.projection_module_option):

    if (ProjectParameters.meso_scale_length <= 0.0
            and balls_model_part.NumberOfElements(0) > 0):