src.acoustools.BEM.Force
1from acoustools.BEM import BEM_forward_model_second_derivative_mixed, BEM_forward_model_second_derivative_unmixed, BEM_forward_model_grad, compute_E, get_cache_or_compute_H, get_cache_or_compute_H_gradients 2from acoustools.Utilities import TRANSDUCERS 3from acoustools.Force import force_mesh 4from acoustools.Mesh import load_scatterer, get_centres_as_points, get_normals_as_points, get_areas, scale_to_diameter,\ 5 centre_scatterer, translate, merge_scatterers, get_edge_data, get_centre_of_mass_as_points, get_volume 6from acoustools.Gorkov import get_gorkov_constants 7 8 9import acoustools.Constants as c 10 11from torch import Tensor 12import torch 13 14from vedo import Mesh 15 16def BEM_compute_force(activations:Tensor, points:Tensor,board:Tensor|None=None,return_components:bool=False, V=c.V, scatterer:Mesh=None, 17 H:Tensor=None, path:str="Media") -> Tensor | tuple[Tensor, Tensor, Tensor]: 18 ''' 19 Returns the force on a particle using the analytical derivative of the Gor'kov potential and BEM\n 20 :param activations: Transducer hologram 21 :param points: Points to propagate to 22 :param board: Transducers to use, if `None` uses `acoustools.Utilities.TRANSDUCERS` 23 :param return_components: If true returns force as one tensor otherwise returns Fx, Fy, Fz 24 :param V: Particle volume 25 :param scatterer: Scatterer to use 26 :param H: H to use, will load/compute if None 27 :param path: Path to folder containing BEMCache 28 :return: force 29 ''' 30 31 #Bk.2 Pg.319 32 33 if board is None: 34 board = TRANSDUCERS 35 36 F = compute_E(scatterer=scatterer,points=points,board=board,H=H, path=path) 37 Fx, Fy, Fz = BEM_forward_model_grad(points,transducers=board,scatterer=scatterer,H=H, path=path) 38 Fxx, Fyy, Fzz = BEM_forward_model_second_derivative_unmixed(points,transducers=board,scatterer=scatterer,H=H, path=path) 39 Fxy, Fxz, Fyz = BEM_forward_model_second_derivative_mixed(points,transducers=board,scatterer=scatterer,H=H, path=path) 40 41 p = (F@activations) 42 Px = (Fx@activations) 43 Py = (Fy@activations) 44 Pz = (Fz@activations) 45 Pxx = (Fxx@activations) 46 Pyy = (Fyy@activations) 47 Pzz = (Fzz@activations) 48 Pxy = (Fxy@activations) 49 Pxz = (Fxz@activations) 50 Pyz = (Fyz@activations) 51 52 53 grad_p = torch.stack([Px,Py,Pz]) 54 grad_px = torch.stack([Pxx,Pxy,Pxz]) 55 grad_py = torch.stack([Pxy,Pyy,Pyz]) 56 grad_pz = torch.stack([Pxz,Pyz,Pzz]) 57 58 59 p_term = p*grad_p.conj() + p.conj()*grad_p 60 61 px_term = Px*grad_px.conj() + Px.conj()*grad_px 62 py_term = Py*grad_py.conj() + Py.conj()*grad_py 63 pz_term = Pz*grad_pz.conj() + Pz.conj()*grad_pz 64 65 K1, K2 = get_gorkov_constants(V=V) 66 67 grad_U = K1 * p_term - K2 * (px_term + py_term + pz_term) 68 force = -1*(grad_U).squeeze().real 69 70 if return_components: 71 return force[0], force[1], force[2] 72 else: 73 return force 74 75 76def force_mesh_surface(activations:Tensor, scatterer:Mesh=None, board:Tensor|None=None, 77 return_components:bool=False, sum_elements = True, return_momentum = False, 78 H:Tensor=None, diameter=c.wavelength*2, 79 path:str="Media", surface_path:str = "/Sphere-solidworks-lam2.stl", 80 surface:Mesh|None=None, use_cache_H:bool=True, E=None, Ex=None, Ey=None, Ez=None, use_momentum=True) -> Tensor | tuple[Tensor, Tensor, Tensor]: 81 82 if surface is None: 83 surface = load_scatterer(path+surface_path) 84 scale_to_diameter(surface,diameter, reset=False, origin=True) 85 centre_scatterer(surface) 86 object_com = get_centre_of_mass_as_points(scatterer) 87 translate(surface, dx = object_com[:,0].item(), dy=object_com[:,1].item(), dz = object_com[:,2].item()) 88 89 90 points = get_centres_as_points(surface) 91 norms = get_normals_as_points(surface) 92 areas = get_areas(surface) 93 94 if E is None: 95 E,F,G,H = compute_E(scatterer, points, board,path=path, H=H, return_components=True, use_cache_H=use_cache_H) 96 97 force, momentum = force_mesh(activations, points,norms,areas,board=board,F=E, use_momentum=use_momentum, 98 grad_function=BEM_forward_model_grad, grad_function_args={'scatterer':scatterer, 99 'H':H, 100 'path':path}, return_components=True, 101 Ax = Ex, Ay=Ey, Az=Ez) 102 103 104 105 if sum_elements: force=torch.sum(force, dim=2) 106 107 if return_components: 108 if not return_momentum: 109 return (force[:,0]), (force[:,1]), (force[:,2]) 110 else: 111 return (force[:,0]), (force[:,1]), (force[:,2]), momentum 112 113 if return_momentum: return force, momentum 114 return force 115 116def force_mesh_surface_divergance(activations:Tensor, scatterer:Mesh=None, board:Tensor|None=None, 117 sum_elements = True, H:Tensor=None, diameter=c.wavelength*2, 118 path:str="Media", surface_path:str = "/Sphere-solidworks-lam2.stl", 119 surface:Mesh|None=None, use_cache_H:bool=True, force=None, norms=None) -> Tensor: 120 121 122 if surface is None: 123 surface = load_scatterer(path+surface_path) 124 scale_to_diameter(surface,diameter, reset=False, origin=True) 125 centre_scatterer(surface) 126 object_com = get_centre_of_mass_as_points(scatterer) 127 translate(surface, dx = object_com[:,0].item(), dy=object_com[:,1].item(), dz = object_com[:,2].item()) 128 129 if force is None: 130 force = force_mesh_surface(activations, scatterer, board, H=H, diameter=diameter, path=path, 131 surface_path=surface_path, surface=surface, use_cache_H=use_cache_H, sum_elements=False, use_momentum=True) 132 133 if norms is None: norms = get_normals_as_points(surface) 134 areas = get_areas(surface) 135 136 div = (torch.sum(norms * force, dim=1) * areas ) 137 138 if sum_elements: div = torch.sum(div, dim=1) 139 140 v = get_volume(surface) 141 142 return div / v 143 144 145def force_mesh_surface_curl(activations:Tensor, scatterer:Mesh=None, board:Tensor|None=None, 146 sum_elements = True, H:Tensor=None, diameter=c.wavelength*2, 147 path:str="Media", surface_path:str = "/Sphere-solidworks-lam2.stl", 148 surface:Mesh|None=None, use_cache_H:bool=True, magnitude = False, force=None) -> Tensor: 149 150 if force is None: force = force_mesh_surface(activations, scatterer, board, H=H, diameter=diameter, path=path, 151 surface_path=surface_path, surface=surface, use_cache_H=use_cache_H, sum_elements=False) 152 153 if surface is None: 154 surface = load_scatterer(path+surface_path) 155 scale_to_diameter(surface,diameter, reset=False, origin=True) 156 centre_scatterer(surface) 157 object_com = get_centre_of_mass_as_points(scatterer) 158 translate(surface, dx = object_com[:,0].item(), dy=object_com[:,1].item(), dz = object_com[:,2].item()) 159 160 norms = get_normals_as_points(surface).real 161 areas = get_areas(surface) 162 163 curl = torch.cross(force, norms, dim=1) * areas 164 165 if sum_elements: curl = torch.sum(curl, dim=2) 166 167 v = get_volume(surface) 168 169 curl = curl/v 170 171 if magnitude: return torch.norm(curl, dim=1) 172 173 return curl 174 175 176def get_force_mesh_along_axis(start:Tensor,end:Tensor, activations:Tensor, scatterers:list[Mesh], board:Tensor, mask:Tensor|None=None, steps:int=200, 177 path:str="Media",print_lines:bool=False, use_cache:bool=True, 178 Hs:Tensor|None = None, Hxs:Tensor|None=None, Hys:Tensor|None=None, Hzs:Tensor|None=None) -> tuple[list[Tensor],list[Tensor],list[Tensor]]: 179 ''' 180 Computes the force on a mesh at each point from `start` to `end` with number of samples = `steps` \n 181 :param start: The starting position 182 :param end: The ending position 183 :param activations: Transducer hologram 184 :param scatterers: First element is the mesh to move, rest is considered static reflectors 185 :param board: Transducers to use 186 :param mask: The mask to apply to filter force for only the mesh to move 187 :param steps: Number of steps to take from start to end 188 :param path: path to folder containing BEMCache/ 189 :param print_lines: if true prints messages detaling progress 190 :param use_cache: If true uses the cache system, otherwise computes H and does not save it 191 :param Hs: List of precomputed forward propagation matricies 192 :param Hxs: List of precomputed derivative of forward propagation matricies wrt x 193 :param Hys: List of precomputed derivative of forward propagation matricies wrt y 194 :param Hzs: List of precomputed derivative of forward propagation matricies wrt z 195 :return: list for each axis of the force at each position 196 ''' 197 # if Ax is None or Ay is None or Az is None: 198 # Ax, Ay, Az = grad_function(points=points, transducers=board, **grad_function_args) 199 direction = (end - start) / steps 200 201 translate(scatterers[0], start[0].item() - direction[0].item(), start[1].item() - direction[1].item(), start[2].item() - direction[2].item()) 202 scatterer = merge_scatterers(*scatterers) 203 204 points = get_centres_as_points(scatterer) 205 if mask is None: 206 mask = torch.ones(points.shape[2]).to(bool) 207 208 Fxs = [] 209 Fys = [] 210 Fzs = [] 211 212 for i in range(steps+1): 213 if print_lines: 214 print(i) 215 216 217 translate(scatterers[0], direction[0].item(), direction[1].item(), direction[2].item()) 218 scatterer = merge_scatterers(*scatterers) 219 220 points = get_centres_as_points(scatterer) 221 areas = get_areas(scatterer) 222 norms = get_normals_as_points(scatterer) 223 224 if Hs is None: 225 H = get_cache_or_compute_H(scatterer, board, path=path, print_lines=print_lines, use_cache_H=use_cache) 226 else: 227 H = Hs[i] 228 229 if Hxs is None or Hys is None or Hzs is None: 230 Hx, Hy, Hz = get_cache_or_compute_H_gradients(scatterer, board, path=path, print_lines=print_lines, use_cache_H_grad=use_cache) 231 else: 232 Hx = Hxs[i] 233 Hy = Hys[i] 234 Hz = Hzs[i] 235 236 237 force = force_mesh(activations, points, norms, areas, board, F=H, Ax=Hx, Ay=Hy, Az=Hz) 238 239 force = torch.sum(force[:,:,mask],dim=2).squeeze() 240 Fxs.append(force[0]) 241 Fys.append(force[1]) 242 Fzs.append(force[2]) 243 244 # print(i, force[0].item(), force[1].item(),force[2].item()) 245 return Fxs, Fys, Fzs
def
BEM_compute_force( activations: torch.Tensor, points: torch.Tensor, board: torch.Tensor | None = None, return_components: bool = False, V=4.188790204666667e-09, scatterer: vedo.mesh.Mesh = None, H: torch.Tensor = None, path: str = 'Media') -> torch.Tensor | tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
18def BEM_compute_force(activations:Tensor, points:Tensor,board:Tensor|None=None,return_components:bool=False, V=c.V, scatterer:Mesh=None, 19 H:Tensor=None, path:str="Media") -> Tensor | tuple[Tensor, Tensor, Tensor]: 20 ''' 21 Returns the force on a particle using the analytical derivative of the Gor'kov potential and BEM\n 22 :param activations: Transducer hologram 23 :param points: Points to propagate to 24 :param board: Transducers to use, if `None` uses `acoustools.Utilities.TRANSDUCERS` 25 :param return_components: If true returns force as one tensor otherwise returns Fx, Fy, Fz 26 :param V: Particle volume 27 :param scatterer: Scatterer to use 28 :param H: H to use, will load/compute if None 29 :param path: Path to folder containing BEMCache 30 :return: force 31 ''' 32 33 #Bk.2 Pg.319 34 35 if board is None: 36 board = TRANSDUCERS 37 38 F = compute_E(scatterer=scatterer,points=points,board=board,H=H, path=path) 39 Fx, Fy, Fz = BEM_forward_model_grad(points,transducers=board,scatterer=scatterer,H=H, path=path) 40 Fxx, Fyy, Fzz = BEM_forward_model_second_derivative_unmixed(points,transducers=board,scatterer=scatterer,H=H, path=path) 41 Fxy, Fxz, Fyz = BEM_forward_model_second_derivative_mixed(points,transducers=board,scatterer=scatterer,H=H, path=path) 42 43 p = (F@activations) 44 Px = (Fx@activations) 45 Py = (Fy@activations) 46 Pz = (Fz@activations) 47 Pxx = (Fxx@activations) 48 Pyy = (Fyy@activations) 49 Pzz = (Fzz@activations) 50 Pxy = (Fxy@activations) 51 Pxz = (Fxz@activations) 52 Pyz = (Fyz@activations) 53 54 55 grad_p = torch.stack([Px,Py,Pz]) 56 grad_px = torch.stack([Pxx,Pxy,Pxz]) 57 grad_py = torch.stack([Pxy,Pyy,Pyz]) 58 grad_pz = torch.stack([Pxz,Pyz,Pzz]) 59 60 61 p_term = p*grad_p.conj() + p.conj()*grad_p 62 63 px_term = Px*grad_px.conj() + Px.conj()*grad_px 64 py_term = Py*grad_py.conj() + Py.conj()*grad_py 65 pz_term = Pz*grad_pz.conj() + Pz.conj()*grad_pz 66 67 K1, K2 = get_gorkov_constants(V=V) 68 69 grad_U = K1 * p_term - K2 * (px_term + py_term + pz_term) 70 force = -1*(grad_U).squeeze().real 71 72 if return_components: 73 return force[0], force[1], force[2] 74 else: 75 return force
Returns the force on a particle using the analytical derivative of the Gor'kov potential and BEM
Parameters
- activations: Transducer hologram
- points: Points to propagate to
- board: Transducers to use, if
None
usesacoustools.Utilities.TRANSDUCERS
- return_components: If true returns force as one tensor otherwise returns Fx, Fy, Fz
- V: Particle volume
- scatterer: Scatterer to use
- H: H to use, will load/compute if None
- path: Path to folder containing BEMCache
Returns
force
def
force_mesh_surface( activations: torch.Tensor, scatterer: vedo.mesh.Mesh = None, board: torch.Tensor | None = None, return_components: bool = False, sum_elements=True, return_momentum=False, H: torch.Tensor = None, diameter=0.01715, path: str = 'Media', surface_path: str = '/Sphere-solidworks-lam2.stl', surface: vedo.mesh.Mesh | None = None, use_cache_H: bool = True, E=None, Ex=None, Ey=None, Ez=None, use_momentum=True) -> torch.Tensor | tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
78def force_mesh_surface(activations:Tensor, scatterer:Mesh=None, board:Tensor|None=None, 79 return_components:bool=False, sum_elements = True, return_momentum = False, 80 H:Tensor=None, diameter=c.wavelength*2, 81 path:str="Media", surface_path:str = "/Sphere-solidworks-lam2.stl", 82 surface:Mesh|None=None, use_cache_H:bool=True, E=None, Ex=None, Ey=None, Ez=None, use_momentum=True) -> Tensor | tuple[Tensor, Tensor, Tensor]: 83 84 if surface is None: 85 surface = load_scatterer(path+surface_path) 86 scale_to_diameter(surface,diameter, reset=False, origin=True) 87 centre_scatterer(surface) 88 object_com = get_centre_of_mass_as_points(scatterer) 89 translate(surface, dx = object_com[:,0].item(), dy=object_com[:,1].item(), dz = object_com[:,2].item()) 90 91 92 points = get_centres_as_points(surface) 93 norms = get_normals_as_points(surface) 94 areas = get_areas(surface) 95 96 if E is None: 97 E,F,G,H = compute_E(scatterer, points, board,path=path, H=H, return_components=True, use_cache_H=use_cache_H) 98 99 force, momentum = force_mesh(activations, points,norms,areas,board=board,F=E, use_momentum=use_momentum, 100 grad_function=BEM_forward_model_grad, grad_function_args={'scatterer':scatterer, 101 'H':H, 102 'path':path}, return_components=True, 103 Ax = Ex, Ay=Ey, Az=Ez) 104 105 106 107 if sum_elements: force=torch.sum(force, dim=2) 108 109 if return_components: 110 if not return_momentum: 111 return (force[:,0]), (force[:,1]), (force[:,2]) 112 else: 113 return (force[:,0]), (force[:,1]), (force[:,2]), momentum 114 115 if return_momentum: return force, momentum 116 return force
def
force_mesh_surface_divergance( activations: torch.Tensor, scatterer: vedo.mesh.Mesh = None, board: torch.Tensor | None = None, sum_elements=True, H: torch.Tensor = None, diameter=0.01715, path: str = 'Media', surface_path: str = '/Sphere-solidworks-lam2.stl', surface: vedo.mesh.Mesh | None = None, use_cache_H: bool = True, force=None, norms=None) -> torch.Tensor:
118def force_mesh_surface_divergance(activations:Tensor, scatterer:Mesh=None, board:Tensor|None=None, 119 sum_elements = True, H:Tensor=None, diameter=c.wavelength*2, 120 path:str="Media", surface_path:str = "/Sphere-solidworks-lam2.stl", 121 surface:Mesh|None=None, use_cache_H:bool=True, force=None, norms=None) -> Tensor: 122 123 124 if surface is None: 125 surface = load_scatterer(path+surface_path) 126 scale_to_diameter(surface,diameter, reset=False, origin=True) 127 centre_scatterer(surface) 128 object_com = get_centre_of_mass_as_points(scatterer) 129 translate(surface, dx = object_com[:,0].item(), dy=object_com[:,1].item(), dz = object_com[:,2].item()) 130 131 if force is None: 132 force = force_mesh_surface(activations, scatterer, board, H=H, diameter=diameter, path=path, 133 surface_path=surface_path, surface=surface, use_cache_H=use_cache_H, sum_elements=False, use_momentum=True) 134 135 if norms is None: norms = get_normals_as_points(surface) 136 areas = get_areas(surface) 137 138 div = (torch.sum(norms * force, dim=1) * areas ) 139 140 if sum_elements: div = torch.sum(div, dim=1) 141 142 v = get_volume(surface) 143 144 return div / v
def
force_mesh_surface_curl( activations: torch.Tensor, scatterer: vedo.mesh.Mesh = None, board: torch.Tensor | None = None, sum_elements=True, H: torch.Tensor = None, diameter=0.01715, path: str = 'Media', surface_path: str = '/Sphere-solidworks-lam2.stl', surface: vedo.mesh.Mesh | None = None, use_cache_H: bool = True, magnitude=False, force=None) -> torch.Tensor:
147def force_mesh_surface_curl(activations:Tensor, scatterer:Mesh=None, board:Tensor|None=None, 148 sum_elements = True, H:Tensor=None, diameter=c.wavelength*2, 149 path:str="Media", surface_path:str = "/Sphere-solidworks-lam2.stl", 150 surface:Mesh|None=None, use_cache_H:bool=True, magnitude = False, force=None) -> Tensor: 151 152 if force is None: force = force_mesh_surface(activations, scatterer, board, H=H, diameter=diameter, path=path, 153 surface_path=surface_path, surface=surface, use_cache_H=use_cache_H, sum_elements=False) 154 155 if surface is None: 156 surface = load_scatterer(path+surface_path) 157 scale_to_diameter(surface,diameter, reset=False, origin=True) 158 centre_scatterer(surface) 159 object_com = get_centre_of_mass_as_points(scatterer) 160 translate(surface, dx = object_com[:,0].item(), dy=object_com[:,1].item(), dz = object_com[:,2].item()) 161 162 norms = get_normals_as_points(surface).real 163 areas = get_areas(surface) 164 165 curl = torch.cross(force, norms, dim=1) * areas 166 167 if sum_elements: curl = torch.sum(curl, dim=2) 168 169 v = get_volume(surface) 170 171 curl = curl/v 172 173 if magnitude: return torch.norm(curl, dim=1) 174 175 return curl
def
get_force_mesh_along_axis( start: torch.Tensor, end: torch.Tensor, activations: torch.Tensor, scatterers: list[vedo.mesh.Mesh], board: torch.Tensor, mask: torch.Tensor | None = None, steps: int = 200, path: str = 'Media', print_lines: bool = False, use_cache: bool = True, Hs: torch.Tensor | None = None, Hxs: torch.Tensor | None = None, Hys: torch.Tensor | None = None, Hzs: torch.Tensor | None = None) -> tuple[list[torch.Tensor], list[torch.Tensor], list[torch.Tensor]]:
178def get_force_mesh_along_axis(start:Tensor,end:Tensor, activations:Tensor, scatterers:list[Mesh], board:Tensor, mask:Tensor|None=None, steps:int=200, 179 path:str="Media",print_lines:bool=False, use_cache:bool=True, 180 Hs:Tensor|None = None, Hxs:Tensor|None=None, Hys:Tensor|None=None, Hzs:Tensor|None=None) -> tuple[list[Tensor],list[Tensor],list[Tensor]]: 181 ''' 182 Computes the force on a mesh at each point from `start` to `end` with number of samples = `steps` \n 183 :param start: The starting position 184 :param end: The ending position 185 :param activations: Transducer hologram 186 :param scatterers: First element is the mesh to move, rest is considered static reflectors 187 :param board: Transducers to use 188 :param mask: The mask to apply to filter force for only the mesh to move 189 :param steps: Number of steps to take from start to end 190 :param path: path to folder containing BEMCache/ 191 :param print_lines: if true prints messages detaling progress 192 :param use_cache: If true uses the cache system, otherwise computes H and does not save it 193 :param Hs: List of precomputed forward propagation matricies 194 :param Hxs: List of precomputed derivative of forward propagation matricies wrt x 195 :param Hys: List of precomputed derivative of forward propagation matricies wrt y 196 :param Hzs: List of precomputed derivative of forward propagation matricies wrt z 197 :return: list for each axis of the force at each position 198 ''' 199 # if Ax is None or Ay is None or Az is None: 200 # Ax, Ay, Az = grad_function(points=points, transducers=board, **grad_function_args) 201 direction = (end - start) / steps 202 203 translate(scatterers[0], start[0].item() - direction[0].item(), start[1].item() - direction[1].item(), start[2].item() - direction[2].item()) 204 scatterer = merge_scatterers(*scatterers) 205 206 points = get_centres_as_points(scatterer) 207 if mask is None: 208 mask = torch.ones(points.shape[2]).to(bool) 209 210 Fxs = [] 211 Fys = [] 212 Fzs = [] 213 214 for i in range(steps+1): 215 if print_lines: 216 print(i) 217 218 219 translate(scatterers[0], direction[0].item(), direction[1].item(), direction[2].item()) 220 scatterer = merge_scatterers(*scatterers) 221 222 points = get_centres_as_points(scatterer) 223 areas = get_areas(scatterer) 224 norms = get_normals_as_points(scatterer) 225 226 if Hs is None: 227 H = get_cache_or_compute_H(scatterer, board, path=path, print_lines=print_lines, use_cache_H=use_cache) 228 else: 229 H = Hs[i] 230 231 if Hxs is None or Hys is None or Hzs is None: 232 Hx, Hy, Hz = get_cache_or_compute_H_gradients(scatterer, board, path=path, print_lines=print_lines, use_cache_H_grad=use_cache) 233 else: 234 Hx = Hxs[i] 235 Hy = Hys[i] 236 Hz = Hzs[i] 237 238 239 force = force_mesh(activations, points, norms, areas, board, F=H, Ax=Hx, Ay=Hy, Az=Hz) 240 241 force = torch.sum(force[:,:,mask],dim=2).squeeze() 242 Fxs.append(force[0]) 243 Fys.append(force[1]) 244 Fzs.append(force[2]) 245 246 # print(i, force[0].item(), force[1].item(),force[2].item()) 247 return Fxs, Fys, Fzs
Computes the force on a mesh at each point from start
to end
with number of samples = steps
Parameters
- start: The starting position
- end: The ending position
- activations: Transducer hologram
- scatterers: First element is the mesh to move, rest is considered static reflectors
- board: Transducers to use
- mask: The mask to apply to filter force for only the mesh to move
- steps: Number of steps to take from start to end
- path: path to folder containing BEMCache/
- print_lines: if true prints messages detaling progress
- use_cache: If true uses the cache system, otherwise computes H and does not save it
- Hs: List of precomputed forward propagation matricies
- Hxs: List of precomputed derivative of forward propagation matricies wrt x
- Hys: List of precomputed derivative of forward propagation matricies wrt y
- Hzs: List of precomputed derivative of forward propagation matricies wrt z
Returns
list for each axis of the force at each position