Esempio n. 1
0
    def setUp(self):
        self.model_part_size = model_part_size = 3
        self.parameters = {
            'interface_a': [{
                'model_part': 'mp1',
                'variables': ['pressure', 'traction']
            }, {
                'model_part': 'mp2',
                'variables': ['density']
            }],
            'interface_b': [{
                'model_part': 'mp1',
                'variables': ['pressure', 'displacement']
            }, {
                'model_part': 'mp2',
                'variables': ['density']
            }],
            'interface_c': [{
                'model_part': 'mp1',
                'variables': ['pressure', 'traction']
            }, {
                'model_part': 'mp3',
                'variables': ['density']
            }],
            'interface_d': [{
                'model_part': 'mp2',
                'variables': ['density']
            }, {
                'model_part': 'mp1',
                'variables': ['pressure', 'displacement']
            }],
        }

        self.model = Model()
        self.x0 = x0 = np.random.rand(3 * model_part_size)
        self.y0 = y0 = np.random.rand(3 * model_part_size)
        self.z0 = z0 = np.random.rand(3 * model_part_size)
        self.ids = ids = np.arange(0, model_part_size)
        np.random.shuffle(ids)
        self.model.create_model_part('mp1', x0[0:model_part_size],
                                     y0[0:model_part_size],
                                     z0[0:model_part_size], ids)
        self.model.create_model_part('mp2',
                                     x0[model_part_size:2 * model_part_size],
                                     y0[model_part_size:2 * model_part_size],
                                     z0[model_part_size:2 * model_part_size],
                                     ids)
        self.model.create_model_part(
            'mp3', x0[2 * model_part_size:3 * model_part_size],
            y0[2 * model_part_size:3 * model_part_size],
            z0[2 * model_part_size:3 * model_part_size], ids)

        self.interface = Interface(self.parameters['interface_a'], self.model)
        self.scalar_size = 1
        self.vector_size = 3
        self.pressure = np.random.rand(model_part_size, self.scalar_size)
        self.traction = np.random.rand(model_part_size, self.vector_size)
        self.temperature = np.random.rand(model_part_size, self.scalar_size)
        self.density = np.random.rand(model_part_size, self.scalar_size)
        self.interface_data = np.random.rand(model_part_size * 5)
Esempio n. 2
0
    def test_eq(self):
        self.interface.set_interface_data(self.interface_data)

        model_part_size = self.model_part_size
        x0 = self.x0
        y0 = self.y0
        z0 = self.z0
        ids = self.ids
        model2 = Model()
        model2.create_model_part('mp1', x0[0:model_part_size],
                                 y0[0:model_part_size], z0[0:model_part_size],
                                 ids)
        model2.create_model_part('mp2',
                                 x0[model_part_size:2 * model_part_size],
                                 y0[model_part_size:2 * model_part_size],
                                 z0[model_part_size:2 * model_part_size], ids)
        interface2 = Interface(self.parameters['interface_a'], model2)
        interface2.set_interface_data(self.interface_data)
        self.assertIsNot(self.interface, interface2)
        self.assertEqual(self.interface, interface2)

        interface3 = Interface(self.parameters['interface_b'], model2)
        interface3.set_interface_data(self.interface_data)
        self.assertNotEqual(self.interface, interface3)

        interface4 = interface2.copy()
        interface_data4 = self.interface_data.copy()
        interface_data4[np.random.randint(interface4.size)] = np.random.rand()
        interface4.set_interface_data(interface_data4)
        self.assertNotEqual(self.interface, interface4)
Esempio n. 3
0
    def test_convergence_criterion_relative_norm(self):
        m = 10
        dz = 2
        a0 = 10
        a1 = 1e-4
        a2 = 1e-6
        variable = 'area'
        model_part_name = 'wall'
        interface_settings = [{'model_part': model_part_name, 'variables': [variable]}]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        a0_array = np.full((m, 1), a0)
        a1_array = np.full((m, 1), a1)
        a2_array = np.full((m, 1), a2)

        # create interface
        interface = Interface(interface_settings, model)

        # create convergence criterion
        parameters = {'type': 'convergence_criteria.relative_norm',
                      'settings': {'tolerance': 1e-6, 'order': 2}}
        convergence_criterion_relative_norm = create_instance(parameters)
        convergence_criterion_relative_norm.initialize()

        # test convergence criterion
        for i in range(3):
            convergence_criterion_relative_norm.initialize_solution_step()
            is_satisfied = convergence_criterion_relative_norm.is_satisfied()
            self.assertFalse(is_satisfied)
            interface.set_variable_data(model_part_name, variable, a0_array)
            convergence_criterion_relative_norm.update(interface)
            is_satisfied = convergence_criterion_relative_norm.is_satisfied()
            self.assertFalse(is_satisfied)
            interface.set_variable_data(model_part_name, variable, a1_array)
            convergence_criterion_relative_norm.update(interface)
            is_satisfied = convergence_criterion_relative_norm.is_satisfied()
            self.assertFalse(is_satisfied)
            interface.set_variable_data(model_part_name, variable, a2_array)
            convergence_criterion_relative_norm.update(interface)
            is_satisfied = convergence_criterion_relative_norm.is_satisfied()
            self.assertTrue(is_satisfied)
            interface.set_variable_data(model_part_name, variable, a1_array)
            convergence_criterion_relative_norm.update(interface)
            is_satisfied = convergence_criterion_relative_norm.is_satisfied()
            self.assertFalse(is_satisfied)
            convergence_criterion_relative_norm.finalize_solution_step()
Esempio n. 4
0
    def test_convergence_criterion_and(self):
        m = 10
        dz = 2
        a0 = 1
        variable = 'area'
        model_part_name = 'wall'
        interface_settings = [{'model_part': model_part_name, 'variables': [variable]}]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        a0_array = np.full((m, 1), a0)

        # create interface
        interface = Interface(interface_settings, model)
        interface.set_variable_data(model_part_name, variable, a0_array)

        # read settings
        parameter_file_name = os.path.join(os.path.dirname(__file__), 'test_and.json')
        with open(parameter_file_name, 'r') as parameter_file:
            parameters = json.load(parameter_file)

        convergence_criterion_and = create_instance(parameters)
        convergence_criterion_and.initialize()
        for i in range(3):
            convergence_criterion_and.initialize_solution_step()
            is_satisfied = convergence_criterion_and.is_satisfied()
            self.assertFalse(is_satisfied)
            convergence_criterion_and.update(interface)
            is_satisfied = convergence_criterion_and.is_satisfied()
            self.assertFalse(is_satisfied)
            convergence_criterion_and.update(interface)
            is_satisfied = convergence_criterion_and.is_satisfied()
            self.assertFalse(is_satisfied)
            convergence_criterion_and.update(interface)
            is_satisfied = convergence_criterion_and.is_satisfied()
            self.assertFalse(is_satisfied)
            convergence_criterion_and.update(interface)
            is_satisfied = convergence_criterion_and.is_satisfied()
            self.assertTrue(is_satisfied)
            convergence_criterion_and.update(interface)
            is_satisfied = convergence_criterion_and.is_satisfied()
            self.assertTrue(is_satisfied)
            convergence_criterion_and.finalize_solution_step()
Esempio n. 5
0
    def __init__(self, parameters):
        super().__init__()
        self.settings = parameters['settings']
        self.model = data_structure.Model()
        dx = lx / (nx - 1)
        dy = ly / (ny - 1)
        perturb_factor = 0.0
        x = np.linspace(0, lx, nx) + np.random.rand(nx) * dx * perturb_factor
        y = np.linspace(0, ly, ny) + np.random.rand(ny) * dy * perturb_factor

        xx, yy = np.meshgrid(x, y)
        x0_in = xx.ravel()
        y0_in = yy.ravel()

        x0_out = xx.ravel()
        y0_out = yy.ravel()

        z0_in = np.zeros_like(x0_in)
        z0_out = np.zeros_like(x0_out)

        node_ids_in = np.arange(0, nx * ny)
        node_ids_out = np.arange(0, nx * ny)

        self.mp_name_in_list = []
        for interface_settings in self.settings['interface_input']:
            self.model.create_model_part(interface_settings['model_part'],
                                         x0_in, y0_in, z0_in, node_ids_in)
            self.mp_name_in_list.append(interface_settings['model_part'])
        self.mp_name_out_list = []
        for interface_settings in self.settings['interface_output']:
            self.model.create_model_part(interface_settings['model_part'],
                                         x0_out, y0_out, z0_out, node_ids_out)
            self.mp_name_out_list.append(interface_settings['model_part'])

        # # Interfaces
        self.interface_input = Interface(self.settings["interface_input"],
                                         self.model)
        self.interface_output = Interface(self.settings["interface_output"],
                                          self.model)

        # run time
        self.run_time = 0.0
Esempio n. 6
0
    def test_predictor_linear(self):
        m = 10
        dz = 3
        a0 = 1
        p1 = 1
        a1 = 2
        p2 = 3
        variable = 'area'
        model_part_name = 'wall'
        interface_settings = [{
            'model_part': model_part_name,
            'variables': [variable]
        }]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        a0_array = np.full((m, 1), a0)

        # create interface
        interface = Interface(interface_settings, model)
        interface.set_variable_data(model_part_name, variable, a0_array)

        # create predictor
        parameters = {'type': 'predictors.linear'}
        predictor_linear = create_instance(parameters)
        predictor_linear.initialize(interface)

        # first prediction needs to be equal to initialized value
        predictor_linear.initialize_solution_step()
        prediction = predictor_linear.predict(interface)
        self.assertIsInstance(prediction, Interface)
        prediction_as_array = prediction.get_interface_data()
        for i in range(m):
            self.assertAlmostEqual(p1, prediction_as_array[i])
        interface_as_array = a1 * prediction_as_array
        interface.set_interface_data(interface_as_array)
        predictor_linear.update(interface)
        predictor_linear.finalize_solution_step()

        # second prediction needs to be linear
        predictor_linear.initialize_solution_step()
        prediction = predictor_linear.predict(interface)
        self.assertIsInstance(prediction, Interface)
        prediction_as_array = prediction.get_interface_data()
        for i in range(m):
            self.assertAlmostEqual(p2, prediction_as_array[i])
Esempio n. 7
0
    def __init__(self, parameters):
        super().__init__()

        self.settings = parameters["settings"]
        self.working_directory = join(os.getcwd(),
                                      self.settings["working_directory"])
        self.env = tools.get_solver_env(__name__, self.working_directory)
        delta_t = self.settings["delta_t"]
        timestep_start = self.settings["timestep_start"]
        dimensions = self.settings["dimensions"]
        self.timestep = None

        input_file_name = join(self.working_directory,
                               self.settings["input_file"])

        with open(input_file_name, "r") as parameter_file:
            kratos_parameters = json.load(parameter_file)

        kratos_parameters["problem_data"]["start_time"] = timestep_start
        kratos_parameters["problem_data"]["time_step"] = delta_t
        kratos_parameters["problem_data"]["domain_size"] = dimensions
        kratos_parameters["problem_data"]["end_time"] = 1e15

        interface_sub_model_parts_list = self.settings[
            "kratos_interface_sub_model_parts_list"]

        kratos_parameters[
            "interface_sub_model_parts_list"] = interface_sub_model_parts_list

        with open(os.path.join(self.working_directory, input_file_name),
                  'w') as f:
            json.dump(kratos_parameters, f, indent=4)

        self.check_interface()

        self.model = data_structure.Model()

        dir_path = os.path.dirname(os.path.realpath(__file__))
        run_script_file = os.path.join(dir_path, 'run_kratos_structural_60.py')

        self.kratos_process = Popen(
            f'python3 {run_script_file} {input_file_name} &> log',
            shell=True,
            cwd=self.working_directory,
            env=self.env)

        self.wait_message('start_ready')

        for mp_name in interface_sub_model_parts_list:
            file_path = os.path.join(self.working_directory,
                                     f'{mp_name}_nodes.csv')
            node_data = pd.read_csv(file_path, skipinitialspace=True)
            node_ids = np.array(node_data.node_id)
            x0 = np.array(node_data.x0)
            y0 = np.array(node_data.y0)
            z0 = np.array(node_data.z0)
            self.model.create_model_part(f'{mp_name}_input', x0, y0, z0,
                                         node_ids)
            self.model.create_model_part(f'{mp_name}_output', x0, y0, z0,
                                         node_ids)

        # # Interfaces
        self.interface_input = Interface(self.settings["interface_input"],
                                         self.model)
        self.interface_output = Interface(self.settings["interface_output"],
                                          self.model)

        # time
        self.init_time = self.init_time
        self.run_time = 0.0

        self.residual_variables = self.settings.get('residual_variables', None)
        self.res_filepath = os.path.join(self.working_directory,
                                         'residuals.csv')

        if self.residual_variables is not None:
            self.write_residuals_fileheader()
Esempio n. 8
0
class SolverWrapperKratosStructure60(Component):
    @tools.time_initialize
    def __init__(self, parameters):
        super().__init__()

        self.settings = parameters["settings"]
        self.working_directory = join(os.getcwd(),
                                      self.settings["working_directory"])
        self.env = tools.get_solver_env(__name__, self.working_directory)
        delta_t = self.settings["delta_t"]
        timestep_start = self.settings["timestep_start"]
        dimensions = self.settings["dimensions"]
        self.timestep = None

        input_file_name = join(self.working_directory,
                               self.settings["input_file"])

        with open(input_file_name, "r") as parameter_file:
            kratos_parameters = json.load(parameter_file)

        kratos_parameters["problem_data"]["start_time"] = timestep_start
        kratos_parameters["problem_data"]["time_step"] = delta_t
        kratos_parameters["problem_data"]["domain_size"] = dimensions
        kratos_parameters["problem_data"]["end_time"] = 1e15

        interface_sub_model_parts_list = self.settings[
            "kratos_interface_sub_model_parts_list"]

        kratos_parameters[
            "interface_sub_model_parts_list"] = interface_sub_model_parts_list

        with open(os.path.join(self.working_directory, input_file_name),
                  'w') as f:
            json.dump(kratos_parameters, f, indent=4)

        self.check_interface()

        self.model = data_structure.Model()

        dir_path = os.path.dirname(os.path.realpath(__file__))
        run_script_file = os.path.join(dir_path, 'run_kratos_structural_60.py')

        self.kratos_process = Popen(
            f'python3 {run_script_file} {input_file_name} &> log',
            shell=True,
            cwd=self.working_directory,
            env=self.env)

        self.wait_message('start_ready')

        for mp_name in interface_sub_model_parts_list:
            file_path = os.path.join(self.working_directory,
                                     f'{mp_name}_nodes.csv')
            node_data = pd.read_csv(file_path, skipinitialspace=True)
            node_ids = np.array(node_data.node_id)
            x0 = np.array(node_data.x0)
            y0 = np.array(node_data.y0)
            z0 = np.array(node_data.z0)
            self.model.create_model_part(f'{mp_name}_input', x0, y0, z0,
                                         node_ids)
            self.model.create_model_part(f'{mp_name}_output', x0, y0, z0,
                                         node_ids)

        # # Interfaces
        self.interface_input = Interface(self.settings["interface_input"],
                                         self.model)
        self.interface_output = Interface(self.settings["interface_output"],
                                          self.model)

        # time
        self.init_time = self.init_time
        self.run_time = 0.0

        self.residual_variables = self.settings.get('residual_variables', None)
        self.res_filepath = os.path.join(self.working_directory,
                                         'residuals.csv')

        if self.residual_variables is not None:
            self.write_residuals_fileheader()

    @tools.time_initialize
    def initialize(self):
        super().initialize()
        self.timestep = 0

    def initialize_solution_step(self):
        super().initialize_solution_step()
        self.timestep += 1

        self.send_message('next')
        self.wait_message('next_ready')

    @tools.time_solve_solution_step
    def solve_solution_step(self, interface_input):

        self.interface_input.set_interface_data(
            interface_input.get_interface_data())
        self.write_input_data()
        self.send_message('continue')
        self.wait_message('continue_ready')
        self.update_interface_output()
        return self.get_interface_output()

    def finalize_solution_step(self):
        super().finalize_solution_step()
        self.send_message('save')
        self.wait_message('save_ready')
        if self.residual_variables is not None:
            self.write_residuals()

    def finalize(self):
        super().finalize()
        self.send_message('stop')
        self.wait_message('stop_ready')
        self.remove_all_messages()
        self.kratos_process.kill()

    def get_interface_input(self):
        return self.interface_input

    def get_interface_output(self):
        return self.interface_output

    def write_input_data(self):
        interface_sub_model_parts_list = self.settings[
            "kratos_interface_sub_model_parts_list"]

        for mp_name in interface_sub_model_parts_list:
            input_mp_name = f'{mp_name}_input'
            input_mp = self.model.get_model_part(input_mp_name)
            file_path_pr = os.path.join(self.working_directory,
                                        f'{mp_name}_pressure.csv')
            with open(file_path_pr, 'w') as f:
                f.write('node_id, pressure\n')
            file_path_sl = os.path.join(self.working_directory,
                                        f'{mp_name}_surface_load.csv')
            with open(file_path_sl, 'w') as f:
                f.write(
                    'node_id, surface_load_x, surface_load_y, surface_load_z\n'
                )

            pressure_array = np.ravel(
                self.interface_input.get_variable_data(input_mp_name,
                                                       'pressure'))
            surface_load_array = self.interface_input.get_variable_data(
                input_mp_name, 'traction')

            for i in range(0, input_mp.size):
                with open(file_path_pr, 'a') as f:
                    f.write(
                        str(input_mp.id[i]) + ', ' + str(pressure_array[i]) +
                        '\n')

                with open(file_path_sl, 'a') as f:
                    f.write(
                        str(input_mp.id[i]) + ', ' +
                        str(surface_load_array[i, 0]) + ', ' +
                        str(surface_load_array[i, 1]) + ', ' +
                        str(surface_load_array[i, 2]) + '\n')

    def update_interface_output(self):
        interface_sub_model_parts_list = self.settings[
            "kratos_interface_sub_model_parts_list"]

        for mp_name in interface_sub_model_parts_list:
            output_mp_name = f'{mp_name}_output'
            file_path = os.path.join(self.working_directory,
                                     f'{mp_name}_displacement.csv')
            disp_data = pd.read_csv(file_path, skipinitialspace=True)
            disp_x = np.array(disp_data.displacement_x)
            disp_y = np.array(disp_data.displacement_y)
            disp_z = np.array(disp_data.displacement_z)
            displacement = np.column_stack((disp_x, disp_y, disp_z))
            self.interface_output.set_variable_data(output_mp_name,
                                                    'displacement',
                                                    displacement)

    def check_interface(self):

        input_interface_model_parts = [
            param["model_part"] for param in self.settings["interface_input"]
        ]
        output_interface_model_parts = [
            param["model_part"] for param in self.settings["interface_output"]
        ]
        sub_mp_name_list = self.settings[
            "kratos_interface_sub_model_parts_list"]

        for sub_mp_name in sub_mp_name_list:
            if f'{sub_mp_name}_input' not in input_interface_model_parts:
                raise RuntimeError(
                    f'Error in json file: {sub_mp_name}_input not listed in "interface_input": '
                    f'{self.settings["interface_input"]}.\n. <sub_mp_name> in the '
                    f'"kratos_interface_sub_model_parts_list" in json file should have corresponding '
                    f'<sub_mp_name>_input in "interface_input" list. ')

            if f'{sub_mp_name}_output' not in output_interface_model_parts:
                raise RuntimeError(
                    f'Error in json file: {sub_mp_name}_output not listed in "interface_output": '
                    f'{self.settings["interface_output"]}.\n. <sub_mp_name> in the '
                    f'"kratos_interface_sub_model_parts_list" in json file should have corresponding '
                    f'<sub_mp_name>_output in "interface_output" list.')

    def send_message(self, message):
        file = join(self.working_directory, message + ".coco")
        open(file, 'w').close()
        return

    def wait_message(self, message):
        file = join(self.working_directory, message + ".coco")
        while not os.path.isfile(file):
            time.sleep(0.01)
        os.remove(file)
        return

    def check_message(self, message):
        file = join(self.working_directory, message + ".coco")
        if os.path.isfile(file):
            os.remove(file)
            return True
        return False

    def remove_all_messages(self):
        for file_name in os.listdir(self.working_directory):
            if file_name.endswith('.coco'):
                file = join(self.working_directory, file_name)
                os.remove(file)

    def write_residuals_fileheader(self):
        header = ''
        sep = ', '
        with open(self.res_filepath, 'w') as f:
            f.write('# Residuals\n')
            for variable in self.residual_variables:
                header += variable + sep
            f.write(header.strip(sep) + '\n')

    def write_residuals(self):
        float_pattern = r'[+-]?\d*\.?\d*[eE]?[+-]?\d*'
        log_filepath = os.path.join(self.working_directory, f'log')
        if os.path.isfile(log_filepath):
            with open(log_filepath, 'r') as f:
                log_string = f.read()
            time_start_string = r'STEP:\s+' + str(self.timestep - 1)
            time_end_string = r'STEP:\s+' + str(self.timestep)
            match = re.search(time_start_string + r'(.*)' + time_end_string,
                              log_string,
                              flags=re.S)
            if match is not None:
                time_block = match.group(1)
                iteration_block_list = re.findall(
                    r'Coupling iteration: \d(.*?)Coupling iteration \d+ end',
                    time_block,
                    flags=re.S)
                for iteration_block in iteration_block_list:
                    residual_array = np.empty(len(self.residual_variables))
                    for i, variable in enumerate(self.residual_variables):
                        search_string = r'\n' + variable + r' CRITERION.*[Nn]orm = ' + r'(' + float_pattern + r')'
                        var_residual_list = re.findall(search_string,
                                                       iteration_block)
                        if var_residual_list:
                            # last initial residual of the non-linear iteration
                            var_residual = float(var_residual_list[-1])
                            residual_array[i] = var_residual
                        else:
                            raise RuntimeError(
                                f'{variable} CRITERION not found in kratos log file'
                            )

                    with open(self.res_filepath, 'a') as f:
                        np.savetxt(f, [residual_array], delimiter=', ')
