All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Disabled hard assertion test that ensured that every edge in a
topology.Mesh()
object was connected to at most 2 faces (manifoldness preservation). Now we print out a warning since we are all consenting adults over here. The implications of this change is that area load calculations might be incorrect, but this needs to be more thoroughly tested at a later time.
- Wrapped two gradient-free optimizers from scipy: Nelder-Mead and Powell. They are available as
jax_fdm.optimizers.NelderMead
andjax_fdm.optimizers.Powell
, respectively. - Linked two evolutionary optimizers from scipy They are available as
jax_fdm.optimizers.DualAnnealing
andjax_fdm.optimizers.DifferentialEvolution
. - Added support for kwargs in
LossPlotter.plot()
. The kwargs control the parameters of the equilibrium model used to plot the loss history. - Added
VertexSupportParameter.index()
. This change might appear redundant, but it was necessary to deal with the method resolution order of the parent classes ofVertexSupportParameter
. - Added
VertexGroupSupportParameter.index()
for similar reasons as the listed above.
- Changed
datastructure.print_stats()
to report positive and negative forces separately. - Turned off display in
TruncatedNewton
. - Fixed bug in
OptimizationRecorder
. The recorder did not know how to record optimization history without an explictly initialized optimizer. - Deprecated
jax_fdm.optimization.optimizers.scipy
in favor ofjax_fdm.optimization.optimizers.gradient_based
. - Fixed bug. Return early in
NetworkArtist.edge_width()
if the artist edges list is empty. - Fixed bug in
EdgesForceEqualGoal.prediction()
: the normalization mean of compressive edge forces was a negative number. This led to negative normalized variance values, which was plainly incorrect. VertexGroupSupportParameter
inherits fromVertexGroupParameter
instead ofNodeGroupParameter
. This was a bug.
- Removed
compas_singular
from dependencies list. That package has been archived and it is not used injax_fdm
source code; only in a couple examples.
- Added
NetworkSmoothGoal
to smoothen the shape of a network based on the fairness energy of its nodes w.r.t. their immediate neighborhood. - Implemented
Graph.adjacency
to access the connectivity among nodes/vertices to compute new goals. - Added
adjacency_matrix
as numpy-only function to assembleGraph.adjacency
. The function is largely inspired bycompas.matrices.adjacency_matrix
.
- Now we use
time.perf_counter
instead oftime.time
to measure logic execution time more accurately.
- Implemented
EdgeLoadPathGoal
.
- Updated how to enable double floating precision (
float64
) to comply with changes ofjax.config
injax==0.4.25
.
- Fixed duplicated fixed point iteration in
EquilibriumModel.equilibrium_iterative
. This led to unnecessarily long runtimes. This change also fixes the "mysterious" bug that madejaxopt
implicit differentiation incompatible with sparse matrices.
LossPlotter
exposesplot_legend
to choose whether or not to show legend with curve labels.FDNetworkArtist
takes absolute force density values to calculate viz colors in"fd"
mode.- Fixed bug in
FDNetworkViewerArtist
that threw error when inputing a custom list of edges to display. The problem was that the artist could not find the width of all the edges connected to a node becauseedge_width
is only computed for the custom list of edges. The artist was expecting a dictionary with all the edge widths. - Package
compas-notebook
became an optional dependency because it does not supportcompas<2.0
anymore.
- Implemented
LogMaxError
. The goal of this error function is to work as a barrier soft constraint for target maximum values. One good use example would be to restrict the height of a shell to a maximum height.
- Added support for efficient reverse-mode AD of the calculation of equilibrium states in the presence of shape-dependent loads, via implicit differentiation. Forward-mode AD is pending.
- Added
EquilibriumModel.equilibrium_iterative
to compute equilibrium states that have shape-dependent edge and face loads using fixed point iteration. - Added
EquiibriumModel.edges_load
andEquiibriumModel.faces_load
to allow computation of edge and face loads. - Implemented
EquilibriumModelSparse.stiffness_matrix
. - Implemented
EquilibriumModel.stiffness_matrix
. - Implemented
EquilibriumModel.force_matrix
. - Implemented
EquilibriumModel.force_fixed_matrix
. - Added
linearsolve_fn
,itersolve_fn
,implicit_diff
, andverbose
as attributes ofEquilibriumModel
. - Added
Equilibrium.load_nodes_iter
as attribute to include the node loads inLoadState.nodes
when runningEquilibriumModel.equilibrium_iterative()
. Defaults toFalse
.
- Restored
vectors
field inEquilibriumState
. - Implemented
equilibrium.states.LoadState
. - Implemented
equilibrium.states.EquilibriumParametersState
.
- Implemented
solver_anderson
, to find fixed points of a function withjaxopt.AndersonAcceleration
. The implicit differentiation operator of the solver provided byjaxopt
is deactivated when usingEquilibriumModelSparse
becausejaxopt
does not support sparse matrices yet. - Defined a
jax.custom_vjp
forfixed_point
, an interface function that solves for fixed points of a function for different root-finding solver types:solver_fixedpoint
,solver_forward
, andsolver_newton
. - Implemented
solver_fixedpoint
, a function that wrapsjaxopt.FixedPointIterator
to calculate static equilibrium iteratively. - Implemented
solver_forward
, to find fixed points of a function using anequinox.while_loop
. - Implemented
solver_netwon
, to find fixed points of a function using Newton's method.
- Added
equilibrium.loads
module to enable support for edge and face-loads, which correspond to line and area loads, respectively. These two load types can be optionally become follower loads setting theis_local
input flag toTrue
. A follower load will update its direction iteratively, according to the local coordinate system of an edge or a face at an iteration. The two main functions that enable this feature areloads.nodes_load_from_faces
andloads.nodes_load_from_edges
. These functions are wrapped byEquilibriumModel
underEquiibriumModel.edges_load
andEquiibriumModel.faces_load
. - Implemented
equilibrium.loads.nodes_
.
- Report standard deviation in
FDDatastructure.print_stats()
. - Added constructor method
FDNetwork.from_mesh
. - Added
FDMesh.face_lcs
to calculate the local coordinaty system of a mesh face. - Added
datastructures.FDDatastructure.edges_loads
. - Added
datastructures.FDMesh
. - Added
datastructures.Datastructure
. - Implemented
structures.EquilibriumStructureMeshSparse
. - Implemented
structures.EquilibriumStructureMesh
. - Implemented
structures.Mesh
. - Implemented
structures.MeshSparse
. - Implemented
structures.Graph
. - Implemented
structures.GraphSparse
. - Added
FDNetwork.is_edge_fully_supported
. - Added
EquilibriumMeshStructure.from_mesh
with support for inhomogenous faces (i.e. faces with different number of vertices). The solution is to pad the rows of thefaces
2D array with-1
to matchmax_num_vertices
.
- Implemented
NetworkXYZLaplacianGoal
. - Implemented base class
MeshGoal
. - Implemented
MeshXYZLaplacianGoal
. - Implemented
MeshXYZFaceLaplacianGoal
. - Implemented
MeshAreaGoal
. - Implemented
MeshFacesAreaEqualizeGoal
.
- Added
optimization.Optimizer.loads_static
attribute to store edge and face loads during optimization.
- Added
polygon_lcs
to compute the local coordinate system of a closed polygon. - Added
line_lcs
to compute the local coordinate system of a line. - Added
nan
gradient guardrail tonormalize_vector
calculations.
- Added support for mesh vertex parameters.
- Added explicit array integer types in
__init__
:DTYPE_INT_NP
andDTYPE_INT_JAX
- Set
spsolve_gpu_ravel
as the default sparse solver on GPUs (spsolve_gpu
). - Added
spsolve_gpu_ravel
to solve the FDM linear system all at once on GPUs. - Implemented helper function
sparse_blockdiag_matrix
tospsolve_gpu_ravel
.
- Added
plotters/VectorArtist
to custom plot loads and reactions arrows. - Implemented
LossPlotter._print_error_stats
to report loss breakdown of error terms.
- The functions
fdm
andconstrained_fdm
take iterative equilibrium parameters as function arguments. - The functions
fdm
andconstrained_fdm
can take anFDMesh
as input, in addition toFDNetwork
.
- Decoupled
sparse_solver
from any force density calculations. Now, it is a simpler solver that only takes as inputs the LHS matrixA
and the RHS matrixb
, and thus, it could be used to potentially solve any sparse linear system of equations. Its signature now is analogous to that ofjax.numpy.linalg.solve
. - Condensed signature of sparse linear solver
sparse_solve
to take a structureEquilibriumStructure
as input, instead of explicit attributes of a structure. - Changed signature of
sparse_solve_bwd
to take two arguments, where the first is the "residual" values produced on the forward pass byfwd
, and the second is the output cotangent with the same structure as the primal function output (sparse_solve
). - Condensed signature of helper functions
sparse_solve_fwd
to take matricesA
andb
as inputs, instead of explicit attributes of the FDM and of aEquilibriumStructure
. - Renamed previous verison of
spsolve_gpu
tospsolve_gpu_stack
.
- Added support for
jnp.nan
inputs in the calculations ofgeometry.normal_polygon
.
- Changed signature of
Regularizer.__call__
to take in parameters instead of equilibirum state.
- Overhauled
EquilibriumStructure
andEquilibriumStructureSparse
. They are subclassesequinox.Module
, and now they are meant to be immutable. They also have little idea of what anFDNetwork
is. - Modified
face_matrix
adjacency matrix creation function to skip -1 vertices. This is to add support forMeshStructures
that have faces with different number of vertices.
- Use
jax.value_and_grad(loss_fn(x))
instead of usingloss_fn(x)
andjax.grad(loss_fn(x))
separately. This results in optimization speedup because we get both value and grad with a single VJP call. Optimizer.problem
takes anFDNetwork
as input.Optimizer.problem
takes booleanjit_fn
as arg to disable jitting if needed.- Changed
ParameterManager
to require anFDNetwork
as argument at initialization. - Changed
Parameter.value
signature. Gets value fromnetwork
directly, not fromstructure.network
optimization.OptimizationRecorder
has support to store, export and import named tuple parameters.
- Fixed bug in
viewers/network_artist.py
that overshifted load arrows. - Edge coloring considers force sign for
force
color scheme inartists/network_artist.py
. - Fixed bug with the coloring of reaction forces in
viewers/network_artist.py
. - Fixed bug with the coloring of reaction forces in
artists/network_artist.py
. LossPlotter
has support to plot named tuple parameters.
- Removed
EquilibriumModel.from_network
. - Removed
sparse.force_densities_to_A
. Superseded byEquilibriumModelSparse.stiffness_matrix
. - Removed
sparse.force_densities_to_b
. Superseded byEquilibriumModel.force_matrix
. - Removed partial jitting from
Loss.__call__
. - Removed partial jitting from
Error.__call__
.
- Fixed signature bug in constraint initialization in
ConstrainedOptimizer.constraints
.
- Removed implicit
partial(jit)
decorator onConstrainedOptimizer.constraint
. Jitting now takes place explicitly inConstrainedOptimizer.constraints
.
- Added
EquilibriumStructure.init
as a quick fix to warm start properties.
- Changed signature of equilibrium model to be
EquilibriumModel(params, structure)
. - The
init
function in goals, constraints and parameter takes(model, structure)
as arguments. - Removed
connectivity
related operations fromEquilibriumModel
and inserted them intoEquilibriumStructure
. - Fixed bug in
EquilibriumStructure.nodes
that led to a recursive timeout error. - Renamed example file
butt.py
tovault.py
/ - Renamed file
optimizers.py
toscipy.py
injax_fdm.optimization
.
- Removed
structure
attribute fromEquilibriumModel
en route to equinox modules.
Support for differentiable CPU sparse solver
- Added support for differentiable CPU and GPU sparse solvers to compute the XYZ coordinates of the free nodes with FDM. The solver is custom made and registered via a
jax.custom_vjp
. The forward and backward passes of the sparse solver were made possible thanks to the contributions of @denizokt. This solver lives inequilibrium.sparse.py
. - Added
spsolve_gpu
andspsolve_cpu
. The sparse solver backend is different (the former uses CUDA and the latter scipy) and it gets selected automatically based on what the value ofjax.default_device
is at runtime with functionregister_sparse_solver
. - Implemented
EquilibriumStructureSparse
. - Division of responsabilities: created a
EquilibriumModelSparse
that solves for static equilibrium using anEquilibriumStructureSparse
and the sparse solver.EquilibriumModel
implements the dense linear solver.
LossPlotter
instantiates a denseEquilibriumModel
.
- Removed
DTYPE
fromcombine_parameters
signature injax_fdm.parameters
due to clashes with JAX versions on windows.
- Added
ParameterManager.indices_opt_sort
to fix bug that mistmatch optimization values for unconsecutive parameter indices. This bug applied to individual parameters and to parameter groups.
- Implemented parameter groups!
- Added
EdgesForceDensityParameter
. - Added
NodesLoadXParameter
,NodesLoadYParameter
,NodesLoadZParameter
. - Added
NodesSupportXParameter
,NodesSupportYParameter
,NodesSupportZParameter
. - Added
EdgesForceEqualGoal
to goals. - Implemented
area_polygon
injax_fdm.geometry
. - Added
FDNetwork.number_of_supports()
to count number of supported nodes in a network. - Added
network_validate
to check the validity of a network before equilibrium calculations.
- Sped up
EquilibriumModel.nodes_free_positions()
computation after replacingjnp.diag(q)
withvmap(jnp.dot)(q, *)
. - Vectorized error computations in
LossPlotter.plot()
to expedite method. OptimizationRecorder.record()
now stores history in a dictionary, not in a list.- Fixed bug in
FDNetworkViewerArtist
that ocurred while plotting reaction forces on unconnected nodes. - Turned
TrustRegionConstrained
into a first order optimizer.
- Removed
LossPlotter.network
attribute. - Replaced
NodeAnchorXParameter
withNodeSupportXParameter
. - Replaced
NodeAnchorYParameter
withNodeSupportYParameter
. - Replaced
NodeAnchorZParameter
withNodeSupportZParameter
.
- Added
Goal.is_collectible
flag to determine if a goal should form part of an optimizationCollection
. - Implemented
EdgesLengthEqualGoal
. - Added
AbsoluteError
term. - Added
MeanAbsoluteError
terms.
- Fixed omission of
gstate.weight
when computingPredictionError
.
- Implemented
LBFGSBS
to ensure compatibility of JAX gradients with scipy.
- Implemented
NotebookViewer
to visualize networks in jupyter notebooks. - Added
FDNetworkNotebookArtist
to visualize networks in jupyter notebooks. - Added
noteboks.shapes.Arrow
to display force vectors as meshed arrows.
- Implemented
NodeTangentAngleGoal
. - Implemented
NodeNormalAngleGoal
. - Implemented
NodeTangentAngleConstraint
. - Implemented
NodeNormalAngleConstraint
. - Added
EquilibriumStructure.connectivity_faces
to optimize for face-related quantities in anFDNetwork
.
- Fixed bug in
edgewidth
sizing inNetworkArtist
when all edges have the same force. - Changed
angle_vectors
to return angle in radians by default. - Shifted loads start point in
plotters.NetworkArtist
for them to be incident to the nodes.
- Changed generator unpacking
*sarrays
inparameters.split
unsupported in Python 3.7. - Changed tension-compression force color map gradient to a binary color map.
- Added
goals.NodeZCoordinateGoal
. - Added
goals.NodeYCoordinateGoal
. - Added
goals.NodeXCoordinateGoal
. - Added
constraints.NodeZCoordinateConstraint
. - Added
constraints.NodeYCoordinateConstraint
. - Added
constraints.NodeXCoordinateConstraint
. - Added
IPOPT
, a second-order, constrained optimizer that wrapscyipopt
, to the repertoire of optimizers.
- Restructured
optimization.optimizers
into separate files. - Renamed
goals.edgegoal
submodule togoals.edge
. - Renamed
goals.nodegoal
submodule togoals.node
. - Renamed
goals.networkgoal
submodule togoals.network
. - Enabled support for one-sided bounds in
constraint.Constraints
. NetworkLoadPathGoal
usesjnp.multiply
instead of multipication operator*
.- Broke down
Optimizer.minimize()
into.problem()
and.solve()
. - For efficiency,
SecondOrderOptimizer
calculateshessian
asjax.jacfwd(jax.jacrev)
. - Changed calculation of the scalar ouput of
Loss
using a compact loop. - Changed calculation of the scalar ouput of
Error
using a compact loop.
- Implemented
jax_fdm.parameters
to choose optimization parameters a la carte! - Created
parameters.EdgeForceDensityParameter
. - Created
parameters.NodeAnchorXParameter
. - Created
parameters.NodeAnchorYParameter
. - Created
parameters.NodeAnchorZParameter
. - Created
parameters.NodeLoadXParameter
. - Created
parameters.NodeLoadYParameter
. - Created
parameters.NodeLoadZParameter
. - Implemented
EquilibriumStructure.nodes
. - Implemented
EquilibriumStructure.edges
. - Added
EquilibriumStructure.anchor_index
. - Implemented
ParameterManager.parameters_ordered
to fix order mismatch between optimization parameters and their bounds.
EquilibriumModel.__call__
tasksq
,xyz_fixed
andloads
as arguments.FDNetwork.transform
only modifies node coordinates.FDNetworkViewerArtist
shifts a node load by the maximum edge width at the node.OptimizationRecorder.history
storesq
,xyz_fixed
andloads
.LossPlotter.plot
supportsq
,xyz_fixed
andloads
to be compatible withOptimizationRecorder.history
.
- Enabled the creation of animations with mesh representations of the elements of a
FDNetwork
! FDNetworkViewerArtist
implementsupdate_*()
methods to update objects in theViewer
.FDNetworViewerArtist
implementsadd_*()
methods to add drawn objects toViewer
.FDNetworkArtist
now stores network element collections as attributes.
- Removed
FDNetworkPlotterArtist.draw_loads()
as it is handled by parent artist class. - Removed
FDNetworkPlotterArtist.draw_reactions()
as it is handled by parent artist class.
- Implemented
SecondOrderOptimizer
, which computes the hessian of a loss function. - Added support for the
NetwtonCG
andLBFGSB
scipy optimizers. - Created
NodeSegmentGoal
- Implemented
closest_point_on_segment
usinglax.cond
- Pinned viewer dependency to
compas_view2==0.7.0
- Removed
Viewer.__init__()
- Added
datastructures.FDNetwork.transformed()
- Created
visualization.plotters.FDNetworkPlotterArtist
- Implemented
visualization.plotters.Plotter
- Rolled back support for python
3.7
.
- Implemented
visualization.viewers.Viewer
as a thin wrapper aroundcompas_view2.App
. - Created
visualization.plotters.LossPlotter
. - Implemented
visualization.viewers.FDNetworkViewerArtist
. - Implemented
visualization.artists.FDNetworkArtist
. - Created
jax_fdm.visualization
module. - Implemented
FDNetwork.print_stats()
. - Implemented
FDNetwork.node_reaction()
to get the reaction force at a fixed node. - Added
FDNetwork.nodes_fixed()
to query nodes with a support.
- Created beta release! 🎉 Since we were busy adding new features to JAX FDM, we forgot to log them. Sorry! We promise to do better from here on. Please check the git log (fairly granular) for details on the all the features.