コード例 #1
0
    def test_call_3d_var(self):
        var = 'displacement'
        mp_name_in = 'wall_in'
        mp_name_out = 'wall_out'

        n = 10
        x, y, z = np.random.rand(n), np.random.rand(n), np.random.rand(n)
        v_in = np.random.rand(n, 3)

        model = data_structure.Model()
        model.create_model_part(mp_name_in, x, y, z, np.arange(n))
        parameters_in = [{'model_part': mp_name_in, 'variables': [var]}]
        interface_in = data_structure.Interface(parameters_in, model)
        interface_in.set_variable_data(mp_name_in, var, v_in)

        mapper = create_instance(self.parameters)
        mapper.initialize(model, mp_name_in, mp_name_out, forward=True)

        parameters_out = [{'model_part': mp_name_out, 'variables': [var]}]
        interface_out = data_structure.Interface(parameters_out, model)
        mapper((interface_in, mp_name_in, var),
               (interface_out, mp_name_out, var))

        v_out = interface_out.get_variable_data(mp_name_out, var)
        np.testing.assert_array_equal(v_in[:, 0], v_out[:, 1])
        np.testing.assert_array_equal(v_in[:, 1], v_out[:, 2])
        np.testing.assert_array_equal(v_in[:, 2], v_out[:, 0])
コード例 #2
0
    def __init__(self, n_from, n_to):
        self.n_from = n_from
        self.n_to = n_to
        self.var = 'pressure'
        self.mp_name_from = 'wall_from'
        self.mp_name_to = 'wall_to'

        self.model = data_structure.Model()

        # Interface from
        dtheta = 2 * np.pi / self.n_from
        self.theta_from = np.linspace(0, 2 * np.pi - dtheta, self.n_from)
        self.x_from, self.y_from = self.get_cartesian(self.theta_from)
        self.v_from = self.fun(self.x_from, self.y_from)
        self.model.create_model_part(self.mp_name_from, self.x_from, self.y_from,
                                     np.zeros(self.n_from), np.arange(self.n_from))
        parameters = [{'model_part': self.mp_name_from, 'variables': [self.var]}]
        self.interface_from = data_structure.Interface(parameters, self.model)
        self.interface_from.set_interface_data(self.v_from)

        # Interface to
        dtheta = 2 * np.pi / self.n_to
        self.theta_to = np.linspace(0, 2 * np.pi - dtheta, self.n_to)
        self.x_to, self.y_to = self.get_cartesian(self.theta_to)
        self.model.create_model_part(self.mp_name_to, self.x_to, self.y_to,
                                     np.zeros(self.n_to), np.arange(self.n_to))
        parameters = [{'model_part': self.mp_name_to, 'variables': [self.var]}]
        self.interface_to = data_structure.Interface(parameters, self.model)
コード例 #3
0
    def __call__(self, args_from, args_to):
        # unpack arguments
        interface_from, mp_name_from, var_from = args_from
        interface_to, mp_name_to, var_to = args_to

        # check variables
        if var_from not in variables_dimensions:
            raise NameError(f'Variable "{var_from}" does not exist')
        if var_from != var_to:
            raise TypeError('Variables must be equal')
        var = var_from

        # create Interfaces
        interfaces = []
        for mp_name in self.mp_names:
            parameters = [{'model_part': mp_name, 'variables': [var]}]
            interfaces.append(data_structure.Interface(parameters, self.model))

        # map data
        data_from = interface_from.get_variable_data(mp_name_from, var)
        interfaces[0].set_variable_data(self.mp_names[0], var, data_from)

        for i, mapper in enumerate(self.mappers):
            mapper((interfaces[i], self.mp_names[i], var),
                   (interfaces[i + 1], self.mp_names[i + 1], var))

        data_to = interfaces[-1].get_variable_data(self.mp_names[-1], var)
        interface_to.set_variable_data(mp_name_to, var, data_to)
コード例 #4
0
    def test_mapper_combined(self):
        parameter_file_name = os.path.join(os.path.dirname(__file__),
                                           'test_combined.json')
        with open(parameter_file_name, 'r') as parameter_file:
            parameters = json.load(parameter_file)

        # compare 3 mappers: nearest, combined_a, combined_b
        for var in ['pressure', 'displacement']:
            mp_name_from = 'wall_from'
            mp_name_to = 'wall_to'
            model = data_structure.Model()

            n = 100
            tmp = np.linspace(0, 1, n)
            x, y, z = tmp, tmp**1.1, tmp**1.2
            v_from = np.random.rand(n,
                                    data_structure.variables_dimensions[var])
            mp_from = model.create_model_part(mp_name_from, x, y, z,
                                              np.arange(n))
            mp_to = model.create_model_part(mp_name_to, np.flip(x), np.flip(y),
                                            np.flip(z), np.arange(n))

            parameters_from = [{
                'model_part': mp_name_from,
                'variables': [var]
            }]
            int_from = data_structure.Interface(parameters_from, model)
            int_from.set_variable_data(mp_name_from, var, v_from)
            parameters_to = [{'model_part': mp_name_to, 'variables': [var]}]
            int_to = data_structure.Interface(parameters_to, model)

            # create mappers, get output data
            data = []
            for mapper_name in [
                    'mapper_nearest', 'mapper_combined_a', 'mapper_combined_b'
            ]:
                mapper = create_instance(parameters[mapper_name])
                mapper.initialize(mp_from, mp_to)
                mapper((int_from, mp_name_from, var),
                       (int_to, mp_name_to, var))
                data.append(int_to.get_variable_data(mp_name_to, var))

            # check output data
            np.testing.assert_array_equal(data[0], data[1])
            np.testing.assert_array_equal(data[0], data[2])