Esempio n. 9
0
    def test_model_mv(self):
        m = 5
        dz = 2
        x = 10
        variable = 'area'
        model_part_name = 'wall'
        interface_settings = [{
            'model_part': model_part_name,
            'variables': [variable]
        }]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        x_array = np.full((m, 1), x)

        # create interface
        interface = Interface(interface_settings, model)
        interface.set_variable_data(model_part_name, variable, x_array)

        # read settings
        parameter_file_name = os.path.join(os.path.dirname(__file__),
                                           'test_mv.json')
        with open(parameter_file_name, 'r') as parameter_file:
            settings = json.load(parameter_file)

        min_significant = settings["settings"]["min_significant"]

        mv = create_instance(settings)
        mv.size_in = mv.size_out = m
        mv.out = interface.copy()
        mv.initialize()
        mv.initialize_solution_step()

        r = interface.copy()
        xt = interface.copy()
        r1 = np.array([1, 2, 3, 4, 5])
        xt1 = np.array([5, 4, 3, 2, 1])
        r2 = np.array([8, 5, 5, 5, 8])
        xt2 = np.array([1, 4, 8, 5, 5])
        r3 = np.array([7, 5, 6, 4, 3])
        r4 = np.array([1, 1, 7, 4, 0])
        xt4 = np.array([9, 7, 5, 8, 4])
        r5 = np.array([9, 5, 10, 6, 4])
        xt5 = np.array([5, 1, 2, 3, 9])
        r6 = np.array([7, 8, 1, 2, 3])
        xt6 = np.array([7, 5, 5, 1, 2])
        r7 = np.array([1, 2, 5, 1, 2])
        xt7 = np.array([4, 2, 1, 1, 2])
        r8 = np.array([6, 3, 9, 0, 3])
        xt8 = np.array([3, 1, 2, 3, 9])
        r9 = np.array([1, 3, 5, 0, 8])
        xt9 = np.array([8, 1, 5, 3, 9])
        r10 = np.array([1, 3, -5, 8, 8])
        xt10 = np.array([8, -9, 5, 3, -9])
        r11 = r1
        xt11 = xt1
        r12 = r2
        xt12 = xt2
        r13 = r10 * 0.95
        xt13 = xt10

        is_ready = mv.is_ready()
        self.assertFalse(is_ready)

        r.set_interface_data(r1)
        xt.set_interface_data(xt1)
        mv.add(r, xt)

        self.assertTrue(mv.added)
        np.testing.assert_array_equal(r1[:, np.newaxis], mv.rref)
        np.testing.assert_array_equal(xt1[:, np.newaxis], mv.xtref)
        self.assertIsNone(mv.ncurr)
        is_ready = mv.is_ready()
        self.assertFalse(is_ready)

        r.set_interface_data(r2)
        xt.set_interface_data(xt2)
        mv.add(r, xt)

        self.assertTrue(mv.added)
        np.testing.assert_array_equal(r2[:, np.newaxis], mv.rref)
        np.testing.assert_array_equal(xt2[:, np.newaxis], mv.xtref)
        self.assertEqual(mv.v.shape, (m, 1))
        np.testing.assert_array_equal(mv.v[:, 0], r2 - r1)
        self.assertEqual(mv.w.shape, (m, 1))
        np.testing.assert_array_equal(mv.w[:, 0], xt2 - xt1)
        n_sol = [
            -0.388888888888889, -0.166666666666667, -0.111111111111111,
            -0.0555555555555556, -0.166666666666667, 0, 0, 0, 0, 0,
            0.486111111111111, 0.208333333333333, 0.138888888888889,
            0.0694444444444445, 0.208333333333333, 0.291666666666667,
            0.125000000000000, 0.0833333333333333, 0.0416666666666667,
            0.125000000000000, 0.388888888888889, 0.166666666666667,
            0.111111111111111, 0.0555555555555556, 0.166666666666667
        ]
        np.testing.assert_allclose(mv.ncurr.flatten(), n_sol)
        np.testing.assert_array_equal(mv.nprev.flatten(),
                                      np.zeros((m, m)).flatten())
        is_ready = mv.is_ready()
        self.assertTrue(is_ready)
        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            4.94444444444445, 0, -6.18055555555556, -3.70833333333333,
            -4.944444444444452
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)

        r.set_interface_data(r4)
        xt.set_interface_data(xt4)
        mv.add(r, xt)

        self.assertEqual(mv.v.shape, (m, 2))
        np.testing.assert_array_equal(mv.v[:, 0], r4 - r2)
        self.assertEqual(mv.w.shape, (m, 2))
        np.testing.assert_array_equal(mv.w[:, 0], xt4 - xt2)
        n_sol = [
            -0.306429548563612, -0.216142270861833, 0.251709986320109,
            -0.0437756497948016, -0.555403556771546, 0.0718194254445965,
            -0.0430916552667578, 0.316005471956224, 0.0102599179206566,
            -0.338577291381669, 0.550615595075240, 0.169630642954856,
            0.422708618331053, 0.0786593707250342, -0.0957592339261285,
            0.445280437756498, 0.0328317373461012, 0.759233926128591,
            0.0636114911080711, -0.599179206566348, 0.474008207934337,
            0.115595075239398, 0.485636114911081, 0.0677154582763338,
            -0.234610123119015
        ]
        np.testing.assert_allclose(mv.ncurr.flatten(), n_sol)
        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            3.55677154582763, -1.20861833105335, -7.26607387140903,
            -6.29343365253078, -6.37688098495212
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)

        r.set_interface_data(r5)
        xt.set_interface_data(xt5)
        mv.add(r, xt)

        self.assertEqual(mv.v.shape, (m, 2))
        np.testing.assert_array_equal(mv.v[:, 0], r5 - r4)
        self.assertEqual(mv.w.shape, (m, 2))
        np.testing.assert_array_equal(mv.w[:, 0], xt5 - xt4)
        n_sol = [
            -0.258792878853669, -0.180633955709944, 0.376899696048632,
            0.0121580547112462, -0.590534085974816, -0.460486322188450,
            -0.200607902735562, -0.446808510638298, -0.159574468085106,
            0.0364741641337384, -0.266391663048198, -0.0651324359531047,
            -0.729483282674772, -0.168693009118541, 0.479374728614850,
            -0.379722101606600, -0.171081198436822, -0.316109422492401,
            -0.123100303951368, -0.0208423795049935, 0.395788102475033,
            0.155449413808076, 0.541033434650456, 0.162613981762918,
            -0.184107685627443
        ]
        np.testing.assert_allclose(mv.ncurr.flatten(), n_sol)
        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            2.17629179331307, 7.43617021276596, 5.80395136778116,
            5.96504559270517, -6.89209726443769
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        self.assertEqual(mv.v.shape, (m, 2))
        np.testing.assert_array_equal(mv.v.T.flatten(),
                                      np.hstack((r5 - r4, r4 - r2)))
        self.assertEqual(mv.w.shape, (m, 2))
        np.testing.assert_array_equal(mv.w.T.flatten(),
                                      np.hstack((xt5 - xt4, xt4 - xt2)))

        r.set_interface_data(r6)
        xt.set_interface_data(xt6)
        mv.add(r, xt)
        r.set_interface_data(r7)
        xt.set_interface_data(xt7)
        mv.add(r, xt)
        r.set_interface_data(r8)
        xt.set_interface_data(xt8)
        mv.add(r, xt)

        n_sol = [
            1.59692513368984, -1.67045454545455, -1.19117647058823,
            0.612967914438510, -1.93649732620321, 3.87433155080215,
            -5.22727272727274, -3.11764705882354, 0.660427807486646,
            -2.01336898395721, 4.65909090909091, -6.15909090909093,
            -3.50000000000001, 0.568181818181834, -1.56818181818181,
            5.05213903743316, -7.02272727272729, -3.32352941176471,
            0.736631016042804, -2.20721925133689, 1.72192513368984,
            -1.54545454545455, 0.0588235294117627, -0.262032085561494,
            -0.561497326203206
        ]
        np.testing.assert_allclose(mv.ncurr.flatten(), n_sol)
        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            7.67847593582868, 21.1203208556145, 21.6136363636358,
            23.3649732620315, -1.94652406417126
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        self.assertEqual(mv.v.shape, (m, 5))
        np.testing.assert_array_equal(
            mv.v.T.flatten(),
            np.hstack((r8 - r7, r7 - r6, r6 - r5, r5 - r4, r4 - r2)))
        self.assertEqual(mv.w.shape, (m, 5))
        np.testing.assert_array_equal(
            mv.w.T.flatten(),
            np.hstack((xt8 - xt7, xt7 - xt6, xt6 - xt5, xt5 - xt4, xt4 - xt2)))

        r.set_interface_data(r9)
        xt.set_interface_data(xt9)
        mv.add(r, xt)
        r.set_interface_data(r10)
        xt.set_interface_data(xt10)
        mv.add(r, xt)

        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        self.assertEqual(mv.v.shape, (m, 5))
        np.testing.assert_array_equal(
            mv.v.T.flatten(),
            np.hstack((r10 - r9, r9 - r8, r8 - r7, r7 - r6, r6 - r5)))
        self.assertEqual(mv.w.shape, (m, 5))
        np.testing.assert_array_equal(
            mv.w.T.flatten(),
            np.hstack(
                (xt10 - xt9, xt9 - xt8, xt8 - xt7, xt7 - xt6, xt6 - xt5)))

        r.set_interface_data(r13)
        xt.set_interface_data(xt13)
        mv.add(r, xt)

        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        self.assertEqual(mv.v.shape, (m, 5))
        np.testing.assert_array_equal(
            mv.v.T.flatten(),
            np.hstack((r10 - r9, r9 - r8, r8 - r7, r7 - r6, r6 - r5)))
        self.assertEqual(mv.w.shape, (m, 5))
        np.testing.assert_array_equal(
            mv.w.T.flatten(),
            np.hstack(
                (xt10 - xt9, xt9 - xt8, xt8 - xt7, xt7 - xt6, xt6 - xt5)))

        v = mv.v
        w = mv.w

        nprev = w @ np.linalg.inv(v.T @ v) @ v.T

        # New solution step
        mv.finalize_solution_step()
        np.testing.assert_array_equal(mv.nprev.flatten(), nprev.flatten())
        mv.initialize_solution_step()
        self.assertIsNone(mv.rref)
        self.assertFalse(mv.added)
        self.assertEqual(mv.v.shape, (m, 0))
        self.assertEqual(mv.w.shape, (m, 0))
        is_ready = mv.is_ready()
        self.assertTrue(is_ready)
        np.testing.assert_allclose(mv.ncurr.flatten(), nprev.flatten())
        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)

        r.set_interface_data(r11)
        xt.set_interface_data(xt11)
        mv.add(r, xt)

        self.assertTrue(mv.added)
        self.assertEqual(mv.v.shape, (m, 0))
        self.assertEqual(mv.w.shape, (m, 0))
        r.set_interface_data(r12)
        xt.set_interface_data(xt12)
        mv.add(r, xt)
        n_sol = [
            -1.07953029089939, 0.852682145716574, -0.00813984520949948,
            0.0950093408059783, 0.306645316253002, -1.08484565430122,
            2.54250066720043, 0.878480562227564, -0.192264923049552,
            -0.532759540966108, 0.315863802152833, 0.444989324793168,
            -0.139022328974290, -0.215427897873855, 0.649152655457700,
            0.519159772262255, -0.566019482252470, -0.0682990837114143,
            -0.0941975802864517, 0.431578596210302, -0.394248732319190,
            0.855284227381908, 1.23271950894049, -0.654857219108619,
            0.794435548438751
        ]
        np.testing.assert_allclose(mv.ncurr.flatten(), n_sol)

        r.set_interface_data(r3)
        dxt = mv.predict(-1 * r)
        dxt_sol = [
            2.04216706698691, -8.02212881416246, -4.68760564006761,
            -1.31217195979005, -8.67687483319990
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        self.assertEqual(mv.v.shape, (m, 1))
        np.testing.assert_array_equal(mv.v,
                                      r12[:, np.newaxis] - r11[:, np.newaxis])
        self.assertEqual(mv.w.shape, (m, 1))
        np.testing.assert_array_equal(
            mv.w, xt12[:, np.newaxis] - xt11[:, np.newaxis])
Esempio n. 10
0
    def test_predictor(self):
        m = 10
        dz = 3
        a0 = 1
        a1 = 2
        a2 = 3
        a3 = 4
        a4 = 5
        variable = 'area'
        model_part_name = 'wall'
        interface_settings = [{
            'model_part': model_part_name,
            'variables': [variable]
        }]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        a0_array = np.full((m, 1), a0)

        # create interface
        interface = Interface(interface_settings, model)
        interface.set_variable_data(model_part_name, variable, a0_array)
        interface_as_array = interface.get_interface_data()

        # create predictor
        parameters = {'type': 'predictors.cubic'}
        predictor_cubic = create_instance(parameters)
        predictor_cubic.initialize(interface)

        # a linear relation should be predicted in the same way by linear, quadratic and cubic predictors
        predictor_cubic.initialize_solution_step()
        interface.set_interface_data(a1 * interface_as_array)
        predictor_cubic.update(interface)
        predictor_cubic.finalize_solution_step()
        predictor_cubic.initialize_solution_step()
        interface.set_interface_data(a2 * interface_as_array)
        predictor_cubic.update(interface)
        predictor_cubic.finalize_solution_step()
        predictor_cubic.initialize_solution_step()
        interface.set_interface_data(a3 * interface_as_array)
        predictor_cubic.update(interface)
        predictor_cubic.finalize_solution_step()

        predictor_cubic.initialize_solution_step()
        prediction_linear = predictor_cubic.linear(
            interface).get_interface_data()
        prediction_quadratic = predictor_cubic.quadratic(
            interface).get_interface_data()
        prediction_cubic = predictor_cubic.cubic(
            interface).get_interface_data()
        for i in range(m):
            self.assertAlmostEqual(a4, prediction_linear[i])
            self.assertAlmostEqual(a4, prediction_quadratic[i])
            self.assertAlmostEqual(a4, prediction_cubic[i])

        # rror if no update
        with self.assertRaises(Exception):
            predictor_cubic.initialize_solution_step()
            predictor_cubic.finalize_solution_step()

        # error if updated twice
        with self.assertRaises(Exception):
            predictor_cubic.initialize_solution_step()
            _ = predictor_cubic.predict(interface)
            _ = predictor_cubic.predict(interface)
            predictor_cubic.finalize_solution_step()

        # error if prediction after update
        with self.assertRaises(Exception):
            predictor_cubic.initialize_solution_step()
            _ = predictor_cubic.update(interface)
            _ = predictor_cubic.predict(interface)
            predictor_cubic.finalize_solution_step()
Esempio n. 11
0
    def test_coupled_solver_aitken(self):
        m = 10
        dz = 2
        r = 0.1
        x = 10
        xt0 = 10.5
        xt1 = 10.2
        xt2 = 10.1
        xt3 = 10.7
        xt4 = 9.9
        variable = 'area'  # TODO: does not match JSON setings
        model_part_name = 'wall'
        interface_settings = [{
            'model_part': model_part_name,
            'variables': [variable]
        }]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        # create interface
        interface = Interface(interface_settings, model)

        omega_max = self.parameters['settings']['omega_max']

        with cd(self.working_dir):
            coupled_solver = create_instance(self.parameters)
            coupled_solver.initialize()
        coupled_solver.initialize_solution_step()

        interface_r = interface.copy()
        interface_r.set_interface_data(np.full(m, r))
        interface_x = interface.copy()
        interface_x.set_interface_data(x * np.ones(m))
        interface_xt0 = interface.copy()
        interface_xt0.set_interface_data(xt0 * np.ones(m))
        interface_xt1 = interface.copy()
        interface_xt1.set_interface_data(xt1 * np.ones(m))
        interface_xt2 = interface.copy()
        interface_xt2.set_interface_data(xt2 * np.ones(m))
        interface_xt3 = interface.copy()
        interface_xt3.set_interface_data(xt3 * np.ones(m))
        interface_xt4 = interface.copy()
        interface_xt4.set_interface_data(xt4 * np.ones(m))

        # test value of self.added
        is_ready = coupled_solver.is_ready()
        self.assertFalse(is_ready)

        # test update()
        coupled_solver.update(interface_x, interface_xt0)
        is_ready = coupled_solver.is_ready()
        self.assertTrue(is_ready)
        omega = coupled_solver.omega
        self.assertEqual(omega, omega_max)
        coupled_solver.update(interface_x, interface_xt1)
        is_ready = coupled_solver.is_ready()
        self.assertTrue(is_ready)
        omega = coupled_solver.omega
        self.assertAlmostEqual(omega, 5 / 3 * omega_max, 10)
        coupled_solver.update(interface_x, interface_xt2)
        omega = coupled_solver.omega
        self.assertAlmostEqual(omega, 10 / 3 * omega_max, 10)

        # test predict()
        interface_dx = coupled_solver.predict(interface_r)
        omega = interface_dx.get_interface_data()[0] / r
        self.assertEqual(omega, coupled_solver.omega)
        coupled_solver.predict(interface_r)
        omega = coupled_solver.omega
        self.assertAlmostEqual(omega, 10 / 3 * omega_max, 10)

        # new solution step
        coupled_solver.finalize_solution_step()
        coupled_solver.initialize_solution_step()

        # test value of self.added
        is_ready = coupled_solver.is_ready()
        self.assertFalse(is_ready)

        # test update()
        coupled_solver.update(interface_x, interface_xt0)
        is_ready = coupled_solver.is_ready()
        self.assertTrue(is_ready)
        omega = coupled_solver.omega
        self.assertEqual(omega, omega_max)
        coupled_solver.update(interface_x, interface_xt3)
        omega = coupled_solver.omega
        self.assertAlmostEqual(omega, -5 / 2 * omega_max, 10)

        # new solution step
        coupled_solver.finalize_solution_step()
        coupled_solver.initialize_solution_step()

        # test update()
        coupled_solver.update(interface_x, interface_xt0)
        omega = coupled_solver.omega
        self.assertEqual(omega, -omega_max)
        coupled_solver.update(interface_x, interface_xt4)
        omega = coupled_solver.omega
        self.assertAlmostEqual(omega, -5 / 6 * omega_max, 10)

        # new solution step
        coupled_solver.finalize_solution_step()
        coupled_solver.initialize_solution_step()

        # test update()
        coupled_solver.update(interface_x, interface_xt0)
        omega = coupled_solver.omega
        self.assertAlmostEqual(omega, -5 / 6 * omega_max, 10)
Esempio n. 12
0
class DummySolver1(Component):
    def __init__(self, parameters):
        super().__init__()
        self.settings = parameters['settings']
        self.model = data_structure.Model()
        dx = lx / (nx - 1)
        dy = ly / (ny - 1)
        perturb_factor = 0.0
        x = np.linspace(0, lx, nx) + np.random.rand(nx) * dx * perturb_factor
        y = np.linspace(0, ly, ny) + np.random.rand(ny) * dy * perturb_factor

        xx, yy = np.meshgrid(x, y)
        x0_in = xx.ravel()
        y0_in = yy.ravel()

        x0_out = xx.ravel()
        y0_out = yy.ravel()

        z0_in = np.zeros_like(x0_in)
        z0_out = np.zeros_like(x0_out)

        node_ids_in = np.arange(0, nx * ny)
        node_ids_out = np.arange(0, nx * ny)

        self.mp_name_in_list = []
        for interface_settings in self.settings['interface_input']:
            self.model.create_model_part(interface_settings['model_part'],
                                         x0_in, y0_in, z0_in, node_ids_in)
            self.mp_name_in_list.append(interface_settings['model_part'])
        self.mp_name_out_list = []
        for interface_settings in self.settings['interface_output']:
            self.model.create_model_part(interface_settings['model_part'],
                                         x0_out, y0_out, z0_out, node_ids_out)
            self.mp_name_out_list.append(interface_settings['model_part'])

        # # Interfaces
        self.interface_input = Interface(self.settings["interface_input"],
                                         self.model)
        self.interface_output = Interface(self.settings["interface_output"],
                                          self.model)

        # run time
        self.run_time = 0.0

    def initialize(self):
        super().initialize()
        self.timestep = 0

    def initialize_solution_step(self):
        super().initialize_solution_step()
        self.timestep += 1

    @tools.time_solve_solution_step
    def solve_solution_step(self, interface_input):
        interface_data = interface_input.get_interface_data()
        for mp_name in self.mp_name_out_list:
            pressure_array, traction_array = self.calculate_output(
                interface_data, self.interface_output, mp_name)
            self.interface_output.set_variable_data(mp_name, 'pressure',
                                                    pressure_array)
            self.interface_output.set_variable_data(mp_name, 'traction',
                                                    traction_array)

        return self.get_interface_output()

    def finalize_solution_step(self):
        super().finalize_solution_step()

    def finalize(self):
        super().finalize()

    def get_interface_input(self):
        return self.interface_input

    def get_interface_output(self):
        return self.interface_output

    def calculate_output(self, data, out_interface, out_mp_name):
        nr_nodes = out_interface.get_model_part(out_mp_name).size
        norm = np.linalg.norm(data)
        min = np.min(data)
        pressure = norm
        traction = [min, -1 * min, 2 * min]
        return np.full((nr_nodes, 1), pressure), np.full((nr_nodes, 3),
                                                         traction)
Esempio n. 13
0
    def test_model_ls(self):
        m = 5
        dz = 2
        x = 10
        variable = 'area'
        model_part_name = 'wall'
        interface_settings = [{
            'model_part': model_part_name,
            'variables': [variable]
        }]

        # create model and model_part
        model = data_structure.Model()
        ids = np.arange(0, m)
        x0 = np.zeros(m)
        y0 = np.zeros(m)
        z0 = np.arange(0, m * dz, dz)
        model.create_model_part(model_part_name, x0, y0, z0, ids)

        x_array = np.full((m, 1), x)

        # create interface
        interface = Interface(interface_settings, model)
        interface.set_variable_data(model_part_name, variable, x_array)

        # read settings
        parameter_file_name = os.path.join(os.path.dirname(__file__),
                                           'test_ls.json')
        with open(parameter_file_name, 'r') as parameter_file:
            settings = json.load(parameter_file)

        # with reuse

        min_significant = settings["setting1"]["settings"]["min_significant"]
        q = settings["setting1"]["settings"]["q"]

        ls = create_instance(settings["setting1"])
        ls.size_in = ls.size_out = m
        ls.out = interface.copy()
        ls.initialize()
        ls.initialize_solution_step()

        r = interface.copy()
        xt = interface.copy()
        r1 = np.array([1, 2, 3, 4, 5])
        xt1 = np.array([5, 4, 3, 2, 1])
        r2 = np.array([8, 5, 5, 5, 8])
        xt2 = np.array([1, 4, 8, 5, 5])
        r3 = np.array([7, 5, 6, 4, 3])
        r4 = np.array([1, 1, 7, 4, 0])
        xt4 = np.array([9, 7, 5, 8, 4])
        r5 = np.array([9, 5, 10, 6, 4])
        xt5 = np.array([5, 1, 2, 3, 9])
        r6 = np.array([7, 8, 1, 2, 3])
        xt6 = np.array([7, 5, 5, 1, 2])
        r7 = np.array([1, 2, 5, 1, 2])
        xt7 = np.array([4, 2, 1, 1, 2])
        r8 = np.array([6, 3, 9, 0, 3])
        xt8 = np.array([3, 1, 2, 3, 9])
        r9 = np.array([1, 3, 5, 0, 8])
        xt9 = np.array([8, 1, 5, 3, 9])
        r10 = np.array([1, 3, -5, 8, 8])
        xt10 = np.array([8, -9, 5, 3, -9])
        r11 = r1
        xt11 = xt1
        r12 = r2
        xt12 = xt2
        r13 = r10 * 0.95
        xt13 = xt10

        is_ready = ls.is_ready()
        self.assertFalse(is_ready)

        r.set_interface_data(r1)
        xt.set_interface_data(xt1)
        ls.add(r, xt)

        self.assertTrue(ls.added)
        np.testing.assert_array_equal(r1[:, np.newaxis], ls.rref)
        np.testing.assert_array_equal(xt1[:, np.newaxis], ls.xtref)
        is_ready = ls.is_ready()
        self.assertFalse(is_ready)

        r.set_interface_data(r2)
        xt.set_interface_data(xt2)
        ls.add(r, xt)

        self.assertTrue(ls.added)
        np.testing.assert_array_equal(r2[:, np.newaxis], ls.rref)
        np.testing.assert_array_equal(xt2[:, np.newaxis], ls.xtref)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 1))
        np.testing.assert_array_equal(v[:, 0], r2 - r1)
        self.assertEqual(w.shape, (m, 1))
        np.testing.assert_array_equal(w[:, 0], xt2 - xt1)
        is_ready = ls.is_ready()
        self.assertTrue(is_ready)
        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            4.94444444444445, 0, -6.18055555555556, -3.70833333333333,
            -4.944444444444452
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)

        r.set_interface_data(r4)
        xt.set_interface_data(xt4)
        ls.add(r, xt)

        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 2))
        np.testing.assert_array_equal(v[:, 0], r4 - r2)
        self.assertEqual(w.shape, (m, 2))
        np.testing.assert_array_equal(w[:, 0], xt4 - xt2)
        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            3.55677154582763, -1.20861833105335, -7.26607387140903,
            -6.29343365253078, -6.37688098495212
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)

        r.set_interface_data(r5)
        xt.set_interface_data(xt5)
        ls.add(r, xt)

        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 2))
        np.testing.assert_array_equal(v[:, 0], r5 - r4)
        self.assertEqual(w.shape, (m, 2))
        np.testing.assert_array_equal(w[:, 0], xt5 - xt4)
        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            2.17629179331307, 7.43617021276596, 5.80395136778116,
            5.96504559270517, -6.89209726443769
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 2))
        np.testing.assert_array_equal(v.T.flatten(),
                                      np.hstack((r5 - r4, r4 - r2)))
        self.assertEqual(w.shape, (m, 2))
        np.testing.assert_array_equal(w.T.flatten(),
                                      np.hstack((xt5 - xt4, xt4 - xt2)))

        r.set_interface_data(r6)
        xt.set_interface_data(xt6)
        ls.add(r, xt)
        r.set_interface_data(r7)
        xt.set_interface_data(xt7)
        ls.add(r, xt)
        r.set_interface_data(r8)
        xt.set_interface_data(xt8)
        ls.add(r, xt)

        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            7.67847593582868, 21.1203208556145, 21.6136363636358,
            23.3649732620315, -1.94652406417126
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 5))
        np.testing.assert_array_equal(
            v.T.flatten(),
            np.hstack((r8 - r7, r7 - r6, r6 - r5, r5 - r4, r4 - r2)))
        self.assertEqual(w.shape, (m, 5))
        np.testing.assert_array_equal(
            w.T.flatten(),
            np.hstack((xt8 - xt7, xt7 - xt6, xt6 - xt5, xt5 - xt4, xt4 - xt2)))

        r.set_interface_data(r9)
        xt.set_interface_data(xt9)
        ls.add(r, xt)
        r.set_interface_data(r10)
        xt.set_interface_data(xt10)
        ls.add(r, xt)

        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 5))
        np.testing.assert_array_equal(
            v.T.flatten(),
            np.hstack((r10 - r9, r9 - r8, r8 - r7, r7 - r6, r6 - r5)))
        self.assertEqual(w.shape, (m, 5))
        np.testing.assert_array_equal(
            w.T.flatten(),
            np.hstack(
                (xt10 - xt9, xt9 - xt8, xt8 - xt7, xt7 - xt6, xt6 - xt5)))

        r.set_interface_data(r13)
        xt.set_interface_data(xt13)
        ls.add(r, xt)
        r.set_interface_data(r3)

        dxt = ls.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 5))
        np.testing.assert_array_equal(
            v.T.flatten(),
            np.hstack((r10 - r9, r9 - r8, r8 - r7, r7 - r6, r6 - r5)))
        self.assertEqual(w.shape, (m, 5))
        np.testing.assert_array_equal(
            w.T.flatten(),
            np.hstack(
                (xt10 - xt9, xt9 - xt8, xt8 - xt7, xt7 - xt6, xt6 - xt5)))

        v1 = ls.vcurr
        w1 = ls.wcurr

        # new solution step
        ls.finalize_solution_step()
        np.testing.assert_array_equal(ls.vprev[0].flatten(), v1.flatten())
        np.testing.assert_array_equal(ls.wprev[0].flatten(), w1.flatten())
        ls.initialize_solution_step()
        self.assertIsNone(ls.rref)
        self.assertFalse(ls.added)
        self.assertEqual(ls.vcurr.shape, (m, 0))
        self.assertEqual(ls.wcurr.shape, (m, 0))
        is_ready = ls.is_ready()
        self.assertTrue(is_ready)

        r.set_interface_data(r11)
        xt.set_interface_data(xt11)
        ls.add(r, xt)

        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        self.assertTrue(ls.added)
        self.assertEqual(ls.vcurr.shape, (m, 0))
        self.assertEqual(ls.wcurr.shape, (m, 0))

        r.set_interface_data(r12)
        xt.set_interface_data(xt12)
        ls.add(r, xt)

        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            -8.52029914529913, -3.96866096866096, -0.505163817663819,
            -0.426103988603991, -14.1239316239316
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 5))
        np.testing.assert_array_equal(
            v.T.flatten(),
            np.hstack((r12 - r11, r10 - r9, r9 - r8, r7 - r6, r6 - r5)))
        self.assertEqual(w.shape, (m, 5))
        np.testing.assert_array_equal(
            w.T.flatten(),
            np.hstack(
                (xt12 - xt11, xt10 - xt9, xt9 - xt8, xt7 - xt6, xt6 - xt5)))

        v2 = ls.vcurr
        w2 = ls.wcurr

        # new solution step
        ls.finalize_solution_step()
        np.testing.assert_array_equal(
            np.hstack(ls.vprev).flatten(),
            np.hstack([v2, v1[:, :2], v1[:, 3:]]).flatten())
        np.testing.assert_array_equal(
            np.hstack(ls.wprev).flatten(),
            np.hstack([w2, w1[:, :2], w1[:, 3:]]).flatten())
        ls.initialize_solution_step()

        # new solution step
        ls.finalize_solution_step()
        np.testing.assert_array_equal(
            np.hstack(ls.vprev).flatten(),
            np.hstack([np.empty((m, 0)), v2]).flatten())
        np.testing.assert_array_equal(
            np.hstack(ls.wprev).flatten(),
            np.hstack([np.empty((m, 0)), w2]).flatten())
        self.assertEqual(len(ls.vprev), q)
        self.assertEqual(len(ls.wprev), q)
        ls.initialize_solution_step()

        # without reuse

        min_significant = settings["setting2"]["settings"]["min_significant"]
        q = settings["setting2"]["settings"]["q"]

        ls = create_instance(settings["setting2"])
        ls.size_in = ls.size_out = m
        ls.out = interface.copy()
        ls.initialize()
        ls.initialize_solution_step()

        r.set_interface_data(r1)
        xt.set_interface_data(xt1)
        ls.add(r, xt)
        r.set_interface_data(r2)
        xt.set_interface_data(xt2)
        ls.add(r, xt)
        r.set_interface_data(r4)
        xt.set_interface_data(xt4)
        ls.add(r, xt)
        r.set_interface_data(r5)
        xt.set_interface_data(xt5)
        ls.add(r, xt)
        r.set_interface_data(r6)
        xt.set_interface_data(xt6)
        ls.add(r, xt)
        r.set_interface_data(r7)
        xt.set_interface_data(xt7)
        ls.add(r, xt)
        r.set_interface_data(r8)
        xt.set_interface_data(xt8)
        ls.add(r, xt)
        r.set_interface_data(r9)
        xt.set_interface_data(xt9)
        ls.add(r, xt)
        r.set_interface_data(r10)
        xt.set_interface_data(xt10)
        ls.add(r, xt)

        r.set_interface_data(r3)
        dxt = ls.predict(-1 * r)
        dxt_sol = [
            -4.19875900720576, -5.62710168134507, -2.21637309847878,
            -0.788630904723781, -11.8953162530024
        ]
        np.testing.assert_allclose(dxt.get_interface_data(), dxt_sol)
        v = np.hstack((ls.vcurr, np.hstack(ls.vprev)))
        w = np.hstack((ls.wcurr, np.hstack(ls.wprev)))
        self.assertEqual(v.shape, (m, 5))
        np.testing.assert_array_equal(
            v.T.flatten(),
            np.hstack((r10 - r9, r9 - r8, r8 - r7, r7 - r6, r6 - r5)))
        self.assertEqual(w.shape, (m, 5))
        np.testing.assert_array_equal(
            w.T.flatten(),
            np.hstack(
                (xt10 - xt9, xt9 - xt8, xt8 - xt7, xt7 - xt6, xt6 - xt5)))

        # new solution step
        ls.finalize_solution_step()
        np.testing.assert_array_equal(
            np.hstack(ls.vprev).flatten(),
            np.hstack((np.empty((m, 0)))).flatten())
        np.testing.assert_array_equal(
            np.hstack(ls.wprev).flatten(),
            np.hstack((np.empty((m, 0)))).flatten())
        ls.initialize_solution_step()
        self.assertIsNone(ls.rref)
        self.assertFalse(ls.added)
        self.assertEqual(ls.vcurr.shape, (m, 0))
        self.assertEqual(ls.wcurr.shape, (m, 0))
        is_ready = ls.is_ready()
        self.assertFalse(is_ready)

        r.set_interface_data(r11)
        xt.set_interface_data(xt11)
        ls.add(r, xt)

        is_ready = ls.is_ready()
        self.assertFalse(is_ready)

        r.set_interface_data(r12)
        xt.set_interface_data(xt12)
        ls.add(r, xt)

        is_ready = ls.is_ready()
        self.assertTrue(is_ready)
Esempio n. 14
0
class TestInterface(unittest.TestCase):
    def setUp(self):
        self.model_part_size = model_part_size = 3
        self.parameters = {
            'interface_a': [{
                'model_part': 'mp1',
                'variables': ['pressure', 'traction']
            }, {
                'model_part': 'mp2',
                'variables': ['density']
            }],
            'interface_b': [{
                'model_part': 'mp1',
                'variables': ['pressure', 'displacement']
            }, {
                'model_part': 'mp2',
                'variables': ['density']
            }],
            'interface_c': [{
                'model_part': 'mp1',
                'variables': ['pressure', 'traction']
            }, {
                'model_part': 'mp3',
                'variables': ['density']
            }],
            'interface_d': [{
                'model_part': 'mp2',
                'variables': ['density']
            }, {
                'model_part': 'mp1',
                'variables': ['pressure', 'displacement']
            }],
        }

        self.model = Model()
        self.x0 = x0 = np.random.rand(3 * model_part_size)
        self.y0 = y0 = np.random.rand(3 * model_part_size)
        self.z0 = z0 = np.random.rand(3 * model_part_size)
        self.ids = ids = np.arange(0, model_part_size)
        np.random.shuffle(ids)
        self.model.create_model_part('mp1', x0[0:model_part_size],
                                     y0[0:model_part_size],
                                     z0[0:model_part_size], ids)
        self.model.create_model_part('mp2',
                                     x0[model_part_size:2 * model_part_size],
                                     y0[model_part_size:2 * model_part_size],
                                     z0[model_part_size:2 * model_part_size],
                                     ids)
        self.model.create_model_part(
            'mp3', x0[2 * model_part_size:3 * model_part_size],
            y0[2 * model_part_size:3 * model_part_size],
            z0[2 * model_part_size:3 * model_part_size], ids)

        self.interface = Interface(self.parameters['interface_a'], self.model)
        self.scalar_size = 1
        self.vector_size = 3
        self.pressure = np.random.rand(model_part_size, self.scalar_size)
        self.traction = np.random.rand(model_part_size, self.vector_size)
        self.temperature = np.random.rand(model_part_size, self.scalar_size)
        self.density = np.random.rand(model_part_size, self.scalar_size)
        self.interface_data = np.random.rand(model_part_size * 5)

    def test_instantiation(self):
        parameters = {'mp1': ['pressure']}
        self.assertRaises(TypeError, Interface, parameters, self.model)
        parameters = [{'model_part': 'mp1', 'variables': ['pressure']}, 2]
        self.assertRaises(TypeError, Interface, parameters, self.model)
        parameters = [{'model_part': 'mp1'}]
        self.assertRaises(KeyError, Interface, parameters, self.model)
        parameters = [{
            'model_part': 'mp1',
            'variables': ['pressure'],
            'extra': 2
        }]
        self.assertRaises(KeyError, Interface, parameters, self.model)
        parameters = [{'model_part': 'mp1', 'variables': 'pressure'}]
        self.assertRaises(TypeError, Interface, parameters, self.model)

        self.assertEqual(self.interface.parameters,
                         self.parameters['interface_a'])

    def test_properties(self):
        # check model_part_variable_pairs() method
        pairs_a = self.interface.model_part_variable_pairs
        pairs_b = self.interface.model_part_variable_pairs
        self.assertFalse(pairs_a is pairs_b)
        self.assertEqual(str(pairs_a), str(pairs_b))

        # check parameters() method
        parameters_bis = self.interface.parameters
        self.assertFalse(parameters_bis is self.parameters['interface_a'])
        self.assertEqual(str(parameters_bis),
                         str(self.parameters['interface_a']))

        # check model() method
        model_bis = self.interface.model
        self.assertTrue(model_bis is self.model)

    def test_model_part_variable_pairs(self):
        ref_result = [('mp1', 'pressure'), ('mp1', 'traction'),
                      ('mp2', 'density')]
        self.assertListEqual(ref_result,
                             self.interface.model_part_variable_pairs)

    def test_size(self):
        self.assertEqual(self.interface.size, 5 * self.model_part_size)

    def test_attribute_change(self):
        with self.assertRaises(AttributeError):
            self.interface.model_part_variable_pairs = ()
        with self.assertRaises(AttributeError):
            parameters = {'mp1': ['pressure']}
            self.interface.parameters = parameters
        with self.assertRaises(AttributeError):
            self.interface.size = 0

    def test_copy(self):
        self.interface.set_interface_data(self.interface_data)
        interface_copy = self.interface.copy()
        self.assertIsNot(self.interface, interface_copy)
        # interface_copy has the same values
        self.assertEqual(self.interface.model_part_variable_pairs,
                         interface_copy.model_part_variable_pairs)
        np.testing.assert_array_equal(self.interface.get_interface_data(),
                                      interface_copy.get_interface_data())
        # interface_copy not affected by change in self.interface
        interface_data = self.interface.get_interface_data()
        self.interface.set_interface_data(interface_data * 2)
        np.testing.assert_array_equal(interface_copy.get_interface_data(),
                                      interface_data)

    def test_get_variable_data(self):
        self.assertRaises(KeyError, self.interface.get_variable_data, 'mp2',
                          'pressure')

        model_part_variable_pair = ('mp1', 'pressure')
        variable_data = self.pressure
        # returns copy
        self.interface.set_variable_data(*model_part_variable_pair,
                                         variable_data)
        variable_data = self.interface.get_variable_data(
            *model_part_variable_pair)
        variable_data *= 2
        np.testing.assert_array_equal(
            self.interface.get_variable_data(*model_part_variable_pair),
            variable_data / 2)

    def test_set_variable_data(self):
        self.interface.set_variable_data('mp1', 'pressure', self.pressure)
        self.interface.set_variable_data('mp1', 'traction', self.traction)
        self.interface.set_variable_data('mp2', 'density', self.density)
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp1']['pressure'], self.pressure)
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp1']['traction'], self.traction)
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp2']['density'], self.density)
        # input is array with correct shape
        self.assertRaises(ValueError, self.interface.set_variable_data, 'mp1',
                          'pressure', self.traction)
        self.assertRaises(ValueError, self.interface.set_variable_data, 'mp1',
                          'pressure', self.pressure.flatten())
        self.assertRaises(ValueError, self.interface.set_variable_data, 'mp1',
                          'pressure', list(self.pressure))
        # copy is made of input
        self.interface.set_variable_data('mp1', 'pressure', self.pressure)
        self.pressure *= 2
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp1']['pressure'],
            self.pressure / 2)

    def test_get_interface_data(self):
        # output has correct size
        self.assertEqual(self.interface.get_interface_data().size,
                         self.interface.size)
        # correct output from variable data
        self.interface.set_variable_data('mp1', 'pressure', self.pressure)
        self.interface.set_variable_data('mp1', 'traction', self.traction)
        self.interface.set_variable_data('mp2', 'density', self.density)
        interface_data = np.concatenate(
            (self.pressure.flatten(), self.traction.flatten(),
             self.density.flatten()))
        np.testing.assert_equal(self.interface.get_interface_data(),
                                interface_data)
        # correct output from interface data
        self.interface.set_interface_data(self.interface_data)
        np.testing.assert_equal(self.interface.get_interface_data(),
                                self.interface_data)
        # returns copy
        self.interface.get_interface_data() * 2
        np.testing.assert_equal(self.interface.get_interface_data(),
                                self.interface_data)

    def test_set_interface_data(self):
        self.interface.set_interface_data(self.interface_data)
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp1']['pressure'].flatten(),
            self.interface_data[:self.scalar_size * self.model_part_size])
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp1']['traction'].flatten(),
            self.interface_data[self.scalar_size *
                                self.model_part_size:(self.scalar_size +
                                                      self.vector_size) *
                                self.model_part_size])
        np.testing.assert_array_equal(
            self.interface._Interface__data['mp2']['density'].flatten(),
            self.interface_data[(self.scalar_size + self.vector_size) *
                                self.model_part_size:])
        # input is array with correct shape
        self.assertRaises(ValueError, self.interface.set_interface_data,
                          self.pressure)
        self.assertRaises(ValueError, self.interface.set_interface_data,
                          self.interface_data.reshape(-1, 1))
        self.assertRaises(ValueError, self.interface.set_interface_data,
                          list(self.interface_data))
        # copy is made of input
        self.interface.set_interface_data(self.interface_data)
        self.interface_data *= 2
        np.testing.assert_array_equal(self.interface.get_interface_data(),
                                      self.interface_data / 2)

    def test_norm(self):
        self.interface.set_interface_data(self.interface_data)
        norm = np.linalg.norm(self.interface_data)
        self.assertEqual(self.interface.norm(), norm)

    def test_has_same_modelparts(self):
        self.interface.set_interface_data(self.interface_data)

        interface_a = self.interface.copy()
        interface_a.set_interface_data(np.random.rand(self.model_part_size *
                                                      5))
        self.assertTrue(self.interface.has_same_model_parts(interface_a))

        interface_b = Interface(self.parameters['interface_b'], self.model)
        interface_b.set_interface_data(self.interface_data)
        self.assertTrue(self.interface.has_same_model_parts(interface_b))

        interface_c = Interface(self.parameters['interface_c'], self.model)
        interface_c.set_interface_data(self.interface_data)
        self.assertFalse(self.interface.has_same_model_parts(interface_c))

        interface_d = Interface(self.parameters['interface_d'], self.model)
        interface_d.set_interface_data(self.interface_data)
        self.assertFalse(self.interface.has_same_model_parts(interface_d))

    def create_test_interfaces(self):
        interface_data1 = np.random.rand(self.interface.size)
        interface_data2 = np.random.rand(self.interface.size)
        interface1 = self.interface.copy()
        interface1.set_interface_data(interface_data1)
        interface2 = self.interface.copy()
        interface2.set_interface_data(interface_data2)
        return interface_data1, interface_data2, interface1, interface2

    def test_eq(self):
        self.interface.set_interface_data(self.interface_data)

        model_part_size = self.model_part_size
        x0 = self.x0
        y0 = self.y0
        z0 = self.z0
        ids = self.ids
        model2 = Model()
        model2.create_model_part('mp1', x0[0:model_part_size],
                                 y0[0:model_part_size], z0[0:model_part_size],
                                 ids)
        model2.create_model_part('mp2',
                                 x0[model_part_size:2 * model_part_size],
                                 y0[model_part_size:2 * model_part_size],
                                 z0[model_part_size:2 * model_part_size], ids)
        interface2 = Interface(self.parameters['interface_a'], model2)
        interface2.set_interface_data(self.interface_data)
        self.assertIsNot(self.interface, interface2)
        self.assertEqual(self.interface, interface2)

        interface3 = Interface(self.parameters['interface_b'], model2)
        interface3.set_interface_data(self.interface_data)
        self.assertNotEqual(self.interface, interface3)

        interface4 = interface2.copy()
        interface_data4 = self.interface_data.copy()
        interface_data4[np.random.randint(interface4.size)] = np.random.rand()
        interface4.set_interface_data(interface_data4)
        self.assertNotEqual(self.interface, interface4)

    def test_add(self):
        interface_data1, interface_data2, interface1, interface2 = self.create_test_interfaces(
        )

        interface_sum = interface1 + interface2
        self.interface.set_interface_data(interface_data1 + interface_data2)
        self.assertEqual(interface_sum, self.interface)
        interface3 = interface1.copy()
        interface3 += interface2
        self.assertEqual(interface3, self.interface)

        for number in (np.random.rand(1), float(np.random.rand(1)),
                       int(10 * np.random.rand(1))):
            interface_sum = interface1 + number
            self.interface.set_interface_data(interface_data1 + number)
            self.assertEqual(interface_sum, self.interface)
            interface_sum = number + interface1
            self.assertEqual(interface_sum, self.interface)
            interface3 = interface1.copy()
            interface3 += number
            self.assertEqual(interface3, self.interface)

        for other in ('a', True):
            with self.assertRaises(TypeError):
                _ = interface1 + other
            with self.assertRaises(TypeError):
                _ = other + interface1
            with self.assertRaises(TypeError):
                interface1 += other

    def test_sub(self):
        interface_data1, interface_data2, interface1, interface2 = self.create_test_interfaces(
        )

        interface_sum = interface1 - interface2
        self.interface.set_interface_data(interface_data1 - interface_data2)
        self.assertEqual(interface_sum, self.interface)
        interface3 = interface1.copy()
        interface3 -= interface2
        self.assertEqual(interface3, self.interface)

        for number in (np.random.rand(1), float(np.random.rand(1)),
                       int(10 * np.random.rand(1))):
            interface_sum = interface1 - number
            self.interface.set_interface_data(interface_data1 - number)
            self.assertEqual(interface_sum, self.interface)
            interface_sum = number - interface1
            self.assertEqual(interface_sum, self.interface)
            interface3 = interface1.copy()
            interface3 -= number
            self.assertEqual(interface3, self.interface)

        for other in ('a', True):
            with self.assertRaises(TypeError):
                _ = interface1 - other
            with self.assertRaises(TypeError):
                _ = other - interface1
            with self.assertRaises(TypeError):
                interface1 -= other

    def test_mul(self):
        interface_data1, interface_data2, interface1, interface2 = self.create_test_interfaces(
        )

        for number in (np.random.rand(1), float(np.random.rand(1)),
                       int(10 * np.random.rand(1))):
            interface_sum = interface1 * number
            self.interface.set_interface_data(interface_data1 * number)
            self.assertEqual(interface_sum, self.interface)
            interface_sum = number * interface1
            self.assertEqual(interface_sum, self.interface)
            interface3 = interface1.copy()
            interface3 *= number
            self.assertEqual(interface3, self.interface)

        for other in ('a', True, interface2):
            with self.assertRaises(TypeError):
                _ = interface1 * other
            with self.assertRaises(TypeError):
                _ = other * interface1
            with self.assertRaises(TypeError):
                interface1 *= other

    def test_truediv(self):
        interface_data1, interface_data2, interface1, interface2 = self.create_test_interfaces(
        )

        for number in (1 - np.random.rand(1), float(1 - np.random.rand(1)),
                       int(10 * (1 - np.random.rand(1)))):
            interface_sum = interface1 / number
            self.interface.set_interface_data(interface_data1 / number)
            self.assertEqual(interface_sum, self.interface)
            with self.assertRaises(TypeError):
                _ = number / interface1
            interface3 = interface1.copy()
            interface3 /= number
            self.assertEqual(interface3, self.interface)

        for other in ('a', True, interface2):
            with self.assertRaises(TypeError):
                _ = interface1 / other
            with self.assertRaises(TypeError):
                _ = other / interface1
            with self.assertRaises(TypeError):
                interface1 /= other
