Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
81ca088
first implementation of aux elems w/ dvs
timryanb Apr 21, 2026
f56ade9
clang/black
timryanb Apr 21, 2026
bd6556d
fix bug in TACSMassInertialForce adjResProduct method
timryanb Apr 21, 2026
81b05bf
adding element tests for inertial force
timryanb Apr 21, 2026
0be6751
adding aux dv to integration test
timryanb Apr 22, 2026
f898704
adding checks for valid dvs in addInertialLoad
timryanb Apr 22, 2026
689affa
Fix missing global DVs in parallel design variable distribution
timryanb Apr 23, 2026
9cf924e
adding more tests
timryanb Apr 23, 2026
cf35790
clang format
timryanb Apr 23, 2026
0320dc8
Add getGlobalDVIndices method to TACSAssembler and update TACSProblem…
timryanb Apr 23, 2026
32dd5a5
Adding dv to pressure classes
timryanb Apr 23, 2026
29ebff9
Adding pressure dv to tests
timryanb Apr 23, 2026
2270192
clang format
timryanb Apr 23, 2026
398d977
memory error fixes
timryanb Apr 25, 2026
1f4d209
Adding dvs to traction classes
timryanb Apr 25, 2026
8603180
format
timryanb Apr 25, 2026
501b42b
Remove design variable map functionality from TACSCreator and related…
timryanb Apr 25, 2026
98ed1c4
Merge branch 'master' into aux_elem_dv_clean
timryanb Jun 5, 2026
0c69bce
generalizing MACH interface to allow promoting global DVs
timryanb Apr 29, 2026
7756a04
Fix lower bound type in `addConstraint` method for consistency
timryanb Jun 24, 2026
6284c71
Merge branch 'master' into aux_elem_dv_clean
timryanb Jul 10, 2026
a9e320b
ruff
timryanb Jul 10, 2026
3a43e20
ruff
timryanb Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 81 additions & 1 deletion src/TACSAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ TACSAssembler::TACSAssembler(MPI_Comm _tacs_comm, int _varsPerNode,
designNodeMap = NULL;
designExtDist = NULL;
designDepNodes = NULL;
numGlobalDVs = 0;
globalDVNums = NULL;

// Set the local element data to NULL
elementData = NULL;
Expand Down Expand Up @@ -281,6 +283,9 @@ TACSAssembler::~TACSAssembler() {
if (elementSensIData) {
delete[] elementSensIData;
}
if (globalDVNums) {
delete[] globalDVNums;
}

// Delete initial condition vectors
if (vars0) {
Expand Down Expand Up @@ -972,6 +977,7 @@ void TACSAssembler::setAuxElements(TACSAuxElements *auxElems) {
auxElements->decref();
}
auxElements = auxElems;
bool maxDVsUpdated = false;

// Check whether the auxiliary elements match
if (auxElements) {
Expand All @@ -987,6 +993,23 @@ void TACSAssembler::setAuxElements(TACSAuxElements *auxElems) {
aux[k].elem->getNumVariables()) {
fprintf(stderr, "[%d] Auxiliary element sizes do not match\n", mpiRank);
}

// Update the maximum number of element design variables
int numDVs = aux[k].elem->getDesignVarNums(aux[k].num, 0, NULL);
if (numDVs > maxElementDesignVars) {
maxElementDesignVars = numDVs;
maxDVsUpdated = true;
}
}

// If the buffers have already been allocated and the new max exceeds their
// current size, reallocate them so downstream code doesn't overflow.
if (maxDVsUpdated && elementSensData && elementSensIData) {
delete[] elementSensData;
delete[] elementSensIData;
elementSensData =
new TacsScalar[designVarsPerNode * maxElementDesignVars];
elementSensIData = new int[maxElementDesignVars];
}
}
}
Expand Down Expand Up @@ -2617,9 +2640,18 @@ int TACSAssembler::initialize() {

// Create the design variable node mapping
if (!designNodeMap) {
// Get the number of design variables
// Get the number of design variables from element scan
int numDVs = getNumDesignVars();

// Extend to cover any global DV indices not referenced by regular elements
// (e.g. DVs that will only be used by aux elements added after
// initialize())
for (int i = 0; i < numGlobalDVs; i++) {
if (globalDVNums[i] + 1 > numDVs) {
numDVs = globalDVNums[i] + 1;
}
}

if (mpiRank > 0) {
numDVs = 0;
}
Expand Down Expand Up @@ -2672,6 +2704,13 @@ int TACSAssembler::initialize() {
}
}

// Count Python-level global DV indices not locally owned
for (int i = 0; i < numGlobalDVs; i++) {
if (globalDVNums[i] < lower || globalDVNums[i] >= upper) {
dvLen++;
}
}

// Allocate space for absolutely everything!
int *allDVs = new int[dvLen];

Expand Down Expand Up @@ -2711,6 +2750,14 @@ int TACSAssembler::initialize() {
}
}

// Add any global DV indices not locally owned
for (int i = 0; i < numGlobalDVs; i++) {
if (globalDVNums[i] < lower || globalDVNums[i] >= upper) {
allDVs[dvLen] = globalDVNums[i];
dvLen++;
}
}

dvLen = TacsUniqueSort(dvLen, allDVs);
int *dvs = new int[dvLen];
memcpy(dvs, allDVs, dvLen * sizeof(int));
Expand Down Expand Up @@ -3062,6 +3109,39 @@ void TACSAssembler::setDesignNodeMap(int _designVarsPerNode,
designNodeMap = _designNodeMap;
}

/**
Store the global DV indices that must be distributed to all procs.

These indices are appended to the external DV distribution during
initialize(), ensuring that aux elements added after initialize() can
always access them via dvs->getValues().

@param n Number of global DV indices
@param dvNums Array of global DV indices (length n)
*/
void TACSAssembler::setGlobalDVIndices(int n, const int *dvNums) {
delete[] globalDVNums;
numGlobalDVs = n;
globalDVNums = new int[n];
memcpy(globalDVNums, dvNums, n * sizeof(int));
}

/**
Retrieve the global DV indices previously registered via setGlobalDVIndices().

Sets *dvNums to point to the internal array (do not free or modify).

@param dvNums Output pointer to the internal array of global DV indices
@return The number of global DV indices (same as n passed to
setGlobalDVIndices)
*/
int TACSAssembler::getGlobalDVIndices(const int **dvNums) {
if (dvNums) {
*dvNums = globalDVNums;
}
return numGlobalDVs;
}

/**
Set the dependent design variable information

Expand Down
8 changes: 8 additions & 0 deletions src/TACSAssembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ class TACSAssembler : public TACSObject {
// --------------------------------------------------
void setDesignNodeMap(int _designVarsPerNode,
TACSNodeMap *_designVarMap = NULL);

// Register global DV indices that must be distributed to all procs.
// These are added to designExtDist during initialize() so that aux
// elements added after initialize() can always access them.
void setGlobalDVIndices(int n, const int *dvNums);
int getGlobalDVIndices(const int **dvNums);
int setDesignDependentNodes(int numDepDesignVars, const int *_depNodePtr,
const int *_depNodes,
const double *_depNodeWeights);
Expand Down Expand Up @@ -406,6 +412,8 @@ class TACSAssembler : public TACSObject {
int numDependentNodes; // number of dependent nodes
int numMultiplierNodes; // number of multiplier nodes/elements
int designVarsPerNode; // number of design variables at each design "node"
int numGlobalDVs; // number of Python-level global DV indices
int *globalDVNums; // the global DV indices

// Maximum element information
int maxElementDesignVars; // maximum number of design variable
Expand Down
23 changes: 23 additions & 0 deletions src/TACSCreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ TACSCreator::TACSCreator(MPI_Comm _comm, int _vars_per_node) {
owned_elements = NULL;
owned_nodes = NULL;

// No global DVs registered yet
numGlobalDVs = 0;
globalDVNums = NULL;

// Set the elements array to NULL
elements = NULL;
element_creator = NULL;
Expand Down Expand Up @@ -162,6 +166,10 @@ TACSCreator::~TACSCreator() {
delete[] local_elem_id_nums;
}

if (globalDVNums) {
delete[] globalDVNums;
}

if (elements) {
for (int i = 0; i < num_elem_ids; i++) {
if (elements[i]) {
Expand Down Expand Up @@ -291,6 +299,16 @@ void TACSCreator::setElementCreator(TACSElement *(*func)(int, int)) {
element_creator = func;
}

/*
Store the global DV indices so they get included in designExtDist on all procs
*/
void TACSCreator::setGlobalDVIndices(int n, const int *dvNums) {
delete[] globalDVNums;
numGlobalDVs = n;
globalDVNums = new int[n];
memcpy(globalDVNums, dvNums, n * sizeof(int));
}

/*
Set the nodal locations
*/
Expand Down Expand Up @@ -873,6 +891,11 @@ TACSAssembler *TACSCreator::createTACS() {
delete[] bc_vals;
bc_vals = NULL;

// Pass global DV indices so they appear in designExtDist on all procs
if (numGlobalDVs > 0) {
tacs->setGlobalDVIndices(numGlobalDVs, globalDVNums);
}

// Use the reordering if the flag has been set in the
// TACSCreator object
if (use_reordering) {
Expand Down
8 changes: 8 additions & 0 deletions src/TACSCreator.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ class TACSCreator : public TACSObject {
// ------------------
void partitionMesh(int split_size = 0, const int *part = NULL);

// Set global DV indices to distribute to all procs
// -------------------------------------------------
void setGlobalDVIndices(int n, const int *dvNums);

// Set the elements into TACS creator
// ----------------------------------
void setElements(int _num_elems, TACSElement **_elements);
Expand Down Expand Up @@ -143,6 +147,10 @@ class TACSCreator : public TACSObject {
// The node locations
TacsScalar *Xpts;

// Global DV indices to force into designExtDist on all procs
int numGlobalDVs;
int *globalDVNums;

// Elements and the corresponding element id numbers
int num_elem_ids;
TACSElement **elements;
Expand Down
4 changes: 2 additions & 2 deletions src/elements/TACSConvectiveTraction2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void TACSConvectiveTraction2D::addResidual(
double weight = basis->getFaceQuadraturePoint(faceIndex, n, pt, tangent);

// Get the face normal
TacsScalar X[3], Xd[4], normal[3];
TacsScalar X[3], Xd[6], normal[3];
TacsScalar area = basis->getFaceNormal(faceIndex, n, Xpts, X, Xd, normal);

// Get the field value
Expand Down Expand Up @@ -132,7 +132,7 @@ void TACSConvectiveTraction2D::addJacobian(
double weight = basis->getFaceQuadraturePoint(faceIndex, n, pt, tangent);

// Get the face normal
TacsScalar X[3], Xd[4], normal[3];
TacsScalar X[3], Xd[6], normal[3];
TacsScalar area = basis->getFaceNormal(faceIndex, n, Xpts, X, Xd, normal);

// Get the field value
Expand Down
9 changes: 6 additions & 3 deletions src/elements/TACSElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ class TACSElement : public TACSObject {
Possibly NULL.
*/
virtual TACSElement *createElementTraction(int faceIndex,
const TacsScalar t[]) {
const TacsScalar t[],
const int *tracDVNums = NULL) {
return NULL;
}

Expand All @@ -213,7 +214,8 @@ class TACSElement : public TACSObject {
@return The TACSElement pressure class associated with this element.
Possibly NULL.
*/
virtual TACSElement *createElementPressure(int faceIndex, TacsScalar p) {
virtual TACSElement *createElementPressure(int faceIndex, TacsScalar p,
int pressureDVNum = -1) {
return NULL;
}

Expand All @@ -223,7 +225,8 @@ class TACSElement : public TACSObject {
@return The TACSElement inertial force class associated with this element.
Possibly NULL.
*/
virtual TACSElement *createElementInertialForce(const TacsScalar g[]) {
virtual TACSElement *createElementInertialForce(
const TacsScalar g[], const int *inertiaVecDVNums = NULL) {
return NULL;
}

Expand Down
15 changes: 9 additions & 6 deletions src/elements/TACSElement2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,24 @@ TACSElementBasis *TACSElement2D::getElementBasis() { return basis; }
TACSElementModel *TACSElement2D::getElementModel() { return model; }

TACSElement *TACSElement2D::createElementTraction(int faceIndex,
const TacsScalar t[]) {
const TacsScalar t[],
const int *tracDVNums) {
int varsPerNode = getVarsPerNode();
return new TACSTraction2D(varsPerNode, faceIndex, basis, t);
return new TACSTraction2D(varsPerNode, faceIndex, basis, t, 1, tracDVNums);
}

TACSElement *TACSElement2D::createElementPressure(int faceIndex, TacsScalar p) {
TACSElement *TACSElement2D::createElementPressure(int faceIndex, TacsScalar p,
int pressureDVNum) {
int varsPerNode = getVarsPerNode();
return new TACSPressure2D(varsPerNode, faceIndex, basis, p);
return new TACSPressure2D(varsPerNode, faceIndex, basis, p, pressureDVNum);
}

TACSElement *TACSElement2D::createElementInertialForce(
const TacsScalar inertiaVec[]) {
const TacsScalar inertiaVec[], const int *inertiaVecDVNums) {
int varsPerNode = getVarsPerNode();
TACSConstitutive *con = model->getConstitutive();
return new TACSInertialForce2D(varsPerNode, con, basis, inertiaVec);
return new TACSInertialForce2D(varsPerNode, con, basis, inertiaVec,
inertiaVecDVNums);
}

int TACSElement2D::getNumQuadraturePoints() {
Expand Down
9 changes: 6 additions & 3 deletions src/elements/TACSElement2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@ class TACSElement2D : public TACSElement {
ElementType getElementType();
TACSElementBasis *getElementBasis();
TACSElementModel *getElementModel();
TACSElement *createElementTraction(int faceIndex, const TacsScalar t[]);
TACSElement *createElementPressure(int faceIndex, TacsScalar p);
TACSElement *createElementInertialForce(const TacsScalar inertiaVec[]);
TACSElement *createElementTraction(int faceIndex, const TacsScalar t[],
const int *tracDVNums = NULL);
TACSElement *createElementPressure(int faceIndex, TacsScalar p,
int pressureDVNum = -1);
TACSElement *createElementInertialForce(const TacsScalar inertiaVec[],
const int *inertiaVecDVNums = NULL);
int getNumQuadraturePoints();
double getQuadratureWeight(int n);
double getQuadraturePoint(int n, double pt[]);
Expand Down
15 changes: 9 additions & 6 deletions src/elements/TACSElement3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,24 @@ int TACSElement3D::getDesignVarsPerNode() {
}

TACSElement *TACSElement3D::createElementTraction(int faceIndex,
const TacsScalar t[]) {
const TacsScalar t[],
const int *tracDVNums) {
int varsPerNode = getVarsPerNode();
return new TACSTraction3D(varsPerNode, faceIndex, basis, t);
return new TACSTraction3D(varsPerNode, faceIndex, basis, t, 1, tracDVNums);
}

TACSElement *TACSElement3D::createElementPressure(int faceIndex, TacsScalar p) {
TACSElement *TACSElement3D::createElementPressure(int faceIndex, TacsScalar p,
int pressureDVNum) {
int varsPerNode = getVarsPerNode();
return new TACSPressure3D(varsPerNode, faceIndex, basis, p);
return new TACSPressure3D(varsPerNode, faceIndex, basis, p, pressureDVNum);
}

TACSElement *TACSElement3D::createElementInertialForce(
const TacsScalar inertiaVec[]) {
const TacsScalar inertiaVec[], const int *inertiaVecDVNums) {
int varsPerNode = getVarsPerNode();
TACSConstitutive *con = model->getConstitutive();
return new TACSInertialForce3D(varsPerNode, con, basis, inertiaVec);
return new TACSInertialForce3D(varsPerNode, con, basis, inertiaVec,
inertiaVecDVNums);
}

TACSElement *TACSElement3D::createElementCentrifugalForce(
Expand Down
9 changes: 6 additions & 3 deletions src/elements/TACSElement3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ class TACSElement3D : public TACSElement {
ElementType getElementType();
TACSElementBasis *getElementBasis();
TACSElementModel *getElementModel();
TACSElement *createElementTraction(int faceIndex, const TacsScalar t[]);
TACSElement *createElementPressure(int faceIndex, TacsScalar p);
TACSElement *createElementInertialForce(const TacsScalar inertiaVec[]);
TACSElement *createElementTraction(int faceIndex, const TacsScalar t[],
const int *tracDVNums = NULL);
TACSElement *createElementPressure(int faceIndex, TacsScalar p,
int pressureDVNum = -1);
TACSElement *createElementInertialForce(const TacsScalar inertiaVec[],
const int *inertiaVecDVNums = NULL);
TACSElement *createElementCentrifugalForce(const TacsScalar omegaVec[],
const TacsScalar rotCenter[],
const bool first_order = false);
Expand Down
Loading
Loading