コード例 #5
0
    def __init__(self, n_x_from, n_theta_from, n_x_to, n_theta_to, length):
        self.n_x_from = n_x_from
        self.n_theta_from = n_theta_from
        self.n_from = n_x_from * n_theta_from
        self.n_x_to = n_x_to
        self.n_theta_to = n_theta_to
        self.n_to = n_x_to * n_theta_to
        self.length = length
        self.var = 'pressure'
        self.mp_name_from = 'wall_from'
        self.mp_name_to = 'wall_to'
        self.model = data_structure.Model()

        self.model = data_structure.Model()

        # Interface from
        shape = (self.n_x_from, self.n_theta_from)
        dtheta = 2 * np.pi / self.n_theta_from
        theta_from = np.ones(shape) * np.linspace(0, 2 * np.pi - dtheta, self.n_theta_from).reshape(1, -1)

        self.x_from = np.ones(shape) * np.linspace(0, self.length, self.n_x_from).reshape(-1, 1)
        self.y_from, self.z_from = self.get_cartesian(theta_from)
        self.v_from = self.fun(self.x_from, self.y_from, self.z_from)
        self.model.create_model_part(self.mp_name_from, self.x_from.flatten(), self.y_from.flatten(),
                                     self.z_from.flatten(), np.arange(self.n_from))
        parameters = [{'model_part': self.mp_name_from, 'variables': [self.var]}]
        self.interface_from = data_structure.Interface(parameters, self.model)
        self.interface_from.set_interface_data(self.v_from.flatten())

        # Interface to
        shape = (self.n_x_to, self.n_theta_to)
        dtheta = 2 * np.pi / self.n_theta_to
        theta_to = np.ones(shape) * np.linspace(0, 2 * np.pi - dtheta, self.n_theta_to).reshape(1, -1)

        self.x_to = np.ones(shape) * np.linspace(0, self.length, self.n_x_to).reshape(-1, 1)
        self.y_to, self.z_to = self.get_cartesian(theta_to)
        self.model.create_model_part(self.mp_name_to, self.x_to.flatten(), self.y_to.flatten(),
                                     self.z_to.flatten(), np.arange(self.n_to))
        parameters = [{'model_part': self.mp_name_to, 'variables': [self.var]}]
        self.interface_to = data_structure.Interface(parameters, self.model)
コード例 #6
0
    def __init__(self, n_x_from, n_y_from, n_x_to, n_y_to):
        self.n_x_from = n_x_from
        self.n_y_from = n_y_from
        self.n_from = n_x_from * n_y_from
        self.n_x_to = n_x_to
        self.n_y_to = n_y_to
        self.n_to = n_x_to * n_y_to
        self.var = 'displacement'
        self.mp_name_from = 'wall_from'
        self.mp_name_to = 'wall_to'
        self.model = data_structure.Model()

        model = data_structure.Model()

        # ModelPart from
        shape = (self.n_x_from, self.n_y_from)
        self.x_from = np.ones(shape) * np.linspace(-1, 1, self.n_x_from).reshape(-1, 1)
        self.y_from = np.ones(shape) * np.linspace(-1, 1, self.n_y_from).reshape(1, -1)
        self.z_from = np.sinc(np.sqrt((10 * self.x_from) ** 2 + (self.y_from * 10) ** 2) / np.pi)
        self.v_from = self.fun(self.x_from, self.y_from, self.z_from)
        self.model.create_model_part(self.mp_name_from, self.x_from.flatten(), self.y_from.flatten(),
                                     self.z_from.flatten(), np.arange(self.n_from))
        parameters = [{'model_part': self.mp_name_from, 'variables': [self.var]}]
        self.interface_from = data_structure.Interface(parameters, self.model)
        tmp = np.hstack((self.v_from[0].reshape(-1, 1),
                         self.v_from[1].reshape(-1, 1),
                         self.v_from[2].reshape(-1, 1)))
        self.interface_from.set_variable_data(self.mp_name_from, self.var, tmp)

        # ModelPart to
        shape = (self.n_x_to, self.n_y_to)
        self.x_to = np.ones(shape) * np.linspace(-1, 1, self.n_x_to).reshape(-1, 1)
        self.y_to = np.ones(shape) * np.linspace(-1, 1, self.n_y_to).reshape(1, -1)
        self.z_to = np.sinc(np.sqrt((10 * self.x_to) ** 2 + (self.y_to * 10) ** 2) / np.pi)
        self.v_to = self.fun(self.x_to, self.y_to, self.z_to)
        self.model.create_model_part(self.mp_name_to, self.x_to.flatten(), self.y_to.flatten(),
                                     self.z_to.flatten(), np.arange(self.n_to))
        parameters = [{'model_part': self.mp_name_to, 'variables': [self.var]}]
        self.interface_to = data_structure.Interface(parameters, self.model)
コード例 #7
0
    def __init__(self, n_theta_from, n_phi_from, n_theta_to, n_phi_to):
        self.n_theta_from = n_theta_from
        self.n_phi_from = n_phi_from
        self.n_from = n_theta_from * n_phi_from
        self.n_theta_to = n_theta_to
        self.n_phi_to = n_phi_to  # for bounding box: not too far from n_phi_from!
        self.n_to = n_theta_to * n_phi_to
        self.var = 'pressure'
        self.mp_name_from = 'wall_from'
        self.mp_name_to = 'wall_to'
        self.model = data_structure.Model()

        # Interface from
        shape = (self.n_theta_from, self.n_phi_from)
        dtheta = 2 * np.pi / self.n_theta_from
        dphi = np.pi / (self.n_phi_from - 1)
        theta = np.ones(shape) * np.linspace(0, 2 * np.pi - dtheta, self.n_theta_from).reshape(-1, 1)
        phi = np.ones(shape) * np.linspace(dphi, np.pi - dphi, self.n_phi_from).reshape(1, -1)

        self.x_from, self.y_from, self.z_from = self.get_cartesian(theta, phi)
        self.v_from = self.fun(self.x_from, self.y_from, self.z_from)
        self.model.create_model_part(self.mp_name_from, self.x_from.flatten(), self.y_from.flatten(),
                                     self.z_from.flatten(), np.arange(self.n_from))
        parameters = [{'model_part': self.mp_name_from, 'variables': [self.var]}]
        self.interface_from = data_structure.Interface(parameters, self.model)
        self.interface_from.set_interface_data(self.v_from.flatten())

        # Interface to
        shape = (self.n_theta_to, self.n_phi_to)
        dtheta = 2 * np.pi / self.n_theta_to
        dphi = np.pi / (self.n_phi_to - 1)
        theta = np.ones(shape) * np.linspace(0, 2 * np.pi - dtheta, self.n_theta_to).reshape(-1, 1)
        phi = np.ones(shape) * np.linspace(dphi, np.pi - dphi, self.n_phi_to).reshape(1, -1)

        self.x_to, self.y_to, self.z_to = self.get_cartesian(theta, phi)
        self.model.create_model_part(self.mp_name_to, self.x_to.flatten(), self.y_to.flatten(),
                                     self.z_to.flatten(), np.arange(self.n_to))
        parameters = [{'model_part': self.mp_name_to, 'variables': [self.var]}]
        self.interface_to = data_structure.Interface(parameters, self.model)
コード例 #8
0
    def __init__(self, n_from, n_to):
        self.n_from = n_from
        self.n_to = n_to
        self.var = 'pressure'
        self.mp_name_from = 'wall_from'
        self.mp_name_to = 'wall_to'

        self.model = data_structure.Model()

        # Interface from
        self.z_from = np.linspace(0, 10, self.n_from) ** .5
        self.v_from = self.fun(self.z_from)
        self.model.create_model_part(self.mp_name_from, np.zeros(self.n_from),
                                     np.zeros(self.n_from), self.z_from, np.arange(self.n_from))
        parameters = [{'model_part': self.mp_name_from, 'variables': [self.var]}]
        self.interface_from = data_structure.Interface(parameters, self.model)
        self.interface_from.set_interface_data(self.v_from)

        # Interface to
        self.z_to = np.linspace(0, 10, self.n_to) ** .5
        self.model.create_model_part(self.mp_name_to, np.zeros(self.n_to),
                                     np.zeros(self.n_to), self.z_to, np.arange(self.n_to))
        parameters = [{'model_part': self.mp_name_to, 'variables': [self.var]}]
        self.interface_to = data_structure.Interface(parameters, self.model)
コード例 #9
0
    def initialize(self):
        super().initialize()

        # prepare Fluent journal
        journal = f'v{self.version}.jou'
        thread_names_str = ''
        for thread_name in self.thread_ids:
            thread_names_str += ' "' + thread_name + '"'
        unsteady = '#f'
        if self.unsteady:
            unsteady = '#t'
        with open(join(self.dir_src, journal)) as infile:
            with open(join(self.dir_cfd, journal), 'w') as outfile:
                for line in infile:
                    line = line.replace('|CASE|', join(self.dir_cfd, self.case_file))
                    line = line.replace('|THREAD_NAMES|', thread_names_str)
                    line = line.replace('|UNSTEADY|', unsteady)
                    line = line.replace('|FLOW_ITERATIONS|', str(self.flow_iterations))
                    line = line.replace('|DELTA_T|', str(self.delta_t))
                    line = line.replace('|TIMESTEP_START|', str(self.timestep_start))
                    outfile.write(line)

        # prepare Fluent UDF
        if self.timestep_start == 0:
            udf = f'v{self.version}.c'
            with open(join(self.dir_src, udf)) as infile:
                with open(join(self.dir_cfd, udf), 'w') as outfile:
                    for line in infile:
                        line = line.replace('|MAX_NODES_PER_FACE|', str(self.mnpf))
                        outfile.write(line)

        # start Fluent with journal
        log = join(self.dir_cfd, 'fluent.log')
        cmd1 = f'fluent -r{self.version_bis} {self.dimensions}ddp '
        cmd2 = f'-t{self.cores} -i {journal}'

        if self.settings['fluent_gui']:
            cmd = cmd1 + cmd2
        else:
            cmd = cmd1 + '-gu ' + cmd2 + f' >> {log} 2>&1'  # TODO: does log work well?
            # cmd = cmd1 + '-gu ' + cmd2 + f' 2> >(tee -a {log}) 1>> {log}'  # TODO: specify what this option does?
        self.fluent_process = subprocess.Popen(cmd, executable='/bin/bash',
                                               shell=True, cwd=self.dir_cfd, env=self.env)

        # get general simulation info from report.sum
        self.wait_message('case_info_exported')
        report = join(self.dir_cfd, 'report.sum')
        check = 0
        with open(report, 'r') as file:
            for line in file:
                if check == 2 and 'Time' in line:
                    if 'Steady' in line and self.unsteady:
                        raise ValueError('unsteady in JSON does not match steady Fluent')
                    elif 'Unsteady' in line and not self.unsteady:
                        raise ValueError('steady in JSON does not match unsteady Fluent')
                    break
                if check == 1 and 'Space' in line:
                    if str(self.dimensions) not in line:
                        if not (self.dimensions == 2 and 'Axisymmetric' in line):
                            raise ValueError(f'dimension in JSON does not match Fluent')
                    check = 2
                if 'Model' in line and 'Settings' in line:
                    check = 1

        # get surface thread ID's from report.sum and write them to bcs.txt
        check = 0
        info = []
        with open(report, 'r') as file:
            for line in file:
                if check == 3 and line.islower():
                    name, id, _ = line.strip().split()
                    if name in self.thread_ids:
                        info.append(' '.join((name, id)))
                        self.thread_ids[name] = id

                if check == 3 and not line.islower():
                    break
                if check == 2:  # skip 1 line
                    check = 3
                if 'name' in line and check == 1:
                    check = 2
                if 'Boundary Conditions' in line:
                    check = 1
        with open(join(self.dir_cfd, 'bcs.txt'), 'w') as file:
            file.write(str(len(info)) + '\n')
            for line in info:
                file.write(line + '\n')
        self.send_message('thread_ids_written_to_file')

        # import node and face information if no restart
        if self.timestep_start == 0:
            self.wait_message('nodes_and_faces_stored')

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

        # create input ModelParts (nodes)
        for item in (self.settings['interface_input']):
            mp_name = item['model_part']

            # get face thread ID that corresponds to ModelPart
            for thread_name in self.thread_ids:
                if thread_name in mp_name:
                    self.model_part_thread_ids[mp_name] = self.thread_ids[thread_name]
            if mp_name not in self.model_part_thread_ids:
                raise AttributeError('Could not find thread name corresponding ' +
                                     f'to ModelPart {mp_name}')

            # read in datafile
            thread_id = self.model_part_thread_ids[mp_name]
            file_name = join(self.dir_cfd, f'nodes_timestep0_thread{thread_id}.dat')
            data = np.loadtxt(file_name, skiprows=1)
            if data.shape[1] != self.dimensions + 1:
                raise ValueError('Given dimension does not match coordinates')

            # get node coordinates and ids
            coords_tmp = np.zeros((data.shape[0], 3)) * 0.
            coords_tmp[:, :self.dimensions] = data[:, :-1]  # add column z if 2D
            ids_tmp = data[:, -1].astype(int)  # array is flattened

            # sort and remove doubles
            args = np.unique(ids_tmp, return_index=True)[1].tolist()
            x0 = coords_tmp[args, 0]
            y0 = coords_tmp[args, 1]
            z0 = coords_tmp[args, 2]
            ids = ids_tmp[args]

            # create ModelPart
            self.model.create_model_part(mp_name, x0, y0, z0, ids)

        # create output ModelParts (faces)
        for item in (self.settings['interface_output']):
            mp_name = item['model_part']

            # get face thread ID that corresponds to ModelPart
            for thread_name in self.thread_ids:
                if thread_name in mp_name:
                    self.model_part_thread_ids[mp_name] = self.thread_ids[thread_name]
            if mp_name not in self.model_part_thread_ids:
                raise AttributeError('Could not find thread name corresponding ' +
                                     f'to ModelPart {mp_name}')
            # read in datafile
            thread_id = self.model_part_thread_ids[mp_name]
            file_name = join(self.dir_cfd, f'faces_timestep0_thread{thread_id}.dat')
            data = np.loadtxt(file_name, skiprows=1)
            if data.shape[1] != self.dimensions + self.mnpf:
                raise ValueError(f'given dimension does not match coordinates')

            # get face coordinates and ids
            coords_tmp = np.zeros((data.shape[0], 3)) * 0.
            coords_tmp[:, :self.dimensions] = data[:, :-self.mnpf]  # add column z if 2D
            ids_tmp = self.get_unique_face_ids(data[:, -self.mnpf:])

            # sort and remove doubles
            args = np.unique(ids_tmp, return_index=True)[1].tolist()
            x0 = coords_tmp[args, 0]
            y0 = coords_tmp[args, 1]
            z0 = coords_tmp[args, 2]
            ids = ids_tmp[args]

            # create ModelPart
            self.model.create_model_part(mp_name, x0, y0, z0, ids)

        # create Interfaces
        self.interface_input = data_structure.Interface(self.settings['interface_input'], self.model)
        self.interface_output = data_structure.Interface(self.settings['interface_output'], self.model)
