Skip to content

Commit

Permalink
Merge pull request #61 from AlabamaASRL/AutoScaling
Browse files Browse the repository at this point in the history
Auto scaling and string naming
  • Loading branch information
jbpezent authored Jun 24, 2024
2 parents 8c6e113 + 5c8d9cc commit 156504d
Show file tree
Hide file tree
Showing 53 changed files with 8,176 additions and 2,790 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/pypi-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
-DCMAKE_LINKER:FILEPATH="C:/Program Files/LLVM/bin/lld-link.exe"
- name: "Build Project"
run: cmake --build build --target asset pypiwheel --config Release -- -j1
run: cmake --build build --target asset pypiwheel --config Release -- -j3

- name: 'Upload Wheels'
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -105,7 +105,7 @@ jobs:
run: cmake -S . -B build -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DPIP_INSTALL=True -DBUILD_ASSET_WHEEL=True

- name: "Build Project"
run: cmake --build build --target asset pypiwheel --config Release -- -j1
run: cmake --build build --target asset pypiwheel --config Release -- -j2

- name: Audit Wheel Test
run: auditwheel show build/pypiwheel/asset_asrl/dist/*.whl
Expand Down Expand Up @@ -154,7 +154,7 @@ jobs:
run: cmake -S . -B build -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DPIP_INSTALL=True -DBUILD_ASSET_WHEEL=True

- name: "Build Project"
run: cmake --build build --target asset pypiwheel --config Release -- -j1
run: cmake --build build --target asset pypiwheel --config Release -- -j2

- name: Audit Wheel Test
run: auditwheel show build/pypiwheel/asset_asrl/dist/*.whl
Expand Down
7 changes: 4 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(ASSET VERSION 0.4.0 LANGUAGES CXX)
project(ASSET VERSION 0.5.0 LANGUAGES CXX)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

set( CMAKE_MESSAGE_LOG_LEVEL "STATUS" )
Expand Down Expand Up @@ -78,9 +78,9 @@ if(BUILD_ASSET_WHEEL)
# Windows runs out of ram with LINK_TIME_OPT on gh-actions
if(NOT WIN32)
list(APPEND RELEASE_FLAGS "-mtune=skylake")
set(LINK_TIME_OPT TRUE) ### DO LTO - Recommended for full release
set(CLANG_MAX_INLINE_DEPTH 300)
endif()
set(LINK_TIME_OPT TRUE) ### DO LTO - Recommended for full release
set(CLANG_MAX_INLINE_DEPTH 400)

else()
list(APPEND RELEASE_FLAGS "-march=native")
Expand Down Expand Up @@ -116,6 +116,7 @@ if(LINK_TIME_OPT)
if(BUILD_ASSET_WHEEL)
## Do full LTO for CI builds since it is single threaded anyway
list(APPEND RELEASE_FLAGS "-flto=full")
list(APPEND RELEASE_FLAGS "/opt:lldltojobs=1")
else()
list(APPEND RELEASE_FLAGS "-flto=thin")
list(APPEND RELEASE_FLAGS "/opt:lldltojobs=8")
Expand Down
166 changes: 165 additions & 1 deletion asset_asrl/OptimalControl/ODEBaseClass.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import asset as _asset
import inspect
import numpy as np
import numbers


class ODEBase:

def __init__(self,odefunc,Xvars,Uvars = None,Pvars = None):
def __init__(self,odefunc,Xvars,Uvars = None,Pvars = None,Vgroups = None):

mlist = inspect.getmembers(_asset.OptimalControl)

Expand Down Expand Up @@ -37,8 +40,169 @@ def __init__(self,odefunc,Xvars,Uvars = None,Pvars = None):
else:
self.ode = _asset.OptimalControl.ode_x.ode(odefunc,Xvars)

if(Vgroups!=None):
self.add_Vgroups(Vgroups)


def _make_index_set(self,idxs):

if(hasattr(idxs, 'input_domain') and hasattr(idxs, 'vf') and hasattr(idxs, 'is_linear')):
## Handle Vector Functions
input_domain = idxs.input_domain()
idxstmp = []
for i in range(0,input_domain.shape[1]):
start = input_domain[0,i]
size = input_domain[1,i]
idxstmp+= list(range(start,start+size))
return idxstmp
elif(isinstance(idxs, (int,np.int32,np.intc))):
return [idxs]
elif(hasattr(idxs, '__iter__') and not isinstance(idxs, str)):
if(len(idxs)==0):
raise Exception("Index list is empty")
idxtmp = []
for idx in idxs:
idxtmp+=self._make_index_set(idx)
return idxtmp
else:
raise Exception("Invalid index: {}".format(str(idxs)))

def add_Vgroups(self,Vgroups):
for name in Vgroups:
idxs = self._make_index_set(Vgroups[name])
if(isinstance(name, str)):
self.ode.add_idx(name,idxs)
elif(hasattr(name, '__iter__')):
for n in name:
self.ode.add_idx(n,idxs)

def make_units(self,**kwargs):
"""
Makes a vector of non-dim units from variable group names and unit values
Parameters
----------
**kwargs : float,list,ndarray
Keyword list of the names of the variable groups and corresponding units.
Returns
-------
units : np.ndarray
Vector of units.
"""
units = np.ones((self.XtUPVars()))

for key, value in kwargs.items():
idx = self.idx(key)

if(isinstance(value, numbers.Number)):
units_t = np.ones((len(idx)))*value
elif(hasattr(value, '__iter__') and not isinstance(value, str)):
units_t = value
else:
raise Exception("Invalid unit: {}".format(str(value)))


for i in range(0,len(idx)):
units[idx[i]] = units_t[i]

return units

def make_input(self,**kwargs):
"""
Makes an ODE input vector. Assigns sub-components to variable group names
and assembles them into single vector with proper ordering
Parameters
----------
**kwargs : float,list,ndarray
Keyword list of the sub-vectors of the full input.
Returns
-------
state : np.ndarray
ODE input vector.
"""
state = np.zeros((self.XtUPVars()))
for key, value in kwargs.items():
idx = self.idx(key)

if(isinstance(value, numbers.Number)):
state_t = np.ones((len(idx)))*value
elif(hasattr(value, '__iter__') and not isinstance(value, str)):
state_t = value
else:
raise Exception("Invalid unit: {}".format(str(value)))

for i in range(0,len(idx)):
state[idx[i]] = state_t[i]
return state



def get_vars(self,names,source,retscalar = False):
"""
Retrieve variables from a ODE input vector or trajectory(2darray/listoflists)
Parameters
----------
names : str,list
Name,list of names/indices of the variables or sub-vectors to retrieve.
source : np.ndarray,list
Source vector or 2d-array for retreiving variables.
retscalar : bool, optional
Return a scalar instead of vector if result has only one element.
The default is False.
Returns
-------
np.ndarray
Concatenated array of the specified variables from source
"""
#############################################################

idxs = []
if(hasattr(names, '__iter__') and not isinstance(names, str)):
for name in names:
if(isinstance(name, str)):
idxs+= list(self.idx(name))
elif(isinstance(name, (int,np.int32,np.intc))):
idxs.append(name)
else:
raise Exception("Invalid name specifier: {}".format(str(name)))
elif(isinstance(names, str)):
idxs+=list(self.idx(names))
else:
raise Exception("Invalid name specifier: {}".format(str(names)))


#############################################################

if(hasattr(source, '__iter__') and isinstance(source[0],numbers.Number)):
# Its a single vector
output = np.zeros(len(idxs))
for i,idx in enumerate(idxs):
output[i] = source[idx]

if(len(output)==1 and retscalar):
return output[0]
else:
return output

else:
# Its a trajectory, nd array or list of lists/arrays
size = len(source)
output = np.zeros((size,len(idxs)))
for j in range(0,size):
for i,idx in enumerate(idxs):
output[j][i] = source[j][idx]

return output



def idx(self,Vname):
return self.ode.idx(Vname)
def phase(self,*args):
return self.ode.phase(*args)
def integrator(self,*args):
Expand Down
Loading

0 comments on commit 156504d

Please sign in to comment.