Skip to content

fdm

FDMMixin

Bases: OverrideResolveMixin

Adds the Force Density Method (FDM) form-finding method to a data class.

Source code in src/torch_structure/mixins/fdm.py
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class FDMMixin(OverrideResolveMixin):
    """Adds the Force Density Method (FDM) form-finding method to a data class."""

    def fdm(
        self,
        inplace: bool=False,
        coords=None,
        load=None,
        support=None,
        edge_index=None,
        force_density=None,
        use_batching=False,
        solve_only_z=False,
        C=None,
        coords_out=None,
        force_out=None,
    ):
        """
        Applies the Force Density Method (FDM) to this structure and updates `coords`
        and `force`.

        See [`torch_structure.formfinding.fdm`](../formfinding/fdm.md).
        """
        batch = getattr(self, "batch", None)

        # Node inputs
        coords = self._resolve_override("coords", coords)
        load = self._resolve_override("load", load)
        support = self._resolve_override("support", support)

        # Edge inputs
        edge_mask = self.directed_mask.view(-1)
        edge_index = self._resolve_override("directed_edge_index", edge_index)
        force_density = self._resolve_override("force_density", force_density, mask=edge_mask)

        # Output keys
        coords_key = "coords" if coords_out is None else coords_out
        force_key = "force" if force_out is None else force_out

        # FDM computation
        new_coords, new_directed_force = fdm(
            coords,
            load,
            support,
            edge_index,
            force_density,
            batch=batch,
            use_batching=use_batching,
            directed=True,
            solve_only_z=solve_only_z,
            C=C,
        )
        new_force = self.edge_attr_to_undirected(new_directed_force, edge_mask)

        # Update data object
        new_data = self if inplace else self.clone()
        new_data[coords_key] = new_coords
        new_data[force_key] = new_force

        if not inplace:
            return new_data

fdm(inplace=False, coords=None, load=None, support=None, edge_index=None, force_density=None, use_batching=False, solve_only_z=False, C=None, coords_out=None, force_out=None)

Applies the Force Density Method (FDM) to this structure and updates coords and force.

See torch_structure.formfinding.fdm.

Source code in src/torch_structure/mixins/fdm.py
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def fdm(
    self,
    inplace: bool=False,
    coords=None,
    load=None,
    support=None,
    edge_index=None,
    force_density=None,
    use_batching=False,
    solve_only_z=False,
    C=None,
    coords_out=None,
    force_out=None,
):
    """
    Applies the Force Density Method (FDM) to this structure and updates `coords`
    and `force`.

    See [`torch_structure.formfinding.fdm`](../formfinding/fdm.md).
    """
    batch = getattr(self, "batch", None)

    # Node inputs
    coords = self._resolve_override("coords", coords)
    load = self._resolve_override("load", load)
    support = self._resolve_override("support", support)

    # Edge inputs
    edge_mask = self.directed_mask.view(-1)
    edge_index = self._resolve_override("directed_edge_index", edge_index)
    force_density = self._resolve_override("force_density", force_density, mask=edge_mask)

    # Output keys
    coords_key = "coords" if coords_out is None else coords_out
    force_key = "force" if force_out is None else force_out

    # FDM computation
    new_coords, new_directed_force = fdm(
        coords,
        load,
        support,
        edge_index,
        force_density,
        batch=batch,
        use_batching=use_batching,
        directed=True,
        solve_only_z=solve_only_z,
        C=C,
    )
    new_force = self.edge_attr_to_undirected(new_directed_force, edge_mask)

    # Update data object
    new_data = self if inplace else self.clone()
    new_data[coords_key] = new_coords
    new_data[force_key] = new_force

    if not inplace:
        return new_data