Beispiel #1
0
    def test_validation_unknown_key(self):
        """Test error raised on unknown key."""

        vol_elem = {
            'grain_idx': np.random.randint(0, 9, (2, 2, 2)),
            'bad_key': 1,
        }
        with self.assertRaises(ValueError):
            validate_volume_element(vol_elem)
Beispiel #2
0
    def test_validation_grain_idx_value(self):
        """Test error raised on incorrect `grain_idx` dimension."""

        vol_elem = {'grain_idx': np.random.randint(0, 9, (2, 2))}
        with self.assertRaises(ValueError):
            validate_volume_element(vol_elem)
Beispiel #3
0
    def test_validation_missing_key(self):
        """Test error raised on missing mandatory key."""

        vol_elem = {}
        with self.assertRaises(ValueError):
            validate_volume_element(vol_elem)
Beispiel #4
0
def write_geom(volume_element, geom_path):
    """Write the geometry file for a spectral DAMASK simulation.

    Parameters
    ----------
    volume_element : dict
        Dict that represents the specification of a volume element, with keys:
            element_material_idx : ndarray of shape equal to `grid_size` of int, optional
                Determines the material to which each geometric model element belongs,
                where P is the number of elements.
            grid_size : ndarray of shape (3,) of int, optional
                Geometric model grid dimensions.
            size : list of length three, optional
                Volume element size. By default set to unit size: [1.0, 1.0, 1.0].
            origin : list of length three, optional
                Volume element origin. By default: [0, 0, 0].
    geom_path : str or Path
        The path to the file that will be generated.

    Returns
    -------
    geom_path : Path
        The path to the generated file.

    Notes
    -----
    The microstructure and texture parts are not included in the header of the generated
    file.

    """

    volume_element = validate_volume_element(volume_element)
    element_material_idx = volume_element['element_material_idx']

    grid_size = element_material_idx.shape
    ve_size = volume_element.get('size') or [1.0, 1.0, 1.0]
    ve_origin = volume_element.get('origin') or [0.0, 0.0, 0.0]
    num_micros = np.max(
        element_material_idx) + 1  # element_material_idx is zero-indexed

    header_lns = [
        f'grid a {grid_size[0]} b {grid_size[1]} c {grid_size[2]}',
        f'size x {ve_size[0]} y {ve_size[1]} z {ve_size[2]}',
        f'origin x {ve_origin[0]} y {ve_origin[1]} z {ve_origin[2]}',
        f'microstructures {num_micros}',
        f'homogenization 1',
    ]
    num_header_lns = len(header_lns)
    header = f'{num_header_lns} header\n' + '\n'.join(header_lns) + '\n'

    elem_mat_idx_2D = np.concatenate(element_material_idx.swapaxes(0, 2))
    elem_mat_idx_2D += 1  # one-indexed

    arr_str = ''
    for row in elem_mat_idx_2D:
        for col in row:
            arr_str += '{:<5d}'.format(col)
        arr_str += '\n'

    geom_path = Path(geom_path)
    with geom_path.open('w') as handle:
        handle.write(header + arr_str)

    return geom_path