コード例 #10
0
    def test_call(self):
        def fun_s(x):
            return 1. + 2.5 * x

        def fun_v(x, y, z):
            theta = np.arctan2(z, y)
            v_x = 1. + 2.5 * x
            v_y = v_x * 0.5 * np.cos(theta)
            v_z = v_x * 0.5 * np.sin(theta)
            return np.column_stack((v_x, v_y, v_z))

        mp_name_from = 'wall_from'
        mp_name_to = 'wall_to'
        var_s = 'pressure'
        var_v = 'displacement'

        n_in = 10
        n_to = n_in * 2
        tmp = np.linspace(0, 5, n_in)
        r_tmp = (1. + 0.2 * np.sin(2 * np.pi / 5 * tmp))

        # create model_part_to (3D)
        x_to = np.zeros(n_to)
        y_to = np.zeros(n_to)
        z_to = np.zeros(n_to)

        i = 0
        for k in range(n_in):
            for p in range(2):
                x_to[i] = tmp[k]
                y_to[i] = r_tmp[k] * np.cos(np.radians(2.5))
                z_to[i] = r_tmp[k] * ((-1)**p) * np.sin(np.radians(2.5))
                i += 1
            k += 1

        model = data_structure.Model()
        model.create_model_part(mp_name_to, x_to, y_to, z_to, np.arange(n_to))

        # initialize mapper to get model_part_from (2D)
        mapper = create_instance(self.parameters)
        mapper.initialize(model, mp_name_to, mp_name_from, forward=False)
        parameters_from = [{
            'model_part': mp_name_from,
            'variables': [var_s, var_v]
        }]
        interface_from = data_structure.Interface(parameters_from, model)
        mp_from = interface_from.get_model_part(mp_name_from)
        x_from, y_from, z_from = mp_from.x0, mp_from.y0, mp_from.z0

        v_s_from = fun_s(x_from).reshape(-1, 1)
        v_v_from = fun_v(x_from, y_from, z_from)
        interface_from.set_variable_data(mp_name_from, var_s, v_s_from)
        interface_from.set_variable_data(mp_name_from, var_v, v_v_from)

        parameters_to = [{
            'model_part': mp_name_to,
            'variables': [var_s, var_v]
        }]
        interface_to = data_structure.Interface(parameters_to, model)

        # check mapped values for 1D variable
        mapper((interface_from, mp_name_from, var_s),
               (interface_to, mp_name_to, var_s))
        v_s_to_ref = fun_s(x_to).reshape(-1, 1)
        v_s_to = interface_to.get_variable_data(mp_name_to, var_s)
        np.testing.assert_allclose(v_s_to, v_s_to_ref, rtol=1e-14)

        # check mapped values for 3D variable
        mapper((interface_from, mp_name_from, var_v),
               (interface_to, mp_name_to, var_v))
        v_v_to_ref = fun_v(x_to, y_to, z_to)
        v_v_to = interface_to.get_variable_data(mp_name_to, var_v)
        np.testing.assert_allclose(v_v_to, v_v_to_ref, rtol=1e-14)

        # extra: visualization
        if self.gui:
            v_s_from, v_s_to = v_s_from.flatten(), v_s_to.flatten()
            c_from = cm.jet((v_s_from - v_s_from.min()) /
                            (v_s_from.max() - v_s_from.min()))
            c_to = cm.jet(
                (v_s_to - v_s_from.min()) / (v_s_from.max() - v_s_from.min()))

            fig = plt.figure()

            ax_s = fig.add_subplot(121, projection='3d')
            ax_s.set_title('check geometry and scalar mapping')
            ax_s.scatter(x_from,
                         y_from,
                         z_from,
                         s=50,
                         c=c_from,
                         depthshade=True,
                         marker='s')
            ax_s.scatter(x_to, y_to, z_to, s=20, c=c_to, depthshade=True)

            ax_v = fig.add_subplot(122, projection='3d')
            ax_v.set_title('check vector mapping')
            ax_v.quiver(x_from,
                        y_from,
                        z_from,
                        v_v_from[:, 0],
                        v_v_from[:, 1],
                        v_v_from[:, 2],
                        pivot='tail',
                        arrow_length_ratio=0.05,
                        normalize=False,
                        length=0.05,
                        colors='r',
                        linewidth=3)
            ax_v.quiver(x_to,
                        y_to,
                        z_to,
                        v_v_to[:, 0],
                        v_v_to[:, 1],
                        v_v_to[:, 2],
                        pivot='tail',
                        arrow_length_ratio=0.05,
                        normalize=False,
                        length=0.05)

            for ax in [ax_s, ax_v]:
                ax.set_xlabel('x')
                ax.set_ylabel('y')
                ax.set_zlabel('z')

            plt.get_current_fig_manager().window.showMaximized()
            plt.xlim(0, 6)
            plt.ylim(0.7, 1.5)
            plt.show()
            plt.close()
