예제 #1
0
def create_square_element(mesh: Mesh, finite_element_field: Field,
                          node_coordinate_set):
    """
    Create a single square 2-D finite element using the supplied
    finite element field and sequence of 4 n-D node coordinates.

    :param mesh: The Zinc Mesh to create elements in.
    :param finite_element_field:  Zinc FieldFiniteElement to interpolate on element.
    :param node_coordinate_set: Sequence of 4 coordinates each with as many components as finite element field.
    :return: None
    """
    assert mesh.getDimension() == 2
    assert finite_element_field.castFiniteElement().isValid()
    assert len(node_coordinate_set) == 4
    fieldmodule = finite_element_field.getFieldmodule()
    nodeset = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES)
    node_template = nodeset.createNodetemplate()
    node_template.defineField(finite_element_field)
    element_template = mesh.createElementtemplate()
    element_template.setElementShapeType(Element.SHAPE_TYPE_SQUARE)
    linear_basis = fieldmodule.createElementbasis(
        2, Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE)
    eft = mesh.createElementfieldtemplate(linear_basis)
    element_template.defineField(finite_element_field, -1, eft)
    field_cache = fieldmodule.createFieldcache()
    with ChangeManager(fieldmodule):
        node_identifiers = []
        for node_coordinate in node_coordinate_set:
            node = nodeset.createNode(-1, node_template)
            node_identifiers.append(node.getIdentifier())
            field_cache.setNode(node)
            finite_element_field.assignReal(field_cache, node_coordinate)
        element = mesh.createElement(-1, element_template)
        element.setNodesByIdentifier(eft, node_identifiers)
    fieldmodule.defineAllFaces()
예제 #2
0
def create_fields_transformations(coordinates: Field,
                                  rotation_angles=None,
                                  scale_value=1.0,
                                  translation_offsets=None):
    """
    Create constant fields for rotation, scale and translation containing the supplied
    values, plus the transformed coordinates applying them in the supplied order.
    :param coordinates: The coordinate field to scale, 3 components.
    :param rotation_angles: List of euler angles, length = number of components.
     See create_field_euler_angles_rotation_matrix.
    :param scale_value: Scalar to multiply all components of coordinates.
    :param translation_offsets: List of offsets, length = number of components.
    :return: 4 fields: transformedCoordinates, rotation, scale, translation
    """
    if rotation_angles is None:
        rotation_angles = [0.0, 0.0, 0.0]
    if translation_offsets is None:
        translation_offsets = [0.0, 0.0, 0.0]
    components_count = coordinates.getNumberOfComponents()
    assert (components_count == 3) and (len(rotation_angles) == components_count) and isinstance(scale_value, float) \
        and (len(translation_offsets) == components_count), "createTransformationFields.  Invalid arguments"
    fieldmodule = coordinates.getFieldmodule()
    with ChangeManager(fieldmodule):
        # scale, translate and rotate model, in that order
        rotation = fieldmodule.createFieldConstant(rotation_angles)
        scale = fieldmodule.createFieldConstant(scale_value)
        translation = fieldmodule.createFieldConstant(translation_offsets)
        rotation_matrix = create_field_euler_angles_rotation_matrix(
            fieldmodule, rotation)
        rotated_coordinates = fieldmodule.createFieldMatrixMultiply(
            components_count, rotation_matrix, coordinates)
        transformed_coordinates = rotated_coordinates * scale + translation
        assert transformed_coordinates.isValid()
    return transformed_coordinates, rotation, scale, translation
