• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mkofler96 / DeepSDFStruct / 18166301994

01 Oct 2025 02:55PM UTC coverage: 73.652% (+1.7%) from 71.932%
18166301994

push

github

mkofler96
removed deep sdf utils

235 of 321 branches covered (73.21%)

Branch coverage included in aggregate %.

2060 of 2795 relevant lines covered (73.7%)

0.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.65
DeepSDFStruct/optimization.py
1
import torchfem.materials
1✔
2
import torchfem.solid
1✔
3
from torchfem.elements import Hexa1, Hexa2, Tetra1, Tetra2
1✔
4
import torch
1✔
5
import numpy as np
1✔
6
from mmapy import mmasub
1✔
7
import pyvista
1✔
8
import logging
1✔
9
import DeepSDFStruct
1✔
10

11

12
logger = logging.getLogger(DeepSDFStruct.__name__)
1✔
13

14

15
def get_mesh_from_torchfem(Solid: torchfem.Solid) -> pyvista.UnstructuredGrid:
1✔
16
    if not isinstance(Solid, torchfem.Solid):
1✔
17
        raise NotImplementedError("Currently only solid mesh is supported.")
×
18
    # VTK cell types
19
    if isinstance(Solid.etype, Tetra1):
1✔
20
        cell_types = Solid.n_elem * [pyvista.CellType.TETRA]
1✔
21
    elif isinstance(Solid.etype, Tetra2):
×
22
        cell_types = Solid.n_elem * [pyvista.CellType.QUADRATIC_TETRA]
×
23
    elif isinstance(Solid.etype, Hexa1):
×
24
        cell_types = Solid.n_elem * [pyvista.CellType.HEXAHEDRON]
×
25
    elif isinstance(Solid.etype, Hexa2):
×
26
        cell_types = Solid.n_elem * [pyvista.CellType.QUADRATIC_HEXAHEDRON]
×
27

28
    # VTK element list
29
    el = len(Solid.elements[0]) * torch.ones(Solid.n_elem, dtype=Solid.elements.dtype)
1✔
30
    elements = torch.cat([el[:, None], Solid.elements], dim=1).view(-1).tolist()
1✔
31

32
    # Deformed node positions
33
    pos = Solid.nodes
1✔
34

35
    # Create unstructured mesh
36
    mesh = pyvista.UnstructuredGrid(elements, cell_types, pos.tolist())
1✔
37
    return mesh
1✔
38

39

40
def tet_signed_vol(vertices, tets):
1✔
41
    v0 = vertices[tets[:, 0]]
1✔
42
    v1 = vertices[tets[:, 1]]
1✔
43
    v2 = vertices[tets[:, 2]]
1✔
44
    v3 = vertices[tets[:, 3]]
1✔
45
    vols = torch.einsum("ij,ij->i", torch.cross(v1 - v0, v2 - v0, dim=1), v3 - v0) / 6.0
1✔
46
    return vols
1✔
47

48

49
class MMA:
1✔
50
    def __init__(self, parameters, bounds, max_step=0.1):
1✔
51
        self.max_step = max_step
1✔
52
        self.bounds = np.array(bounds)
1✔
53
        self.parameters = parameters
1✔
54
        self.m = 1
1✔
55
        self.n = len(parameters)
1✔
56
        self.x = parameters.detach().cpu().numpy()
1✔
57
        self.xold1 = parameters.detach().cpu().numpy()
1✔
58
        self.xold2 = parameters.detach().cpu().numpy()
1✔
59
        self.low = []
1✔
60
        self.upp = []
1✔
61
        self.a0_MMA = 1
1✔
62
        self.a_MMA = np.zeros((self.m, 1))
1✔
63
        self.c_MMA = 10000 * np.ones((self.m, 1))
1✔
64
        self.d_MMA = np.zeros((self.m, 1))
1✔
65

66
        self.loop = 0
1✔
67
        self.ch = 1.0
1✔
68
        self.F0 = None
1✔
69

70
    def step(self, F, dF, G, dG):
1✔
71
        """
72
        performs an optimizer step
73
        """
74
        F_np = F.detach().cpu().numpy().reshape(-1, 1)
1✔
75
        dFdx_np = dF.detach().cpu().numpy()
1✔
76
        G_np = G.detach().cpu().numpy().reshape(-1, 1)
1✔
77
        dGdx_np = dG.detach().cpu().numpy().reshape(1, -1)
1✔
78
        if self.loop == 0:
1✔
79
            self.F0 = F_np
1✔
80
        F_np = F_np / self.F0
1✔
81
        dFdx_np = dFdx_np / self.F0
1✔
82

83
        xmin = np.maximum(self.x - self.max_step, self.bounds[:, 0].reshape(-1, 1))
1✔
84
        xmax = np.minimum(self.x + self.max_step, self.bounds[:, 1].reshape(-1, 1))
1✔
85
        move = 0.1
1✔
86
        self.loop = self.loop + 1
1✔
87
        xmma, ymma, zmma, lam, xsi, eta, muMMA, zet, s, low, upp = mmasub(
1✔
88
            self.m,
89
            self.n,
90
            self.loop,
91
            self.x,
92
            xmin,
93
            xmax,
94
            self.xold1,
95
            self.xold2,
96
            F_np,
97
            dFdx_np,
98
            G_np,
99
            dGdx_np,
100
            self.low,
101
            self.upp,
102
            self.a0_MMA,
103
            self.a_MMA,
104
            self.c_MMA,
105
            self.d_MMA,
106
        )
107

108
        self.xold2 = self.xold1.copy()
1✔
109
        self.xold1 = self.x.copy()
1✔
110
        self.x = xmma
1✔
111
        self.upp = upp
1✔
112
        self.low = low
1✔
113

114
        ch = np.abs(np.mean(self.x.T - self.xold1.T) / np.mean(self.x.T))
1✔
115
        with torch.no_grad():
1✔
116
            self.parameters.copy_(
1✔
117
                torch.tensor(
118
                    xmma, dtype=self.parameters.dtype, device=self.parameters.device
119
                )
120
            )
121
        logger.info(
1✔
122
            "It.: {0:4} | C.: {1:1.3e} | Constr.:  {2:1.3e} | ch.: {3:1.3e}".format(
123
                self.loop, F_np[0][0], G_np[0][0], ch
124
            )
125
        )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc