diff --git a/fluid_dynamics/validation/compressible_sod_shock_tube/data/density.png b/fluid_dynamics/validation/compressible_sod_shock_tube/data/density.png index c9605596..7666ec28 100644 Binary files a/fluid_dynamics/validation/compressible_sod_shock_tube/data/density.png and b/fluid_dynamics/validation/compressible_sod_shock_tube/data/density.png differ diff --git a/fluid_dynamics/validation/compressible_sod_shock_tube/data/pressure.png b/fluid_dynamics/validation/compressible_sod_shock_tube/data/pressure.png index a86de6f2..a76047d1 100644 Binary files a/fluid_dynamics/validation/compressible_sod_shock_tube/data/pressure.png and b/fluid_dynamics/validation/compressible_sod_shock_tube/data/pressure.png differ diff --git a/fluid_dynamics/validation/compressible_sod_shock_tube/data/velocity.png b/fluid_dynamics/validation/compressible_sod_shock_tube/data/velocity.png index 45f46517..33545b75 100644 Binary files a/fluid_dynamics/validation/compressible_sod_shock_tube/data/velocity.png and b/fluid_dynamics/validation/compressible_sod_shock_tube/data/velocity.png differ diff --git a/fluid_dynamics/validation/compressible_sod_shock_tube/source/MainKratos.py b/fluid_dynamics/validation/compressible_sod_shock_tube/source/MainKratos.py old mode 100755 new mode 100644 index 876d32c3..cc21d991 --- a/fluid_dynamics/validation/compressible_sod_shock_tube/source/MainKratos.py +++ b/fluid_dynamics/validation/compressible_sod_shock_tube/source/MainKratos.py @@ -1,58 +1,39 @@ -#!/usr/bin/env python - -import time import sys -import pathlib +import time +import importlib import KratosMultiphysics -import KratosMultiphysics.FluidDynamicsApplication -from KratosMultiphysics.FluidDynamicsApplication.fluid_dynamics_analysis \ - import FluidDynamicsAnalysis - - -def abs_filepath(relative_filepath: str) -> str: - return str(pathlib.Path(__file__).parent.resolve()) + "/" \ - + relative_filepath - -class FluidDynamicsAnalysisCompressible(FluidDynamicsAnalysis): - """ - Modified FluidDynamicsAnalysis in order to: - - Print at the first step - - Force stdout to flush at regular intervals - """ +def CreateAnalysisStageWithFlushInstance(cls, global_model, parameters): + class AnalysisStageWithFlush(cls): + + def __init__(self, model,project_parameters, flush_frequency=10.0): + super().__init__(model,project_parameters) + self.flush_frequency = flush_frequency + self.last_flush = time.time() + sys.stdout.flush() + + def Flush(self): + if self.parallel_type == "OpenMP": + now = time.time() + if now - self.last_flush > self.flush_frequency: + sys.stdout.flush() + self.last_flush = now + + return AnalysisStageWithFlush(global_model, parameters) - def __init__(self, model, parameters, flush_frequency=10.0): - super().__init__(model, parameters) - self.flush_frequency = flush_frequency - self.last_flush = time.time() - sys.stdout.flush() - - def Initialize(self): - super().Initialize() - sys.stdout.flush() - self.OutputSolutionStep() - - def OutputSolutionStep(self): - self.Flush() - super().OutputSolutionStep() - - def Flush(self, force=False): - if not force and self.parallel_type != "OpenMP": - return - - now = time.time() - if not force and (now - self.last_flush < self.flush_frequency): - return +if __name__ == "__main__": - sys.stdout.flush() - self.last_flush = now + with open("ProjectParameters.json", 'r') as parameter_file: + parameters = KratosMultiphysics.Parameters(parameter_file.read()) + analysis_stage_module_name = parameters["analysis_stage"].GetString() + analysis_stage_class_name = analysis_stage_module_name.split('.')[-1] + analysis_stage_class_name = ''.join(x.title() for x in analysis_stage_class_name.split('_')) -if __name__ == "__main__": - with open(abs_filepath("ProjectParameters.json"), 'r') as parameter_file: - project_parameters = KratosMultiphysics.Parameters(parameter_file.read()) + analysis_stage_module = importlib.import_module(analysis_stage_module_name) + analysis_stage_class = getattr(analysis_stage_module, analysis_stage_class_name) - global_model = KratosMultiphysics.Model() - simulation = FluidDynamicsAnalysisCompressible(global_model, project_parameters) - simulation.Run() + global_model = KratosMultiphysics.Model() + simulation = CreateAnalysisStageWithFlushInstance(analysis_stage_class, global_model, parameters) + simulation.Run() diff --git a/fluid_dynamics/validation/compressible_sod_shock_tube/source/ProjectParameters.json b/fluid_dynamics/validation/compressible_sod_shock_tube/source/ProjectParameters.json index adcb9342..67d03218 100644 --- a/fluid_dynamics/validation/compressible_sod_shock_tube/source/ProjectParameters.json +++ b/fluid_dynamics/validation/compressible_sod_shock_tube/source/ProjectParameters.json @@ -1,76 +1,40 @@ { - "problem_data": { - "problem_name": "sod_triangle", - "parallel_type": "OpenMP", - "echo_level": 5, - "start_time": 0.0, - "end_time": 0.16 - }, - "output_processes": { - "gid_output": [ - { - "python_module": "gid_output_process", - "kratos_module": "KratosMultiphysics", - "process_name": "GiDOutputProcess", - "help": "This process writes postprocessing files for GiD", - "Parameters": { - "model_part_name": "FluidModelPart.fluid_computational_model_part", - "output_name": "sod", - "postprocess_parameters": { - "result_file_configuration": { - "gidpost_flags": { - "GiDPostMode": "GiD_PostBinary", - "WriteDeformedMeshFlag": "WriteDeformed", - "WriteConditionsFlag": "WriteConditions", - "MultiFileFlag": "SingleFile" - }, - "file_label": "time", - "output_control_type": "time", - "output_interval": 0.05, - "body_output": true, - "node_output": false, - "skin_output": false, - "plane_output": [], - "nodal_results": ["MOMENTUM","DENSITY","TOTAL_ENERGY","PRESSURE","TEMPERATURE","VELOCITY", "NUMERICAL_ENTROPY"], - "gauss_point_results": ["SHOCK_SENSOR","THERMAL_SENSOR","SHEAR_SENSOR", "VELOCITY_DIVERGENCE"], - "nodal_nonhistorical_results": ["SOUND_VELOCITY", "ARTIFICIAL_MASS_DIFFUSIVITY", "ARTIFICIAL_BULK_VISCOSITY","ARTIFICIAL_DYNAMIC_VISCOSITY","ARTIFICIAL_CONDUCTIVITY","MACH"] - }, - "point_data_configuration": [] - } - } - } - ] - }, + "analysis_stage": "KratosMultiphysics.FluidDynamicsApplication.fluid_dynamics_analysis", + "problem_data" : { + "problem_name" : "sod_with_triangles", + "parallel_type" : "OpenMP", + "echo_level" : 0, + "start_time" : 0.0, + "end_time" : 0.1 + }, "solver_settings": { - "model_part_name": "FluidModelPart", - "domain_size": 2, - "solver_type": "CompressibleExplicit", - "model_import_settings": { - "input_type": "mdpa", - "input_filename": "rectangle" - }, - "material_import_settings": { - "materials_filename": "FluidMaterials.json" - }, - "echo_level": 0, - "compute_reactions": false, - "shock_capturing_settings": { - "type" : "physics_based" - }, - "time_scheme" : "RK3-TVD", - "use_oss": false, - "volume_model_part_name": "FluidParts_Fluid", - "skin_parts": ["Slip2D", "Boundaries-Left", "Boundaries-Right"], - "no_skin_parts": [], - "time_stepping": { - "automatic_time_step": true, - "CFL_number": 0.5, - "minimum_delta_time": 1e-8, - "maximum_delta_time": 0.01, - "Viscous_Fourier_number": -1, - "Thermal_Fourier_number": -1 - }, - "reform_dofs_at_each_step": false + "model_part_name" : "FluidModelPart", + "domain_size" : 2, + "solver_type" : "CompressibleExplicit", + "model_import_settings": { + "input_type": "mdpa", + "input_filename": "rectangle" + }, + "material_import_settings": { + "materials_filename": "FluidMaterials.json" + }, + "echo_level": 0, + "compute_reactions": false, + "shock_capturing_settings": { + "type" : "physics_based", + "Parameters" : {} + }, + "time_scheme" : "RK4", + "use_oss": false, + "volume_model_part_name": "FluidParts_Fluid", + "skin_parts": ["Slip2D", "Boundaries-Left", "Boundaries-Right"], + "no_skin_parts": [], + "time_stepping": { + "automatic_time_step": true, + "minimum_delta_time" : 1e-8, + "CFL_number": 1.0 + }, + "reform_dofs_at_each_step": false }, "processes": { "initial_conditions_process_list": @@ -141,5 +105,56 @@ } ], "auxiliar_process_list": [] + }, + "output_processes": { + "gid_output": [ + { + "python_module": "gid_output_process", + "kratos_module": "KratosMultiphysics", + "process_name": "GiDOutputProcess", + "help": "This process writes postprocessing files for GiD", + "Parameters": { + "model_part_name": "FluidModelPart.fluid_computational_model_part", + "output_name": "sod", + "postprocess_parameters": { + "result_file_configuration": { + "gidpost_flags": { + "GiDPostMode": "GiD_PostBinary", + "WriteDeformedMeshFlag": "WriteDeformed", + "WriteConditionsFlag": "WriteConditions", + "MultiFileFlag": "SingleFile" + }, + "file_label": "time", + "output_control_type": "time", + "output_interval": 0.01, + "body_output": true, + "node_output": false, + "skin_output": false, + "plane_output": [], + "nodal_results": [ + "MOMENTUM", + "DENSITY", + "TOTAL_ENERGY", + "PRESSURE", + "TEMPERATURE", + "VELOCITY"], + "gauss_point_results": [ + "SHOCK_SENSOR", + "THERMAL_SENSOR", + "SHEAR_SENSOR", + "VELOCITY_DIVERGENCE"], + "nodal_nonhistorical_results": [ + "SOUND_VELOCITY", + "ARTIFICIAL_MASS_DIFFUSIVITY", + "ARTIFICIAL_BULK_VISCOSITY", + "ARTIFICIAL_DYNAMIC_VISCOSITY", + "ARTIFICIAL_CONDUCTIVITY", + "MACH"] + }, + "point_data_configuration": [] + } + } + } + ] } } diff --git a/fluid_dynamics/validation/compressible_step_woodward_colella/source/MainKratos.py b/fluid_dynamics/validation/compressible_step_woodward_colella/source/MainKratos.py index 3f9026db..a1339c57 100644 --- a/fluid_dynamics/validation/compressible_step_woodward_colella/source/MainKratos.py +++ b/fluid_dynamics/validation/compressible_step_woodward_colella/source/MainKratos.py @@ -1,115 +1,64 @@ -import time import sys -import os -import pathlib -import math +import time +import importlib import KratosMultiphysics -import KratosMultiphysics.FluidDynamicsApplication -from KratosMultiphysics.FluidDynamicsApplication.fluid_dynamics_analysis \ - import FluidDynamicsAnalysis - - -def abs_filepath(relative_filepath: str) -> str: - return str(pathlib.Path(__file__).parent.resolve()) + "/" \ - + relative_filepath - - -class FluidDynamicsAnalysisCompressible(FluidDynamicsAnalysis): - """ - Modified FluidDynamicsAnalysis in order to: - - Print at the first step - - Print when T<0 - - Terminate simulation when T<0 - - Force stdout to flush at regular intervals - """ - - def __init__(self, model, parameters, flush_frequency=10.0): - super().__init__(model, parameters) - self.flush_frequency = flush_frequency - self.last_flush = time.time() - sys.stdout.flush() - - self.print_count = 0 - self.negative_temp = False - - @classmethod - def distance_to_corner(cls, u: KratosMultiphysics.Node): - return (u.X - 0.6)**2 + (u.Y - 0.0)**2 + (u.Y - 0.0)**2 - def _find_lower_corner_node(self): - eps_2 = 1e-16 - for node in self._GetSolver().GetComputingModelPart().Nodes: - if self.distance_to_corner(node) < eps_2: - self._lower_corner_node = node.Id - KratosMultiphysics.Logger.Print(f"Lower corner node has ID: {self._lower_corner_node}") - return - raise RuntimeError("Lower corner node not found") +def CreateAnalysisStageWithFlushInstance(cls, global_model, parameters): + class AnalysisStageWithFlush(cls): + + def __init__(self, model,project_parameters, flush_frequency=10.0): + super().__init__(model,project_parameters) + self.flush_frequency = flush_frequency + self.last_flush = time.time() + sys.stdout.flush() + + @classmethod + def distance_to_corner(cls, u: KratosMultiphysics.Node): + return (u.X - 0.6)**2 + (u.Y - 0.0)**2 + (u.Y - 0.0)**2 + + def _find_lower_corner_node(self): + eps_2 = 1e-16 + for node in self._GetSolver().GetComputingModelPart().Nodes: + if self.distance_to_corner(node) < eps_2: + self._lower_corner_node = node.Id + return + raise RuntimeError("Lower corner node not found") + + def Initialize(self): + super().Initialize() + sys.stdout.flush() + self._find_lower_corner_node() + + def InitializeSolutionStep(self): + node = self._GetSolver().GetComputingModelPart().GetNode(self._lower_corner_node) + node.SetSolutionStepValue(KratosMultiphysics.MOMENTUM_X, 0.0) + node.SetSolutionStepValue(KratosMultiphysics.MOMENTUM_Y, 0.0) + node.Fix(KratosMultiphysics.MOMENTUM_X) + node.Fix(KratosMultiphysics.MOMENTUM_Y) + super().InitializeSolutionStep() + + def Flush(self): + if self.parallel_type == "OpenMP": + now = time.time() + if now - self.last_flush > self.flush_frequency: + sys.stdout.flush() + self.last_flush = now + + return AnalysisStageWithFlush(global_model, parameters) - def Initialize(self): - super().Initialize() - sys.stdout.flush() - self._find_lower_corner_node() - - self.OutputSolutionStep() - - def InitializeSolutionStep(self): - node = self._GetSolver().GetComputingModelPart().GetNode(self._lower_corner_node) - node.SetSolutionStepValue(KratosMultiphysics.MOMENTUM_X, 0.0) - node.SetSolutionStepValue(KratosMultiphysics.MOMENTUM_Y, 0.0) - super().InitializeSolutionStep() - - def FinalizeSolutionStep(self): - """This function performs all the required operations that should - be executed (for each step) AFTER solving the solution step. - """ - - super().FinalizeSolutionStep() - self.negative_temp = not self.TemperatureIsPositive() - - def OutputSolutionStep(self): - """This function printes / writes output files after the solution - of a step - """ - self.Flush() - super().OutputSolutionStep() - - def KeepAdvancingSolutionLoop(self): - """This function specifies the stopping criteria for breaking the - solution loop. It can be overridden by derived classes - """ - if self.negative_temp: - return False - - return super().KeepAdvancingSolutionLoop() +if __name__ == "__main__": - def TemperatureIsPositive(self): - "Checks if the temperature is a positive number at every node" - for node in self._GetSolver().GetComputingModelPart().Nodes: - T = node.GetSolutionStepValue(KratosMultiphysics.TEMPERATURE) - if T < 0.0: - KratosMultiphysics.Logger.Print("Negative temperature in node with ID: %d" % node.Id) - return False - if math.isnan(T): - KratosMultiphysics.Logger.Print("NaN temperature in node with ID: %d" % node.Id) - return False - if math.isinf(T): - KratosMultiphysics.Logger.Print("Infinite temperature in node with ID: %d" % node.Id) - return False - return True + with open("ProjectParameters.json", 'r') as parameter_file: + parameters = KratosMultiphysics.Parameters(parameter_file.read()) - def Flush(self): - if self.parallel_type == "OpenMP": - now = time.time() - if now - self.last_flush > self.flush_frequency: - KratosMultiphysics.Logger.Flush() - sys.stdout.flush() - self.last_flush = now + analysis_stage_module_name = parameters["analysis_stage"].GetString() + analysis_stage_class_name = analysis_stage_module_name.split('.')[-1] + analysis_stage_class_name = ''.join(x.title() for x in analysis_stage_class_name.split('_')) + analysis_stage_module = importlib.import_module(analysis_stage_module_name) + analysis_stage_class = getattr(analysis_stage_module, analysis_stage_class_name) -if __name__ == "__main__": - with open(abs_filepath("ProjectParameters.json"), 'r') as parameter_file: - project_parameters = KratosMultiphysics.Parameters(parameter_file.read()) - global_model = KratosMultiphysics.Model() - simulation = FluidDynamicsAnalysisCompressible(global_model, project_parameters) - simulation.Run() + global_model = KratosMultiphysics.Model() + simulation = CreateAnalysisStageWithFlushInstance(analysis_stage_class, global_model, parameters) + simulation.Run() diff --git a/fluid_dynamics/validation/compressible_step_woodward_colella/source/ProjectParameters.json b/fluid_dynamics/validation/compressible_step_woodward_colella/source/ProjectParameters.json index 8ccb9fb3..6f4f982d 100644 --- a/fluid_dynamics/validation/compressible_step_woodward_colella/source/ProjectParameters.json +++ b/fluid_dynamics/validation/compressible_step_woodward_colella/source/ProjectParameters.json @@ -1,46 +1,18 @@ { + "analysis_stage" : "KratosMultiphysics.FluidDynamicsApplication.fluid_dynamics_analysis", "problem_data": { - "problem_name": "step_woodward", - "parallel_type": "OpenMP", - "echo_level": 0, - "start_time": 0.0, - "end_time": 5 + "problem_name" : "step_woodward_colella", + "parallel_type" : "OpenMP", + "echo_level" : 0, + "start_time" : 0.0, + "end_time" : 4.0 }, - "output_processes": { - "gid_output": [ - { - "python_module": "gid_output_process", - "kratos_module": "KratosMultiphysics", - "process_name": "GiDOutputProcess", - "help": "This process writes postprocessing files for GiD", - "Parameters": { - "model_part_name": "FluidModelPart.fluid_computational_model_part", - "output_name": "step_woodward_colella", - "postprocess_parameters": { - "result_file_configuration": { - "gidpost_flags": { - "GiDPostMode": "GiD_PostBinary", - "WriteDeformedMeshFlag": "WriteDeformed", - "WriteConditionsFlag": "WriteConditions", - "MultiFileFlag": "SingleFile" + "restart_options" : { + "SaveRestart" : "False", + "RestartFrequency" : 0, + "LoadRestart" : "False", + "Restart_Step" : 0 }, - "file_label": "time", - "output_control_type": "time", - "output_interval": 0.01, - "body_output": true, - "node_output": false, - "skin_output": false, - "plane_output": [], - "nodal_results": ["MOMENTUM","DENSITY","TOTAL_ENERGY","PRESSURE","TEMPERATURE","VELOCITY"], - "gauss_point_results": ["SHOCK_SENSOR","THERMAL_SENSOR","SHEAR_SENSOR", "DENSITY_GRADIENT"], - "nodal_nonhistorical_results": ["SOUND_VELOCITY", "ARTIFICIAL_MASS_DIFFUSIVITY", "ARTIFICIAL_BULK_VISCOSITY","ARTIFICIAL_DYNAMIC_VISCOSITY","ARTIFICIAL_CONDUCTIVITY","MACH"] - }, - "point_data_configuration": [] - } - } - } - ] - }, "solver_settings": { "model_part_name": "FluidModelPart", "domain_size": 2, @@ -56,21 +28,17 @@ "compute_reactions": false, "shock_capturing_settings": { "type" : "physics_based", - "Parameters" : { - } + "Parameters" : {} }, - "time_scheme" : "bfecc", + "time_scheme" : "RK4", "use_oss": false, "volume_model_part_name": "FluidParts_Fluid", "skin_parts": ["Slip2D"], "no_skin_parts": [], "time_stepping": { "automatic_time_step": true, - "CFL_number": 0.1, - "minimum_delta_time": 1e-7, - "maximum_delta_time": 1e-3, - "Viscous_Fourier_number": 0.1, - "Thermal_Fourier_number": 0.1 + "minimum_delta_time" : 1e-8, + "CFL_number": 0.2 }, "reform_dofs_at_each_step": false }, @@ -87,7 +55,7 @@ "variable_name": "DENSITY", "interval": [0.0, 0.0], "constrained": false, - "value": "1.4" + "value": 1.4 } }, { @@ -100,7 +68,7 @@ "variable_name": "MOMENTUM_X", "interval": [0.0, 0.0], "constrained": false, - "value": "4.2" + "value": 4.2 } }, { @@ -113,7 +81,7 @@ "variable_name": "MOMENTUM_Y", "interval": [0.0, 0.0], "constrained": false, - "value": "0.0" + "value": 0.0 } }, { @@ -126,23 +94,19 @@ "variable_name": "TOTAL_ENERGY", "interval": [0.0, 0.0], "constrained": false, - "value": "8.8" + "value": 8.8 } } ], "boundary_conditions_process_list": [ { - "kratos_module": "KratosMultiphysics", - "process_name": "AssignScalarVariableProcess", - "python_module": "assign_scalar_variable_process", + "kratos_module": "KratosMultiphysics.FluidDynamicsApplication", + "process_name": "ApplySlipProcess", + "python_module": "apply_slip_process", "Parameters": { - "model_part_name": "FluidModelPart.Slip2D.Slip2D_Walls-Bottom", - "variable_name": "MOMENTUM_Y", - "interval": [0.0, 1e+30], - "constrained": true, - "value": "0.0" + "model_part_name": "FluidModelPart.Slip2D" } }, { @@ -151,24 +115,11 @@ "python_module": "assign_scalar_variable_process", "Parameters": { - "model_part_name": "FluidModelPart.Slip2D.Slip2D_Walls-Top", - "variable_name": "MOMENTUM_Y", - "interval": [0.0, 1e+30], - "constrained": true, - "value": "0.0" - } - }, - { - "kratos_module": "KratosMultiphysics", - "process_name": "AssignScalarVariableProcess", - "python_module": "assign_scalar_variable_process", - "Parameters": - { - "model_part_name": "FluidModelPart.Slip2D.Slip2D_Walls-Obstacle", - "variable_name": "MOMENTUM_X", - "interval": [0.0, 1e+30], + "model_part_name": "FluidModelPart.Inlet", + "variable_name": "DENSITY", + "interval": [0.0, "End"], "constrained": true, - "value": "0.0" + "value": 1.4 } }, { @@ -178,10 +129,10 @@ "Parameters": { "model_part_name": "FluidModelPart.Inlet", - "variable_name": "DENSITY", - "interval": [0.0, 1e+30], + "variable_name": "MOMENTUM_X", + "interval": [0.0, "End"], "constrained": true, - "value": "1.4" + "value": 4.2 } }, { @@ -191,10 +142,10 @@ "Parameters": { "model_part_name": "FluidModelPart.Inlet", - "variable_name": "MOMENTUM_X", - "interval": [0.0, 1e+30], + "variable_name": "MOMENTUM_Y", + "interval": [0.0, "End"], "constrained": true, - "value": "4.2" + "value": 0.0 } }, { @@ -205,12 +156,62 @@ { "model_part_name": "FluidModelPart.Inlet", "variable_name": "TOTAL_ENERGY", - "interval": [0.0, 1e+30], + "interval": [0.0, "End"], "constrained": true, - "value": "8.8" + "value": 8.8 } } ], "auxiliar_process_list": [] + }, + "output_processes": { + "gid_output": [ + { + "python_module": "gid_output_process", + "kratos_module": "KratosMultiphysics", + "process_name": "GiDOutputProcess", + "help": "This process writes postprocessing files for GiD", + "Parameters": { + "model_part_name": "FluidModelPart.fluid_computational_model_part", + "output_name": "step_woodward_colella", + "postprocess_parameters": { + "result_file_configuration": { + "gidpost_flags": { + "GiDPostMode": "GiD_PostBinary", + "WriteDeformedMeshFlag": "WriteDeformed", + "WriteConditionsFlag": "WriteConditions", + "MultiFileFlag": "SingleFile" + }, + "file_label": "time", + "output_control_type": "time", + "output_interval": 0.1, + "body_output": true, + "node_output": false, + "skin_output": false, + "plane_output": [], + "nodal_results": [ + "MOMENTUM", + "DENSITY", + "TOTAL_ENERGY", + "PRESSURE", + "TEMPERATURE", + "VELOCITY"], + "gauss_point_results": [ + "SHOCK_SENSOR", + "THERMAL_SENSOR", + "SHEAR_SENSOR", + "DENSITY_GRADIENT"], + "nodal_nonhistorical_results": [ + "SOUND_VELOCITY", + "ARTIFICIAL_BULK_VISCOSITY", + "ARTIFICIAL_DYNAMIC_VISCOSITY", + "ARTIFICIAL_CONDUCTIVITY", + "MACH"] + }, + "point_data_configuration": [] + } + } + } + ] } }