예제 #3
0
def createFieldsTransformations(coordinates: Field, rotation_angles=None, scale_value=1.0, \
    translation_offsets=None, translation_scale_factor=1.0):
    """
    Create constant fields for rotation, scale and translation containing the supplied
    values, plus the transformed coordinates applying them in the supplied order.
    :param coordinates: The coordinate field to scale, 3 components.
    :param rotation_angles: List of euler angles, length = number of components.
     See create_field_euler_angles_rotation_matrix.
    :param scale_value: Scalar to multiply all components of coordinates.
    :param translation_offsets: List of offsets, length = number of components.
    :param translation_scale_factor: Scaling to multiply translation by so it's magnitude can remain
    close to other parameters for rotation (radians) and scale (assumed close to unit).
    :return: 4 fields: transformedCoordinates, rotation, scale, translation
    """
    if rotation_angles is None:
        rotation_angles = [0.0, 0.0, 0.0]
    if translation_offsets is None:
        translation_offsets = [0.0, 0.0, 0.0]
    components_count = coordinates.getNumberOfComponents()
    assert (components_count == 3) and (len(rotation_angles) == components_count) and isinstance(scale_value, float) \
        and (len(translation_offsets) == components_count), "createFieldsTransformations.  Invalid arguments"
    fieldmodule = coordinates.getFieldmodule()
    with ChangeManager(fieldmodule):
        # Rotate, scale, and translate model, in that order
        rotation = fieldmodule.createFieldConstant(rotation_angles)
        scale = fieldmodule.createFieldConstant(scale_value)
        translation = fieldmodule.createFieldConstant(translation_offsets)
        rotation_matrix = create_field_euler_angles_rotation_matrix(
            fieldmodule, rotation)
        rotated_coordinates = fieldmodule.createFieldMatrixMultiply(
            components_count, rotation_matrix, coordinates)
        transformed_coordinates = rotated_coordinates*scale + (translation if (translation_scale_factor == 1.0) else \
            translation*fieldmodule.createFieldConstant([ translation_scale_factor ]*components_count))
        assert transformed_coordinates.isValid()
    return transformed_coordinates, rotation, scale, translation
예제 #4
0
def create_field_mesh_integral(coordinates: Field, mesh: Mesh, number_of_points=3):
    """
    Create a field integrating the coordinates to give scalar volume/area/length over
    the mesh, depending on its dimension.
    :param coordinates:
    :param mesh:
    :param number_of_points: Number of Gauss points.
    :return: Field giving volume of coordinates field over mesh via Gaussian quadrature.
    """
    fieldmodule = coordinates.getFieldmodule()
    with ChangeManager(fieldmodule):
        mesh_integral_field = fieldmodule.createFieldMeshIntegral(fieldmodule.createFieldConstant(1.0),
                                                                  coordinates, mesh)
        mesh_integral_field.setNumbersOfPoints(number_of_points)
    return mesh_integral_field
예제 #5
0
def getNodesetConditionalSize(nodeset: Nodeset, conditionalField: Field):
    """
    :return: Number of objects in nodeset for which conditionalField is True.
    """
    assert conditionalField.getNumberOfComponents() == 1
    fieldmodule = conditionalField.getFieldmodule()
    fieldcache = fieldmodule.createFieldcache()
    nodeiterator = nodeset.createNodeiterator()
    size = 0
    node = nodeiterator.next()
    while node.isValid():
        fieldcache.setNode(node)
        result, value = conditionalField.evaluateReal(fieldcache, 1)
        if value != 0.0:
            size += 1
        node = nodeiterator.next()
    return size
예제 #6
0
def create_field_finite_element_clone(source_field: Field,
                                      name: str,
                                      managed=False) -> FieldFiniteElement:
    """
    Copy an existing Finite Element Field to a new field of supplied name.
    Note: does not handle time-varying parameters.
    New field is not managed by default.
    :param source_field: Zinc finite element field to copy.
    :param name: The name of the new field, asserts that no field of that name exists.
    :param managed: Managed state of field created here.
    :return: New identically defined field with supplied name.
    """
    assert source_field.castFiniteElement().isValid(), \
        "opencmiss.utils.zinc.field.createFieldFiniteElementClone.  Not a Zinc finite element field"
    fieldmodule = source_field.getFieldmodule()
    field = fieldmodule.findFieldByName(name)
    assert not field.isValid(
    ), "opencmiss.utils.zinc.field.createFieldFiniteElementClone.  Target field name is in use"
    with ChangeManager(fieldmodule):
        # Zinc needs a function to do this efficiently; currently serialise to string, replace field name and reload!
        source_name = source_field.getName()
        region = fieldmodule.getRegion()
        sir = region.createStreaminformationRegion()
        srm = sir.createStreamresourceMemory()
        sir.setFieldNames([source_name])
        region.write(sir)
        result, buffer = srm.getBuffer()
        # small risk of modifying other text here:
        source_bytes = bytes(") " + source_name + ",", "utf-8")
        target_bytes = bytes(") " + name + ",", "utf-8")
        buffer = buffer.replace(source_bytes, target_bytes)
        sir = region.createStreaminformationRegion()
        sir.createStreamresourceMemoryBuffer(buffer)
        result = region.read(sir)
        assert result == RESULT_OK
    # note currently must have called endChange before field can be found
    field = fieldmodule.findFieldByName(name).castFiniteElement()
    field.setManaged(managed)
    assert field.isValid()
    return field
