Skip to content

Commit 0a9e809

Browse files
committed
2 parents 3bf9947 + 5701100 commit 0a9e809

23 files changed

+902
-379
lines changed

.github/workflows/release-please.yml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
name: Linting
77
runs-on: ubuntu-latest
88
steps:
9-
- uses: actions/checkout@v2
9+
- uses: actions/checkout@v4
1010
- name: Install dependencies
1111
run: |
1212
python -m pip install --upgrade pip
@@ -17,7 +17,7 @@ jobs:
1717
- name: Lint with ruff
1818
run: |
1919
ruff check LoopStructural --fix
20-
- uses: stefanzweifel/git-auto-commit-action@v4
20+
- uses: stefanzweifel/git-auto-commit-action@v5
2121
with:
2222
commit_message: "style: style fixes by ruff and autoformatting by black"
2323

@@ -30,8 +30,9 @@ jobs:
3030
os: ${{ fromJSON(vars.BUILD_OS)}}
3131
python-version: ${{ fromJSON(vars.PYTHON_VERSIONS)}}
3232
steps:
33-
- uses: actions/checkout@v2
34-
- uses: conda-incubator/setup-miniconda@v2
33+
- uses: actions/checkout@v4
34+
- uses: conda-incubator/setup-miniconda@v3
35+
3536
with:
3637
python-version: ${{ matrix.python }}
3738
- name: Installing dependencies
@@ -50,7 +51,7 @@ jobs:
5051
runs-on: ubuntu-latest
5152
#needs: continuous-integration
5253
steps:
53-
- uses: actions/checkout@v2
54+
- uses: actions/checkout@v4
5455
- run: |
5556
cp CHANGELOG.md docs/source/getting_started/CHANGELOG.md
5657
docker build . -t=lsdocs -f docs/Dockerfile
@@ -65,12 +66,12 @@ jobs:
6566
needs: documentation-test
6667
if: github.ref == 'refs/heads/master'
6768
steps:
68-
- uses: GoogleCloudPlatform/release-please-action@v3.5.0
69+
- uses: GoogleCloudPlatform/release-please-action@v4
6970
id: release
7071
with:
7172
release-type: python
7273
package-name: LoopStructural
73-
#version-file: LoopStructural/version.py
74+
version-file: LoopStructural/version.py
7475
outputs:
7576
release_created: ${{ steps.release.outputs.release_created }}
7677
# if a release is created then run the deploy scripts for github.io, conda, pypi and docker
@@ -79,7 +80,7 @@ jobs:
7980
needs: release-please
8081
if: ${{ needs.release-please.outputs.release_created }}
8182
steps:
82-
- uses: actions/checkout@v2
83+
- uses: actions/checkout@v4
8384
- run: |
8485
cp CHANGELOG.md docs/source/getting_started/CHANGELOG.md
8586
docker build . -t=lsdocs -f docs/Dockerfile
@@ -100,12 +101,12 @@ jobs:
100101
os: ["ubuntu-latest"]
101102
python-version: ${{ fromJSON(vars.PYTHON_VERSIONS)}}
102103
steps:
103-
- uses: conda-incubator/setup-miniconda@v2
104+
- uses: conda-incubator/setup-miniconda@v3
104105
with:
105106
auto-update-conda: true
106107
python-version: ${{ matrix.python-version }}
107108

