Skip to content

Commit

Permalink
merge all numba compilable functions into a single one
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmanuelMess committed Aug 7, 2024
1 parent 364510f commit ac979cd
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 26 deletions.
15 changes: 5 additions & 10 deletions code/simulator/Simulation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from timeit import default_timer as timer
from typing import Callable, List

import numba
import numpy as np

from simulator.SimulationFunctions import SimulationFunctions
Expand Down Expand Up @@ -43,14 +44,11 @@ def acceleration(x, v) -> np.ndarray:
particle.aApplied = self.force(self.t)[particle.index].copy()
particle.a = particle.aApplied.copy()

f, g, J, C, dC = SimulationFunctions.matrices(self.ks, self.kd, self.particles, self.constraints)
dq, Q, C, dC, W, J, dJ = SimulationFunctions.matrices(self.particles, self.constraints)

# Solve for λ in g λ = -f, minimizing ||g λ + f||, where f = dJ dq + J W Q + ks C + kd dC and g = J W J.T
l, _, _, _ = np.linalg.lstsq(g, -f, rcond=1e-8)
l, aConstraint = SimulationFunctions.precompiledMinimizeAndForceCalculation(self.ks, self.kd, dq, Q, C, dC, W, J, dJ )
self.error = f"constraint {np.linalg.norm(self.ks * C + self.kd * dC)} solve {np.linalg.norm(g * l + f)}"

aConstraint = SimulationFunctions.precompiledForceCalculation(J, l)

return aConstraint[particle.index]

grapher.draw(acceleration, self.constraints, self.particles)
Expand All @@ -77,14 +75,11 @@ def update(self, timestep: np.float64) -> None:
particle.aApplied = self.force(self.t)[particle.index].copy()
particle.a = particle.aApplied.copy()

f, g, J, C, dC = SimulationFunctions.matrices(self.ks, self.kd, self.particles, self.constraints)
dq, Q, C, dC, W, J, dJ = SimulationFunctions.matrices(self.particles, self.constraints)

# Solve for λ in g λ = -f, minimizing ||g λ + f||, where f = dJ dq + J W Q + ks C + kd dC and g = J W J.T
l, _, _, _ = np.linalg.lstsq(g, -f, rcond=1e-8)
aConstraint, l, f, g = SimulationFunctions.precompiledMinimizeAndForceCalculation(self.ks, self.kd, dq, Q, C, dC, W, J, dJ)
self.error = f"constraint {np.linalg.norm(self.ks * C + self.kd * dC)} solve {np.linalg.norm(g * l + f)}"

aConstraint = SimulationFunctions.precompiledForceCalculation(J, l)

for particle in self.particles:
if particle.static:
continue
Expand Down
27 changes: 12 additions & 15 deletions code/simulator/SimulationFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,24 @@
class SimulationFunctions:
@staticmethod
@numba.jit(nopython=True, parallel=True, fastmath=True)
def precompiledForceCalculation(J: np.ndarray, l: np.ndarray) -> np.ndarray:
def precompiledMinimizeAndForceCalculation(ks: np.float64, kd: np.float64, dq: np.ndarray, Q: np.ndarray,
C: np.ndarray, dC: np.ndarray, W: np.ndarray, J: np.ndarray,
dJ: np.ndarray) \
-> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
"""
Resulting force for the particles (see mathematical model)
"""
return (J.T @ l).reshape((-1, 2))

@staticmethod
@numba.jit(nopython=True, parallel=True, fastmath=True)
def precompiledMatricesComputation(ks: np.float64, kd: np.float64, dq: np.ndarray, Q: np.ndarray, C: np.ndarray,
dC: np.ndarray, W: np.ndarray, J: np.ndarray, dJ: np.ndarray)\
-> Tuple[np.ndarray, np.ndarray]:
f = dJ @ dq + J @ W @ Q + ks * C + kd * dC
g = J @ W @ J.T @ (np.eye(J.shape[0]) * 3)
return f, g
# Solve for λ in g λ = -f, minimizing ||g λ + f||, where f = dJ dq + J W Q + ks C + kd dC and g = J W J.T
l, _, _, _ = np.linalg.lstsq(g, -f, rcond=1e-8)
force = (J.T @ l).reshape((-1, 2))
return force, l, f, g

@staticmethod
def matrices(ks: np.float64, kd: np.float64, particles: List[Particle],
constraints: List[Constraint], weight: np.float64 = np.float64(1))\
-> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray]: # pylint: disable=too-many-locals
def matrices(particles: List[Particle], constraints: List[Constraint], weight: np.float64 = np.float64(1))\
-> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray,
np.ndarray]: # pylint: disable=too-many-locals
"""
Compute the matrices to run the lagrangian multipliers (see mathematical model)
"""
Expand Down Expand Up @@ -68,9 +67,7 @@ def matrices(ks: np.float64, kd: np.float64, particles: List[Particle],
J = J.reshape((m, n * d))
dJ = dJ.reshape((m, n * d))

f, g = SimulationFunctions.precompiledMatricesComputation(ks, kd, dq, Q, C, dC, W, J, dJ)

return f, g, J, C, dC
return dq, Q, C, dC, W, J, dJ

@staticmethod
def x(p: np.ndarray, v: np.ndarray, a: np.ndarray, t: np.float64) -> np.ndarray:
Expand Down
3 changes: 2 additions & 1 deletion code/simulator/UI.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import numpy as np
from typing import List

from simulator import Constants
from simulator.Constants import HEIGHT, WIDTH
from simulator.drawers.Drawable import Drawable

Expand All @@ -25,7 +26,7 @@ def __init__(self, drawables: List[Drawable], timestep: np.float64) -> None:
drawable.initDrawer()

def showDrawables(self) -> None:
allText = []
allText = [f"UI target FPS {Constants.FPS}"]

for text in self.drawables:
allText += text.getDrawer().getText().split("\n")
Expand Down

0 comments on commit ac979cd

Please sign in to comment.