예제 #7
0
def create_triangle_elements(mesh: Mesh, finite_element_field: Field,
                             element_node_set):
    """
    Create a linear triangular element for every set of 3 local nodes in element_node_set.

    :param mesh: The Zinc Mesh to create elements in.
    :param finite_element_field: Zinc FieldFiniteElement to interpolate from nodes.
    :param element_node_set: Sequence of 3 node identifiers for each element.
    :return: None
    """
    assert mesh.getDimension() == 2
    assert finite_element_field.castFiniteElement().isValid()
    fieldmodule = finite_element_field.getFieldmodule()
    element_template = mesh.createElementtemplate()
    element_template.setElementShapeType(Element.SHAPE_TYPE_TRIANGLE)
    linear_basis = fieldmodule.createElementbasis(
        2, Elementbasis.FUNCTION_TYPE_LINEAR_SIMPLEX)
    eft = mesh.createElementfieldtemplate(linear_basis)
    element_template.defineField(finite_element_field, -1, eft)
    with ChangeManager(fieldmodule):
        for element_nodes in element_node_set:
            element = mesh.createElement(-1, element_template)
            element.setNodesByIdentifier(eft, element_nodes)
    fieldmodule.defineAllFaces()
예제 #8
0
def transform_coordinates(field: Field,
                          rotation_scale,
                          offset,
                          time=0.0) -> bool:
    """
    Transform finite element field coordinates by matrix and offset, handling nodal derivatives and versions.
    Limited to nodal parameters, rectangular cartesian coordinates
    :param field: the coordinate field to transform
    :param rotation_scale: square transformation matrix 2-D array with as many rows and columns as field components.
    :param offset: coordinates offset.
    :param time: time value.
    :return: True on success, otherwise false.
    """
    ncomp = field.getNumberOfComponents()
    if (ncomp != 2) and (ncomp != 3):
        print(
            'zinc.transformCoordinates: field has invalid number of components'
        )
        return False
    if (len(rotation_scale) != ncomp) or (len(offset) != ncomp):
        print(
            'zinc.transformCoordinates: invalid matrix number of columns or offset size'
        )
        return False
    for matRow in rotation_scale:
        if len(matRow) != ncomp:
            print(
                'zinc.transformCoordinates: invalid matrix number of columns')
            return False
    if field.getCoordinateSystemType(
    ) != Field.COORDINATE_SYSTEM_TYPE_RECTANGULAR_CARTESIAN:
        print('zinc.transformCoordinates: field is not rectangular cartesian')
        return False
    fe_field = field.castFiniteElement()
    if not fe_field.isValid():
        print(
            'zinc.transformCoordinates: field is not finite element field type'
        )
        return False
    success = True
    fm = field.getFieldmodule()
    fm.beginChange()
    cache = fm.createFieldcache()
    cache.setTime(time)
    nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES)
    node_template = nodes.createNodetemplate()
    node_iter = nodes.createNodeiterator()
    node = node_iter.next()
    while node.isValid():
        node_template.defineFieldFromNode(fe_field, node)
        cache.setNode(node)
        for derivative in [
                Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1,
                Node.VALUE_LABEL_D_DS2, Node.VALUE_LABEL_D2_DS1DS2,
                Node.VALUE_LABEL_D_DS3, Node.VALUE_LABEL_D2_DS1DS3,
                Node.VALUE_LABEL_D2_DS2DS3, Node.VALUE_LABEL_D3_DS1DS2DS3
        ]:
            versions = node_template.getValueNumberOfVersions(
                fe_field, -1, derivative)
            for v in range(versions):
                result, values = fe_field.getNodeParameters(
                    cache, -1, derivative, v + 1, ncomp)
                if result != RESULT_OK:
                    success = False
                else:
                    new_values = vectorops.matrixvectormult(
                        rotation_scale, values)
                    if derivative == Node.VALUE_LABEL_VALUE:
                        new_values = vectorops.add(new_values, offset)
                    result = fe_field.setNodeParameters(
                        cache, -1, derivative, v + 1, new_values)
                    if result != RESULT_OK:
                        success = False
        node = node_iter.next()
    fm.endChange()
    if not success:
        print('zinc.transformCoordinates: failed to get/set some values')
    return success