Esempio n. 15
0
class SolverWrapperOpenFOAM41(Component):
    @tools.time_initialize
    def __init__(self, parameters):
        super().__init__()

        # settings
        self.settings = parameters['settings']
        self.working_directory = self.settings['working_directory']
        self.env = get_solver_env(__name__, self.working_directory)
        # adapted application from openfoam ('coconut_<application name>')
        self.application = self.settings['application']
        self.delta_t = self.settings['delta_t']
        self.time_precision = self.settings['time_precision']
        self.start_time = self.settings['timestep_start'] * self.delta_t
        self.timestep = self.physical_time = self.iteration = self.prev_timestamp = self.cur_timestamp = None
        self.openfoam_process = None
        self.write_interval = self.write_precision = None
        # boundary_names is the set of boundaries in OpenFoam used for coupling
        self.boundary_names = self.settings['boundary_names']
        self.version = '4.1'

        # set on True to save copy of input and output files in every iteration
        self.debug = False

        # check interface names in 'interface_input' and 'interface_output' with boundary names provided in
        # boundary_names
        self.check_interfaces()

        # check that the correct modules have been loaded
        self.check_software()

        # remove possible CoCoNuT-message from previous interrupt
        self.remove_all_messages()

        # obtain number of cores from self.working_directory/system/decomposeParDict
        self.cores = 1
        if self.settings['parallel']:
            file_name = os.path.join(self.working_directory,
                                     'system/decomposeParDict')
            if not os.path.isfile(file_name):
                raise RuntimeError(
                    f'In the parameters:\n{self.settings}\n key "parallel" is set to {True} but {file_name} '
                    f'does not exist')
            else:
                with open(file_name, 'r') as file:
                    decomposedict_string = file.read()
                self.cores = of_io.get_int(input_string=decomposedict_string,
                                           keyword='numberOfSubdomains')

        # modify controlDict file to add pressure and wall shear stress functionObjects for all the boundaries in
        # self.settings["boundary_names"]
        self.read_modify_controldict()

        # creating Model
        self.model = data_structure.Model()

        # writeCellcentres writes cellcentres in internal field and face centres in boundaryField
        check_call(f'writeCellCentres -time 0 &> log.writeCellCentres;',
                   cwd=self.working_directory,
                   shell=True,
                   env=self.env)
        boundary_filename = os.path.join(self.working_directory,
                                         'constant/polyMesh/boundary')

        for boundary in self.boundary_names:
            with open(boundary_filename, 'r') as boundary_file:
                boundary_file_string = boundary_file.read()
            boundary_dict = of_io.get_dict(input_string=boundary_file_string,
                                           keyword=boundary)
            # get point ids and coordinates for all the faces in the boundary
            node_ids, node_coords = of_io.get_boundary_points(
                case_directory=self.working_directory,
                time_folder='0',
                boundary_name=boundary)
            nfaces = of_io.get_int(input_string=boundary_dict,
                                   keyword='nFaces')
            start_face = of_io.get_int(input_string=boundary_dict,
                                       keyword='startFace')

            # create input model part
            self.model.create_model_part(f'{boundary}_input',
                                         node_coords[:, 0], node_coords[:, 1],
                                         node_coords[:, 2], node_ids)

            filename_x = os.path.join(self.working_directory, '0/ccx')
            filename_y = os.path.join(self.working_directory, '0/ccy')
            filename_z = os.path.join(self.working_directory, '0/ccz')

            x0 = of_io.get_boundary_field(file_name=filename_x,
                                          boundary_name=boundary,
                                          size=nfaces,
                                          is_scalar=True)
            y0 = of_io.get_boundary_field(file_name=filename_y,
                                          boundary_name=boundary,
                                          size=nfaces,
                                          is_scalar=True)
            z0 = of_io.get_boundary_field(file_name=filename_z,
                                          boundary_name=boundary,
                                          size=nfaces,
                                          is_scalar=True)
            ids = np.arange(0, nfaces)

            # create output model part
            mp_output = self.model.create_model_part(f'{boundary}_output', x0,
                                                     y0, z0, ids)
            mp_output.start_face = start_face
            mp_output.nfaces = nfaces

        # create interfaces
        self.interface_input = Interface(self.settings['interface_input'],
                                         self.model)
        self.interface_output = Interface(self.settings['interface_output'],
                                          self.model)

        # time
        self.init_time = self.init_time
        self.run_time = 0.0

        # compile openfoam adapted solver
        solver_dir = os.path.join(os.path.dirname(__file__), self.application)
        try:
            check_call(f'wmake {solver_dir} &> log.wmake',
                       cwd=self.working_directory,
                       shell=True,
                       env=self.env)
        except subprocess.CalledProcessError:
            raise RuntimeError(
                f'Compilation of {self.application} failed. Check {os.path.join(self.working_directory, "log.wmake")}'
            )

        self.residual_variables = self.settings.get('residual_variables', None)
        self.res_filepath = os.path.join(self.working_directory,
                                         'residuals.csv')

        if self.residual_variables is not None:
            self.write_residuals_fileheader()

    @tools.time_initialize
    def initialize(self):
        super().initialize()

        # define timestep and physical time
        self.timestep = 0
        self.physical_time = self.start_time

        # copy zero folder to folder with correctly named timeformat
        if self.start_time == 0:
            timestamp = '{:.{}f}'.format(self.physical_time,
                                         self.time_precision)
            path_orig = os.path.join(self.working_directory, '0')
            path_new = os.path.join(self.working_directory, timestamp)
            shutil.rmtree(path_new, ignore_errors=True)
            shutil.copytree(path_orig, path_new)

        # if parallel do a decomposition and establish a remapping for the output based on the faceProcAddressing
        """Note concerning the sequence: The file ./processorX/constant/polyMesh/pointprocAddressing contains a list of 
        indices referring to the original index in the ./constant/polyMesh/points file, these indices go from 0 to 
        nPoints -1
        However, mesh faces can be shared between processors and it has to be tracked whether these are inverted or not
        This inversion is indicated by negative indices
        However, as minus 0 is not a thing, the indices are first incremented by 1 before inversion
        Therefore to get the correct index one should use |index|-1!!
        Normally no doubles should be encountered on an interface as these faces are not shared by processors
        """

        if self.settings['parallel']:
            if self.start_time == 0:
                check_call(
                    f'decomposePar -force -time {self.start_time} &> log.decomposePar',
                    cwd=self.working_directory,
                    shell=True,
                    env=self.env)

            for boundary in self.boundary_names:
                mp_output = self.model.get_model_part(f'{boundary}_output')
                mp_output.sequence = []
                for p in range(self.cores):
                    path = os.path.join(
                        self.working_directory,
                        f'processor{p}/constant/polyMesh/faceProcAddressing')
                    with open(path, 'r') as f:
                        face_proc_add_string = f.read()
                    face_proc_add = np.abs(
                        of_io.get_scalar_array(
                            input_string=face_proc_add_string, is_int=True))
                    face_proc_add -= 1

                    mp_output.sequence += (
                        face_proc_add[(face_proc_add >= mp_output.start_face)
                                      & (face_proc_add < mp_output.start_face +
                                         mp_output.nfaces)] -
                        mp_output.start_face).tolist()

                np.savetxt(os.path.join(self.working_directory,
                                        f'sequence_{boundary}.txt'),
                           np.array(mp_output.sequence),
                           fmt='%i')

                if len(mp_output.sequence) != mp_output.nfaces:
                    print(f'sequence: {len(mp_output.sequence)}')
                    print(f'nNodes: {mp_output.size}')
                    raise ValueError(
                        'Number of face indices in sequence does not correspond to number of faces'
                    )

        # starting the OpenFOAM infinite loop for coupling!
        if not self.settings['parallel']:
            cmd = self.application + '&> log.' + self.application
        else:
            cmd = 'mpirun -np ' + str(
                self.cores
            ) + ' ' + self.application + ' -parallel &> log.' + self.application

        self.openfoam_process = subprocess.Popen(cmd,
                                                 cwd=self.working_directory,
                                                 shell=True,
                                                 env=self.env)

    def initialize_solution_step(self):
        super().initialize_solution_step()

        # for parallel: create a folder with the correct time stamp for decomposition of pointDisplacement_Next
        # for serial: folder will normally be present, except for time 0: make a folder 0.0000 with specified precision
        timestamp = '{:.{}f}'.format(self.physical_time, self.time_precision)
        path = os.path.join(self.working_directory, timestamp)
        if self.cores > 1 or self.physical_time == 0:
            os.makedirs(path, exist_ok=True)

        # prepare new time step folder and reset the number of iterations
        self.timestep += 1
        self.iteration = 0
        self.physical_time += self.delta_t

        self.prev_timestamp = timestamp
        self.cur_timestamp = f'{self.physical_time:.{self.time_precision}f}'

        if not self.settings['parallel']:  # if serial
            new_path = os.path.join(self.working_directory, self.cur_timestamp)
            if os.path.isdir(new_path):
                tools.print_info(
                    f'Overwrite existing time step folder: {new_path}',
                    layout='warning')
                check_call(f'rm -rf {new_path}', shell=True)
            check_call(f'mkdir -p {new_path}', shell=True)
        else:
            for i in np.arange(self.cores):
                new_path = os.path.join(self.working_directory,
                                        'processor' + str(i),
                                        self.cur_timestamp)
                if os.path.isdir(new_path):
                    if i == 0:
                        tools.print_info(
                            f'Overwrite existing time step folder: {new_path}',
                            layout='warning')
                    check_call(f'rm -rf {new_path}', shell=True)
                check_call(f'mkdir -p {new_path}', shell=True)

        self.send_message('next')
        self.wait_message('next_ready')

    @tools.time_solve_solution_step
    def solve_solution_step(self, interface_input):
        self.iteration += 1

        # store incoming displacements
        self.interface_input.set_interface_data(
            interface_input.get_interface_data())

        # write interface data to OpenFOAM-file
        self.write_node_input()

        # copy output data for debugging
        if self.debug:
            if self.cores > 1:
                for i in range(0, self.cores):
                    path_from = os.path.join(self.working_directory,
                                             'processor' + str(i),
                                             self.prev_timestamp,
                                             'pointDisplacement_Next')
                    path_to = os.path.join(
                        self.working_directory, 'processor' + str(i),
                        self.prev_timestamp,
                        'pointDisplacement_Next_Iter' + str(self.iteration))
                    shutil.copy(path_from, path_to)
            else:
                path_from = os.path.join(self.working_directory,
                                         self.prev_timestamp,
                                         'pointDisplacement_Next')
                path_to = os.path.join(
                    self.working_directory, self.prev_timestamp,
                    'pointDisplacement_Next_Iter' + str(self.iteration))
                shutil.copy(path_from, path_to)

        self.delete_prev_iter_output()

        self.send_message('continue')
        self.wait_message('continue_ready')

        # copy output data for debugging
        if self.debug:
            for boundary in self.boundary_names:
                # specify location of pressure and traction
                traction_name = 'TRACTION_' + boundary
                pressure_name = 'PRESSURE_' + boundary
                wss_filepath = os.path.join(
                    self.working_directory, 'postProcessing', traction_name,
                    'surface', self.cur_timestamp,
                    f'wallShearStress_patch_{boundary}.raw')
                pres_filepath = os.path.join(self.working_directory,
                                             'postProcessing', pressure_name,
                                             'surface', self.cur_timestamp,
                                             f'p_patch_{boundary}.raw')
                wss_iter_filepath = os.path.join(
                    self.working_directory, 'postProcessing', traction_name,
                    'surface', self.cur_timestamp,
                    f'wallShearStress_patch_{boundary}_{self.iteration}.raw')
                pres_iter_filepath = os.path.join(
                    self.working_directory, 'postProcessing', pressure_name,
                    'surface', self.cur_timestamp,
                    f'p_patch_{boundary}_{self.iteration}.raw')
                shutil.copy(wss_filepath, wss_iter_filepath)
                shutil.copy(pres_filepath, pres_iter_filepath)

        # read data from OpenFOAM
        self.read_node_output()

        # return interface_output object
        return self.interface_output

    def finalize_solution_step(self):
        super().finalize_solution_step()

        prev_timestep = self.timestep - 1
        # remove the folder that was used for pointDisplacement_Next if not in writeInterval
        if self.settings['parallel']:
            dir_pointdisp_next = os.path.join(self.working_directory,
                                              self.prev_timestamp)
            shutil.rmtree(dir_pointdisp_next)

            if prev_timestep % self.write_interval:
                for p in range(self.cores):
                    prev_timestep_dir = os.path.join(
                        self.working_directory,
                        f'processor{p}/{self.prev_timestamp}')
                    shutil.rmtree(prev_timestep_dir)
        else:
            if prev_timestep % self.write_interval:
                dir_pointdisp_next = os.path.join(self.working_directory,
                                                  self.prev_timestamp)
                shutil.rmtree(dir_pointdisp_next)

        if not (self.timestep % self.write_interval):
            self.send_message('save')
            self.wait_message('save_ready')

        if self.residual_variables is not None:
            self.write_of_residuals()

    def finalize(self):
        super().finalize()

        self.send_message('stop')
        self.wait_message('stop_ready')
        self.openfoam_process.wait()

    def get_interface_input(self):
        return self.interface_input

    def get_interface_output(self):
        return self.interface_output

    def delete_prev_iter_output(self):
        # pressure and wall shear stress files are removed to avoid openfoam to append data in the new iteration
        for boundary in self.boundary_names:
            # specify location of pressure and traction
            traction_name = 'TRACTION_' + boundary
            pressure_name = 'PRESSURE_' + boundary
            wss_file = os.path.join(
                self.working_directory, 'postProcessing', traction_name,
                'surface', self.cur_timestamp,
                'wallShearStress_patch_' + boundary + '.raw')
            pres_file = os.path.join(self.working_directory, 'postProcessing',
                                     pressure_name, 'surface',
                                     self.cur_timestamp,
                                     'p_patch_' + boundary + '.raw')
            if os.path.isfile(wss_file):
                os.remove(wss_file)
            if os.path.isfile(pres_file):
                os.remove(pres_file)

    def read_node_output(self):
        """
        reads the pressure and wall shear stress from the <case directory>/postProcessing for serial and parallel. In
        case of parallel, it uses mp.sequence (using faceProcAddressing) to map the values to the face centres.

        :return:
        """

        # default value is 1.0 for compressible case
        # when the solver is incompressible, the pressure and shear stress are kinematic; therefore multiply with
        # the fluid density
        density = 1.0
        if self.settings['is_incompressible']:
            density = self.settings['density']

        for boundary in self.boundary_names:
            # specify location of pressure and traction
            traction_name = 'TRACTION_' + boundary
            pressure_name = 'PRESSURE_' + boundary
            mp_name = f'{boundary}_output'
            mp = self.model.get_model_part(mp_name)
            nfaces = mp.size
            wss_filename = os.path.join(
                self.working_directory, 'postProcessing', traction_name,
                'surface', self.cur_timestamp,
                'wallShearStress_patch_' + boundary + '.raw')
            pres_filepath = os.path.join(self.working_directory,
                                         'postProcessing', pressure_name,
                                         'surface', self.cur_timestamp,
                                         'p_patch_' + boundary + '.raw')

            # check if the pressure and wall shear stress files completed by openfoam and read data
            self.check_output_file(wss_filename, nfaces)
            wss_tmp = np.loadtxt(wss_filename, comments='#')[:, 3:]
            self.check_output_file(pres_filepath, nfaces)
            pres_tmp = np.loadtxt(pres_filepath, comments='#')[:, 3]

            if self.settings['parallel']:
                pos_list = mp.sequence
            else:
                pos_list = [pos for pos in range(0, nfaces)]

            wall_shear_stress = np.empty_like(wss_tmp)
            pressure = np.empty((pres_tmp.size, 1))

            wall_shear_stress[pos_list, ] = wss_tmp[:, ]
            pressure[pos_list, 0] = pres_tmp

            self.interface_output.set_variable_data(
                mp_name, 'traction', wall_shear_stress * -1 * density)
            self.interface_output.set_variable_data(mp_name, 'pressure',
                                                    pressure * density)

    # noinspection PyMethodMayBeStatic
    def write_footer(self, file_name):
        # write OpenFOAM-footer at the end of file
        with open(file_name, 'a') as f:
            f.write(
                '\n// ************************************************************************* //\n'
            )

    def write_node_input(self):
        """
        creates pointDisplacementNext for supplying the displacement field in the FSI coupling. This file is created
        from 0/pointDisplacement. The boundary field for boundaries participating in the FSI coupling is modified to
        supply the boundary displacement field from structural solver. If the OpenFOAM solver is run in parallel,
        the field is subsequently decomposed using the command: decomposePar.
       :return:
       """

        pointdisp_filename_ref = os.path.join(self.working_directory, '0',
                                              'pointDisplacement')

        pointdisp_filename = os.path.join(self.working_directory,
                                          self.prev_timestamp,
                                          'pointDisplacement_Next')

        with open(pointdisp_filename_ref, 'r') as ref_file:
            pointdisp_string = ref_file.read()

        for boundary in self.boundary_names:
            mp_name = f'{boundary}_input'
            displacement = self.interface_input.get_variable_data(
                mp_name, 'displacement')
            boundary_dict = of_io.get_dict(input_string=pointdisp_string,
                                           keyword=boundary)
            boundary_dict_new = of_io.update_vector_array_dict(
                dict_string=boundary_dict, vector_array=displacement)
            pointdisp_string = pointdisp_string.replace(
                boundary_dict, boundary_dict_new)

        with open(pointdisp_filename, 'w') as f:
            f.write(pointdisp_string)

        if self.settings['parallel']:
            check_call(
                f'decomposePar -fields -time {self.prev_timestamp} &> log.decomposePar;',
                cwd=self.working_directory,
                shell=True,
                env=self.env)

    # noinspection PyMethodMayBeStatic
    def check_output_file(self, filename, nfaces):
        counter = 0
        nlines = 0
        lim = 1000
        while (nlines < nfaces + 2) and counter < lim:
            if os.path.isfile(filename):
                with open(filename, 'r') as f:
                    nlines = sum(1 for _ in f)
            time.sleep(0.01)
            counter += 1
        if counter == lim:
            raise RuntimeError(f'Timed out waiting for file: {filename}')
        else:
            return True

    def send_message(self, message):
        file = os.path.join(self.working_directory, message + '.coco')
        open(file, 'w').close()
        return

    def wait_message(self, message):
        wait_time_lim = 10 * 60  # 10 minutes maximum waiting time for a single flow solver iteration
        cumul_time = 0
        file = os.path.join(self.working_directory, message + '.coco')
        while not os.path.isfile(file):
            time.sleep(0.01)
            cumul_time += 0.01
            if cumul_time > wait_time_lim:
                self.openfoam_process.kill()
                self.openfoam_process.wait()
                raise RuntimeError(
                    f'CoCoNuT timed out in the OpenFOAM solver_wrapper, waiting for message: '
                    f'{message}.coco')
        os.remove(file)
        return

    def check_message(self, message):
        file = os.path.join(self.working_directory, message + '.coco')
        if os.path.isfile(file):
            os.remove(file)
            return True
        return False

    def remove_all_messages(self):
        for file_name in os.listdir(self.working_directory):
            if file_name.endswith('.coco'):
                file = os.path.join(self.working_directory, file_name)
                os.remove(file)

    def check_software(self):
        if check_call(self.application + ' -help &> checkSoftware',
                      shell=True,
                      env=self.env) != 0:
            raise RuntimeError(
                f'OpenFOAM not loaded properly. You should perform the following steps:\n'
                f'-\tLoad the module for OpenFOAM-{self.version},\n'
                f'-\tSource $FOAM_BASH,\n'
                f'-\tCompile {self.application}')

        # check version
        with open('checkSoftware', 'r') as f:
            last_line = f.readlines(
            )[-2]  # second last line contains 'Build: XX' with XX the version number
        os.remove('checkSoftware')
        version_nr = last_line.split(' ')[-1]
        if version_nr[:-1] != self.version:
            raise RuntimeError(
                f'OpenFOAM-{self.version} should be loaded! Currently, OpenFOAM-{version_nr[:-1]} is loaded'
            )

    def check_interfaces(self):
        """
        checks the dictionaries from 'interface_input' and 'interface_output' in parameters.json file. The model part
        name must be the concatenation of an entry from `boundary_names` and the string `_input`, for 'interface_input'
        and for 'interface_output' it must be the concatenation of an entry from `boundary_names` and the string
        `_output`.
        :return:
        """
        input_interface_model_parts = [
            param['model_part'] for param in self.settings['interface_input']
        ]
        output_interface_model_parts = [
            param['model_part'] for param in self.settings['interface_output']
        ]
        boundary_names = self.settings['boundary_names']

        for boundary_name in boundary_names:
            if f'{boundary_name}_input' not in input_interface_model_parts:
                raise RuntimeError(
                    f'Error in json file: {boundary_name}_input not listed in "interface_input": '
                    f'{self.settings["interface_input"]}.\n. <boundary> in the "boundary_names" in json file should '
                    f'have corresponding <boundary>_input in "interface_input" list'
                )

            if f'{boundary_name}_output' not in output_interface_model_parts:
                raise RuntimeError(
                    f'Error in json file: {boundary_name}_output not listed in "interface_output": '
                    f'{self.settings["interface_output"]}.\n. <boundary> in the "boundary_names" in json file should '
                    f'have corresponding <boundary>_output in "interface_output" list'
                )

    def read_modify_controldict(self):
        """
        reads the controlDict file in the case-directory and modifies some entries required by the coconut_pimpleFoam.
        The values of these entries are taken from paramters.json file.
        :return:
        """

        file_name = os.path.join(self.working_directory, 'system/controlDict')
        with open(file_name, 'r') as control_dict_file:
            control_dict = control_dict_file.read()
            self.write_interval = of_io.get_int(input_string=control_dict,
                                                keyword='writeInterval')
            time_format = of_io.get_string(input_string=control_dict,
                                           keyword='timeFormat')
            self.write_precision = of_io.get_int(input_string=control_dict,
                                                 keyword='writePrecision')

            if not time_format == 'fixed':
                msg = f'timeFormat:{time_format} in controlDict not implemented. Changed to "fixed"'
                tools.print_info(msg, layout='warning')
                control_dict = re.sub(r'timeFormat' + of_io.delimter + r'\w+',
                                      f'timeFormat    fixed', control_dict)
            control_dict = re.sub(r'application' + of_io.delimter + r'\w+',
                                  f'application    {self.application}',
                                  control_dict)
            control_dict = re.sub(
                r'startTime' + of_io.delimter + of_io.float_pattern,
                f'startTime    {self.start_time}', control_dict)
            control_dict = re.sub(
                r'deltaT' + of_io.delimter + of_io.float_pattern,
                f'deltaT    {self.delta_t}', control_dict)
            control_dict = re.sub(
                r'timePrecision' + of_io.delimter + of_io.int_pattern,
                f'timePrecision    {self.time_precision}', control_dict)
            control_dict = re.sub(
                r'endTime' + of_io.delimter + of_io.float_pattern,
                f'endTime    1e15', control_dict)

            # delete previously defined coconut functions
            coconut_start_string = '// CoCoNuT function objects'
            control_dict = re.sub(coconut_start_string + r'.*',
                                  '',
                                  control_dict,
                                  flags=re.S)

        with open(file_name, 'w') as control_dict_file:
            control_dict_file.write(control_dict)
            control_dict_file.write(coconut_start_string + '\n')
            control_dict_file.write('boundary_names (')

            for boundary_name in self.boundary_names:
                control_dict_file.write(boundary_name + ' ')

            control_dict_file.write(');\n\n')
            control_dict_file.write('functions\n{\n')

            for boundary_name in self.boundary_names:
                control_dict_file.write(
                    f'PRESSURE_{boundary_name}\n'
                    f'{{\n'
                    f'type  	 surfaceRegion;\n'
                    f'libs 	 ("libfieldFunctionObjects.so");\n'
                    f'executeControl 	 timeStep;\n'
                    f'executeInterval 	 1;\n'
                    f'writeControl 	 timeStep;\n'
                    f'writeInterval 	 1;\n'
                    f'timeFormat 	 fixed;\n'
                    f'timePrecision 	 {self.time_precision};\n'
                    f'operation 	 none;\n'
                    f'writeFields 	 true;\n'
                    f'surfaceFormat 	 raw;\n'
                    f'regionType 	 patch;\n'
                    f'name 	 {boundary_name};\n'
                    f'fields (p);\n'
                    f'}}\n')
                control_dict_file.write(
                    f'wallShearStress\n'
                    f'{{\n'
                    f'type  	 wallShearStress;\n'
                    f'libs 	 ("libfieldFunctionObjects.so");\n'
                    f'executeControl 	 timeStep;\n'
                    f'executeInterval 	 1;\n'
                    f'writeControl 	 timeStep;\n'
                    f'writeInterval 	 1;\n'
                    f'timeFormat 	 fixed;\n'
                    f'timePrecision 	 {self.time_precision};\n'
                    f'log 	 false;\n'
                    f'}}\n')
                control_dict_file.write(
                    f'TRACTION_{boundary_name}\n'
                    f'{{\n'
                    f'type  	 surfaceRegion;\n'
                    f'libs 	 ("libfieldFunctionObjects.so");\n'
                    f''
                    f'executeControl 	 timeStep;\n'
                    f'executeInterval 	 1;\n'
                    f'writeControl 	 timeStep;\n'
                    f'writeInterval 	 1;\n'
                    f'timeFormat 	 fixed;\n'
                    f'timePrecision 	 {self.time_precision};\n'
                    f'operation 	 none;\n'
                    f'writeFields 	 true;\n'
                    f'surfaceFormat 	 raw;\n'
                    f'regionType 	 patch;\n'
                    f'name 	 {boundary_name};\n'
                    f'fields ( wallShearStress);\n'
                    f'}}\n')
            control_dict_file.write('}')
        self.write_footer(file_name)

    def write_residuals_fileheader(self):
        header = ''
        sep = ', '
        with open(self.res_filepath, 'w') as f:
            f.write('# Residuals\n')
            for variable in self.residual_variables:
                header += variable + sep
            f.write(header.strip(sep) + '\n')

    def write_of_residuals(self):
        """
        it reads the log file generated by coconut_pimpleFoam solver and writes the last initial residual of the fields
        in the pimple iterations, for every coupling iteration. The fields should be given in the parameters.json file
        with the key-'residual_variables' and values-list(OpenFOAM variables), e.g. 'residual_variables': ['U', 'p']
        :return:
        """
        log_filepath = os.path.join(self.working_directory,
                                    f'log.{self.application}')
        if os.path.isfile(log_filepath):
            with open(log_filepath, 'r') as f:
                log_string = f.read()
            time_start_string = f'Time = {self.prev_timestamp}'
            time_end_string = f'Time = {self.cur_timestamp}'
            match = re.search(time_start_string + r'(.*)' + time_end_string,
                              log_string,
                              flags=re.S)
            if match is not None:
                time_block = match.group(1)
                iteration_block_list = re.findall(
                    r'Coupling iteration = \d+(.*?)Coupling iteration \d+ end',
                    time_block,
                    flags=re.S)
                for iteration_block in iteration_block_list:
                    residual_array = np.empty(len(self.residual_variables))
                    for i, variable in enumerate(self.residual_variables):
                        search_string = f'Solving for {variable}, Initial residual = ({of_io.float_pattern})'
                        var_residual_list = re.findall(search_string,
                                                       iteration_block)
                        if var_residual_list:
                            # last initial residual of pimple loop
                            var_residual = float(var_residual_list[-1])
                            residual_array[i] = var_residual
                        else:
                            raise RuntimeError(
                                f'Variable: {variable} equation is not solved in {self.application}'
                            )

                    with open(self.res_filepath, 'a') as f:
                        np.savetxt(f, [residual_array], delimiter=', ')