108-
- uses: actions/checkout@v2
109+
- uses: actions/checkout@v4
109110
- name: update submodules
110111
# shell: bash -l {0}
111112
run: |
@@ -120,29 +121,29 @@ jobs:
120121
conda convert -p all conda/linux-64/*.tar.bz2 -f -o conda
121122
conda install anaconda-client -y
122123
- name: upload artifacts
123-
uses: actions/upload-artifact@v3
124+
uses: actions/upload-artifact@v4
124125
with:
125-
name: conda
126+
name: conda-${{ matrix.os }}-${{ matrix.python-version }}
126127
path: conda
127128

128129
make_sdist:
129130
needs: ["documentation-test", "continuous-integration"]
130131
name: Make SDist
131132
runs-on: ubuntu-latest
132133
steps:
133-
- uses: actions/checkout@v3
134+
- uses: actions/checkout@v4
134135

135136
- name: Build SDist
136137
run: |
137138
pip install numpy
138139
python setup.py sdist
139140
pip wheel -w wheelhouse .
140141
141-
- uses: actions/upload-artifact@v3
142+
- uses: actions/upload-artifact@v4
142143
with:
143144
name: dist
144145
path: dist/*.tar.gz
145-
- uses: actions/upload-artifact@v3
146+
- uses: actions/upload-artifact@v4
146147
with:
147148
name: dist
148149
path: wheelhouse/*.whl
@@ -152,21 +153,20 @@ jobs:
152153
runs-on: ubuntu-latest
153154
if: ${{ needs.release-please.outputs.release_created }}
154155
steps:
155-
- uses: actions/download-artifact@v3
156+
- uses: actions/download-artifact@v4
156157
with:
157158
name: dist
158159
path: dist
159-
- uses: actions/download-artifact@v3
160+
- uses: actions/download-artifact@v4
160161
with:
161-
name: conda
162162
path: conda
163-
- uses: pypa/gh-action-pypi-publish@v1.6.4
163+
- uses: pypa/gh-action-pypi-publish@v1
164164
with:
165165
skip_existing: true
166166
verbose: true
167167
user: ${{ secrets.PYPI_USERNAME }}
168168
password: ${{ secrets.PYPI_PASSWORD }}
169-
- uses: conda-incubator/setup-miniconda@v2
169+
- uses: conda-incubator/setup-miniconda@v3
170170
- name: upload all files to conda-forge
171171
shell: bash -l {0}
172172
env:

LoopStructural/interpolators/_builders.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
StructuredGrid,
1111
TetMesh,
1212
)
13-
from LoopStructural.utils import BoundingBox
13+
from LoopStructural.datatypes import BoundingBox
1414
from LoopStructural.utils.logging import getLogger
1515

1616
logger = getLogger(__name__)
@@ -61,6 +61,7 @@ def get_interpolator(
6161
)
6262

6363
return P1Interpolator(support)
64+
return P1Interpolator(support)
6465
if interpolatortype == "P2":
6566
if support is not None:
6667
logger.info(
@@ -69,9 +70,7 @@ def get_interpolator(
6970
)
7071
return P2Interpolator(support)
7172
else:
72-
raise ValueError(
73-
"Cannot create P2 interpolator without support, try using PLI"
74-
)
73+
raise ValueError("Cannot create P2 interpolator without support, try using PLI")
7574

7675
if interpolatortype == "FDI":
7776
# find the volume of one element
@@ -96,8 +95,7 @@ def get_interpolator(
9695

9796
grid = StructuredGrid(origin=origin, nsteps=nsteps, step_vector=step_vector)
9897
logger.info(
99-
f"Creating regular grid with {grid.n_elements} elements \n"
100-
"for modelling using FDI"
98+
f"Creating regular grid with {grid.n_elements} elements \n" "for modelling using FDI"
10199
)
102100
return FiniteDifferenceInterpolator(grid)
103101
if interpolatortype == "DFI":

LoopStructural/interpolators/_discrete_interpolator.py

Lines changed: 9 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Discrete interpolator base for least squares
33
"""
44

5+
from abc import abstractmethod
56
import logging
67

78
from time import time
@@ -39,16 +40,12 @@ def __init__(self, support, data={}, c=None, up_to_date=False):
3940
else np.zeros(self.support.n_nodes)
4041
)
4142
self.region_function = lambda xyz: np.ones(xyz.shape[0], dtype=bool)
42-
# self.region_map[self.region] = np.array(range(0,
43-
# len(self.region_map[self.region])))
43+
4444
self.shape = "rectangular"
4545
if self.shape == "square":
4646
self.B = np.zeros(self.nx)
4747
self.c_ = 0
48-
# self.A = [] # sparse matrix storage coo format
49-
# self.col = []
50-
# self.row = [] # sparse matrix storage
51-
# self.w = []
48+
5249
self.solver = "cg"
5350

5451
self.eq_const_C = []
@@ -221,6 +218,12 @@ def add_constraints_to_least_squares(self, A, B, idc, w=1.0, name="undefined"):
221218
'w': w,
222219
}
223220

221+
@abstractmethod
222+
def add_gradient_orthogonal_constraints(
223+
self, points: np.ndarray, vectors: np.ndarray, w: float = 1.0
224+
):
225+
pass
226+
224227
def calculate_residual_for_constraints(self):
225228
"""Calculates Ax-B for all constraints added to the interpolator
226229
This could be a proxy to identify which constraints are controlling the model
@@ -252,7 +255,6 @@ def remove_constraints_from_least_squares(self, name="undefined", constraint_ids
252255
-------
253256
254257
"""
255-
256258
pass
257259

258260
def add_equality_constraints(self, node_idx, values, name="undefined"):
@@ -288,72 +290,6 @@ def add_equality_constraints(self, node_idx, values, name="undefined"):
288290
}
289291
self.eq_const_c += idc[outside].shape[0]
290292

291-
def add_inequality_constraints_to_matrix(self, A, l, u, idc, name="undefined"):
292-
"""Adds constraints for a matrix where the linear function
293-
l < Ax > u constrains the objective function
294-
295-
296-
Parameters
297-
----------
298-
A : numpy array
299-
matrix of coefficients
300-
l : numpy array
301-
lower bounds
302-
u : numpy array
303-
upper bounds
304-
idc : numpy array
305-
index of constraints
306-
Returns
307-
-------
308-
309-
"""
310-
# map from mesh node index to region node index
311-
gi = np.zeros(self.support.n_nodes, dtype=int)
312-
gi[:] = -1
313-
gi[self.region] = np.arange(0, self.nx, dtype=int)
314-
idc = gi[idc]
315-
rows = np.arange(self.ineq_const_c, self.ineq_const_c + idc.shape[0])
316-
rows = np.tile(rows, (A.shape[-1], 1)).T
317-
self.ineq_constraints[name] = {"A": A, "l": l, "col": idc, "u": u, "row": rows}
318-
self.ineq_const_c += idc.shape[0]
319-
320-
def add_inequality_feature(self, feature, lower=True, mask=None):
321-
"""Add an inequality constraint to the interpolator using an existing feature.
322-
This will make the interpolator greater than or less than the exising feature.
323-
Evaluate the feature at the interpolation nodes.
324-
Can provide a boolean mask to restrict to only some parts
325-
326-
Parameters
327-
----------
328-
feature : BaseFeature
329-
the feature that will be used to constraint the interpolator
330-
lower : bool, optional
331-
lower or upper constraint, by default True
332-
mask : np.ndarray, optional
333-
restrict the nodes to evaluate on, by default None
334-
"""
335-
# add inequality value for the nodes of the mesh
336-
# flag lower determines whether the feature is a lower bound or upper bound
337-
# mask is just a boolean array determining which nodes to apply it to
338-
339-
value = feature(self.support.nodes)
340-
if mask is None:
341-
mask = np.ones(value.shape[0], dtype=bool)
342-
l = np.zeros(value.shape[0]) - np.inf
343-
u = np.zeros(value.shape[0]) + np.inf
344-
mask = np.logical_and(mask, ~np.isnan(value))
345-
if lower:
346-
l[mask] = value[mask]
347-
if not lower:
348-
u[mask] = value[mask]
349-
350-
self.add_inequality_constraints_to_matrix(
351-
np.ones((value.shape[0], 1)),
352-
l,
353-
u,
354-
np.arange(0, self.nx, dtype=int),
355-
)
356-
357293
def add_tangent_constraints(self, w=1.0):
358294
"""Adds the constraints :math:`f(X)\cdotT=0`
359295

LoopStructural/interpolators/_finite_difference_interpolator.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ def setup_interpolator(self, **kwargs):
121121
self.assemble_inner(operator, weight)
122122
self.add_norm_constraints(self.interpolation_weights["npw"])
123123
self.add_gradient_constraints(self.interpolation_weights["gpw"])
124-
self.add_vaue_constraints(self.interpolation_weights["cpw"])
124+
self.add_value_constraints(self.interpolation_weights["cpw"])
125125
self.add_tangent_constraints(self.interpolation_weights["tpw"])
126126
self.add_interface_constraints(self.interpolation_weights["ipw"])
127127
self.add_inequality_constraints()
@@ -136,7 +136,7 @@ def copy(self):
136136
"""
137137
return FiniteDifferenceInterpolator(self.support)
138138

139-
def add_vaue_constraints(self, w=1.0):
139+
def add_value_constraints(self, w=1.0):
140140
"""
141141
142142
Parameters
@@ -151,7 +151,9 @@ def add_vaue_constraints(self, w=1.0):
151151
points = self.get_value_constraints()
152152
# check that we have added some points
153153
if points.shape[0] > 0:
154-
node_idx, inside = self.support.position_to_cell_corners(points[:, :3])
154+
node_idx, inside = self.support.position_to_cell_corners(
155+
points[:, : self.support.dimension]
156+
)
155157
# print(points[inside,:].shape)
156158
gi = np.zeros(self.support.n_nodes, dtype=int)
157159
gi[:] = -1
@@ -160,14 +162,14 @@ def add_vaue_constraints(self, w=1.0):
160162
idc[:] = -1
161163
idc[inside, :] = gi[node_idx[inside, :]]
162164
inside = np.logical_and(~np.any(idc == -1, axis=1), inside)
163-
a = self.support.position_to_dof_coefs(points[inside, :3])
164-
# a*=w
165-
# a/=np.product(self.support.step_vector)
165+
a = self.support.position_to_dof_coefs(points[inside, : self.support.dimension])
166+
# a *= w
167+
# a/=self.support.enp.product(self.support.step_vector)
166168
self.add_constraints_to_least_squares(
167169
a,
168170
points[inside, 3],
169171
idc[inside, :],
170-
w=w * points[inside, 4],
172+
w=w * points[inside, 4] * self.support.element_size,
171173
name="value",
172174
)
173175
if np.sum(inside) <= 0:
@@ -233,7 +235,9 @@ def add_interface_constraints(self, w=1.0):
233235
# get elements for points
234236
points = self.get_interface_constraints()
235237
if points.shape[0] > 1:
236-
vertices, c, tetras, inside = self.support.get_element_for_location(points[:, :3])
238+
vertices, c, tetras, inside = self.support.get_element_for_location(
239+
points[:, : self.support.dimension]
240+
)
237241
# calculate volume of tetras
238242
# vecs = vertices[inside, 1:, :] - vertices[inside, 0, None, :]
239243
# vol = np.abs(np.linalg.det(vecs)) / 6
@@ -391,7 +395,7 @@ def add_norm_constraints(self, w=1.0):
391395
self.up_to_date = False
392396

393397
def add_gradient_orthogonal_constraints(
394-
self, points: np.ndarray, vector: np.ndarray, w: float = 1.0, B: float = 0
398+
self, points: np.ndarray, vectors: np.ndarray, w: float = 1.0, B: float = 0
395399
):
396400
"""
397401
constraints scalar field to be orthogonal to a given vector
@@ -424,8 +428,8 @@ def add_gradient_orthogonal_constraints(
424428
idc[inside, :] = gi[node_idx[inside, :]]
425429
inside = np.logical_and(~np.any(idc == -1, axis=1), inside)
426430
# normalise vector and scale element gradient matrix by norm as well
427-
norm = np.linalg.norm(vector, axis=1)
428-
vector[norm > 0, :] /= norm[norm > 0, None]
431+
norm = np.linalg.norm(vectors, axis=1)
432+
vectors[norm > 0, :] /= norm[norm > 0, None]
429433

430434
# normalise element vector to unit vector for dot product
431435
(
@@ -437,7 +441,7 @@ def add_gradient_orthogonal_constraints(
437441
T[norm > 0, :, :] /= norm[norm > 0, None, None]
438442

439443
# dot product of vector and element gradient = 0
440-
A = np.einsum("ij,ijk->ik", vector[inside, :3], T)
444+
A = np.einsum("ij,ijk->ik", vectors[inside, :3], T)
441445
B = np.zeros(points[inside, :].shape[0]) + B
442446
self.add_constraints_to_least_squares(
443447
A, B, idc[inside, :], w=w * self.vol, name="gradient orthogonal"
@@ -461,7 +465,7 @@ def add_regularisation(self, operator, w=0.1):
461465
-------
462466
463467
"""
464-
self.assemble_inner(operator)
468+
self.assemble_inner(operator, w)
465469
# self.assemble_borders()
466470

467471
# def assemble_borders(self, operator, w):

0 commit comments

Comments
 (0)