class IgaTestFactory(KratosUnittest.TestCase): def setUp(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): # Reading the ProjectParameters with open(self.file_name + "_project_parameters.json",'r') as parameter_file: ProjectParameters = KratosMultiphysics.Parameters(parameter_file.read()) # To avoid many prints if ProjectParameters["problem_data"]["echo_level"].GetInt() == 0: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity(KratosMultiphysics.Logger.Severity.WARNING) else: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity(KratosMultiphysics.Logger.Severity.INFO) # Creating the test model = KratosMultiphysics.Model() self.test = StructuralMechanicsAnalysis(model, ProjectParameters) self.test.Initialize() def test_execution(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.RunSolutionLoop() def tearDown(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.Finalize()
class StructuralMechanicsTestFactory(KratosUnittest.TestCase): def setUp(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): # Reading the ProjectParameters with open(self.file_name + "_parameters.json",'r') as parameter_file: ProjectParameters = KratosMultiphysics.Parameters(parameter_file.read()) # The mechanical solver selects automatically the fastest linear-solver available # this might not be appropriate for a test, therefore in case nothing is specified, # the previous default linear-solver is set if not ProjectParameters["solver_settings"].Has("linear_solver_settings"): # check if running in MPI because there we use a different default linear solver if IsDistributedRun(): default_lin_solver_settings = KratosMultiphysics.Parameters("""{ "solver_type" : "amesos", "amesos_solver_type" : "Amesos_Klu" }""") else: default_lin_solver_settings = KratosMultiphysics.Parameters("""{ "solver_type": "ExternalSolversApplication.super_lu", "max_iteration": 500, "tolerance": 1e-9, "scaling": false, "symmetric_scaling": true, "verbosity": 0 }""") ProjectParameters["solver_settings"].AddValue("linear_solver_settings", default_lin_solver_settings) self.modify_parameters(ProjectParameters) # To avoid many prints if ProjectParameters["problem_data"]["echo_level"].GetInt() == 0: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity(KratosMultiphysics.Logger.Severity.WARNING) else: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity(KratosMultiphysics.Logger.Severity.INFO) # Creating the test model = KratosMultiphysics.Model() self.test = StructuralMechanicsAnalysis(model, ProjectParameters) self.test.Initialize() def modify_parameters(self, project_parameters): """This function can be used in derived classes to modify existing parameters before the execution of the test (e.g. switch to MPI) """ pass def test_execution(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.RunSolutionLoop() def tearDown(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.Finalize()
class StructuralMechanicsTestFactory(KratosUnittest.TestCase): def setUp(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): # Reading the ProjectParameters with open(self.file_name + "_parameters.json", 'r') as parameter_file: ProjectParameters = KratosMultiphysics.Parameters( parameter_file.read()) SelectAndVerifyLinearSolver(ProjectParameters, self.skipTest) self.modify_parameters(ProjectParameters) # To avoid many prints if ProjectParameters["problem_data"]["echo_level"].GetInt() == 0: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity( KratosMultiphysics.Logger.Severity.WARNING) else: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity( KratosMultiphysics.Logger.Severity.INFO) # Creating the test model = KratosMultiphysics.Model() self.test = StructuralMechanicsAnalysis(model, ProjectParameters) self.test.Initialize() def modify_parameters(self, project_parameters): """This function can be used in derived classes to modify existing parameters before the execution of the test (e.g. switch to MPI) """ pass def test_execution(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.RunSolutionLoop() def tearDown(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.Finalize()
class AdjointResponseFunction(ResponseFunctionInterface): """Linear static adjoint strain energy response function. - runs the primal analysis (writes the primal results to an .h5 file) - reads the primal results from the .h5 file into the adjoint model part - uses primal results to calculate value - uses primal results to calculate gradient by running the adjoint analysis Attributes ---------- primal_analysis : Primal analysis object of the response function adjoint_analysis : Adjoint analysis object of the response function """ def __init__(self, identifier, response_settings, model): self.identifier = identifier self.response_settings = response_settings # Create the primal solver with open(self.response_settings["primal_settings"].GetString(), 'r') as parameter_file: primal_parameters = Parameters(parameter_file.read()) self.primal_model_part = _GetModelPart( model, primal_parameters["solver_settings"]) self.primal_analysis = StructuralMechanicsAnalysis( model, primal_parameters) self.primal_data_transfer_with_python = self.response_settings[ "primal_data_transfer_with_python"].GetBool() # Create the adjoint solver adjoint_parameters = self._GetAdjointParameters() adjoint_model = KratosMultiphysics.Model() self.adjoint_model_part = _GetModelPart( adjoint_model, adjoint_parameters["solver_settings"]) # TODO find out why it is not possible to use the same model_part self.adjoint_analysis = StructuralMechanicsAnalysis( adjoint_model, adjoint_parameters) self.primal_state_variables = [KratosMultiphysics.DISPLACEMENT] if primal_parameters["solver_settings"].Has("rotation_dofs"): if primal_parameters["solver_settings"]["rotation_dofs"].GetBool(): self.primal_state_variables.append(KratosMultiphysics.ROTATION) def Initialize(self): self.primal_analysis.Initialize() self.adjoint_analysis.Initialize() def InitializeSolutionStep(self): # Run the primal analysis. # TODO if primal_analysis.status==solved: return Logger.PrintInfo(self._GetLabel(), "Starting primal analysis for response:", self.identifier) startTime = timer.time() if not self.primal_analysis.time < self.primal_analysis.end_time: self.primal_analysis.end_time += 1 self.primal_analysis.RunSolutionLoop() Logger.PrintInfo(self._GetLabel(), "Time needed for solving the primal analysis = ", round(timer.time() - startTime, 2), "s") def CalculateValue(self): startTime = timer.time() value = self._GetResponseFunctionUtility().CalculateValue( self.primal_model_part) Logger.PrintInfo(self._GetLabel(), "Time needed for calculating the response value = ", round(timer.time() - startTime, 2), "s") self.primal_model_part.ProcessInfo[ StructuralMechanicsApplication.RESPONSE_VALUE] = value def CalculateGradient(self): # synchronize the modelparts self._SynchronizeAdjointFromPrimal() startTime = timer.time() Logger.PrintInfo(self._GetLabel(), "Starting adjoint analysis for response:", self.identifier) if not self.adjoint_analysis.time < self.adjoint_analysis.end_time: self.adjoint_analysis.end_time += 1 self.adjoint_analysis.RunSolutionLoop() Logger.PrintInfo(self._GetLabel(), "Time needed for solving the adjoint analysis = ", round(timer.time() - startTime, 2), "s") def GetValue(self): return self.primal_model_part.ProcessInfo[ StructuralMechanicsApplication.RESPONSE_VALUE] def GetNodalGradient(self, variable): if variable != KratosMultiphysics.SHAPE_SENSITIVITY: raise RuntimeError("GetNodalGradient: No gradient for {}!".format( variable.Name)) gradient = {} for node in self.adjoint_model_part.Nodes: gradient[node.Id] = node.GetSolutionStepValue(variable) return gradient def Finalize(self): self.primal_analysis.Finalize() self.adjoint_analysis.Finalize() def _GetResponseFunctionUtility(self): return self.adjoint_analysis._GetSolver().response_function def _SynchronizeAdjointFromPrimal(self): Logger.PrintInfo( self._GetLabel(), "Synchronize primal and adjoint modelpart for response:", self.identifier) if len(self.primal_model_part.Nodes) != len( self.adjoint_model_part.Nodes): raise RuntimeError( "_SynchronizeAdjointFromPrimal: Model parts have a different number of nodes!" ) # TODO this should happen automatically for primal_node, adjoint_node in zip(self.primal_model_part.Nodes, self.adjoint_model_part.Nodes): adjoint_node.X0 = primal_node.X0 adjoint_node.Y0 = primal_node.Y0 adjoint_node.Z0 = primal_node.Z0 adjoint_node.X = primal_node.X adjoint_node.Y = primal_node.Y adjoint_node.Z = primal_node.Z # Put primal solution on adjoint model if self.primal_data_transfer_with_python: Logger.PrintInfo(self._GetLabel(), "Transfer primal state to adjoint model part.") variable_utils = KratosMultiphysics.VariableUtils() for variable in self.primal_state_variables: variable_utils.CopyModelPartNodalVar(variable, self.primal_model_part, self.adjoint_model_part, 0) def _GetAdjointParameters(self): adjoint_settings = self.response_settings[ "adjoint_settings"].GetString() if adjoint_settings == "auto": Logger.PrintInfo( self._GetLabel(), "Automatic set up adjoint parameters for response:", self.identifier) if not self.primal_data_transfer_with_python: raise Exception( "Auto setup of adjoint parameters does only support primal data transfer with python." ) with open(self.response_settings["primal_settings"].GetString(), 'r') as parameter_file: primal_parameters = Parameters(parameter_file.read()) # check that HDF5 process is not there if primal_parameters["processes"].Has("list_other_processes"): for i in range( 0, primal_parameters["processes"] ["list_other_processes"].size()): process = primal_parameters["processes"][ "list_other_processes"][i] raise Exception( "Auto setup of adjoint parameters does not support {} in list_other_processes" .format(process["python_module"].GetString())) # clone primal settings as base for adjoint adjoint_parameters = primal_parameters.Clone() # analysis settings solver_settings = adjoint_parameters["solver_settings"] primal_solver_type = solver_settings["solver_type"].GetString() if primal_solver_type != "static": raise Exception( "Auto setup of adjoint parameters does not support {} solver_type. Only available for 'static'" .format(primal_solver_type)) solver_settings["solver_type"].SetString("adjoint_" + primal_solver_type) if not solver_settings.Has("compute_reactions"): solver_settings.AddEmptyValue("compute_reactions") solver_settings["compute_reactions"].SetBool(False) if not solver_settings.Has("move_mesh_flag"): solver_settings.AddEmptyValue("move_mesh_flag") solver_settings["move_mesh_flag"].SetBool(False) if solver_settings.Has("scheme_settings"): depr_msg = '\nDEPRECATION-WARNING: "scheme_settings" is deprecated, please remove it from your json parameters.\n' Logger.PrintWarning(__name__, depr_msg) solver_settings.RemoveValue("scheme_settings") if solver_settings["model_import_settings"][ "input_type"].GetString() == "use_input_model_part": solver_settings["model_import_settings"][ "input_type"].SetString("mdpa") if solver_settings["model_import_settings"].Has( "input_filename"): file_name = solver_settings["model_import_settings"][ "input_filename"].GetString() else: Logger.PrintWarning( self._GetLabel(), "Automatic adjoint settings creator assumes the model_part_name as input_filename." ) solver_settings["model_import_settings"].AddEmptyValue( "input_filename") file_name = solver_settings["model_part_name"].GetString() solver_settings["model_import_settings"][ "input_filename"].SetString(file_name) # Dirichlet conditions: change variables for i in range( 0, primal_parameters["processes"] ["constraints_process_list"].size()): process = adjoint_parameters["processes"][ "constraints_process_list"][i] variable_name = process["Parameters"][ "variable_name"].GetString() process["Parameters"]["variable_name"].SetString("ADJOINT_" + variable_name) # Neumann conditions - do not modify to read the same load values as in primal: # Output process: # TODO how to add the output process? How find out about the variables? if adjoint_parameters.Has("output_processes"): Logger.PrintInfo( self._GetLabel(), "Output process is removed for adjoint analysis. To enable it define adjoint_parameters yourself." ) adjoint_parameters.RemoveValue("output_processes") # sensitivity settings adjoint_parameters["solver_settings"].AddValue( "sensitivity_settings", self.response_settings["sensitivity_settings"]) # response settings adjoint_parameters["solver_settings"].AddValue( "response_function_settings", self.response_settings) else: # adjoint parameters file is explicitely given - do not change it. with open(self.response_settings["adjoint_settings"].GetString(), 'r') as parameter_file: adjoint_parameters = Parameters(parameter_file.read()) return adjoint_parameters def _GetLabel(self): type_labels = { "adjoint_nodal_displacement": "NodalDisplacement", "adjoint_linear_strain_energy": "StrainEnergy", "adjoint_local_stress": "LocalStress", "adjoint_max_stress": "MaxStress", "adjoint_nodal_reaction": "NodalReaction" } response_type = self.response_settings["response_type"].GetString() return "Adjoint" + type_labels[response_type] + "Response"
class StructuralMechanicsTestFactory(KratosUnittest.TestCase): def setUp(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): # Reading the ProjectParameters with open(self.file_name + "_parameters.json", 'r') as parameter_file: ProjectParameters = KratosMultiphysics.Parameters( parameter_file.read()) # The mechanical solver selects automatically the fastest linear-solver available # this might not be appropriate for a test, therefore in case nothing is specified, # the previous default linear-solver is set if not ProjectParameters["solver_settings"].Has( "linear_solver_settings"): # check if running in MPI because there we use a different default linear solver if IsDistributedRun(): default_lin_solver_settings = KratosMultiphysics.Parameters( """{ "solver_type" : "amesos", "amesos_solver_type" : "Amesos_Klu" }""") else: default_lin_solver_settings = KratosMultiphysics.Parameters( """{ "solver_type": "EigenSolversApplication.sparse_lu" }""") ProjectParameters["solver_settings"].AddValue( "linear_solver_settings", default_lin_solver_settings) solver_type = ProjectParameters["solver_settings"][ "linear_solver_settings"]["solver_type"].GetString() solver_type_splitted = solver_type.split(".") if len(solver_type_splitted) == 2: # this means that we use a solver from an application # hence we have to check if it exists, otherwise skip the test app_name = solver_type_splitted[0] solver_name = solver_type_splitted[1] if not kratos_utils.CheckIfApplicationsAvailable(app_name): self.skipTest( 'Application "{}" is needed for the specified solver "{}" but is not available' .format(app_name, solver_name)) self.modify_parameters(ProjectParameters) # To avoid many prints if ProjectParameters["problem_data"]["echo_level"].GetInt() == 0: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity( KratosMultiphysics.Logger.Severity.WARNING) else: KratosMultiphysics.Logger.GetDefaultOutput().SetSeverity( KratosMultiphysics.Logger.Severity.INFO) # Creating the test model = KratosMultiphysics.Model() self.test = StructuralMechanicsAnalysis(model, ProjectParameters) self.test.Initialize() def modify_parameters(self, project_parameters): """This function can be used in derived classes to modify existing parameters before the execution of the test (e.g. switch to MPI) """ pass def test_execution(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.RunSolutionLoop() def tearDown(self): # Within this location context: with KratosUnittest.WorkFolderScope(".", __file__): self.test.Finalize()