def geom_to_volume_element(geom_path,
                           phase_labels,
                           homog_label,
                           orientations=None):
    """Read a DAMASK geom file and parse to a volume element.

    Parameters
    ----------
    geom_path : str or Path
        Path to the DAMASK geometry file. The geom file must include texture and
        microstructure parts in its header if `orientations` is None.
    phase_labels : list or ndarray of str, optional
        List of phase labels to associate with the constituents. The first list element is
        the phase label that will be associated with all of the geometrical elements
        for which an orientation is also specified. Additional list elements are
        phase labels for geometrical elements for which no orientations are
        specified. For instance, if the DAMASK command `geom_canvas` was used on
        a geom file to generate a new geom file that included additional material indices,
        the phases assigned to those additional material indices would be specified as
        additional list elements in `phase_labels`.
    homog_label : str, optional
        The homogenization scheme label to use for all materials in the volume element.
    orientations : dict, optional
        If specified, use these orientations instead of those that might be specified in
        the geometry file. Dict containing the following keys:
            type : str
                One of "euler", "quat".
            quaternions : (list or ndarray of shape (R, 4)) of float, optional
                Array of R row four-vectors of unit quaternions. Specify either
                `quaternions` or `euler_angles`.
            euler_angles : (list or ndarray of shape (R, 3)) of float, optional            
                Array of R row three-vectors of Euler angles. Specify either `quaternions`
                or `euler_angles`. Specified as proper Euler angles in the Bunge
                convention (rotations are about Z, new-X, new-new-Z).
            euler_degrees : bool, optional
                If True, `euler_angles` are expected in degrees, rather than radians.
            unit_cell_alignment : dict
                Alignment of the unit cell.
            P : int, optional
                The "P" constant, either +1 or -1, as defined within [1].                

    Returns
    -------
    volume_element : dict

    References
    ----------
    [1] Rowenhorst, D, A D Rollett, G S Rohrer, M Groeber, M Jackson,
        P J Konijnenberg, and M De Graef. "Consistent Representations
        of and Conversions between 3D Rotations". Modelling and Simulation
        in Materials Science and Engineering 23, no. 8 (1 December 2015):
        083501. https://doi.org/10.1088/0965-0393/23/8/083501.

    """

    geom_dat = read_geom(geom_path)
    volume_element = {
        'orientations': orientations or geom_dat['orientations'],
        'element_material_idx': geom_dat['element_material_idx'],
        'grid_size': geom_dat['grid_size'],
        'size': geom_dat['size'],
        'phase_labels': phase_labels,
        'homog_label': homog_label,
    }
    volume_element = validate_volume_element(volume_element)
    return volume_element
def read_material(path):
    """Parse a DAMASK material.yaml input file.

    Parameters
    ----------
    path : str or Path
        Path to the DAMASK material.yaml file.

    Returns
    -------
    material_data : dict
        Parsed data from the DAMASK material.yaml file. Keys are:
            phases : dict
                The "phase" dict contained within the material file.
            homog_schemes : dict
                The "homogenization" dict contained within the material file.
            volume_element : dict
                Dict representing the volume element. The distribution of materials
                across the elements (i.e. keys `element_material_idx` and `grid_size`)
                are not included, since this information is not contained in the
                material file. With keys:
                    constituent_material_idx : ndarray of shape (N,) of int
                        Determines the material to which each constituent belongs, where N
                        is the number of constituents.
                    constituent_material_fraction: ndarray of shape (N,) of float
                        The fraction that each constituent occupies within its respective
                        material, where N is the number of constituents.
                    constituent_phase_label : ndarray of shape (N,) of str
                        Determines the phase label of each constituent, where N is the
                        number of constituents.
                    constituent_orientation_idx : ndarray of shape (N,) of int
                        Determines the orientation (as an index into `orientations`)
                        associated with each constituent, where N is the number of
                        constituents.
                    material_homog : ndarray of shape (M,) of str
                        Determines the homogenization scheme (from a list of available
                        homogenization schemes defined elsewhere) to which each material
                        belongs, where M is the number of materials.
                    orientations : dict
                        Dict containing the following keys:
                            type : str
                                Value is "quat".
                            quaternions : ndarray of shape (R, 4) of float
                                Array of R row four-vectors of unit quaternions.

    """

    yaml = YAML(typ='safe')
    material_dat = yaml.load(Path(path))

    material_homog = []
    const_material_idx = []
    const_material_fraction = []
    const_phase_label = []
    const_orientation_idx = []
    orientations = {
        'type': 'quat',
        'quaternions': [],
    }

    for mat_idx, material in enumerate(material_dat['microstructure']):
        material_homog.append(material['homogenization'])
        for const in material['constituents']:
            const_material_idx.append(mat_idx)
            const_material_fraction.append(const['fraction'])
            const_phase_label.append(const['phase'])
            orientations['quaternions'].append(const['orientation'])
            const_orientation_idx.append(len(const_orientation_idx))

    vol_elem = {
        'constituent_material_idx': const_material_idx,
        'constituent_material_fraction': const_material_fraction,
        'constituent_phase_label': const_phase_label,
        'constituent_orientation_idx': const_orientation_idx,
        'material_homog': material_homog,
        'orientations': orientations,
    }
    material_data = {
        'volume_element': vol_elem,
        'phases': material_dat['phase'],
        'homog_schemes': material_dat['homogenization'],
    }
    material_data['volume_element'] = validate_volume_element(**material_data)

    return material_data