def PrintOutput(self): """The output file is created, filled and closed. If several output timesteps are specified, there will be one file for each timestep. """ time = self.model_part.ProcessInfo.GetValue(KM.TIME) file_name = self.settings["file_name"].GetString() + "_{:.4f}.dat".format(time) self.out_file_params["file_name"].SetString(file_name) file = TimeBasedAsciiFileWriterUtility(self.model_part, self.out_file_params, self._GetHeader()).file for node in self.nodes: file.write(self._GetData(node, self._DistanceToOrigin(node))) file.close()
class ComputeDragProcess(KratosMultiphysics.Process): """ Auxiliary base class to output total flow forces over obstacles in fluid dynamics problems. A derived class needs to be implemented to be able to use this functionality, as calling the base class alone is not enough. """ def __init__(self, model, params): """ Auxiliary class to output total flow forces over obstacles in fluid dynamics problems for a body fitted model part. """ KratosMultiphysics.Process.__init__(self) default_settings = KratosMultiphysics.Parameters(""" { "model_part_name" : "", "interval" : [0.0, 1e30], "print_drag_to_screen" : false, "print_format" : ".8f", "write_drag_output_file" : true, "output_file_settings": {} } """) self.params = params # Detect "End" as a tag and replace it by a large number if (self.params.Has("interval")): if (self.params["interval"][1].IsString()): if (self.params["interval"][1].GetString() == "End"): self.params["interval"][1].SetDouble(1e30) else: raise Exception( "The second value of interval can be \"End\" or a number, interval currently:" + self.params["interval"].PrettyPrintJsonString()) self.params.ValidateAndAssignDefaults(default_settings) self.format = self.params["print_format"].GetString() # getting the ModelPart from the Model model_part_name = self.params["model_part_name"].GetString() if model_part_name == "": raise Exception('No "model_part_name" was specified!') else: self.model_part = model[self.params["model_part_name"].GetString()] def ExecuteInitialize(self): self.interval = KratosMultiphysics.Vector(2) self.interval[0] = self.params["interval"][0].GetDouble() self.interval[1] = self.params["interval"][1].GetDouble() self.print_drag_to_screen = self.params[ "print_drag_to_screen"].GetBool() self.write_drag_output_file = self.params[ "write_drag_output_file"].GetBool() if (self.write_drag_output_file): if (self.model_part.GetCommunicator().MyPID() == 0): output_file_name = self.params["model_part_name"].GetString( ) + "_drag.dat" file_handler_params = KratosMultiphysics.Parameters( self.params["output_file_settings"]) if file_handler_params.Has("file_name"): warn_msg = 'Unexpected user-specified entry found in "output_file_settings": {"file_name": ' warn_msg += '"' + file_handler_params[ "file_name"].GetString() + '"}\n' warn_msg += 'Using this specififed file name instead of the default "' + output_file_name + '"' KratosMultiphysics.Logger.PrintWarning( "ComputeDragProcess", warn_msg) else: file_handler_params.AddEmptyValue("file_name") file_handler_params["file_name"].SetString( output_file_name) file_header = self._GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part, file_handler_params, file_header).file def ExecuteFinalizeSolutionStep(self): current_step = self.model_part.ProcessInfo[KratosMultiphysics.STEP] current_time = self.model_part.ProcessInfo[KratosMultiphysics.TIME] if (((current_time >= self.interval[0]) and (current_time < self.interval[1])) and (current_step + 1 >= self.model_part.GetBufferSize())): # Compute the drag force drag_force = self._GetCorrespondingDragForce() # Write the drag force values if (self.model_part.GetCommunicator().MyPID() == 0): if (self.print_drag_to_screen): result_msg = str(current_time) + " x-drag: " + format( drag_force[0], self.format) + " y-drag: " + format( drag_force[1], self.format) + " z-drag: " + format( drag_force[2], self.format) self._PrintToScreen(result_msg) # not formatting time in order to not lead to problems with time recognition # in the file writer when restarting if (self.write_drag_output_file): self.output_file.write( str(current_time) + " " + format(drag_force[0], self.format) + " " + format(drag_force[1], self.format) + " " + format(drag_force[2], self.format) + "\n") def ExecuteFinalize(self): if (self.write_drag_output_file): if (self.model_part.GetCommunicator().MyPID() == 0): self.output_file.close() def _GetFileHeader(self): err_msg = 'ComputeDragProcess: _GetFileHeader called in base class\n' err_msg += 'this needs to be implemented and called from derived class' raise Exception(err_msg) def _PrintToScreen(self, result_msg): err_msg = 'ComputeDragProcess: _PrinToScreen called in base class\n' err_msg += 'this needs to be implemented and called from derived class' raise Exception(err_msg) def _GetCorrespondingDragForce(self): err_msg = 'ComputeDragProcess: _GetCorrespondingDragForce called in base class\n' err_msg += 'this needs to be implemented and called from derived class' raise Exception(err_msg)
class FlowOutputProcess(KratosMultiphysics.Process): """This process calculates(using c++ utilities) and writes the flow through a given list of (sub)model parts. In 3D use a surface eg. Inlet, Outlet In 2D use a line eg. Inlet, Outlet This process works in MPI as well as with restarts """ def __init__(self, model, params): KratosMultiphysics.Process.__init__(self) default_settings = KratosMultiphysics.Parameters('''{ "help" : "This process calculates(using c++ utilities) and writes the flow through a given list of (sub)model parts.", "model_part_name_list" : [], "print_format" : "", "output_file_settings": {} }''') self.model = model self.params = params self.params.ValidateAndAssignDefaults(default_settings) self.output_file = None self.format = self.params["print_format"].GetString() def ExecuteInitialize(self): # getting the ModelPart from the Model model_part_name_list = self.params["model_part_name_list"] if model_part_name_list.size() == 0: raise Exception('No model parts are specified!') self.model_part_for_time = self.model[ model_part_name_list[0].GetString()] # Only rank 0 writes in MPI my_rank = 0 comm = self.model_part_for_time.GetCommunicator().GetDataCommunicator() self.is_writing_rank = my_rank == comm.Rank() if self.is_writing_rank: file_handler_params = KratosMultiphysics.Parameters( self.params["output_file_settings"]) file_header = self.GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part_for_time, file_handler_params, file_header).file def ExecuteFinalizeSolutionStep(self): time = self.model_part_for_time.ProcessInfo[KratosMultiphysics.TIME] model_part_name_list = self.params["model_part_name_list"] out = str(time) for model_part_name_param in model_part_name_list: model_part_name = model_part_name_param.GetString() model_part = self.model[model_part_name] flow_value = self.CalculateFlow(model_part) out += " " + format(flow_value, self.format) out += "\n" if self.is_writing_rank: self.output_file.write(out) def ExecuteFinalize(self): if self.is_writing_rank: self.output_file.close() def GetFileHeader(self): model_part_name_list = self.params["model_part_name_list"] header = '# Flow results ' + '\n' header += '# time ' for model_part_name_param in model_part_name_list: model_part_name = model_part_name_param.GetString() model_part = self.model[model_part_name] header += model_part.Name header += ' ' header += "\n" return header def CalculateFlow(self, model_part): flow_value = KratosCFD.FluidAuxiliaryUtilities.CalculateFlowRate( model_part) return flow_value
class CFLOutputProcess(KratosMultiphysics.Process): """ A class responsible for the CFL output, which is an element value in Kratos. """ def __init__(self, model, params): KratosMultiphysics.Process.__init__(self) default_settings = KratosMultiphysics.Parameters(""" { "model_part_name" : "", "interval" : [0.0, 1e30], "cfl_output_limit" : 2.5, "print_to_screen" : false, "print_format" : ".8f", "write_output_file" : true, "output_step" : 8, "output_file_settings": {} } """) # Detect "End" as a tag and replace it by a large number if (params.Has("interval")): if (params["interval"][1].IsString()): if (params["interval"][1].GetString() == "End"): params["interval"][1].SetDouble(1e30) else: raise Exception( "The second value of interval can be \"End\" or a number, interval currently:" + params["interval"].PrettyPrintJsonString()) params.ValidateAndAssignDefaults(default_settings) # getting the ModelPart from the Model self.model_part_name = params["model_part_name"].GetString() if self.model_part_name == "": raise Exception('No "model_part_name" was specified!') else: self.model_part = model[self.model_part_name] self.interval = params["interval"].GetVector() # getting output limit for summarization self.cfl_output_limit = params["cfl_output_limit"].GetDouble() # TODO: Is it ok to do this check? If not, distribution calculation is going to be messy with if conditions for # case with cfl_output_limit <= 1.0 if (self.cfl_output_limit <= 1.0): raise Exception("Please provide cfl_output_limit greater than 1.0") self.format = params["print_format"].GetString() self.output_step = params["output_step"].GetInt() self.print_to_screen = params["print_to_screen"].GetBool() self.write_output_file = params["write_output_file"].GetBool() if (self.model_part.GetCommunicator().MyPID() == 0): if (self.write_output_file): file_handler_params = KratosMultiphysics.Parameters( params["output_file_settings"]) file_header = self._GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part, file_handler_params, file_header).file self.distribution_params = KratosMultiphysics.Parameters('''{ "number_of_value_groups" : 1, "min_value" : "min", "max_value" : "max" }''') self.distribution_params["min_value"].SetDouble( min(self.cfl_output_limit, 1.0)) self.distribution_params["max_value"].SetDouble( max(self.cfl_output_limit, 1.0)) def ExecuteFinalizeSolutionStep(self): current_time = self.model_part.ProcessInfo[KratosMultiphysics.TIME] current_step = self.model_part.ProcessInfo[KratosMultiphysics.STEP] if ((current_time >= self.interval[0]) and (current_time < self.interval[1])) and (current_step % self.output_step == 0): self._EvaluateCFL() output = self._CalculateWithRespectToThreshold() if (self.model_part.GetCommunicator().MyPID() == 0): output_vals = [format(val, self.format) for val in output] # not formatting time in order to not lead to problems with time recognition # in the file writer when restarting output_vals.insert(0, str(current_time)) res_labels = [ "time: ", "mean: ", "std: ", "max: ", "cfl" + "{:.1f}".format(self.cfl_output_limit) + ": ", "cfl1.0: " ] if (self.print_to_screen): result_msg = 'CFL evaluation for model part ' + \ self.model_part_name + '\n' result_msg += ', '.join( [a + b for a, b in zip(res_labels, output_vals)]) self._PrintToScreen(result_msg) if (self.write_output_file): self.output_file.write(' '.join(output_vals) + "\n") def ExecuteFinalize(self): if (self.model_part.GetCommunicator().MyPID() == 0): self.output_file.close() def _GetFileHeader(self): header = '# CFL for model part ' + self.model_part_name + \ '| CFL_threshold: ' + str(self.cfl_output_limit) + '\n' header += '# Time Mean Std Max HowMany>' + \ "{:.1f}".format(self.cfl_output_limit) + ' [%] HowMany>1.0 [%]\n' return header def _PrintToScreen(self, result_msg): KratosMultiphysics.Logger.PrintInfo("CFLOutputProcess", "CFL VALUE RESULTS:") KratosMultiphysics.Logger.PrintInfo("CFLOutputProcess", "Current time: " + result_msg) def _CalculateWithRespectToThreshold(self): current_container = spatial_methods.NonHistorical.Elements.NormMethods _, _, _, group_histogram, group_percentage_distribution, group_means, group_variances = current_container.Distribution( self.model_part, KratosMultiphysics.CFL_NUMBER, "value", self.distribution_params) # % of element with cfl above threshold how_many = group_percentage_distribution[-1] * 100.0 # % of element with cfl above 1 how_many1 = (1.0 - group_percentage_distribution[0]) * 100.0 # quantifying the mean and std for values below the threshold total_elements_in_threshold_range = group_histogram[ 0] + group_histogram[1] if (total_elements_in_threshold_range > 0): y_mean = (group_means[0] * group_histogram[0] + group_means[1] * group_histogram[1]) / total_elements_in_threshold_range threshold_sum_squared = (group_variances[0] + pow( group_means[0], 2)) * group_histogram[0] + ( group_variances[1] + pow(group_means[1], 2)) * group_histogram[1] y_std = sqrt((threshold_sum_squared - total_elements_in_threshold_range * pow(y_mean, 2)) / (total_elements_in_threshold_range - 1.0)) else: y_mean = 0.0 y_std = 0.0 # qunatifying the global max # TODO: @Mate, where should we put the id of the element, where max is (second bland output argument is max_id)? x_max, _ = current_container.Max(self.model_part, KratosMultiphysics.CFL_NUMBER, "value") return [y_mean, y_std, x_max, how_many, how_many1] def _EvaluateCFL(self): if (self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2): KratosCFD.EstimateDtUtility2D.CalculateLocalCFL(self.model_part) else: KratosCFD.EstimateDtUtility3D.CalculateLocalCFL(self.model_part)
class ComputeGlobalForceProcess(KratosMultiphysics.Process): ''' Computes the flow- and body-attached forces for a the whole model part with body-fitted mesh thus the naming GlobalForces Takes as input a CCW positive (in degrees) rotation around axis z for the body-attached forces ''' def __init__(self, Model, params): KratosMultiphysics.Process.__init__(self) default_settings = KratosMultiphysics.Parameters(""" { "model_part_name" : "", "interval" : [0.0, 1e30], "reference_point" : [0.0,0.0,0.0], "z_rotation_angle" : 0.0, "print_to_screen" : false, "print_format" : ".8f", "write_output_file" : true, "output_file_settings" : {} } """) # Detect 'End' as a tag and replace it by a large number if (params.Has('interval')): if (params['interval'][1].IsString()): if (params['interval'][1].GetString() == 'End'): params['interval'][1].SetDouble(1e30) else: raise Exception( 'The second value of interval can be \'End\' or a number, interval currently:' + params['interval'].PrettyPrintJsonString()) params.ValidateAndAssignDefaults(default_settings) self.model_part_name = params['model_part_name'].GetString() self.model_part = Model[self.model_part_name] self.interval = params["interval"].GetVector() self.print_to_screen = params['print_to_screen'].GetBool() self.write_output_file = params['write_output_file'].GetBool() self.format = params["print_format"].GetString() # added reference point for moment calculation self.reference = params['reference_point'].GetVector() if self.reference.Size() != 3: raise Exception( 'The reference point position has to be provided with 3 coordinates!' ) # user inpput expected in degrees, here changing to radians self.theta = math.radians(params['z_rotation_angle'].GetDouble()) if (self.model_part.GetCommunicator().MyPID() == 0): if (self.write_output_file): output_file_name = params["model_part_name"].GetString( ) + "_global_force.dat" file_handler_params = KratosMultiphysics.Parameters( params["output_file_settings"]) if file_handler_params.Has("file_name"): warn_msg = 'Unexpected user-specified entry found in "output_file_settings": {"file_name": ' warn_msg += '"' + \ file_handler_params["file_name"].GetString() + '"}\n' warn_msg += 'Using this specififed file name instead of the default "' + \ output_file_name + '"' KratosMultiphysics.Logger.PrintWarning( "ComputeGlobalForceProcess", warn_msg) else: file_handler_params.AddEmptyValue("file_name") file_handler_params["file_name"].SetString( output_file_name) file_header = self._GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part, file_handler_params, file_header).file def ExecuteFinalizeSolutionStep(self): current_time = self.model_part.ProcessInfo[KratosMultiphysics.TIME] if ((current_time >= self.interval[0]) and (current_time < self.interval[1])): ff, mf, fb, mb = self._EvaluateGlobalForces() if (self.model_part.GetCommunicator().MyPID() == 0): output = [] output.extend(ff) output.extend(mf) output.extend(fb) output.extend(mb) output_vals = [format(val, self.format) for val in output] # not formatting time in order to not lead to problems with time recognition # in the file writer when restarting output_vals.insert(0, str(current_time)) res_labels = [ 'time: ', 'fx: ', 'fy: ', 'fz: ', 'mx: ', 'my: ', 'mz: ', 'fx\': ', 'fy\': ', 'fz\': ', 'mx\': ', 'my\': ', 'mz\': ' ] if (self.print_to_screen): result_msg = 'Global force evaluation for model part ' + \ self.model_part_name + '\n' result_msg += ', '.join( [a + b for a, b in zip(res_labels, output_vals)]) self._PrintToScreen(result_msg) sys.stdout.flush() if (self.write_output_file): self.output_file.write(' '.join(output_vals) + '\n') def _EvaluateGlobalForces(self): # flow-attached forces: in x-y-z coordinate system ff = [0.0, 0.0, 0.0] mf = [0.0, 0.0, 0.0] for node in self.model_part.GetCommunicator().LocalMesh().Nodes: # sign is flipped to go from reaction to action -> force nodal_force = (-1) * node.GetSolutionStepValue( KratosMultiphysics.REACTION, 0) # summing up nodal contributions to get resultant for model_part ff[0] += nodal_force[0] ff[1] += nodal_force[1] ff[2] += nodal_force[2] x = node.X - self.reference[0] y = node.Y - self.reference[1] z = node.Z - self.reference[2] mf[0] += y * nodal_force[2] - z * nodal_force[1] mf[1] += z * nodal_force[0] - x * nodal_force[2] mf[2] += x * nodal_force[1] - y * nodal_force[0] # body-attached forces -> here only a rotation around z-axis # in x'-y'-z' coordinate system # of the summed-up forces and moment fb = ccw_rotate_comp_around_z(ff, self.theta) mb = ccw_rotate_comp_around_z(mf, self.theta) ff = self.model_part.GetCommunicator().GetDataCommunicator( ).SumDoubles(ff, 0) mf = self.model_part.GetCommunicator().GetDataCommunicator( ).SumDoubles(mf, 0) fb = self.model_part.GetCommunicator().GetDataCommunicator( ).SumDoubles(fb, 0) mb = self.model_part.GetCommunicator().GetDataCommunicator( ).SumDoubles(mb, 0) return ff, mf, fb, mb def _GetFileHeader(self): header = '# Global force for model part ' + self.model_part_name + '\n' header += '# Time Fx Fy Fz Mx My Mz Fx\' Fy\' Fz\' Mx\' My\' Mz\'\n' return header def _PrintToScreen(self, result_msg): KratosMultiphysics.Logger.PrintInfo( 'ComputeGlobalForceProcess', 'Global force results - flow- and body-attached:') KratosMultiphysics.Logger.PrintInfo('ComputeGlobalForceProcess', 'Current time: ' + result_msg)
class ComputeCustomBaseReactionProcess(KratosMultiphysics.Process): def __init__(self, Model, settings): KratosMultiphysics.Process.__init__(self) default_settings = KratosMultiphysics.Parameters(""" { "model_part_name" : "please_specify_model_part_name", "interval" : [0.0, 1e30], "reference_point" : [0.0, 0.0, 0.0], "print_drag_to_screen" : false, "print_format" : ".8f", "write_drag_output_file" : true, "output_file_settings": {} } """) self.settings = settings # Detect "End" as a tag and replace it by a large number if (self.settings.Has("interval")): if (self.settings["interval"][1].IsString()): if (self.settings["interval"][1].GetString() == "End"): self.settings["interval"][1].SetDouble(1e30) else: raise Exception( "The second value of interval can be \"End\" or a number, interval currently:" + self.settings["interval"].PrettyPrintJsonString()) self.settings.ValidateAndAssignDefaults(default_settings) self.model_part = Model[self.settings["model_part_name"].GetString()] self.interval = KratosMultiphysics.Vector(2) self.interval[0] = self.settings["interval"][0].GetDouble() self.interval[1] = self.settings["interval"][1].GetDouble() self.print_drag_to_screen = self.settings[ "print_drag_to_screen"].GetBool() self.write_drag_output_file = self.settings[ "write_drag_output_file"].GetBool() self.format = self.settings["print_format"].GetString() # PMT: added reference point for moment calculation self.reference_x = self.settings["reference_point"][0].GetDouble() self.reference_y = self.settings["reference_point"][1].GetDouble() self.reference_z = self.settings["reference_point"][2].GetDouble() if (self.model_part.GetCommunicator().MyPID() == 0): if (self.write_drag_output_file): file_handler_params = KratosMultiphysics.Parameters( settings["output_file_settings"]) file_header = self._GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part, file_handler_params, file_header).file def ExecuteFinalizeSolutionStep(self): current_time = self.model_part.ProcessInfo[KratosMultiphysics.TIME] if ((current_time >= self.interval[0]) and (current_time < self.interval[1])): # Note that MPI communication is done within VariableUtils().SumHistoricalNodeVectorVariable() #reaction_vector = KratosMultiphysics.VariableUtils().SumHistoricalNodeVectorVariable(KratosMultiphysics.REACTION, self.model_part, 0) # PMT: TODO: only checked for OpenMP, update for MPI fx = 0.0 fy = 0.0 fz = 0.0 mx = 0.0 my = 0.0 mz = 0.0 for node in self.model_part.Nodes: reaction = node.GetSolutionStepValue( KratosMultiphysics.REACTION, 0) moment_reaction = node.GetSolutionStepValue( KratosMultiphysics.REACTION_MOMENT, 0) # PMT: NOTE: sign is flipped to go from reaction to action fx += (1) * reaction[0] fy += (1) * reaction[1] fz += (1) * reaction[2] x = node.X - self.reference_x y = node.Y - self.reference_y z = node.Z - self.reference_z mx += y * (1) * reaction[2] - z * (1) * reaction[1] + ( 1) * moment_reaction[0] my += z * (1) * reaction[0] - x * (1) * reaction[2] + ( 1) * moment_reaction[1] mz += x * (1) * reaction[1] - y * (1) * reaction[0] + ( 1) * moment_reaction[2] if (self.model_part.GetCommunicator().MyPID() == 0): if (self.print_drag_to_screen): print("CUSTOM BASE REACTION RESULTS:") print("Current time: " + str(current_time)) print("Forces:" + " Fx: " + str(fx) + " Fy: " + str(fy) + " Fz: " + str(fz)) print("Moments:" + " Mx: " + str(mx) + " My: " + str(my) + " Mz: " + str(mz)) if (self.write_drag_output_file): # with open(self.drag_filename, 'a') as file: # output_str = str(current_time) # output_str += " " + str(fx) + " " + str(fy) + " " + str(fz) # output_str += " " + str(mx) + " " + str(my) + " " + str(mz) + "\n" # file.write(output_str) # file.close() # if (self.write_output_file): # output_str = str(current_time) # output_str += " " + format(fx, self.format) + " " + format(fy, self.format) + " " + format(fz, self.format) # output_str += " " + format(mx, self.format) + " " + format(my, self.format) + " " + format(mz, self.format) + "\n" output_str = str(current_time) output_str += " " + str(fx) + " " + str( fy) + " " + str(fz) output_str += " " + str(mx) + " " + str( my) + " " + str(mz) + "\n" self.output_file.write(output_str) # self.output_file.write(str(current_time)+" "+format(integral_value[0], self.format)+" "+format( # integral_value[1], self.format)+" "+format(integral_value[2], self.format)+"\n") def _GetFileHeader(self): header = '# Integral value for model part ' + self.settings[ "model_part_name"].GetString( ) + ' ' + 'at reference point X = ' + str( self.reference_x) + ', Y = ' + str( self.reference_y) + ', Z = ' + str(self.reference_z) + '\n' header += '# Time Fx: Fy: Fz: Mx: My: Mz:\n' return header def ExecuteFinalize(self): if (self.model_part.GetCommunicator().MyPID() == 0): self.output_file.close()
class CFLOutputProcess(KratosMultiphysics.Process): """ A class responsible for the CFL output, which is an element value in Kratos. """ def __init__(self, model, params): KratosMultiphysics.Process.__init__(self) default_settings = KratosMultiphysics.Parameters(""" { "model_part_name" : "", "interval" : [0.0, 1e30], "cfl_output_limit" : 2.5, "print_to_screen" : false, "print_format" : ".8f", "write_output_file" : true, "output_step" : 8, "output_file_settings": {} } """) # Detect "End" as a tag and replace it by a large number if (params.Has("interval")): if (params["interval"][1].IsString()): if (params["interval"][1].GetString() == "End"): params["interval"][1].SetDouble(1e30) else: raise Exception( "The second value of interval can be \"End\" or a number, interval currently:" + params["interval"].PrettyPrintJsonString()) params.ValidateAndAssignDefaults(default_settings) # getting the ModelPart from the Model self.model_part_name = params["model_part_name"].GetString() if self.model_part_name == "": raise Exception('No "model_part_name" was specified!') else: self.model_part = model[self.model_part_name] self.interval = params["interval"].GetVector() # getting output limit for summarization self.cfl_output_limit = params["cfl_output_limit"].GetDouble() self.format = params["print_format"].GetString() self.output_step = params["output_step"].GetInt() self.print_to_screen = params["print_to_screen"].GetBool() self.write_output_file = params["write_output_file"].GetBool() if (self.model_part.GetCommunicator().MyPID() == 0): if (self.write_output_file): file_handler_params = KratosMultiphysics.Parameters( params["output_file_settings"]) file_header = self._GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part, file_handler_params, file_header).file def ExecuteFinalizeSolutionStep(self): current_time = self.model_part.ProcessInfo[KratosMultiphysics.TIME] current_step = self.model_part.ProcessInfo[KratosMultiphysics.STEP] if ((current_time >= self.interval[0]) and (current_time < self.interval[1])) and (current_step % self.output_step == 0): cfl_value = self._EvaluateCFL() if (self.model_part.GetCommunicator().MyPID() == 0): output = self._SummarizeCFL(cfl_value) output_vals = [format(val, self.format) for val in output] # not formatting time in order to not lead to problems with time recognition # in the file writer when restarting output_vals.insert(0, str(current_time)) res_labels = [ "time: ", "mean: ", "std: ", "max: ", "cfl" + "{:.1f}".format(self.cfl_output_limit) + ": ", "cfl1.0: " ] if (self.print_to_screen): result_msg = 'CFL evaluation for model part ' + \ self.model_part_name + '\n' result_msg += ', '.join( [a + b for a, b in zip(res_labels, output_vals)]) self._PrintToScreen(result_msg) if (self.write_output_file): self.output_file.write(' '.join(output_vals) + "\n") def ExecuteFinalize(self): if (self.model_part.GetCommunicator().MyPID() == 0): self.output_file.close() def _GetFileHeader(self): header = '# CFL for model part ' + self.model_part_name + \ '| CFL_threshold: ' + str(self.cfl_output_limit) + '\n' header += '# Time Mean Std Max HowMany>' + \ "{:.1f}".format(self.cfl_output_limit) + ' [%] HowMany>1.0 [%]\n' return header def _PrintToScreen(self, result_msg): KratosMultiphysics.Logger.PrintInfo("CFLOutputProcess", "CFL VALUE RESULTS:") KratosMultiphysics.Logger.PrintInfo("CFLOutputProcess", "Current time: " + result_msg) def _CalculateWithRespectToThreshold(self, x): y = [val for val in x if val < self.cfl_output_limit] y1 = [val for val in x if val < 1.0] # % of element with cfl above threshold how_many = ((len(x) - len(y)) / len(x)) * 100 # % of element with cfl above 1 how_many1 = ((len(x) - len(y1)) / len(x)) * 100 # quantifying the mean and std for values below the threshold y_mean = mean(y) y_std = stdev(y) # qunatifying the global max x_max = max(x) return [y_mean, y_std, x_max, how_many, how_many1] def _EvaluateCFL(self): if (self.model_part.ProcessInfo[KratosMultiphysics.DOMAIN_SIZE] == 2): KratosCFD.EstimateDtUtility2D.CalculateLocalCFL(self.model_part) else: KratosCFD.EstimateDtUtility3D.CalculateLocalCFL(self.model_part) local_cfl = [] for elem in self.model_part.Elements: local_cfl.append(elem.GetValue(KratosMultiphysics.CFL_NUMBER)) local_cfl = self.model_part.GetCommunicator().GetDataCommunicator( ).GathervDoubles(local_cfl, 0) return local_cfl def _SummarizeCFL(self, local_cfl): global_cfl = [] for k in local_cfl: global_cfl.extend(k) cfl_mean, cfl_std, cfl_max, cfl_how_many, cfl_how_many1 = self._CalculateWithRespectToThreshold( global_cfl) return [cfl_mean, cfl_std, cfl_max, cfl_how_many, cfl_how_many1]
class ResponseFunctionOutputProcess(Kratos.OutputProcess): def __init__(self, model, params): Kratos.OutputProcess.__init__(self) default_settings = Kratos.Parameters('''{ "response_type" : "PLEASE_SPECIFY_RESPONSE_TYPE", "model_part_name" : "PLEASE_SPECIFY_MAIN_MODEL_PART_NAME", "response_settings" : {}, "output_file_settings": {} }''') self.model = model self.params = params self.main_model_part = self.model.GetModelPart( self.params["model_part_name"].GetString()) self.params.ValidateAndAssignDefaults(default_settings) self.output_file = None response_type = self.params["response_type"].GetString() if (response_type == "norm_square"): self.response = KratosCFD.VelocityPressureNormSquareResponseFunction( self.params["response_settings"], self.model) else: raise Exception( "Unknown response_type = \"" + response_type + "\". Supported response types are: \n\t 1. norm_square") def ExecuteInitialize(self): self.response.Initialize() # Only rank 0 writes in MPI my_rank = 0 comm = self.main_model_part.GetCommunicator().GetDataCommunicator() self.is_writing_rank = my_rank == comm.Rank() if self.is_writing_rank: file_handler_params = Kratos.Parameters( self.params["output_file_settings"]) file_header = self.GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.main_model_part, file_handler_params, file_header).file def PrintOutput(self): time = self.main_model_part.ProcessInfo[Kratos.TIME] out = str(time) response_value = self.response.CalculateValue(self.main_model_part) out += "," + str(response_value) out += "\n" if self.is_writing_rank: self.output_file.write(out) def ExecuteFinalize(self): if self.is_writing_rank: self.output_file.close() def GetFileHeader(self): header = '# Response results ' + '\n' header += '# time, ResponseValue' header += "\n" return header
class ComputeBoundaryForceProcess(KM.Process): ''' Get the external accelerations and computes the hydrostatic forces. The results are written in a file or printed into screen. ''' def __init__(self, model, params): '''Constructor of ComputeBoundaryForceProcess.''' super().__init__() default_settings = KM.Parameters(""" { "model_part_wall_name" : "", "model_part_bottom_name" : "", "interval" : [0.0, 1e30], "print_to_screen" : false, "print_format" : ".8f", "write_output_file" : true, "output_file_settings" : {} } """) self.interval = KM.IntervalUtility(params) params.ValidateAndAssignDefaults(default_settings) self.model_part_wall_name = params['model_part_wall_name'].GetString() self.model_part_wall = model[self.model_part_wall_name] self.model_part_bottom_name = params[ 'model_part_bottom_name'].GetString() self.model_part_bottom = model[self.model_part_bottom_name] self.print_to_screen = params['print_to_screen'].GetBool() self.write_output_file = params['write_output_file'].GetBool() self.print_format = params["print_format"].GetString() if (self.model_part_wall.GetCommunicator().MyPID() == 0): if (self.write_output_file): default_file_name = params["model_part_wall_name"].GetString( ) + "_global_force.dat" file_handler_params = KM.Parameters( params["output_file_settings"]) if file_handler_params.Has("file_name"): file_name = file_handler_params["file_name"].GetString() msg = 'Unexpected user-specified entry found in "output_file_settings":\n' msg += '\t"file_name" : "{}"\n' msg += 'Using this specified file name instead of the default ("{}")' KM.Logger.PrintWarning( "ComputeBoundaryForceProcess", msg.format(file_name, default_file_name)) else: file_handler_params.AddString("file_name", default_file_name) file_header = self._GetFileHeader() self.output_file = TimeBasedAsciiFileWriterUtility( self.model_part_wall, file_handler_params, file_header).file def ExecuteFinalizeSolutionStep(self): '''Print the boundary forces to a file or into screen.''' current_time = self.model_part_wall.ProcessInfo[KM.TIME] if self.interval.IsInInterval(current_time): accelerations, forces = self._EvaluateGlobalForces() if self.model_part_wall.GetCommunicator().MyPID() == 0: output_values = [] # not formatting time in order to not lead to problems with time recognition # in the file writer when restarting output_values.append(str(current_time)) for val in accelerations: output_values.append(format(val, self.print_format)) for val in forces: output_values.append(format(val, self.print_format)) if self.print_to_screen: result_msg = 'Global force evaluation for model part ' + \ self.model_part_wall_name + '\n' res_labels = [ 'time: ', 'acc_x: ', 'acc_y: ', 'acc_z: ', 'f_x: ', 'f_y: ', 'f_z: ' ] result_msg += ', '.join( [a + b for a, b in zip(res_labels, output_values)]) self._PrintToScreen(result_msg) if self.write_output_file: self.output_file.write(' '.join(output_values) + '\n') def _EvaluateGlobalForces(self): for node in self.model_part_wall.Nodes: acceleration = node.GetSolutionStepValue(KM.MESH_ACCELERATION) break process_info = self.model_part_wall.ProcessInfo sum_forces = SW.ShallowWaterUtilities().ComputeHydrostaticForces( self.model_part_wall.Conditions, process_info) sum_forces += SW.ShallowWaterUtilities().ComputeHydrostaticForces( self.model_part_bottom.Elements, process_info) return acceleration, sum_forces def _GetFileHeader(self): header = '# Global force for model part ' + self.model_part_wall_name + '\n' header += '# Time acc_x acc_y acc_z f_x f_y f_z\n' return header @staticmethod def _PrintToScreen(result_msg): KM.Logger.PrintInfo('ComputeBoundaryForceProcess', 'Global force results - flow- and body-attached:') KM.Logger.PrintInfo('ComputeBoundaryForceProcess', 'Current time: ' + result_msg)