コード例 #11
0
    def __init__(self, parameters):
        super().__init__()

        # set parameters
        self.settings = parameters['settings']
        self.dir_csm = join(
            os.getcwd(),
            self.settings['working_directory'])  # *** alternative for getcwd?
        self.env = tools.get_solver_env(__name__, self.dir_csm)
        self.check_software()
        path_src = os.path.realpath(os.path.dirname(__file__))
        self.logfile = 'abaqus.log'

        self.cores = self.settings['cores']  # number of CPUs Abaqus has to use
        self.dimensions = self.settings['dimensions']
        self.array_size = self.settings['arraysize']
        self.delta_t = self.settings['delta_t']
        self.timestep_start = self.settings['timestep_start']
        self.surfaceIDs = self.settings['surfaceIDs']
        self.n_surfaces = len(self.surfaceIDs)
        self.mp_mode = self.settings['mp_mode']
        self.input_file = self.settings['input_file']
        self.save_interval = self.settings.get('save_interval', 1)
        self.timestep = self.timestep_start
        self.iteration = None
        self.model_part_surface_ids = {
        }  # surface IDs corresponding to ModelParts

        self.subcycling = self.settings.get(
            'subcycling',
            False)  # value from parameters or False if not present
        if self.subcycling:
            self.min_inc = self.settings['min_inc']
            self.initial_inc = self.settings['initial_inc']
            self.max_num_inc = self.settings['max_num_inc']
            self.max_inc = self.settings['max_inc']
            self.ramp = int(
                self.settings['ramp']
            )  # 0 or 1 required to substitute in user-subroutines (FORTRAN)
        else:
            self.ramp = 0
            self.max_num_inc = 1

        # prepare abaqus_v6.env
        hostname_replace = ''
        if self.mp_mode == 'MPI' and 'AbaqusHosts.txt' in os.listdir(
                self.dir_csm):
            with open(join(self.dir_csm, 'AbaqusHosts.txt'), 'r') as host_file:
                host_names = host_file.read().split()
            hostname_replace = str([[hostname,
                                     host_names.count(hostname)]
                                    for hostname in set(host_names)])
        with open(join(path_src, 'abaqus_v6.env'), 'r') as infile:
            with open(join(self.dir_csm, 'abaqus_v6.env'), 'w') as outfile:
                for line in infile:
                    line = line.replace('|HOSTNAME|', hostname_replace) if self.mp_mode == 'MPI' \
                        else (line, '')['|HOSTNAME|' in line]  # replace |HOSTNAME| if MPI else remove line
                    line = line.replace('|MP_MODE|', self.mp_mode)
                    line = line.replace('|PID|', str(os.getpid()))
                    if '|' in line:
                        raise ValueError(
                            f'The following line in abaqus_v6.env still contains a \'|\' after '
                            f'substitution: \n \t{line} \n Probably a parameter was not substituted'
                        )
                    outfile.write(line)

        # create start and restart file (each time step > 1 is a restart of the previous converged time step)
        self.write_start_and_restart_inp(join(self.dir_csm, self.input_file),
                                         self.dir_csm + '/CSM_Time0.inp',
                                         self.dir_csm + '/CSM_Restart.inp')

        # prepare Abaqus USRInit.f
        usr = '******'
        with open(join(path_src, usr), 'r') as infile:
            with open(join(self.dir_csm, 'usrInit.f'), 'w') as outfile:
                for line in infile:
                    line = line.replace('|dimension|', str(self.dimensions))
                    line = line.replace('|surfaces|', str(self.n_surfaces))
                    line = line.replace('|cpus|', str(self.cores))

                    # if PWD is too long then FORTRAN code can not compile so this needs special treatment
                    line = self.replace_fortran(line, '|PWD|',
                                                os.path.abspath(os.getcwd()))
                    line = self.replace_fortran(
                        line, '|CSM_dir|', self.settings['working_directory'])
                    if '|' in line:
                        raise ValueError(
                            f'The following line in USRInit.f still contains a \'|\' after substitution: '
                            f'\n \t{line} \nProbably a parameter was not substituted'
                        )
                    outfile.write(line)

        # compile Abaqus USRInit.f in library libusr
        path_libusr = join(self.dir_csm, 'libusr/')
        shutil.rmtree(path_libusr, ignore_errors=True)  # needed if restart
        os.mkdir(path_libusr)
        cmd = f'abaqus make library=usrInit.f directory={path_libusr} >> {self.logfile} 2>&1'
        self.print_log(f'### Compilation of usrInit.f ###')
        subprocess.run(cmd,
                       shell=True,
                       cwd=self.dir_csm,
                       executable='/bin/bash',
                       env=self.env)

        # get load points from usrInit.f at timestep_start
        self.print_log(
            f'\n### Get load integration points using usrInit.f ###')
        if self.timestep_start == 0:
            cmd1 = f'rm -f CSM_Time{self.timestep_start}Surface*Faces.dat ' \
                f'CSM_Time{self.timestep_start}Surface*FacesBis.dat'
            # the output files will have a name with a higher time step  ('job=') than the input file ('input=')
            cmd2 = f'abaqus job=CSM_Time{self.timestep_start + 1} input=CSM_Time{self.timestep_start} ' \
                f'cpus=1 output_precision=full interactive >> {self.logfile} 2>&1'
            commands = cmd1 + '; ' + cmd2
            subprocess.run(commands,
                           shell=True,
                           cwd=self.dir_csm,
                           executable='/bin/bash',
                           env=self.env)
        else:  # restart: this only used for checks
            cmd1 = f'rm -f CSM_Time{self.timestep_start}Surface*Faces.dat ' \
                f'CSM_Time{self.timestep_start}Surface*FacesBis.dat'
            cmd2 = f'abaqus job=CSM_Time{self.timestep_start + 1} oldjob=CSM_Time{self.timestep_start} ' \
                f'input=CSM_Restart cpus=1 output_precision=full interactive >> {self.logfile} 2>&1'
            commands = cmd1 + '; ' + cmd2
            subprocess.run(commands,
                           shell=True,
                           cwd=self.dir_csm,
                           executable='/bin/bash',
                           env=self.env)

        # prepare GetOutput.cpp
        get_output = 'GetOutput.cpp'
        temp_str = ''
        for j in range(0, self.n_surfaces - 1):
            temp_str += f'\"{self.surfaceIDs[j]}\", '
        temp_str += f'\"{self.surfaceIDs[self.n_surfaces-1]}\"'

        with open(join(path_src, get_output), 'r') as infile:
            with open(join(self.dir_csm, get_output), 'w') as outfile:
                for line in infile:
                    line = line.replace('|surfaces|', str(self.n_surfaces))
                    line = line.replace('|surfaceIDs|', temp_str)
                    line = line.replace('|dimension|', str(self.dimensions))
                    if '|' in line:
                        raise ValueError(
                            f'The following line in GetOutput.cpp still contains a \'|\' after '
                            f'substitution: \n \t{line} \n Probably a parameter was not substituted'
                        )
                    outfile.write(line)

        # compile GetOutput.cpp
        self.print_log(f'\n### Compilation of GetOutput.cpp ###')
        cmd = f'abaqus make job=GetOutput user=GetOutput.cpp >> {self.logfile} 2>&1'
        subprocess.run(cmd,
                       shell=True,
                       cwd=self.dir_csm,
                       executable='/bin/bash',
                       env=self.env)

        # get node positions (not load points) at timestep_start (0 is an argument to GetOutput.exe)
        self.print_log(
            f'\n### Get geometrical node positions using GetOutput ###')
        cmd = f'abaqus ./GetOutput.exe CSM_Time{self.timestep_start + 1} 0 >> {self.logfile} 2>&1'
        subprocess.run(cmd,
                       shell=True,
                       cwd=self.dir_csm,
                       executable='/bin/bash',
                       env=self.env)

        for i in range(0, self.n_surfaces):
            path_output = join(
                self.dir_csm,
                f'CSM_Time{self.timestep_start + 1}Surface{i}Output.dat')
            path_nodes = join(
                self.dir_csm,
                f'CSM_Time{self.timestep_start}Surface{i}Nodes.dat')
            shutil.move(path_output, path_nodes)

            # create elements file per surface
            face_file = os.path.join(
                self.dir_csm,
                f'CSM_Time{self.timestep_start}Surface{i}Cpu0Faces.dat')
            output_file = os.path.join(
                self.dir_csm,
                f'CSM_Time{self.timestep_start}Surface{i}Elements.dat')
            self.make_elements(face_file, output_file)

        # prepare Abaqus USR.f
        usr = '******'
        with open(join(path_src, usr), 'r') as infile:
            with open(join(self.dir_csm, 'usr.f'), 'w') as outfile:
                for line in infile:
                    line = line.replace('|dimension|', str(self.dimensions))
                    line = line.replace('|arraySize|', str(self.array_size))
                    line = line.replace('|surfaces|', str(self.n_surfaces))
                    line = line.replace('|cpus|', str(self.cores))
                    line = line.replace('|ramp|', str(self.ramp))
                    line = line.replace('|deltaT|', str(self.delta_t))

                    # if PWD is too long then FORTRAN code cannot compile so this needs special treatment
                    line = self.replace_fortran(line, '|PWD|',
                                                os.path.abspath(os.getcwd()))
                    line = self.replace_fortran(
                        line, '|CSM_dir|', self.settings['working_directory'])
                    if '|' in line:
                        raise ValueError(
                            f'The following line in USR.f still contains a \'|\' after substitution: '
                            f'\n \t{line} \n Probably a parameter was not substituted'
                        )
                    outfile.write(line)

        # compile Abaqus USR.f
        self.print_log(f'\n### Compilation of usr.f ###')
        shutil.rmtree(
            path_libusr)  # remove libusr containing compiled USRInit.f
        os.mkdir(path_libusr)
        cmd = f'abaqus make library=usr.f directory={path_libusr} >> {self.logfile} 2>&1'
        subprocess.run(cmd,
                       shell=True,
                       cwd=self.dir_csm,
                       executable='/bin/bash',
                       env=self.env)

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

        # create input ModelParts (load points)
        for item in (self.settings['interface_input']):
            mp_name = item['model_part']

            for i, surfaceID in enumerate(
                    self.surfaceIDs
            ):  # identify surfaceID corresponding to ModelPart
                if surfaceID in mp_name:
                    self.model_part_surface_ids[mp_name] = i
                    break
            if mp_name not in self.model_part_surface_ids:
                raise AttributeError(
                    f'Could not identify surfaceID corresponding to ModelPart {mp_name}'
                )
            mp_id = self.model_part_surface_ids[mp_name]

            # read in elements file
            elem0_file = join(self.dir_csm,
                              f'CSM_Time0Surface{mp_id}Elements.dat')
            elements0 = np.loadtxt(elem0_file)
            n_elem = int(
                elements0[0, 0]
            )  # elements first item on line 1 contains number of elements
            n_lp = int(
                elements0[0, 1]
            )  # elements second item on line 1 contains number of total load points
            if elements0.shape[0] - 1 != int(
                    n_elem
            ):  # elements remainder contains element numbers in interface
                raise ValueError(
                    f'Number of lines ({elements0.shape[0]}) in {elem0_file} does not correspond with '
                    f'the number of elements ({n_elem})')
            if self.timestep_start != 0:  # check if elements0 corresponds to timestep_start
                elem_file = join(
                    self.dir_csm,
                    f'CSM_Time{self.timestep_start}Surface{mp_id}Elements.dat')
                elements = np.loadtxt(elem_file)
                if int(elements[0, 0]) != n_elem or int(elements[0,
                                                                 1]) != n_lp:
                    raise ValueError(
                        f'Number of load points has changed for {mp_name}')

            # read in faces file for load points
            faces0_file = join(self.dir_csm,
                               f'CSM_Time0Surface{mp_id}Cpu0Faces.dat')
            faces0 = np.loadtxt(faces0_file)
            if faces0.shape[1] != self.dimensions + 2:
                raise ValueError(f'Given dimension does not match coordinates')

            # get load point coordinates and ids of load points
            prev_elem = 0
            prev_lp = 0
            ids = np.arange(n_lp)
            coords_tmp = np.zeros(
                (n_lp, 3))  # z-coordinate mandatory: 0.0 for 2D
            for i in range(0, n_lp):
                elem = int(faces0[i, 0])
                lp = int(faces0[i, 1])
                if elem < prev_elem:
                    raise ValueError(
                        f'Element sequence is wrong ({elem}<{prev_elem})')
                elif elem == prev_elem and lp != prev_lp + 1:
                    raise ValueError(
                        f'Next line for same element ({elem}) does not contain next load point'
                    )
                elif elem > prev_elem and lp != 1:
                    raise ValueError(
                        f'First line for element ({elem}) does not contain its first load point'
                    )

                coords_tmp[i, :self.dimensions] = faces0[
                    i, -self.dimensions:]  # extract last 'dimensions' columns

                prev_elem = elem
                prev_lp = lp

            x0 = coords_tmp[:, 0]
            y0 = coords_tmp[:, 1]
            z0 = coords_tmp[:, 2]

            # create ModelPart
            self.model.create_model_part(mp_name, x0, y0, z0, ids)

        # create output ModelParts (geometrical nodes)
        for item in (self.settings['interface_output']):
            mp_name = item['model_part']

            for i, surfaceID in enumerate(
                    self.surfaceIDs
            ):  # identify surfaceID corresponding to ModelPart
                if surfaceID in mp_name:
                    self.model_part_surface_ids[mp_name] = i
                    break
            if mp_name not in self.model_part_surface_ids:
                raise AttributeError(
                    f'Could not identify surfaceID corresponding to ModelPart {mp_name}'
                )
            mp_id = self.model_part_surface_ids[mp_name]

            # read in nodes file
            nodes0_file = join(self.dir_csm,
                               f'CSM_Time0Surface{mp_id}Nodes.dat')
            nodes0 = np.loadtxt(nodes0_file,
                                skiprows=1)  # first line is a header
            n_nodes0 = nodes0.shape[0]
            if nodes0.shape[1] != self.dimensions:
                raise ValueError(f'Given dimension does not match coordinates')
            if self.timestep_start != 0:  # check if nodes0 corresponds to timestep_start
                nodes_file = join(
                    self.dir_csm,
                    f'CSM_Time{self.timestep_start}Surface{mp_id}Nodes.dat')
                nodes = np.loadtxt(nodes_file,
                                   skiprows=1)  # first line is a header
                n_nodes = nodes.shape[0]
                if n_nodes != n_nodes0:
                    raise ValueError(
                        f'Number of interface nodes has changed for {mp_name}')

            # get geometrical node coordinates
            ids = np.arange(
                n_nodes0
            )  # Abaqus does not use node ids but maintains the output order
            coords_tmp = np.zeros(
                (n_nodes0, 3))  # z-coordinate mandatory: 0.0 for 2D
            coords_tmp[:, :self.dimensions] = nodes0

            x0 = coords_tmp[:, 0]
            y0 = coords_tmp[:, 1]
            z0 = coords_tmp[:, 2]

            # create ModelPart
            self.model.create_model_part(mp_name, x0, y0, z0, ids)

        # check whether the input ModelParts and output ModelParts have proper overlap
        for surfaceID in self.surfaceIDs:
            for item in self.settings['interface_input']:
                mp_name = item['model_part']
                if surfaceID in mp_name:
                    mp_in = self.model.get_model_part(mp_name)
                    break
            for item in self.settings['interface_output']:
                mp_name = item['model_part']
                if surfaceID in mp_name:
                    mp_out = self.model.get_model_part(mp_name)
                    break
            tools.check_bounding_box(mp_in, mp_out)

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

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

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