Esempio n. 16
0
    def test_has_same_modelparts(self):
        self.interface.set_interface_data(self.interface_data)

        interface_a = self.interface.copy()
        interface_a.set_interface_data(np.random.rand(self.model_part_size *
                                                      5))
        self.assertTrue(self.interface.has_same_model_parts(interface_a))

        interface_b = Interface(self.parameters['interface_b'], self.model)
        interface_b.set_interface_data(self.interface_data)
        self.assertTrue(self.interface.has_same_model_parts(interface_b))

        interface_c = Interface(self.parameters['interface_c'], self.model)
        interface_c.set_interface_data(self.interface_data)
        self.assertFalse(self.interface.has_same_model_parts(interface_c))

        interface_d = Interface(self.parameters['interface_d'], self.model)
        interface_d.set_interface_data(self.interface_data)
        self.assertFalse(self.interface.has_same_model_parts(interface_d))
Esempio n. 17
0
    def __init__(self, parameters):
        super().__init__()

        # settings
        self.settings = parameters['settings']
        self.working_directory = self.settings['working_directory']
        self.env = get_solver_env(__name__, self.working_directory)
        # adapted application from openfoam ('coconut_<application name>')
        self.application = self.settings['application']
        self.delta_t = self.settings['delta_t']
        self.time_precision = self.settings['time_precision']
        self.start_time = self.settings['timestep_start'] * self.delta_t
        self.timestep = self.physical_time = self.iteration = self.prev_timestamp = self.cur_timestamp = None
        self.openfoam_process = None
        self.write_interval = self.write_precision = None
        # boundary_names is the set of boundaries in OpenFoam used for coupling
        self.boundary_names = self.settings['boundary_names']
        self.version = '4.1'

        # set on True to save copy of input and output files in every iteration
        self.debug = False

        # check interface names in 'interface_input' and 'interface_output' with boundary names provided in
        # boundary_names
        self.check_interfaces()

        # check that the correct modules have been loaded
        self.check_software()

        # remove possible CoCoNuT-message from previous interrupt
        self.remove_all_messages()

        # obtain number of cores from self.working_directory/system/decomposeParDict
        self.cores = 1
        if self.settings['parallel']:
            file_name = os.path.join(self.working_directory,
                                     'system/decomposeParDict')
            if not os.path.isfile(file_name):
                raise RuntimeError(
                    f'In the parameters:\n{self.settings}\n key "parallel" is set to {True} but {file_name} '
                    f'does not exist')
            else:
                with open(file_name, 'r') as file:
                    decomposedict_string = file.read()
                self.cores = of_io.get_int(input_string=decomposedict_string,
                                           keyword='numberOfSubdomains')

        # modify controlDict file to add pressure and wall shear stress functionObjects for all the boundaries in
        # self.settings["boundary_names"]
        self.read_modify_controldict()

        # creating Model
        self.model = data_structure.Model()

        # writeCellcentres writes cellcentres in internal field and face centres in boundaryField
        check_call(f'writeCellCentres -time 0 &> log.writeCellCentres;',
                   cwd=self.working_directory,
                   shell=True,
                   env=self.env)
        boundary_filename = os.path.join(self.working_directory,
                                         'constant/polyMesh/boundary')

        for boundary in self.boundary_names:
            with open(boundary_filename, 'r') as boundary_file:
                boundary_file_string = boundary_file.read()
            boundary_dict = of_io.get_dict(input_string=boundary_file_string,
                                           keyword=boundary)
            # get point ids and coordinates for all the faces in the boundary
            node_ids, node_coords = of_io.get_boundary_points(
                case_directory=self.working_directory,
                time_folder='0',
                boundary_name=boundary)
            nfaces = of_io.get_int(input_string=boundary_dict,
                                   keyword='nFaces')
            start_face = of_io.get_int(input_string=boundary_dict,
                                       keyword='startFace')

            # create input model part
            self.model.create_model_part(f'{boundary}_input',
                                         node_coords[:, 0], node_coords[:, 1],
                                         node_coords[:, 2], node_ids)

            filename_x = os.path.join(self.working_directory, '0/ccx')
            filename_y = os.path.join(self.working_directory, '0/ccy')
            filename_z = os.path.join(self.working_directory, '0/ccz')

            x0 = of_io.get_boundary_field(file_name=filename_x,
                                          boundary_name=boundary,
                                          size=nfaces,
                                          is_scalar=True)
            y0 = of_io.get_boundary_field(file_name=filename_y,
                                          boundary_name=boundary,
                                          size=nfaces,
                                          is_scalar=True)
            z0 = of_io.get_boundary_field(file_name=filename_z,
                                          boundary_name=boundary,
                                          size=nfaces,
                                          is_scalar=True)
            ids = np.arange(0, nfaces)

            # create output model part
            mp_output = self.model.create_model_part(f'{boundary}_output', x0,
                                                     y0, z0, ids)
            mp_output.start_face = start_face
            mp_output.nfaces = nfaces

        # create interfaces
        self.interface_input = Interface(self.settings['interface_input'],
                                         self.model)
        self.interface_output = Interface(self.settings['interface_output'],
                                          self.model)

        # time
        self.init_time = self.init_time
        self.run_time = 0.0

        # compile openfoam adapted solver
        solver_dir = os.path.join(os.path.dirname(__file__), self.application)
        try:
            check_call(f'wmake {solver_dir} &> log.wmake',
                       cwd=self.working_directory,
                       shell=True,
                       env=self.env)
        except subprocess.CalledProcessError:
            raise RuntimeError(
                f'Compilation of {self.application} failed. Check {os.path.join(self.working_directory, "log.wmake")}'
            )

        self.residual_variables = self.settings.get('residual_variables', None)
        self.res_filepath = os.path.join(self.working_directory,
                                         'residuals.csv')

        if self.residual_variables is not None:
            self.write_residuals_fileheader()