From 0a900f282ab7c2f5e0ada7e0c051e523b5af635e Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:46:22 -0800 Subject: [PATCH 001/161] Fix memory corruption when getTangent(k=...) is used without prior transient analysis. Add unset methods for LinearSOE and TransientIntegrator. --- SRC/runtime/commands/analysis/analysis.cpp | 4 +- SRC/runtime/runtime/BasicAnalysisBuilder.cpp | 52 ++++++++++++++++---- SRC/runtime/runtime/BasicAnalysisBuilder.h | 10 +++- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/SRC/runtime/commands/analysis/analysis.cpp b/SRC/runtime/commands/analysis/analysis.cpp index a0aa81e5ef..c51e699b8f 100644 --- a/SRC/runtime/commands/analysis/analysis.cpp +++ b/SRC/runtime/commands/analysis/analysis.cpp @@ -140,7 +140,7 @@ specifyAnalysis(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, } else { opserr << OpenSees::PromptValueError << "Analysis type '" << argv[1] - << "' does not exists (Static or Transient only). \n"; + << "' does not exists (Static or Transient only). \n"; return TCL_ERROR; } @@ -675,9 +675,11 @@ printA(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, TCL_Char ** con builder->getDomain()->revertToLastCommit(); // put the original SOE back. + builder->unset(theSOE); if (oldSOE != nullptr) builder->set(oldSOE, true); + builder->unset(integrator); if (oldint != nullptr) builder->set(*oldint, true); diff --git a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp index 677fcf08c0..7701b73e7f 100644 --- a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp +++ b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp @@ -155,14 +155,15 @@ BasicAnalysisBuilder::setLinks(CurrentAnalysis flag) if (theTest && theAlgorithm) theAlgorithm->setConvergenceTest(theTest); + if (theAnalysisModel && theHandler) + theHandler->setLinks(*theAnalysisModel); switch (flag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: break; case TRANSIENT_ANALYSIS: - if (theAnalysisModel && theTransientIntegrator && theHandler) - theHandler->setLinks(*theAnalysisModel); if (theTransientIntegrator && theSOE && theTest && theAlgorithm) theAlgorithm->setLinks(*theTransientIntegrator, *theSOE, theTest); @@ -177,9 +178,6 @@ BasicAnalysisBuilder::setLinks(CurrentAnalysis flag) break; case STATIC_ANALYSIS: - if (theAnalysisModel && theStaticIntegrator && theHandler) - theHandler->setLinks(*theAnalysisModel); - if (theAnalysisModel && theSOE && theTest && theStaticIntegrator) theStaticIntegrator->setLinks(*theAnalysisModel, *theSOE, theTest); @@ -205,6 +203,7 @@ BasicAnalysisBuilder::initialize() switch (this->CurrentAnalysisFlag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: break; case STATIC_ANALYSIS: @@ -323,6 +322,7 @@ BasicAnalysisBuilder::domainChanged() int BasicAnalysisBuilder::analyze(int num_steps, double size_steps, int flag) { + int status = -1; switch (this->CurrentAnalysisFlag) { @@ -803,6 +803,7 @@ BasicAnalysisBuilder::fillDefaults(BasicAnalysisBuilder::CurrentAnalysis flag) switch (flag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: break; case STATIC_ANALYSIS: @@ -868,12 +869,15 @@ void BasicAnalysisBuilder::newEigenAnalysis(int typeSolver, double shift) { assert(theAnalysisModel != nullptr); - if (theHandler == nullptr) theHandler = new TransformationConstraintHandler(); - if (this->CurrentAnalysisFlag == EMPTY_ANALYSIS) - this->CurrentAnalysisFlag = TRANSIENT_ANALYSIS; + if (theNumberer == nullptr) + theNumberer = new DOF_Numberer(*(new RCM(false))); + + if (theSOE == nullptr) + // TODO: CHANGE TO MORE GENERAL SOE + theSOE = new ProfileSPDLinSOE(*(new ProfileSPDLinDirectSolver())); // create a new eigen system and solver @@ -883,8 +887,9 @@ BasicAnalysisBuilder::newEigenAnalysis(int typeSolver, double shift) theEigenSOE = nullptr; // } } - this->fillDefaults(this->CurrentAnalysisFlag); - this->setLinks(this->CurrentAnalysisFlag); + + this->fillDefaults(EIGEN_ANALYSIS); + this->setLinks(EIGEN_ANALYSIS); if (theEigenSOE == nullptr) { domainStamp = 0; @@ -1077,6 +1082,7 @@ BasicAnalysisBuilder::analyzeGradient() { switch (this->CurrentAnalysisFlag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: return -1; case STATIC_ANALYSIS: @@ -1096,6 +1102,7 @@ BasicAnalysisBuilder::setGradientType(int flag) { switch (this->CurrentAnalysisFlag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: return -1; case STATIC_ANALYSIS: @@ -1113,4 +1120,29 @@ BasicAnalysisBuilder::setGradientType(int flag) break; } return 0; +} + + +void +BasicAnalysisBuilder::Print(OPS_Stream &s, int flag) +{ + s << " Analysis Type: "; + switch (this->CurrentAnalysisFlag) { + case STATIC_ANALYSIS: + s << " Static"; + break; + case TRANSIENT_ANALYSIS: + s << " Transient"; + break; + case EMPTY_ANALYSIS: + s << " No Analysis Specified\n"; + return; + case EIGEN_ANALYSIS: + s << " Eigenvalue"; + break; + } + s << " (" + << int(0 != this->theStaticIntegrator) << ", " + << int(0 != this->theTransientIntegrator) << ")"; + s << "\n"; } \ No newline at end of file diff --git a/SRC/runtime/runtime/BasicAnalysisBuilder.h b/SRC/runtime/runtime/BasicAnalysisBuilder.h index 2e9d4674f4..4962fb06cb 100644 --- a/SRC/runtime/runtime/BasicAnalysisBuilder.h +++ b/SRC/runtime/runtime/BasicAnalysisBuilder.h @@ -49,6 +49,7 @@ class StaticIntegrator; class TransientIntegrator; class ConvergenceTest; + class BasicAnalysisBuilder { public: @@ -57,6 +58,7 @@ class BasicAnalysisBuilder enum CurrentAnalysis { EMPTY_ANALYSIS, + EIGEN_ANALYSIS, STATIC_ANALYSIS, TRANSIENT_ANALYSIS }; @@ -71,8 +73,14 @@ class BasicAnalysisBuilder void set(DOF_Numberer*); void set(EquiSolnAlgo*); void set(LinearSOE*, bool free=true); + void unset(LinearSOE&) { + theSOE = nullptr; + } void set(StaticIntegrator&); void set(TransientIntegrator&, bool free=true); + void unset(TransientIntegrator&) { + theTransientIntegrator = nullptr; + } void set(ConvergenceTest*); void set(EigenSOE&); LinearSOE* getLinearSOE(); @@ -103,6 +111,7 @@ class BasicAnalysisBuilder int analyzeTransient(int numSteps, double dT); int analyzeVariable(int numSteps, double dT, double dtMin, double dtMax, int Jd); + void Print(OPS_Stream &s, int flag); private: int analyzeStep(double dT); int analyzeSubLevel(int level, double dT); @@ -143,7 +152,6 @@ class BasicAnalysisBuilder bool freeSOE = true; bool freeTI = true; - }; #endif From f14a6dad8ab0ef48edcc09a1d31bc71c9493fdea Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:54:24 -0800 Subject: [PATCH 002/161] Create FrameTraceSection3d.h --- SRC/material/Frame/FrameTraceSection3d.h | 187 +++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 SRC/material/Frame/FrameTraceSection3d.h diff --git a/SRC/material/Frame/FrameTraceSection3d.h b/SRC/material/Frame/FrameTraceSection3d.h new file mode 100644 index 0000000000..1311bf0780 --- /dev/null +++ b/SRC/material/Frame/FrameTraceSection3d.h @@ -0,0 +1,187 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +//===----------------------------------------------------------------------===// +// +// Description: FrameTraceSection3d provides the abstraction of a +// 3D beam section discretized by fibers. The section stiffness and +// stress resultants are obtained by summing fiber contributions. +// +// Written: cmp +// Created: Jan. 2026 +// +#ifndef FrameTraceSection3d_h +#define FrameTraceSection3d_h +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class NDMaterial; +class Response; + +namespace OpenSees { +class FrameTraceSection3d : public FrameSection +{ + public: + FrameTraceSection3d(); + FrameTraceSection3d(int tag, int numFibers); + private: + FrameTraceSection3d(const FrameTraceSection3d &); + public: + ~FrameTraceSection3d(); + + int addFiber(NDMaterial&, double area, double y, double z=0.0); + + // + const char *getClassType() const { + return "FrameTraceSection3d"; + } + + int setTrialSectionDeformation(const Vector &e); + const Vector &getSectionDeformation(); + + int getIntegral(Field field, State state, double& value) const final; + const Vector &getStressResultant() override; + const Matrix &getSectionTangent() override; + const Matrix &getInitialTangent() override; + MatrixND<12,12> getFullTangent(State state) override; + + int commitState() override; + int revertToLastCommit() override; + int revertToStart() override; + + FrameSection *getFrameCopy() override; + const ID &getType() override; + int getOrder () const override; + + // MovableObject + int sendSelf(int tag, Channel &) override; + int recvSelf(int tag, Channel &, FEM_ObjectBroker &) override; + // TaggedObject + void Print(OPS_Stream &s, int flag) override; + + Response *setResponse(const char **argv, int argc, OPS_Stream &) override; + int getResponse(int responseID, Information &) override; + + + // Sensitivity + int setParameter(const char **argv, int argc, Parameter &) override; + int updateParameter(int id, Information &) override; + int activateParameter(int id) override; + const Vector& getStressResultantSensitivity(int gradIndex, bool conditional); + const Vector& getSectionDeformationSensitivity(int gradIndex); + const Matrix& getInitialTangentSensitivity(int gradIndex); + int commitSensitivity(const Vector& strainGrad, int gradIndex, int numGrads); + + + private: + constexpr static int nsr = 12; + constexpr static int nwm = 3; // Number of warping modes + + struct Tangent { + OpenSees::MatrixND<6,6> se; + OpenSees::MatrixND<6,3> sw, sv; + OpenSees::MatrixND<3,3> ww, vv, wv; + void zero() { + se.zero(); sw.zero(); sv.zero(); + ww.zero(); wv.zero(); + vv.zero(); + } + }; + Tangent K_pres; + std::shared_ptr K_init; + + int form_shifts(MatrixND<3,6>& Lw, MatrixND<6,6>& Lr) const; + + int stateDetermination(Tangent& K, VectorND* s_trial, const VectorND * const e_trial, int tangentFlag); + + struct Param { + enum : int { + FiberWarpX=0, + FiberWarpXY, + FiberWarpXZ, + FiberWarpY, + FiberWarpYY, + FiberWarpYZ, + FiberWarpZ, + FiberWarpZY, + FiberWarpZZ, + FiberY, + FiberZ, + FiberArea, + ShearAlignYY, + ShearAlignZZ, + ShearAlignYZ, + ShearAlignZY, + ShiftTwistY, + ShiftTwistZ, + ShiftAxialY, + ShiftAxialZ, + FiberFieldBase=10000 + }; + }; + + enum: int { + CurrentTangent, InitialTangent + }; + + enum : int { + inx = 0, + iny, + inz, + + imx, + imy, + imz, + + iwx, + iwy, + iwz, + + ivx, + ivy, + ivz + }; + + struct FiberData { + double area; + using WarpArray = std::array,nwm>; + WarpArray warp{{{0}}}; + OpenSees::VectorND<2> r; + }; + const std::shared_ptr> fibers; + std::vector materials; + + VectorND s, e; + Vector s_wrap, e_wrap; + Matrix3D shear_align; + VectorND<3> shift_twist, shift_axial; + Vector3D centroid; + double nubar; + enum class FiberState { + Dirty, Clean + } fiber_state; + + bool wagner; + int parameterID; + + static ID code; + + Vector dedh; +}; + +#endif +} // namespace OpenSees \ No newline at end of file From 3b5bd3f037c69908f178fb2849bcbaadd0e0726f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:54:37 -0800 Subject: [PATCH 003/161] Create FrameTraceSection3d.cpp --- SRC/material/Frame/FrameTraceSection3d.cpp | 1258 ++++++++++++++++++++ 1 file changed, 1258 insertions(+) create mode 100644 SRC/material/Frame/FrameTraceSection3d.cpp diff --git a/SRC/material/Frame/FrameTraceSection3d.cpp b/SRC/material/Frame/FrameTraceSection3d.cpp new file mode 100644 index 0000000000..eaf7d73925 --- /dev/null +++ b/SRC/material/Frame/FrameTraceSection3d.cpp @@ -0,0 +1,1258 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// +// +// Description: This file contains the class implementation of FrameTraceSection3d. +// FrameTraceSection3d provides the abstraction of a 3D beam section discretized by fibers. +// +// Written: cmp +// Created: Jan. 2026 +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "FrameTraceSection3d.h" +#include +#include +#include +#include +#include +typedef SensitiveResponse SectionResponse; +#include +#include + +#define SEC_TAG_FrameTraceSection3d 0 + +using namespace OpenSees; + +ID FrameTraceSection3d::code(nsr); + +FrameTraceSection3d::FrameTraceSection3d(int tag, int num): + FrameSection(tag, SEC_TAG_FrameTraceSection3d), + s(), e(), + e_wrap(e), s_wrap(s), + shear_align{}, + shift_twist{}, + shift_axial{}, + centroid{}, + nubar(0.0), + parameterID(0), dedh(nsr), + fibers(new std::vector), + K_init(new Tangent), + fiber_state(FiberState::Clean) +{ + code(inx) = FrameStress::N; + code(iny) = FrameStress::Vy; + code(inz) = FrameStress::Vz; + code(imx) = FrameStress::T; + code(imy) = FrameStress::My; + code(imz) = FrameStress::Mz; + code(iwx) = FrameStress::Bimoment; + code(iwy) = FrameStress::By; + code(iwz) = FrameStress::Bz; + code(ivx) = FrameStress::Bishear; + code(ivy) = FrameStress::Qy; + code(ivz) = FrameStress::Qz; + + wagner = getenv("Wagner") != nullptr; +} + + +// for recvSelf +FrameTraceSection3d::FrameTraceSection3d(): + FrameSection(0, SEC_TAG_FrameTraceSection3d), + s(), e(), + e_wrap(e), s_wrap(s), + shear_align{}, + shift_twist{}, + shift_axial{}, + centroid{}, + nubar(0.0), + parameterID(0), dedh(nsr), + fibers(new std::vector), + fiber_state(FiberState::Clean) +{ + code(inx) = FrameStress::N; + code(iny) = SECTION_RESPONSE_VY; + code(inz) = SECTION_RESPONSE_VZ; + code(imx) = SECTION_RESPONSE_T; + code(imy) = SECTION_RESPONSE_MY; + code(imz) = SECTION_RESPONSE_MZ; + code(iwx) = FrameStress::Bimoment; + code(iwy) = FrameStress::By; + code(iwz) = FrameStress::Bz; + code(ivx) = FrameStress::Bishear; + code(ivy) = FrameStress::Qy; + code(ivz) = FrameStress::Qz; + wagner = getenv("Wagner") != nullptr; +} + +// Used in getCopy to create an element instance from a reference instance +FrameTraceSection3d::FrameTraceSection3d(const FrameTraceSection3d &other) + : FrameSection(other.getTag(), other.getClassTag()), + K_pres(other.K_pres), + K_init(other.K_init), + fibers(other.fibers), + s(), + e(), + s_wrap(s), + e_wrap(e), + shear_align(other.shear_align), + shift_twist(other.shift_twist), + shift_axial(other.shift_axial), + centroid(other.centroid), + nubar(other.nubar), + wagner(other.wagner), + fiber_state(FiberState::Clean), + parameterID(0) +{ + materials.reserve(other.materials.size()); + for (int i = 0; i < other.materials.size(); i++) + materials.push_back(other.materials[i]->getCopy("BeamFiber")); + // materials[i] = other.materials[i]->getCopy("BeamFiber"); + + this->revertToStart(); +} + + +int +FrameTraceSection3d::getIntegral(Field field, State state, double& value) const +{ + value = 0.0; + + const int nf = fibers->size(); + switch (field) { + case Field::Unit: + for (int i=0; iFrameSection::getIntegral(field, state, value) == 0) + return 0; + + for (int i=0; igetRho() != 0) + value += A*density; + else + return -1; + } + return 0; + + case Field::UnitY: // TODO: Centroid + for (int i=0; i,3> warp{0}; + FiberData fiber {Area, warp, {yLoc, zLoc}}; + fibers->emplace_back(fiber); + + materials.emplace_back(theMat.getCopy("BeamFiber")); + + if (materials[materials.size()-1] == nullptr) + return -1; + + fiber_state = FiberState::Dirty; + return materials.size()-1; +} + + + +FrameTraceSection3d::~FrameTraceSection3d() +{ + for (auto material : materials) { + if (material != nullptr) + delete material; + } +} + + +int +FrameTraceSection3d::setTrialSectionDeformation(const Vector &e_trial) +{ + e = e_trial; + s.zero(); + return stateDetermination(K_pres, &s, &e, CurrentTangent); +} + + +FrameSection* +FrameTraceSection3d::getFrameCopy() +{ + + double area = 0.0; + if (fiber_state == FiberState::Dirty) { + nubar = 0.0; + centroid.zero(); + const int nf = fibers->size(); + for (int i = 0; i < nf; i++) { + NDMaterial &theMat = *materials[i]; + auto & fiber = (*fibers)[i]; + const Matrix & tangent = theMat.getInitialTangent(); + double nu = tangent(0,0)/(2.0*tangent(1,1)) - 1.0; + area += fiber.area; + nubar += nu*fiber.area; + centroid[1] += fiber.r[0]*fiber.area; + centroid[2] += fiber.r[1]*fiber.area; + } + centroid /= area; + nubar /= area; + } + + fiber_state = FiberState::Clean; + + return new FrameTraceSection3d(*this); +} + +int +FrameTraceSection3d::form_shifts(MatrixND<3,6>& Lw, MatrixND<6,6>& Lr) const +{ + constexpr static Matrix3D oneS {{ + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + }}; + // iesan_center + + Vector3D iesan_center{}; + + const int nf = fibers->size(); + for (int i = 0; i < nf; i++) { + auto & fiber = (*fibers)[i]; + const FiberData::WarpArray& w = fiber.warp; + const Vector3D r = {0.0, fiber.r[0], fiber.r[1]}; + + Matrix3D Aw {{ + 0.0, w[0][1], w[0][2], + 0.0, w[1][1], w[1][2], + 0.0, w[2][1], w[2][2] + }}; + const Vector3D rxi { + 0.0, + r[2], + -r[1] + }; + + Aw.addTensorProduct(r, r, -nubar); + Aw.addMatrix(oneS, 0.5*r.dot(r)*nubar); + // + roc + Aw.addTensorProduct(r, centroid, nubar); + + iesan_center += (Aw^rxi)*fiber.area; + iesan_center[0] -= r.dot(r)*fiber.area; + } + const double J = -iesan_center[0]; + iesan_center[1] /= J; + iesan_center[2] /= J; + + const Vector3D zg = -1.0*(shear_align*shift_twist); + + + Lr.assemble(oneS, 0,0, -1.0); + { + const Vector3D a = shear_align^iesan_center; + Vector3D b = (shear_align*shift_axial); + Lr(3,1) = a[1]-b[1]; + Lr(3,2) = a[2]-b[2]; + Lr(3,3) = zg.dot(iesan_center - shift_axial); + Lw(0,1) = a[1]-b[1]; + Lw(0,2) = a[2]-b[2]; + } + // Lw + Lw(0,3) = 1.0 + zg.dot(iesan_center - shift_axial); + Lw.assemble(shear_align, 0,0, 1.0); + Lw(1, 3) = zg[1]; + Lw(2, 3) = zg[2]; + return 0; +} + + +int +FrameTraceSection3d::stateDetermination(Tangent& K, VectorND* s_trial, const VectorND * const e_trial, int tangentFlag) +{ + + const bool do_shift = shear_align.norm() != 0.0; + + + Vector3D gamma{}, kappa{}, dalpha{}, alpha{}; + if (e_trial != nullptr) { + gamma = Vector3D { (*e_trial)(inx), (*e_trial)(iny), (*e_trial)(inz) }; + kappa = Vector3D { (*e_trial)(imx), (*e_trial)(imy), (*e_trial)(imz) }; + dalpha = Vector3D { (*e_trial)(iwx), (*e_trial)(iwy), (*e_trial)(iwz) }; + alpha = Vector3D { (*e_trial)(ivx), (*e_trial)(ivy), (*e_trial)(ivz) }; + } + const VectorND<6> enm{ + gamma[0], + gamma[1], + gamma[2], + kappa[0], + kappa[1], + kappa[2] + }; + + + constexpr static Matrix3D oneS {{ + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + }}; + + // Lr + MatrixND<6,6> Lr{}; + MatrixND<3,6> Lw{}; + this->form_shifts(Lw, Lr); + + // + if (s_trial != nullptr) + s_trial->zero(); + + K.zero(); + + // + // integrate over fibers + // + int res = 0; + const int nf = fibers->size(); + for (int i = 0; i < nf; i++) { + + NDMaterial &theMat = *materials[i]; + auto & fiber = (*fibers)[i]; + const FiberData::WarpArray& w = fiber.warp; + const Vector3D r = {0.0, fiber.r[0], fiber.r[1]}; + double tr2 = 0; + + // NOTE: Matrix 3D is column major so these are transposed. + const MatrixND<6,3> As {{ + 1.0, 0.0, 0.0, 0.0, r[2], -r[1], + 0.0, 1.0, 0.0, -r[2], 0.0, 0.0, + 0.0, 0.0, 1.0, r[1], 0.0, 0.0 + }}; + const Matrix3D iow {{ + w[0][0], 0.0, 0.0, + w[1][0], 0.0, 0.0, + w[2][0], 0.0, 0.0 + }}; + + const Matrix3D iodw {{ + 0.0, w[0][1], w[0][2], + 0.0, w[1][1], w[1][2], + 0.0, w[2][1], w[2][2] + }}; + + MatrixND<3,6> Ae = As.transpose(); + if (do_shift) [[likely]] { + Ae.addMatrixTransposeProduct(As, Lr); + + Matrix3D Aw = iodw; + // -(dev ror)Xi + Aw.addTensorProduct(r, r, -nubar); + Aw.addMatrix(oneS, 0.5*r.dot(r)*nubar); + // + roc + Aw.addTensorProduct(r, centroid, nubar); + + Ae.addMatrixProduct(Aw, Lw, 1.0); + } + + + if (e_trial != nullptr) { + // Form material strain + Vector3D eps = Ae*enm; + if (!do_shift) + for (int k=0; k +FrameTraceSection3d::getFullTangent(State state) +{ + MatrixND<12,12> K{}; + + if (state == State::Init) + this->stateDetermination(K_pres, nullptr, nullptr, InitialTangent); + // else + // this->stateDetermination(K_pres, nullptr, nullptr, CurrentTangent); + + K.assemble(K_pres.se, 0, 0, 1.0); + K.assemble(K_pres.sw, 0, 6, 1.0); + K.assemble(K_pres.sv, 0, 9, 1.0); + + K.assemble(K_pres.ww, 6, 6, 1.0); + K.assemble(K_pres.wv, 6, 9, 1.0); + K.assemble(K_pres.vv, 9, 9, 1.0); + + K.assembleTranspose(K_pres.sw, 6, 0, 1.0); + K.assembleTranspose(K_pres.sv, 9, 0, 1.0); + K.assembleTranspose(K_pres.wv, 9, 6, 1.0); + return K; +} + +const Matrix& +FrameTraceSection3d::getSectionTangent() +{ +#ifndef SEES_SECTION_THREADS + static MatrixND K; + static Matrix K_wrap(K); + K_wrap.setData(K); +#endif + + K = this->getFullTangent(State::Pres); + + return K_wrap; +} + + +const Matrix& +FrameTraceSection3d::getInitialTangent() +{ + static MatrixND K; + static Matrix wrap(K); //, nsr, nsr); + + K = this->getFullTangent(State::Init); + // K_pres.zero(); + // this->stateDetermination(K_pres, nullptr, nullptr, InitialTangent); + + // K.zero(); + // K.assemble(K_pres.se, 0, 0, 1.0); + // K.assemble(K_pres.sw, 0, 6, 1.0); + // K.assemble(K_pres.sv, 0, 9, 1.0); + + // K.assemble(K_pres.ww, 6, 6, 1.0); + // K.assemble(K_pres.wv, 6, 9, 1.0); + // K.assemble(K_pres.vv, 9, 9, 1.0); + + // K.assembleTranspose(K_pres.sw, 6, 0, 1.0); + // K.assembleTranspose(K_pres.sv, 9, 0, 1.0); + // K.assembleTranspose(K_pres.wv, 9, 6, 1.0); + return wrap; +} + + + +const Vector& +FrameTraceSection3d::getStressResultant() +{ + return s_wrap; +} + + + +const ID& +FrameTraceSection3d::getType() +{ + return code; +} + + +int +FrameTraceSection3d::getOrder() const +{ + return nsr; +} + + +int +FrameTraceSection3d::commitState() +{ + int err = 0; + + for (auto& material: materials) + err += material->commitState(); + + return err; +} + +int +FrameTraceSection3d::revertToLastCommit() +{ + int err = 0; + for (auto& material : materials) + err += material->revertToLastCommit(); + + // TODO: we may need to recompute e to be perfectly consistent + // when Wagner is enabled. + s.zero(); + err += this->stateDetermination(K_pres, &s, nullptr, CurrentTangent); + + return err; +} + + +int +FrameTraceSection3d::revertToStart() +{ + int err = 0; + for (auto& material: materials) + err += material->revertToStart(); + + s.zero(); + e.zero(); + err += this->stateDetermination(K_pres, &s, nullptr, CurrentTangent); + + return err; +} + + +int +FrameTraceSection3d::sendSelf(int commitTag, Channel &) +{ + return -1; +} + +int +FrameTraceSection3d::recvSelf(int , Channel &, + FEM_ObjectBroker &) +{ + return -1; +} + + +Response* +FrameTraceSection3d::setResponse(const char **argv, int argc, + OPS_Stream &output) +{ + Response *theResponse = nullptr; + + if (argc > 2 && strcmp(argv[0], "fiber") == 0) { + + + int key = fibers->size(); + int passarg = 2; + + if (argc <= 3) { // fiber number was input directly + key = atoi(argv[1]); + } + + else if (argc > 4) { // find fiber closest to coord. with mat tag + + int matTag = atoi(argv[3]); + double yCoord = atof(argv[1]); + double zCoord = atof(argv[2]); + VectorND<2> r_given{{yCoord, zCoord}}; + double closestDist = 0; + + // Find first fiber with specified material tag + const int nf = fibers->size(); + int j; + for (j = 0; j < nf; j++) { + auto& fiber = (*fibers)[j]; + if (matTag == materials[j]->getTag()) { + const VectorND<2> dr = fiber.r - r_given; + closestDist = dr.dot(dr); + key = j; + break; + } + } + + // Search the remaining fibers + double distance; + for ( ; j < nf; j++) { + auto& fiber = (*fibers)[j]; + if (matTag == materials[j]->getTag()) { + const VectorND<2> dr = fiber.r - r_given; + distance = dr.dot(dr); + if (distance < closestDist) { + closestDist = distance; + key = j; + } + } + } + passarg = 4; + } + + else { + // fiber near-to coordinate specified + VectorND<2> r_given{ + atof(argv[1]), atof(argv[2]) + }; + + VectorND<2> dr = (*fibers)[0].r - r_given; + double closestDist = dr.dot(dr); + key = 0; + double distance; + + const int nf = fibers->size(); + for (int j = 1; j < nf; j++) { + auto& fiber = (*fibers)[j]; + VectorND<2> dr = fiber.r - r_given; + distance = dr.dot(dr); + if (distance < closestDist) { + closestDist = distance; + key = j; + } + } + passarg = 3; + } + + if (key < fibers->size() && key >= 0) { + output.tag("FiberOutput"); + output.attr("y", (*fibers)[key].r[0]); + output.attr("z", (*fibers)[key].r[1]); + output.attr("area", (*fibers)[key].area); + + theResponse = materials[key]->setResponse(&argv[passarg], argc-passarg, output); + + output.endTag(); + } + } + + if (theResponse == nullptr) + return FrameSection::setResponse(argv, argc, output); + + return theResponse; +} + + +int +FrameTraceSection3d::getResponse(int responseID, Information §Info) +{ + return FrameSection::getResponse(responseID, sectInfo); +} + +int +FrameTraceSection3d::setParameter(const char **argv, int argc, Parameter ¶m) +{ + if (argc < 1) + return -1; + + int result = -1; + + if (strcmp(argv[0], "warp") == 0) { + // ... warp $fiberID $warpField + if (argc < 3) { + opserr << "FrameTraceSection3d::setParameter - fiberID is required\n"; + return -1; + } + int fiberID = atoi(argv[1]); + if (fiberID < 0 || fiberID >= fibers->size()) { + opserr << "FrameTraceSection3d::setParameter - fiberID " << fiberID << " out of range\n"; + return -1; + } + + int field = atoi(argv[2]); + + return param.addObject(Param::FiberFieldBase+fiberID*100+field, this); + } + + else if (strcmp(argv[0], "shift_shear") == 0) { + // ... shift_shear i j + if (argc < 3) { + opserr << "FrameTraceSection3d::setParameter - i, j, value are required\n"; + return -1; + } + int i = atoi(argv[1]); + int j = atoi(argv[2]); + if ((i == 1) && (j == 1)) + return param.addObject(Param::ShearAlignYY, this); + else if ((i == 2) && (j == 2)) + return param.addObject(Param::ShearAlignZZ, this); + else if ((i == 1) && (j == 2)) + return param.addObject(Param::ShearAlignYZ, this); + else if ((i == 2) && (j == 1)) + return param.addObject(Param::ShearAlignZY, this); + else { + opserr << "FrameTraceSection3d::setParameter - invalid i, j: " << i << ", " << j << "\n"; + return -1; + } + } + + else if (strcmp(argv[0], "shift_axial") == 0) { + // ... shift_axial i + if (argc < 2) { + opserr << "FrameTraceSection3d::setParameter - i is required\n"; + return -1; + } + int i = atoi(argv[1]); + switch (i) { + case 1: + return param.addObject(Param::ShiftAxialY, this); + case 2: + return param.addObject(Param::ShiftAxialZ, this); + default: + opserr << "FrameTraceSection3d::setParameter - invalid i: " << i << "\n"; + return -1; + } + } + + else if (strcmp(argv[0], "shift_twist") == 0) { + // ... shift_twist i + if (argc < 2) { + opserr << "FrameTraceSection3d::setParameter - i is required\n"; + return -1; + } + int i = atoi(argv[1]); + switch (i) { + case 1: + return param.addObject(Param::ShiftTwistY, this); + case 2: + return param.addObject(Param::ShiftTwistZ, this); + default: + opserr << "FrameTraceSection3d::setParameter - invalid i: " << i << "\n"; + return -1; + } + } + + // Check if the parameter belongs to the material + if (strstr(argv[0], "material") != 0) { + + if (argc < 3) + return 0; + + // Get the tag of the material + int materialTag = atoi(argv[1]); + + // Loop over fibers to find the right material + for (auto& material: materials) + if (materialTag == material->getTag()) { + int ok = material->setParameter(&argv[2], argc-2, param); + if (ok != -1) + result = ok; + } + return result; + } + + int ok = 0; + for (auto& material: materials) { + ok = material->setParameter(argv, argc, param); + if (ok != -1) + result = ok; + } + return result; +} + +int +FrameTraceSection3d::updateParameter(int paramID, Information &info) +{ + fiber_state = FiberState::Dirty; + + if (paramID == Param::ShearAlignYY) { + shear_align(1,1) = info.theDouble; + return 0; + } + else if (paramID == Param::ShearAlignZZ) { + shear_align(2,2) = info.theDouble; + return 0; + } + else if (paramID == Param::ShearAlignYZ) { + shear_align(1,2) = info.theDouble; + return 0; + } + else if (paramID == Param::ShearAlignZY) { + shear_align(2,1) = info.theDouble; + return 0; + } + else if (paramID == Param::ShiftAxialY) { + shift_axial[1] = info.theDouble; + return 0; + } + else if (paramID == Param::ShiftAxialZ) { + shift_axial[2] = info.theDouble; + return 0; + } + else if (paramID == Param::ShiftTwistY) { + shift_twist[1] = info.theDouble; + return 0; + } + else if (paramID == Param::ShiftTwistZ) { + shift_twist[2] = info.theDouble; + return 0; + } + + if (paramID >= Param::FiberFieldBase) { + int fiberID = (paramID - Param::FiberFieldBase) / 100; + int field = (paramID - Param::FiberFieldBase) % 100; + + if (fiberID >= fibers->size()) + return -1; + + switch (field) { + case Param::FiberArea: + (*fibers)[fiberID].area = info.theDouble; + break; + case Param::FiberY: + (*fibers)[fiberID].r[0] = info.theDouble; + break; + case Param::FiberZ: + (*fibers)[fiberID].r[1] = info.theDouble; + break; + case Param::FiberWarpX: + (*fibers)[fiberID].warp[0][0] = info.theDouble; + break; + case Param::FiberWarpXY: + (*fibers)[fiberID].warp[0][1] = info.theDouble; + break; + case Param::FiberWarpXZ: + (*fibers)[fiberID].warp[0][2] = info.theDouble; + break; + // + case Param::FiberWarpY: + (*fibers)[fiberID].warp[1][0] = info.theDouble; + break; + case Param::FiberWarpYY: + (*fibers)[fiberID].warp[1][1] = info.theDouble; + break; + case Param::FiberWarpYZ: + (*fibers)[fiberID].warp[1][2] = info.theDouble; + break; + + case Param::FiberWarpZ: + (*fibers)[fiberID].warp[2][0] = info.theDouble; + break; + case Param::FiberWarpZY: + (*fibers)[fiberID].warp[2][1] = info.theDouble; + break; + case Param::FiberWarpZZ: + (*fibers)[fiberID].warp[2][2] = info.theDouble; + break; + + default: + return -1; + } + return 0; + } + + return -1; +} + +int +FrameTraceSection3d::activateParameter(int paramID) +{ + parameterID = paramID; + + return 0; +} + +const Vector & +FrameTraceSection3d::getSectionDeformationSensitivity(int gradIndex) +{ + return dedh; +} + +const Vector & +FrameTraceSection3d::getStressResultantSensitivity(int gradIndex, bool conditional) +{ + static Vector ds(nsr); + + ds.Zero(); + + static Vector stress(3); + static Vector dsigdh(3); + static Vector sig_dAdh(3); + static Matrix tangent(3,3); + + static double areaDeriv[10000]; + const int nf = fibers->size(); + + for (int i = 0; i < nf; i++) { + double dA = 0.0, + dy = 0.0, + dz = 0.0; + if (parameterID >= Param::FiberFieldBase) { + int fiberID = (parameterID - Param::FiberFieldBase) / 100; + int field = (parameterID - Param::FiberFieldBase) % 100; + if (i == fiberID) { + switch (field) { + case Param::FiberArea: + dA = 1.0; + break; + case Param::FiberY: + dy = 1.0; + break; + case Param::FiberZ: + dz = 1.0; + break; + case Param::FiberWarpX: + case Param::FiberWarpXY: + case Param::FiberWarpXZ: + case Param::FiberWarpY: + case Param::FiberWarpYY: + case Param::FiberWarpYZ: + case Param::FiberWarpZ: + case Param::FiberWarpZY: + case Param::FiberWarpZZ: + default: + break; + } + } + } + + const double y = (*fibers)[i].r[0]; // - yBar; + const double z = (*fibers)[i].r[1]; // - zBar; + const double A = (*fibers)[i].area; + + dsigdh = materials[i]->getStressSensitivity(gradIndex,true); + + ds[0] += dsigdh(0)*A; + ds[1] += -y*dsigdh(0)*A; + ds[2] += z*dsigdh(0)*A; + ds[3] += dsigdh(1)*A; + ds[4] += dsigdh(2)*A; + ds[5] += (-z*dsigdh(1)+y*dsigdh(2))*A; + + if (dA != 0.0 || dy != 0.0 || dz != 0.0) + stress = materials[i]->getStress(); + + if (dy != 0.0 || dz != 0.0) + tangent = materials[i]->getTangent(); + + if (dA != 0.0) { + sig_dAdh(0) = stress(0)*dA; + sig_dAdh(1) = stress(1)*dA; + sig_dAdh(2) = stress(2)*dA; + + ds[0] += sig_dAdh(0); + ds[1] += -y*sig_dAdh(0); + ds[2] += z*sig_dAdh(0); + ds[3] += sig_dAdh(1); + ds[4] += sig_dAdh(2); + ds[5] += -z*sig_dAdh(1)+y*sig_dAdh(2); + } + + if (dy != 0.0) { + ds(1) += -dy * (stress(0)*A); + ds(5) += dy * (stress(2)*A); + } + + if (dz != 0.0) { + ds[2] += dz * (stress(0)*A); + ds[5] += -dz * (stress(1)*A); + } + + if (parameterID == 1) { + ds[3] += (stress(1)*A); + ds[4] += (stress(2)*A); + } + + MatrixND<3,6> as{}; + as(0,0) = 1; + as(1,3) = 1; + as(2,4) = 1; + as(0,1) = -y; + as(0,2) = z; + as(1,5) = -z; + as(2,5) = y; + + MatrixND<3,nsr> dAe{}; + dAe(0,1) = -dy; + dAe(0,2) = dz; + dAe(1,3) = 0; + dAe(2,4) = 0; + dAe(1,5) = -dz; + dAe(2,5) = dy; +#if 0 // removed to eliminate implicit cast from MatrixND to Matrix + MatrixND tmpMatrix{}; + tmpMatrix.addMatrixTripleProduct(0.0, as, tangent, dAe, 1.0); + + ds.addMatrixVector(1.0, tmpMatrix, e, A); +#endif + } + + return ds; +} + +const Matrix & +FrameTraceSection3d::getInitialTangentSensitivity(int gradIndex) +{ + static Matrix dksdh(6,6); + + dksdh.Zero(); + return dksdh; +} + + +int +FrameTraceSection3d::commitSensitivity(const Vector& defSens, + int gradIndex, int numGrads) +{ + double d0 = defSens(0); + double d1 = defSens(1); + double d2 = defSens(2); + double d3 = defSens(3); + double d4 = defSens(4); + double d5 = defSens(5); + + dedh = defSens; + + static double dydh[10000]; + static double dzdh[10000]; + const int nf = fibers->size(); + + { // TODO + for (int i = 0; i < nf; i++) { + dydh[i] = 0.0; + dzdh[i] = 0.0; + } + } + + static Vector depsdh(3); + + + for (int i = 0; i < nf; i++) { + auto& fiber = (*fibers)[i]; + const double y = fiber.r[0]; + const double z = fiber.r[1]; + + // determine material strain sensitivity + depsdh[0] = d0 - y*d1 + z*d2 - dydh[i]*e(1) + dzdh[i]*e(2); + depsdh[1] = d3 - z*d5 + e(3) - dzdh[i]*e(5); + depsdh[2] = d4 + y*d5 + e(4) + dydh[i]*e(5); + + materials[i]->commitSensitivity(depsdh,gradIndex,numGrads); + } + + return 0; +} + + +void +FrameTraceSection3d::Print(OPS_Stream &s, int flag) +{ + const int nf = fibers->size(); + if (flag == OPS_PRINT_PRINTMODEL_JSON) { + s << OPS_PRINT_JSON_MATE_INDENT << "{"; + s << "\"name\": " << this->getTag() << ", "; + s << "\"type\": \"" << this->getClassType() << "\", "; + + double mass; + if (this->FrameSection::getIntegral(Field::Density, State::Init, mass) == 0) + s << "\"mass\": " << mass << ", "; + + + s << "\"shear_align\": ["; + for (int i = 1; i < 3; i++) { + s << "["; + for (int j = 1; j < 3; j++) { + s << shear_align(i,j); + if (j < 2) + s << ", "; + } + s << "]"; + if (i < 2) + s << ", "; + } + s << "], "; + s << "\"shift_axial\": [" << shift_axial[1] << ", " << shift_axial[2] << "], "; + s << "\"shift_twist\": [" << shift_twist[1] << ", " << shift_twist[2] << "], "; + + s << "\"fibers\": [\n"; + + for (int i = 0; i < nf; i++) { + s << OPS_PRINT_JSON_MATE_INDENT << "\t{\"location\": [" + << (*fibers)[i].r[0] << ", " + << (*fibers)[i].r[1] << "], "; + s << "\"area\": " << (*fibers)[i].area << ", "; + s << "\"warp\": ["; + for (int j = 0; j < nwm; j++) { + s << "["; + for (int k = 0; k < 3; k++) { + s << (*fibers)[i].warp[j][k]; + if (k < 2) + s << ", "; + } + s << "]"; + if (j < nwm-1) + s << ", "; + } + s << "], "; + + s << "\"material\": " << materials[i]->getTag(); + if (i < nf - 1) + s << "},\n"; + else + s << "}\n"; + } + s << OPS_PRINT_JSON_MATE_INDENT << "]}"; + return; + } + + else if (flag == 1) { + for (int i = 0; i < nf; i++) { + auto & fiber = (*fibers)[i]; + s << "\nLocation (y,z) = " << fiber.r[0] << ' ' << fiber.r[1]; + s << "\nArea = " << fiber.area << endln; + materials[i]->Print(s, flag); + } + } +} From 632051182f69206fa230046427152269c09bdbc4 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 7 Jan 2026 01:54:47 -0800 Subject: [PATCH 004/161] Update CMakeLists.txt --- SRC/material/Frame/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/SRC/material/Frame/CMakeLists.txt b/SRC/material/Frame/CMakeLists.txt index 6ab0add896..13cfc12ea2 100644 --- a/SRC/material/Frame/CMakeLists.txt +++ b/SRC/material/Frame/CMakeLists.txt @@ -9,6 +9,7 @@ target_sources(OPS_Material PRIVATE FrameFiberSection3d.cpp FrameSolidSection3d.cpp + FrameTraceSection3d.cpp ElasticLinearFrameSection3d.cpp PUBLIC FrameFiberSection3d.h From 63fe27337f4d6b4d070266cdaf133f03c3f52e2b Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 9 Jan 2026 08:51:16 -0800 Subject: [PATCH 005/161] Refactor AnalysisModel to use VectorOfTaggedObjects Replaces ArrayOfTaggedObjects with VectorOfTaggedObjects in AnalysisModel and updates related code to use the new storage and iterator types. Removes legacy FE_EleIter and DOF_GrpIter implementations, updates includes, and adapts TaggedIterator for template storage. Cleans up code formatting and improves consistency in error handling and printing. --- .../StaticDomainDecompositionAnalysis.cpp | 48 ++-- .../TransientDomainDecompositionAnalysis.cpp | 14 +- .../handler/AutoConstraintHandler.cpp | 2 - SRC/analysis/handler/ConstraintHandler.cpp | 2 - .../TransformationConstraintHandler.cpp | 2 - .../Dynamic/AlphaOS/AlphaOSGeneralized_TP.cpp | 2 - .../integrator/Dynamic/CentralDifference.cpp | 2 - .../Dynamic/CentralDifferenceAlternative.cpp | 2 - .../Dynamic/CentralDifferenceNoDamping.cpp | 2 - .../integrator/Dynamic/ExplicitDifference.cpp | 2 - .../integrator/Dynamic/GeneralizedNewmark.cpp | 2 - SRC/analysis/integrator/Dynamic/Newmark1.cpp | 1 - .../integrator/Dynamic/NewmarkSO3.cpp | 4 +- .../integrator/Dynamic/PFEMIntegrator.cpp | 2 - SRC/analysis/integrator/EigenIntegrator.cpp | 10 +- .../Hybrid/HHTGeneralizedExplicit_TP.cpp | 2 - .../integrator/Hybrid/HHTHSFixedNumIter.cpp | 2 - .../Hybrid/HHTHSFixedNumIter_TP.cpp | 2 - .../integrator/Hybrid/HHTHSIncrLimit.cpp | 2 - .../integrator/Static/MinUnbalDispNorm.cpp | 6 +- SRC/analysis/model/AnalysisModel.cpp | 63 ++++-- SRC/analysis/model/AnalysisModel.h | 18 +- SRC/analysis/model/CMakeLists.txt | 4 +- SRC/analysis/model/DOF_GrpIter.h | 4 +- SRC/analysis/model/FE_EleIter.h | 4 +- SRC/analysis/model/numberer/DOF_Numberer.cpp | 93 ++++---- .../model/numberer/ParallelNumberer.cpp | 2 - .../CorotCrdTransfWarping3d.cpp | 3 +- SRC/domain/subdomain/Subdomain.cpp | 6 +- SRC/graph/graph/DOF_Graph.cpp | 2 - SRC/graph/graph/DOF_GroupGraph.cpp | 2 - .../transform/FrameTransformBuilder.hpp | 4 + SRC/runtime/runtime/BasicAnalysisBuilder.cpp | 2 - SRC/system_of_eqn/eigenSOE/ArpackSOE.cpp | 2 - .../eigenSOE/SymBandEigenSolver.cpp | 2 - .../eigenSOE/SymmGeneralizedEigenSolver.cpp | 2 - SRC/tagged/TaggedIterator.hpp | 16 +- SRC/tagged/storage/CMakeLists.txt | 27 ++- SRC/tagged/storage/TaggedObjectIter.h | 4 +- SRC/tagged/storage/TaggedObjectStorage.h | 18 +- SRC/tagged/storage/VectorOfTaggedObjects.cpp | 206 ++++++++---------- SRC/tagged/storage/VectorOfTaggedObjects.h | 55 +++-- .../storage/VectorOfTaggedObjectsIter.cpp | 69 ------ .../storage/VectorOfTaggedObjectsIter.h | 63 ------ 44 files changed, 319 insertions(+), 463 deletions(-) delete mode 100644 SRC/tagged/storage/VectorOfTaggedObjectsIter.cpp delete mode 100644 SRC/tagged/storage/VectorOfTaggedObjectsIter.h diff --git a/SRC/analysis/analysis/StaticDomainDecompositionAnalysis.cpp b/SRC/analysis/analysis/StaticDomainDecompositionAnalysis.cpp index 95e501a885..3e79f4b04d 100644 --- a/SRC/analysis/analysis/StaticDomainDecompositionAnalysis.cpp +++ b/SRC/analysis/analysis/StaticDomainDecompositionAnalysis.cpp @@ -38,8 +38,6 @@ #include #include -#include -#include #include #include #include @@ -258,7 +256,7 @@ StaticDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool fin // form K // - FE_EleIter &theEles = theAnalysisModel->getFEs(); + auto &theEles = theAnalysisModel->getFEs(); FE_Element *elePtr; while((elePtr = theEles()) != 0) { @@ -276,7 +274,7 @@ StaticDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool fin // if (generalized == true) { - FE_EleIter &theEles2 = theAnalysisModel->getFEs(); + auto &theEles2 = theAnalysisModel->getFEs(); while((elePtr = theEles2()) != 0) { elePtr->zeroTangent(); elePtr->addMtoTang(1.0); @@ -288,7 +286,7 @@ StaticDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool fin } DOF_Group *dofPtr; - DOF_GrpIter &theDofs = theAnalysisModel->getDOFs(); + auto &theDofs = theAnalysisModel->getDOFs(); while((dofPtr = theDofs()) != 0) { dofPtr->zeroTangent(); dofPtr->addMtoTang(1.0); @@ -305,8 +303,8 @@ StaticDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool fin // if (theEigenSOE->solve(numMode, generalized, findSmallest) < 0) { - opserr << "WARNING StaticAnalysis::eigen() - EigenSOE failed in solve()\n"; - return -4; + opserr << "WARNING StaticAnalysis::eigen() - EigenSOE failed in solve()\n"; + return -4; } // @@ -328,24 +326,24 @@ StaticDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool fin int StaticDomainDecompositionAnalysis::initialize() { - Domain *the_Domain = this->getDomainPtr(); - - // check if domain has undergone change - int stamp = the_Domain->hasDomainChanged(); - if (stamp != domainStamp) { - domainStamp = stamp; - if (this->domainChanged() < 0) { - opserr << "DirectIntegrationAnalysis::initialize() - domainChanged() failed\n"; - return -1; - } - } - if (theIntegrator->initialize() < 0) { - opserr << "DirectIntegrationAnalysis::initialize() - integrator initialize() failed\n"; - return -2; - } else - theIntegrator->commit(); - - return 0; + Domain *the_Domain = this->getDomainPtr(); + + // check if domain has undergone change + int stamp = the_Domain->hasDomainChanged(); + if (stamp != domainStamp) { + domainStamp = stamp; + if (this->domainChanged() < 0) { + opserr << "DirectIntegrationAnalysis::initialize() - domainChanged() failed\n"; + return -1; + } + } + if (theIntegrator->initialize() < 0) { + opserr << "DirectIntegrationAnalysis::initialize() - integrator initialize() failed\n"; + return -2; + } else + theIntegrator->commit(); + + return 0; } int diff --git a/SRC/analysis/analysis/TransientDomainDecompositionAnalysis.cpp b/SRC/analysis/analysis/TransientDomainDecompositionAnalysis.cpp index 3a93a0dafe..c0cc9b2f8e 100644 --- a/SRC/analysis/analysis/TransientDomainDecompositionAnalysis.cpp +++ b/SRC/analysis/analysis/TransientDomainDecompositionAnalysis.cpp @@ -44,8 +44,6 @@ #include #include -#include -#include #include #include #include @@ -261,7 +259,7 @@ TransientDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool // form K // - FE_EleIter &theEles = theAnalysisModel->getFEs(); + auto &theEles = theAnalysisModel->getFEs(); FE_Element *elePtr; while((elePtr = theEles()) != 0) { @@ -279,7 +277,7 @@ TransientDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool // if (generalized == true) { - FE_EleIter &theEles2 = theAnalysisModel->getFEs(); + auto &theEles2 = theAnalysisModel->getFEs(); while((elePtr = theEles2()) != 0) { elePtr->zeroTangent(); elePtr->addMtoTang(1.0); @@ -289,9 +287,9 @@ TransientDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool result = -2; } } - + DOF_Group *dofPtr; - DOF_GrpIter &theDofs = theAnalysisModel->getDOFs(); + auto &theDofs = theAnalysisModel->getDOFs(); while((dofPtr = theDofs()) != 0) { dofPtr->zeroTangent(); dofPtr->addMtoTang(1.0); @@ -307,8 +305,8 @@ TransientDomainDecompositionAnalysis::eigen(int numMode, bool generalized, bool // solve for the eigen values & vectors // if (theEigenSOE->solve(numMode, generalized, findSmallest) < 0) { - opserr << "WARNING TransientDomainDecomposition::eigen() - EigenSOE failed in solve()\n"; - return -4; + opserr << "WARNING TransientDomainDecomposition::eigen() - EigenSOE failed in solve()\n"; + return -4; } // diff --git a/SRC/analysis/handler/AutoConstraintHandler.cpp b/SRC/analysis/handler/AutoConstraintHandler.cpp index d3f8714576..b06a4b59ff 100644 --- a/SRC/analysis/handler/AutoConstraintHandler.cpp +++ b/SRC/analysis/handler/AutoConstraintHandler.cpp @@ -35,9 +35,7 @@ #include #include #include -#include #include -#include #include #include #include diff --git a/SRC/analysis/handler/ConstraintHandler.cpp b/SRC/analysis/handler/ConstraintHandler.cpp index ef8796d97d..ef6944e484 100644 --- a/SRC/analysis/handler/ConstraintHandler.cpp +++ b/SRC/analysis/handler/ConstraintHandler.cpp @@ -33,9 +33,7 @@ #include #include #include -#include #include -#include #include ConstraintHandler::ConstraintHandler(int clasTag) diff --git a/SRC/analysis/handler/TransformationConstraintHandler.cpp b/SRC/analysis/handler/TransformationConstraintHandler.cpp index e0cc9be26d..989ee20877 100644 --- a/SRC/analysis/handler/TransformationConstraintHandler.cpp +++ b/SRC/analysis/handler/TransformationConstraintHandler.cpp @@ -35,9 +35,7 @@ #include #include #include -#include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized_TP.cpp b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized_TP.cpp index 8206972f53..b73655971e 100644 --- a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized_TP.cpp +++ b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized_TP.cpp @@ -26,12 +26,10 @@ // #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/CentralDifference.cpp b/SRC/analysis/integrator/Dynamic/CentralDifference.cpp index de8edfa7b2..06753aa6d3 100644 --- a/SRC/analysis/integrator/Dynamic/CentralDifference.cpp +++ b/SRC/analysis/integrator/Dynamic/CentralDifference.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/CentralDifferenceAlternative.cpp b/SRC/analysis/integrator/Dynamic/CentralDifferenceAlternative.cpp index 9407ed936b..caef451e9e 100644 --- a/SRC/analysis/integrator/Dynamic/CentralDifferenceAlternative.cpp +++ b/SRC/analysis/integrator/Dynamic/CentralDifferenceAlternative.cpp @@ -27,12 +27,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/CentralDifferenceNoDamping.cpp b/SRC/analysis/integrator/Dynamic/CentralDifferenceNoDamping.cpp index 7cabb698c1..7be139075c 100644 --- a/SRC/analysis/integrator/Dynamic/CentralDifferenceNoDamping.cpp +++ b/SRC/analysis/integrator/Dynamic/CentralDifferenceNoDamping.cpp @@ -26,12 +26,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/ExplicitDifference.cpp b/SRC/analysis/integrator/Dynamic/ExplicitDifference.cpp index 1e83d9e5f8..e8af93ff78 100644 --- a/SRC/analysis/integrator/Dynamic/ExplicitDifference.cpp +++ b/SRC/analysis/integrator/Dynamic/ExplicitDifference.cpp @@ -1,11 +1,9 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp b/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp index 2888ec8825..69bd014d67 100644 --- a/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp +++ b/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp @@ -15,12 +15,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/Newmark1.cpp b/SRC/analysis/integrator/Dynamic/Newmark1.cpp index 878b9da85c..c2f46c8550 100644 --- a/SRC/analysis/integrator/Dynamic/Newmark1.cpp +++ b/SRC/analysis/integrator/Dynamic/Newmark1.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp b/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp index dee1a1d97d..3396148530 100644 --- a/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp +++ b/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp @@ -29,12 +29,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -46,7 +44,7 @@ #include #include #include -#include //Abbas +#include static bool converged = false; // static int count = 0; diff --git a/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp b/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp index 265a354b60..ddbc68ef3f 100644 --- a/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp +++ b/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -50,7 +49,6 @@ #include #include #include -#include #include #include "sparseGEN/PFEMLinSOE.h" diff --git a/SRC/analysis/integrator/EigenIntegrator.cpp b/SRC/analysis/integrator/EigenIntegrator.cpp index 41baa10893..bfd8cdfb17 100644 --- a/SRC/analysis/integrator/EigenIntegrator.cpp +++ b/SRC/analysis/integrator/EigenIntegrator.cpp @@ -40,8 +40,6 @@ #include #include #include -#include -#include EigenIntegrator::EigenIntegrator(AnalysisModel &theModel, EigenSOE &theSysOE) : theSOE(&theSysOE), theAnalysisModel(&theModel) @@ -96,7 +94,7 @@ EigenIntegrator::formK() // efficiency when performing parallel computations // loop through the FE_Elements getting them to form the tangent - // FE_EleIter &theEles1 = theAnalysisModel->getFEs(); + // auto &theEles1 = theAnalysisModel->getFEs(); FE_Element *elePtr; flagK = 0; @@ -108,7 +106,7 @@ EigenIntegrator::formK() // loop through the FE_Elements getting them to add the tangent int result = 0; - FE_EleIter &theEles2 = theAnalysisModel->getFEs(); + auto &theEles2 = theAnalysisModel->getFEs(); while((elePtr = theEles2()) != 0) { if (theSOE->addA(elePtr->getTangent(this), elePtr->getID()) < 0) { opserr << "WARNING EigenIntegrator::formK -"; @@ -139,7 +137,7 @@ EigenIntegrator::formM() // loop through the FE_Elements getting them to add the tangent int result = 0; FE_Element *elePtr; - FE_EleIter &theEles2 = theAnalysisModel->getFEs(); + auto &theEles2 = theAnalysisModel->getFEs(); while((elePtr = theEles2()) != nullptr) { if (theSOE->addM(elePtr->getTangent(this), elePtr->getID()) < 0) { opserr << "WARNING EigenIntegrator::formK -"; @@ -149,7 +147,7 @@ EigenIntegrator::formM() } DOF_Group *dofPtr; - DOF_GrpIter &theDofs = theAnalysisModel->getDOFs(); + auto &theDofs = theAnalysisModel->getDOFs(); while((dofPtr = theDofs()) != nullptr) { // dofPtr->formTangent(this); if (theSOE->addM(dofPtr->getTangent(this),dofPtr->getID()) < 0) { diff --git a/SRC/analysis/integrator/Hybrid/HHTGeneralizedExplicit_TP.cpp b/SRC/analysis/integrator/Hybrid/HHTGeneralizedExplicit_TP.cpp index f5a980de58..26e5173696 100644 --- a/SRC/analysis/integrator/Hybrid/HHTGeneralizedExplicit_TP.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTGeneralizedExplicit_TP.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter.cpp b/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter.cpp index 9262679ee3..0929a40b38 100755 --- a/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter_TP.cpp b/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter_TP.cpp index 6505ae414b..aa325dc8f2 100644 --- a/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter_TP.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSFixedNumIter_TP.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit.cpp b/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit.cpp index a34881f6db..cabb852129 100644 --- a/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp index 96ac8eac82..9db6e8616e 100644 --- a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp +++ b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp @@ -106,9 +106,9 @@ MinUnbalDispNorm::newStep() AnalysisModel *theModel = this->getAnalysisModel(); LinearSOE *theLinSOE = this->getLinearSOE(); if (theModel == 0 || theLinSOE == 0) { - opserr << "WARNING MinUnbalDispNorm::newStep() "; - opserr << "No AnalysisModel or LinearSOE has been set\n"; - return -1; + opserr << "WARNING MinUnbalDispNorm::newStep() "; + opserr << "No AnalysisModel or LinearSOE has been set\n"; + return -1; } // get the current load factor diff --git a/SRC/analysis/model/AnalysisModel.cpp b/SRC/analysis/model/AnalysisModel.cpp index a341296df8..56cb98f258 100644 --- a/SRC/analysis/model/AnalysisModel.cpp +++ b/SRC/analysis/model/AnalysisModel.cpp @@ -31,13 +31,10 @@ #include #include -#include #include #include #include #include -#include -#include #include #include #include @@ -55,6 +52,7 @@ #include #include +#include #define START_EQN_NUM 0 #define START_VERTEX_NUM 0 @@ -68,8 +66,8 @@ AnalysisModel::AnalysisModel() , eigenVectors(0), eigenValues(0), dampingForces(0) , isDiagonal(false),diagMass(0) { - theFEs = new ArrayOfTaggedObjects(256); - theDOFs = new ArrayOfTaggedObjects(256); + theFEs = new VectorOfTaggedObjects(); // 256); + theDOFs = new VectorOfTaggedObjects(); // 256); theFEiter = new FE_EleIter(theFEs); theDOFiter = new DOF_GrpIter(theDOFs); } @@ -123,7 +121,8 @@ AnalysisModel::addFE_Element(FE_Element *theElement) int tag = theElement->getTag(); TaggedObject *other = theFEs->getComponentPtr(tag); if (other != 0) { - opserr << "AnalysisModel::addFE_Element - element with tag " << tag << "already exists in model\n"; + opserr << "AnalysisModel::addFE_Element - element with tag " + << tag << " already exists in model\n"; return false; } @@ -338,7 +337,7 @@ AnalysisModel::getDOFGraph() Graph & AnalysisModel::getDOFGroupGraph() { - if (myGroupGraph == 0) { + if (myGroupGraph == nullptr) { // int numVertex = this->getNumDOF_Groups(); // assert(numVertex != 0); // myGroupGraph = new Graph(numVertex); @@ -367,16 +366,16 @@ AnalysisModel::getDOFGroupGraph() FE_EleIter &eleIter = this->getFEs(); while((elePtr = eleIter()) != 0) { - const ID &id = elePtr->getDOFtags(); - int size = id.Size(); - for (int i=0; iaddEdge(dof1,dof2); - } - } + const ID &id = elePtr->getDOFtags(); + int size = id.Size(); + for (int i=0; iaddEdge(dof1,dof2); + } + } } } @@ -507,7 +506,7 @@ AnalysisModel::incrVel(const Vector &vel) DOF_GrpIter &theDOFGrps = this->getDOFs(); DOF_Group *dofPtr; while ((dofPtr = theDOFGrps()) != nullptr) - dofPtr->incrNodeVel(vel); + dofPtr->incrNodeVel(vel); } @@ -611,7 +610,6 @@ AnalysisModel::formVector(Integrator& assm, LinearSOE& soe) // loop through the FE_Elements and add the residual FE_Element *elePtr; - FE_EleIter &theEles2 = this->getFEs(); while ((elePtr = theEles2()) != nullptr) { if (soe.addB(elePtr->getResidual(&assm), elePtr->getID()) < 0) { @@ -834,7 +832,7 @@ AnalysisModel::setNumEigenvectors(int numEigenvectors) Node *theNode; NodeIter &theNodes = myDomain->getNodes(); while ((theNode = theNodes()) != 0) - theNode->setNumEigenvectors(numEigenvectors); + theNode->setNumEigenvectors(numEigenvectors); } void @@ -1008,6 +1006,31 @@ AnalysisModel::getDomainPtr() const return myDomain; } +void +AnalysisModel::Print(OPS_Stream &s, int flag) +{ + opserr << "{\n"; + opserr << " \"u\": [\n"; + Node* theNode; + NodeIter &theNodes = myDomain->getNodes(); + bool firstNode = true; + while ((theNode = theNodes()) != nullptr) { + if (firstNode) + firstNode = false; + else + opserr << ",\n"; + opserr << " ["; + const Vector &disp = theNode->getDisp(); + for (int i = 0; i < disp.Size(); i++) { + if (i != 0) + opserr << ", "; + opserr << disp(i); + } + opserr << "]"; + } + opserr << "\n ]\n"; + opserr << "}\n"; +} int AnalysisModel::sendSelf(int cTag, Channel &theChannel) diff --git a/SRC/analysis/model/AnalysisModel.h b/SRC/analysis/model/AnalysisModel.h index 223b07c8f5..843cf21a3e 100644 --- a/SRC/analysis/model/AnalysisModel.h +++ b/SRC/analysis/model/AnalysisModel.h @@ -33,11 +33,11 @@ #define AnalysisModel_h #include +#include +#include class TaggedObjectStorage; class Domain; -class FE_EleIter; -class DOF_GrpIter; class Graph; class FE_Element; class DOF_Group; @@ -46,6 +46,10 @@ class FEM_ObjectBroker; class ConstraintHandler; class Integrator; class LinearSOE; +class OPS_Stream; + +using DOF_GrpIter = TaggedIterator; +using FE_EleIter = TaggedIterator; class AnalysisModel: public MovableObject { @@ -62,7 +66,7 @@ class AnalysisModel: public MovableObject void clearDOFGroupGraph(); int getNumDOF_Groups() const; DOF_Group *getDOF_GroupPtr(int tag); - FE_EleIter &getFEs(); + FE_EleIter &getFEs(); DOF_GrpIter &getDOFs(); void setNumEqn(int); @@ -105,6 +109,8 @@ class AnalysisModel: public MovableObject void setRayleighDampingFactors(double alphaM, double betaK, double betaKi, double betaKc); const Vector &getEigenvalues(); + void Print(OPS_Stream &s, int flag =0); + // Parallel int sendSelf(int commitTag, Channel &); int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); @@ -120,6 +126,8 @@ class AnalysisModel: public MovableObject bool inclModalDampingMatrix(); private: + using Storage = VectorOfTaggedObjects; + int addModalDampingForce(LinearSOE *); int setupModal(LinearSOE*, const Vector *modalDampingValues); int doMv(const Vector &v, Vector &res); @@ -135,8 +143,8 @@ class AnalysisModel: public MovableObject int numDOF_Grp; // number of DOF_Group objects added int numEqn; // numEqn set by the ConstraintHandler typically - TaggedObjectStorage *theFEs; - TaggedObjectStorage *theDOFs; + Storage *theFEs; + Storage *theDOFs; FE_EleIter *theFEiter; DOF_GrpIter *theDOFiter; diff --git a/SRC/analysis/model/CMakeLists.txt b/SRC/analysis/model/CMakeLists.txt index 540d952b1f..4b2f7da118 100644 --- a/SRC/analysis/model/CMakeLists.txt +++ b/SRC/analysis/model/CMakeLists.txt @@ -7,8 +7,8 @@ target_sources(OPS_Analysis PRIVATE AnalysisModel.cpp - FE_EleIter.cpp - DOF_GrpIter.cpp + # FE_EleIter.cpp + # DOF_GrpIter.cpp PUBLIC AnalysisModel.h FE_EleIter.h diff --git a/SRC/analysis/model/DOF_GrpIter.h b/SRC/analysis/model/DOF_GrpIter.h index a2aa571031..cd38753bf1 100644 --- a/SRC/analysis/model/DOF_GrpIter.h +++ b/SRC/analysis/model/DOF_GrpIter.h @@ -38,7 +38,7 @@ class DOF_Group; class TaggedObjectStorage; class TaggedObjectIter; - +#if 0 class DOF_GrpIter { public: @@ -54,6 +54,6 @@ class DOF_GrpIter private: TaggedObjectIter *myIter; }; - +#endif #endif diff --git a/SRC/analysis/model/FE_EleIter.h b/SRC/analysis/model/FE_EleIter.h index 3c942078a2..e66a02f5ee 100644 --- a/SRC/analysis/model/FE_EleIter.h +++ b/SRC/analysis/model/FE_EleIter.h @@ -42,7 +42,7 @@ class TaggedObjectIter; class TaggedObjectStorage; class FE_Element; - +#if 0 class FE_EleIter { public: @@ -58,6 +58,6 @@ class FE_EleIter private: TaggedObjectIter *myIter; }; - +#endif #endif diff --git a/SRC/analysis/model/numberer/DOF_Numberer.cpp b/SRC/analysis/model/numberer/DOF_Numberer.cpp index 948d2f4963..a8f92a5fda 100644 --- a/SRC/analysis/model/numberer/DOF_Numberer.cpp +++ b/SRC/analysis/model/numberer/DOF_Numberer.cpp @@ -45,7 +45,6 @@ #include #include #include -#include DOF_Numberer::DOF_Numberer(int clsTag) @@ -189,7 +188,7 @@ DOF_Numberer::numberDOF(int lastDOF_Group) FE_EleIter &theEle = theAnalysisModel->getFEs(); FE_Element *elePtr; while ((elePtr = theEle()) != 0) - elePtr->setID(); + elePtr->setID(); // set the numOfEquation in the Model theAnalysisModel->setNumEqn(numEqn); @@ -219,8 +218,8 @@ DOF_Numberer::numberDOF(ID &lastDOFs) // we first number the dofs using the dof group graph - const ID &orderedRefs = theGraphNumberer-> - number(theAnalysisModel->getDOFGroupGraph(), lastDOFs); + const ID &orderedRefs + = theGraphNumberer->number(theAnalysisModel->getDOFGroupGraph(), lastDOFs); theAnalysisModel->clearDOFGroupGraph(); @@ -232,9 +231,9 @@ DOF_Numberer::numberDOF(ID &lastDOFs) int result =0; int size = orderedRefs.Size(); for (int i=0; igetDOF_GroupPtr(dofTag); + int dofTag = orderedRefs(i); + DOF_Group *dofPtr; + dofPtr = theAnalysisModel->getDOF_GroupPtr(dofTag); assert(dofPtr != nullptr); const ID &theID = dofPtr->getID(); @@ -246,15 +245,15 @@ DOF_Numberer::numberDOF(ID &lastDOFs) // iterate through the DOFs first time setting -3 values for (int k=0; kgetDOF_GroupPtr(dofTag); - if (dofPtr != 0) { - const ID &theID = dofPtr->getID(); - int idSize = theID.Size(); - for (int j=0; jsetID(j,eqnNumber++); - } + int dofTag = orderedRefs(k); + DOF_Group *dofPtr; + dofPtr = theAnalysisModel->getDOF_GroupPtr(dofTag); + if (dofPtr != 0) { + const ID &theID = dofPtr->getID(); + int idSize = theID.Size(); + for (int j=0; jsetID(j,eqnNumber++); + } } // iterate through the DOFs one last time setting any -4 values @@ -264,35 +263,35 @@ DOF_Numberer::numberDOF(ID &lastDOFs) while ((dofPtr = tDOFs()) != 0) { const ID &theID = dofPtr->getID(); int have4s = 0; - for (int i=0; igetNodeTag(); - // loop through the MP_Constraints to see if any of the - // DOFs are constrained, note constraint matrix must be diagonal - // with 1's on the diagonal - MP_ConstraintIter &theMPs = theDomain->getMPs(); - MP_Constraint *mpPtr; - while ((mpPtr = theMPs()) != 0 ) { - // note keep looping over all in case multiple constraints - // are used to constrain a node -- can't assume intelli user - if (mpPtr->getNodeConstrained() == nodeID) { - int nodeRetained = mpPtr->getNodeRetained(); - Node *nodeRetainedPtr = theDomain->getNode(nodeRetained); - DOF_Group *retainedDOF = nodeRetainedPtr->getDOF_GroupPtr(); - const ID&retainedDOFIDs = retainedDOF->getID(); - const ID&constrainedDOFs = mpPtr->getConstrainedDOFs(); - const ID&retainedDOFs = mpPtr->getRetainedDOFs(); - for (int i=0; isetID(dofC, dofID); - } - } - } - } + for (int i=0; igetNodeTag(); + // loop through the MP_Constraints to see if any of the + // DOFs are constrained, note constraint matrix must be diagonal + // with 1's on the diagonal + MP_ConstraintIter &theMPs = theDomain->getMPs(); + MP_Constraint *mpPtr; + while ((mpPtr = theMPs()) != 0 ) { + // note keep looping over all in case multiple constraints + // are used to constrain a node -- can't assume intelli user + if (mpPtr->getNodeConstrained() == nodeID) { + int nodeRetained = mpPtr->getNodeRetained(); + Node *nodeRetainedPtr = theDomain->getNode(nodeRetained); + DOF_Group *retainedDOF = nodeRetainedPtr->getDOF_GroupPtr(); + const ID&retainedDOFIDs = retainedDOF->getID(); + const ID&constrainedDOFs = mpPtr->getConstrainedDOFs(); + const ID&retainedDOFs = mpPtr->getRetainedDOFs(); + for (int i=0; isetID(dofC, dofID); + } + } + } + } } int numEqn = eqnNumber; @@ -301,13 +300,13 @@ DOF_Numberer::numberDOF(ID &lastDOFs) FE_EleIter &theEle = theAnalysisModel->getFEs(); FE_Element *elePtr; while ((elePtr = theEle()) != 0) - elePtr->setID(); + elePtr->setID(); // set the numOfEquation in the Model theAnalysisModel->setNumEqn(numEqn); if (result == 0) - return numEqn; + return numEqn; return result; diff --git a/SRC/analysis/model/numberer/ParallelNumberer.cpp b/SRC/analysis/model/numberer/ParallelNumberer.cpp index 9e9959eddc..fb164e9726 100644 --- a/SRC/analysis/model/numberer/ParallelNumberer.cpp +++ b/SRC/analysis/model/numberer/ParallelNumberer.cpp @@ -35,10 +35,8 @@ #include #include #include -#include #include #include -#include #include #include #include diff --git a/SRC/coordTransformation/CorotCrdTransfWarping3d.cpp b/SRC/coordTransformation/CorotCrdTransfWarping3d.cpp index 6a46802003..e8b4dddcdf 100644 --- a/SRC/coordTransformation/CorotCrdTransfWarping3d.cpp +++ b/SRC/coordTransformation/CorotCrdTransfWarping3d.cpp @@ -1331,7 +1331,8 @@ CorotCrdTransfWarping3d::getInitialGlobalStiffMatrix(const Matrix &kb) } int -CorotCrdTransfWarping3d::getLocalAxes(Vector &XAxis, Vector &YAxis, +CorotCrdTransfWarping3d::getLocalAxes(Vector &XAxis, + Vector &YAxis, Vector &ZAxis) { // element projection diff --git a/SRC/domain/subdomain/Subdomain.cpp b/SRC/domain/subdomain/Subdomain.cpp index 665e51a94b..9c1e74b401 100644 --- a/SRC/domain/subdomain/Subdomain.cpp +++ b/SRC/domain/subdomain/Subdomain.cpp @@ -377,13 +377,13 @@ Subdomain::Print(OPS_Stream &s, int flag) s << "\nINTERNAL NODE DATA: NumNodes: "; s << internalNodes->getNumComponents() << "\n"; - internalNodes->Print(s); + internalNodes->Print(s, 0); s << "\nEXTERNAL NODE DATA: NumNodes: "; s << externalNodes->getNumComponents() << "\n"; - externalNodes->Print(s); + externalNodes->Print(s, 0); - this->Domain::Print(s); + this->Domain::Print(s, 0); s << "\nEnd Subdomain Information\n"; } diff --git a/SRC/graph/graph/DOF_Graph.cpp b/SRC/graph/graph/DOF_Graph.cpp index 40cf0fa8ed..54e798ef10 100644 --- a/SRC/graph/graph/DOF_Graph.cpp +++ b/SRC/graph/graph/DOF_Graph.cpp @@ -33,9 +33,7 @@ #include #include #include -#include #include -#include #include #define START_EQN_NUM 0 diff --git a/SRC/graph/graph/DOF_GroupGraph.cpp b/SRC/graph/graph/DOF_GroupGraph.cpp index 7201fba8e6..008961f38c 100644 --- a/SRC/graph/graph/DOF_GroupGraph.cpp +++ b/SRC/graph/graph/DOF_GroupGraph.cpp @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include // constructs the Graph diff --git a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp index 0791db32e1..d44355a5e5 100644 --- a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp +++ b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp @@ -98,6 +98,10 @@ class FrameTransformBuilder : public TaggedObject { return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); } + else if (strcmp(name, "Corotational04") == 0) + { + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); + } return nullptr; } diff --git a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp index 7701b73e7f..8bbff621a4 100644 --- a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp +++ b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp @@ -36,10 +36,8 @@ #include // For eigen -#include #include #include -#include // Default concrete analysis classes #include diff --git a/SRC/system_of_eqn/eigenSOE/ArpackSOE.cpp b/SRC/system_of_eqn/eigenSOE/ArpackSOE.cpp index c1408ca3f2..3c0a045ca8 100644 --- a/SRC/system_of_eqn/eigenSOE/ArpackSOE.cpp +++ b/SRC/system_of_eqn/eigenSOE/ArpackSOE.cpp @@ -37,9 +37,7 @@ #include #include #include -#include #include -#include #include #include diff --git a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp index 81d0bbc0bc..dc72d6c692 100644 --- a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp @@ -33,9 +33,7 @@ #include #include #include -#include #include -#include #include SymBandEigenSolver::SymBandEigenSolver() diff --git a/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp index a64b1bd489..5d5ffffc05 100644 --- a/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp @@ -23,9 +23,7 @@ #include #include #include -#include #include -#include #include #include diff --git a/SRC/tagged/TaggedIterator.hpp b/SRC/tagged/TaggedIterator.hpp index cd7a635e15..58e1ba61ae 100644 --- a/SRC/tagged/TaggedIterator.hpp +++ b/SRC/tagged/TaggedIterator.hpp @@ -2,22 +2,22 @@ #include #include -template +template class TaggedIterator { public: - TaggedIterator(TaggedObjectStorage* storage) : mIter(storage->getComponents()) {} + TaggedIterator(StorageType* storage) : mIter(storage->getIterRef()) {} void reset() { - mIter.reset(); + mIter.reset(); } T* operator()() { - TaggedObject* item = mIter(); - if (item == nullptr) - return nullptr; - return (T*)item; + TaggedObject* item = mIter(); + if (item == nullptr) + return nullptr; + return (T*)item; } private: - TaggedObjectIter &mIter; + StorageType::Iterator &mIter; }; \ No newline at end of file diff --git a/SRC/tagged/storage/CMakeLists.txt b/SRC/tagged/storage/CMakeLists.txt index b032f6e7a0..e3a1961ce8 100644 --- a/SRC/tagged/storage/CMakeLists.txt +++ b/SRC/tagged/storage/CMakeLists.txt @@ -5,20 +5,19 @@ # #============================================================================== target_sources(OPS_Tagged - PRIVATE - ArrayOfTaggedObjects.cpp - ArrayOfTaggedObjectsIter.cpp - MapOfTaggedObjectsIter.cpp - MapOfTaggedObjects.cpp - HashMapOfTaggedObjectsIter.cpp - HashMapOfTaggedObjects.cpp - VectorOfTaggedObjectsIter.cpp - VectorOfTaggedObjects.cpp - PUBLIC - ArrayOfTaggedObjects.h - ArrayOfTaggedObjectsIter.h - MapOfTaggedObjectsIter.h - MapOfTaggedObjects.h + PRIVATE + ArrayOfTaggedObjects.cpp + ArrayOfTaggedObjectsIter.cpp + MapOfTaggedObjectsIter.cpp + MapOfTaggedObjects.cpp + HashMapOfTaggedObjectsIter.cpp + HashMapOfTaggedObjects.cpp + VectorOfTaggedObjects.cpp + PUBLIC + ArrayOfTaggedObjects.h + ArrayOfTaggedObjectsIter.h + MapOfTaggedObjectsIter.h + MapOfTaggedObjects.h ) target_include_directories(OPS_Tagged PUBLIC ${CMAKE_CURRENT_LIST_DIR}) diff --git a/SRC/tagged/storage/TaggedObjectIter.h b/SRC/tagged/storage/TaggedObjectIter.h index c910939aab..209c1a2ff8 100644 --- a/SRC/tagged/storage/TaggedObjectIter.h +++ b/SRC/tagged/storage/TaggedObjectIter.h @@ -40,8 +40,8 @@ class TaggedObjectIter TaggedObjectIter() {}; virtual ~TaggedObjectIter() {}; - virtual void reset(void) =0; - virtual TaggedObject *operator()(void) =0; + virtual void reset() =0; + virtual TaggedObject *operator()() =0; protected: diff --git a/SRC/tagged/storage/TaggedObjectStorage.h b/SRC/tagged/storage/TaggedObjectStorage.h index 9a619040d8..226f358211 100644 --- a/SRC/tagged/storage/TaggedObjectStorage.h +++ b/SRC/tagged/storage/TaggedObjectStorage.h @@ -44,21 +44,27 @@ class TaggedObjectStorage { public: TaggedObjectStorage() {}; - virtual ~TaggedObjectStorage() {}; + virtual ~TaggedObjectStorage() {}; + + using Iterator = TaggedObjectIter; // public methods to populate the container - virtual int setSize(int newSize) =0; + [[nodiscard]] virtual int setSize(int newSize) =0; virtual bool addComponent(TaggedObject *newComponent) =0; virtual TaggedObject *removeComponent(int tag) =0; - virtual int getNumComponents(void) const =0; + virtual int getNumComponents() const =0; virtual TaggedObject *getComponentPtr(int tag) =0; - virtual TaggedObjectIter &getComponents(void) =0; + virtual TaggedObjectIter &getComponents() =0; - virtual TaggedObjectStorage *getEmptyCopy(void) =0; + virtual TaggedObjectStorage *getEmptyCopy() =0; virtual void clearAll(bool invokeDestructors = true) =0; - virtual void Print(OPS_Stream &s, int flag =0) =0; + virtual void Print(OPS_Stream &s, int flag) =0; + + Iterator& getIterRef() { + return this->getComponents(); + } protected: diff --git a/SRC/tagged/storage/VectorOfTaggedObjects.cpp b/SRC/tagged/storage/VectorOfTaggedObjects.cpp index 912f277dca..52a40c4286 100644 --- a/SRC/tagged/storage/VectorOfTaggedObjects.cpp +++ b/SRC/tagged/storage/VectorOfTaggedObjects.cpp @@ -21,190 +21,174 @@ // Purpose: This file contains the implementation of the VectorOfTaggedObjects // class. // -// Written: fmk -// Created: 02/00 +// Written: cmp +// Created: Jan 2026 // Revision: A // -#include +#include #include -#include -#include - -// some typedefs that will be useful -typedef std::map MAP_TAGGED; -typedef MAP_TAGGED::value_type MAP_TAGGED_TYPE; -typedef MAP_TAGGED::iterator MAP_TAGGED_ITERATOR; +#include "VectorOfTaggedObjects.h" +#include VectorOfTaggedObjects::VectorOfTaggedObjects() :myIter(*this) { - // creates the iter with this as the argument + // creates the iter with this as the argument } VectorOfTaggedObjects::~VectorOfTaggedObjects() { - this->clearAll(); + this->clearAll(); } int VectorOfTaggedObjects::setSize(int newSize) { - // no setSize for map template .. can only check enough space available - int maxSize = int(theMap.max_size()); - if (newSize > maxSize) { - opserr << "VectorOfTaggedObjects::setSize - failed as map STL has a max size of " << maxSize << "\n"; - return -1; - } - - return 0; + // no setSize for map template .. can only check enough space available + int maxSize = int(container.max_size()); + if (newSize > maxSize) + return -1; + + container.reserve(newSize); + return 0; } bool VectorOfTaggedObjects::addComponent(TaggedObject *newComponent) { - MAP_TAGGED_ITERATOR theEle; - int tag = newComponent->getTag(); - - // check if the ele already in map, if not we add - std::pair res = theMap.insert(MAP_TAGGED_TYPE(tag,newComponent)); - if (res.second == false) { - opserr << "VectorOfTaggedObjects::addComponent - not adding as one with similar tag exists, tag: " << - tag << "\n"; - return false; - } + int tag = newComponent->getTag(); - /* - theEle = theMap.find(tag); - if (theEle == theMap.end()) { - theMap.insert(MAP_TAGGED_TYPE(tag,newComponent)); - - // check if sucessfully added - theEle = theMap.find(tag); - if (theEle == theMap.end()) { - opserr << "VectorOfTaggedObjects::addComponent - map STL failed to add object with tag : " << - newComponent->getTag() << "\n"; - return false; - } - } else { - opserr << "VectorOfTaggedObjects::addComponent - not adding as one with similar tag exists, tag: " << - tag << "\n"; + // check if the ele already in map, if not we add + for (auto const& item : container) { + if (item->getTag() == tag) { return false; } - */ + } - return true; // o.k. + container.push_back(newComponent); + return true; // o.k. } TaggedObject * VectorOfTaggedObjects::removeComponent(int tag) { - TaggedObject *removed =0; - MAP_TAGGED_ITERATOR theEle; - - // return 0 if component does not exist, otherwise remove it - theEle = theMap.find(tag); - if (theEle == theMap.end()) // the object has not been added - return 0; - else { // the object exists so we remove it - removed = (*theEle).second; - int ok = int(theMap.erase(tag)); - if (ok != 1) { // ensure the map did remove the object - opserr << "VectorOfTaggedObjects::removeComponent - map STL failed to remove object with tag " << - tag << "\n"; - return 0; - } + for (auto it = container.begin(); it != container.end(); ++it) { + if ((*it)->getTag() == tag) { + TaggedObject* item = *it; + container.erase(it); + return item; } - - return removed; + } + return nullptr; } int -VectorOfTaggedObjects::getNumComponents(void) const +VectorOfTaggedObjects::getNumComponents() const { - return int(theMap.size()); + return int(container.size()); } TaggedObject * VectorOfTaggedObjects::getComponentPtr(int tag) { - TaggedObject *removed = nullptr; - MAP_TAGGED_ITERATOR theEle; - - // return 0 if component does not exist, otherwise remove it - theEle = theMap.find(tag); - if (theEle == theMap.end()) - return nullptr; - else - removed = (*theEle).second; - - return removed; + for (TaggedObject* item : container) { + if (item->getTag() == tag) { + return item; + } + } + return nullptr; } -TaggedObjectIter & -VectorOfTaggedObjects::getComponents() +VectorOfTaggedObjects::Iterator & +VectorOfTaggedObjects::getIterRef() { - myIter.reset(); - return myIter; + myIter.reset(); + return myIter; } - -VectorOfTaggedObjectsIter +VectorOfTaggedObjects::Iterator VectorOfTaggedObjects::getIter() { - return VectorOfTaggedObjectsIter(*this); + return Iterator(*this); } TaggedObjectStorage * VectorOfTaggedObjects::getEmptyCopy() { - VectorOfTaggedObjects *theCopy = new VectorOfTaggedObjects(); - return theCopy; + VectorOfTaggedObjects *theCopy = new VectorOfTaggedObjects(); + return theCopy; } + void VectorOfTaggedObjects::clearAll(bool invokeDestructor) { - - // invoke the destructor on all the tagged objects stored - if (invokeDestructor == true) { - MAP_TAGGED_ITERATOR p = theMap.begin(); - while (p != theMap.end()) { - delete (*p).second; - p++; - } + // invoke the destructor on all the tagged objects stored + if (invokeDestructor == true) { + for (TaggedObject* item : container) { + delete item; } + } - // now clear the map of all entries - theMap.clear(); + // now clear the map of all entries + container.clear(); } + void VectorOfTaggedObjects::Print(OPS_Stream &s, int flag) { - if (flag == OPS_PRINT_PRINTMODEL_JSON) { - MAP_TAGGED_ITERATOR p = theMap.begin(); - while (p != theMap.end()) { - ((*p).second)->Print(s, flag); - p++; - s << ",\n"; - } - return; + if (flag == OPS_PRINT_PRINTMODEL_JSON) { + bool first = true; + for (TaggedObject* p : container) { + if (!first) + s << ", "; + first = false; + p->Print(s, flag); } + return; + } - // s << "\nnumComponents: " << this->getNumComponents(); - // go through the array invoking Print on non-zero entries - MAP_TAGGED_ITERATOR p = theMap.begin(); - while (p != theMap.end()) { - ((*p).second)->Print(s, flag); - p++; - } + for (TaggedObject* p : container) + p->Print(s, flag); } + +VectorOfTaggedObjects::Iterator::Iterator(VectorOfTaggedObjects &theComponents) +{ + container = &(theComponents.container); + this->reset(); +} + + +VectorOfTaggedObjects::Iterator::~Iterator() +{ + +} + +void +VectorOfTaggedObjects::Iterator::reset() +{ + currentComponent = container->begin(); +} + + +TaggedObject * +VectorOfTaggedObjects::Iterator::operator()() +{ + if (currentComponent != container->end()) { + TaggedObject *result = *currentComponent; + currentComponent++; + return result; + } else + return 0; +} + diff --git a/SRC/tagged/storage/VectorOfTaggedObjects.h b/SRC/tagged/storage/VectorOfTaggedObjects.h index 63534c0b25..36adef0242 100644 --- a/SRC/tagged/storage/VectorOfTaggedObjects.h +++ b/SRC/tagged/storage/VectorOfTaggedObjects.h @@ -24,9 +24,11 @@ // File: ~/tagged/storage/VectorOfTaggedObjects.h // // Description: This file contains the class definition for -// VectorOfTaggedObjects. VectorOfTaggedObjects is a storage class. The class +// VectorOfTaggedObjects. +// VectorOfTaggedObjects is a storage class. The class // is responsible for holding and providing access to objects of type -// TaggedObject. A map template of the standard template class is used to store +// TaggedObject. +// A std::map is used to store // the pointers to these objects. // // Written: fmk @@ -36,9 +38,9 @@ #ifndef VectorOfTaggedObjects_h #define VectorOfTaggedObjects_h // -#include +#include #include -#include +#include class VectorOfTaggedObjects : public TaggedObjectStorage { @@ -46,29 +48,42 @@ class VectorOfTaggedObjects : public TaggedObjectStorage VectorOfTaggedObjects(); ~VectorOfTaggedObjects(); + class Iterator: public TaggedObjectIter + { + public: + Iterator(VectorOfTaggedObjects &theComponents); + virtual ~Iterator(); + + void reset() final; + TaggedObject *operator()() final; + + private: + std::vector *container; + std::vector::iterator currentComponent; + }; + // public methods to populate a domain int setSize(int newSize); - bool addComponent(TaggedObject *newComponent); -// bool allowMutltipleTags = false); - TaggedObject *removeComponent(int tag); - int getNumComponents(void) const; - - TaggedObject *getComponentPtr(int tag); - TaggedObjectIter &getComponents(); - - VectorOfTaggedObjectsIter getIter(); + bool addComponent(TaggedObject *newComponent) final; + TaggedObject *removeComponent(int tag) final; + int getNumComponents() const; - TaggedObjectStorage *getEmptyCopy(void); + TaggedObject *getComponentPtr(int tag) final; + TaggedObjectIter &getComponents() final { + return this->getIterRef(); + } + Iterator& getIterRef(); + Iterator getIter(); + + TaggedObjectStorage *getEmptyCopy(); void clearAll(bool invokeDestructor = true); - void Print(OPS_Stream &s, int flag =0); - friend class VectorOfTaggedObjectsIter; - - protected: + void Print(OPS_Stream &s, int flag); + private: - std::map theMap; // the map container for storing the pointers - VectorOfTaggedObjectsIter myIter; // the iter for this object + std::vector container; // the map container for storing the pointers + Iterator myIter; // the iter for this object }; #endif diff --git a/SRC/tagged/storage/VectorOfTaggedObjectsIter.cpp b/SRC/tagged/storage/VectorOfTaggedObjectsIter.cpp deleted file mode 100644 index 98d3f53399..0000000000 --- a/SRC/tagged/storage/VectorOfTaggedObjectsIter.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ -// -// Description: This file contains the implementation of VectorOfTaggedObjects. -// -// $Date: 2000-09-15 08:23:30 $ -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -#include -#include -#include - -// some typedefs that will be useful -typedef std::map MAP_TAGGED; -typedef MAP_TAGGED::value_type MAP_TAGGED_TYPE; -typedef MAP_TAGGED::iterator MAP_TAGGED_ITERATOR; - -// VectorOfTaggedObjectsIter(SingleDomain &theDomain): -// constructor that takes the model, just the basic iter -VectorOfTaggedObjectsIter::VectorOfTaggedObjectsIter(VectorOfTaggedObjects &theComponents) -{ - theMap = &(theComponents.theMap); -} - - -VectorOfTaggedObjectsIter::~VectorOfTaggedObjectsIter() -{ - -} - -void -VectorOfTaggedObjectsIter::reset(void) -{ - currentComponent = theMap->begin(); -} - -TaggedObject * -VectorOfTaggedObjectsIter::operator()(void) -{ - if (currentComponent != theMap->end()) { - TaggedObject *result = (*currentComponent).second; - currentComponent++; - return result; - } else - return 0; -} - - - diff --git a/SRC/tagged/storage/VectorOfTaggedObjectsIter.h b/SRC/tagged/storage/VectorOfTaggedObjectsIter.h deleted file mode 100644 index 1e393a55a8..0000000000 --- a/SRC/tagged/storage/VectorOfTaggedObjectsIter.h +++ /dev/null @@ -1,63 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:30 $ -// $Source: /usr/local/cvs/OpenSees/SRC/tagged/storage/VectorOfTaggedObjectsIter.h,v $ - -// File: ~/tagged/storage/ArrayComponentIter -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the class definition for -// VectorOfTaggedObjectsIter. A VectorOfTaggedObjectsIter is an iter for -// returning the TaggedObjects of a storage objects of type -// VectorOfTaggedComponents. -// -#ifndef VectorOfTaggedObjectsIter_h -#define VectorOfTaggedObjectsIter_h - -#include -#include - -class VectorOfTaggedObjects; - -class VectorOfTaggedObjectsIter: public TaggedObjectIter -{ - public: - VectorOfTaggedObjectsIter(VectorOfTaggedObjects &theComponents); - virtual ~VectorOfTaggedObjectsIter(); - - virtual void reset(void); - virtual TaggedObject *operator()(void); - - private: - std::map *theMap; - std::map::iterator currentComponent; -}; - -#endif - - - - - From a6d93fc28a610b8a763a32ff2e75df698d590307 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:47:08 -0800 Subject: [PATCH 006/161] Update IGAKLShell.cpp --- SRC/element/IGA/IGAKLShell.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SRC/element/IGA/IGAKLShell.cpp b/SRC/element/IGA/IGAKLShell.cpp index ea3e641029..e8b5adccd9 100644 --- a/SRC/element/IGA/IGAKLShell.cpp +++ b/SRC/element/IGA/IGAKLShell.cpp @@ -1658,11 +1658,7 @@ const Matrix& IGAKLShell::getTangentStiff( ) // // opserr << "Finished making Ke!!" << endln << endln; - // // opserr << "K = " << K << endln; - - // // opserr << "K = " << K << endln; // // return K ; - // // opserr << "*stiff = " << *stiff << endln; // return *stiff; } From 0d592742b6573d54e146f28ae5a6d4e59cddbcd3 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:48:32 -0800 Subject: [PATCH 007/161] Update MatrixND.h --- SRC/matrix/MatrixND.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/SRC/matrix/MatrixND.h b/SRC/matrix/MatrixND.h index d5738ca879..5ad6e9de50 100644 --- a/SRC/matrix/MatrixND.h +++ b/SRC/matrix/MatrixND.h @@ -53,10 +53,13 @@ struct alignas(64) MatrixND { inline constexpr const T* data() const noexcept { return values.data(); } // Convert to regular Matrix class + #ifndef ALLOW_IMPLICIT_MATRIX + explicit operator Matrix() { return Matrix(&(*this)(0,0), NR, NC);} + explicit operator const Matrix() const { return Matrix(&(*this)(0,0), NR, NC);} + #else operator Matrix() { return Matrix(&(*this)(0,0), NR, NC);} - operator const Matrix() const { return Matrix(&(*this)(0,0), NR, NC);} - + #endif inline constexpr void zero() noexcept; constexpr T @@ -70,12 +73,19 @@ struct alignas(64) MatrixND { return sum; } + const double norm() const noexcept; + constexpr double determinant() const ; inline constexpr MatrixND transpose() const noexcept; inline constexpr MatrixND& addDiagonal(const double vol) noexcept; + template + void addMatrix(const MatT& A, const double scale); + + void addTranspose(const MatrixND& A, const double scale); + template constexpr void setMatrixProduct(const MatrixND& A, const MatrixND& B, double scale) noexcept; @@ -91,9 +101,6 @@ struct alignas(64) MatrixND { template constexpr void addMatrixTransposeProduct(const MatrixND& B, const MatrixND& C) noexcept; - - template - void addMatrix(const MatT& A, const double scale); template constexpr MatrixND& addTensorProduct(const VecA& V, const VecB& W, const double scale) noexcept; From adc4b5e014a9f5b7c92a81ee01a2cb5ea6a7161a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:48:47 -0800 Subject: [PATCH 008/161] Update MatrixND.tpp --- SRC/matrix/MatrixND.tpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/SRC/matrix/MatrixND.tpp b/SRC/matrix/MatrixND.tpp index 30ec5d8773..5067d09a40 100644 --- a/SRC/matrix/MatrixND.tpp +++ b/SRC/matrix/MatrixND.tpp @@ -33,6 +33,19 @@ MatrixND::zero() noexcept values.fill(0.0); } +template +const double +MatrixND::norm() const noexcept +{ + double sum = 0.0; + for (index_t j = 0; j < nc; ++j) { + for (index_t i = 0; i < nr; ++i) { + const double val = static_cast((*this)(i,j)); + sum += val * val; + } + } + return std::sqrt(sum); +} #if 0 template @@ -350,6 +363,15 @@ void MatrixND::addMatrix(const MatT& A, const double scale) (*this)(i,j) += A(i,j)*scale; } +template +inline void +MatrixND::addTranspose(const MatrixND& A, const double scale) +{ + for (int i=0; i template From f4e0cca351c3369ddb99dfee335824d04b993148 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:38:44 -0800 Subject: [PATCH 009/161] Update MapOfTaggedObjectsIter.h --- SRC/tagged/storage/MapOfTaggedObjectsIter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/tagged/storage/MapOfTaggedObjectsIter.h b/SRC/tagged/storage/MapOfTaggedObjectsIter.h index d6cfe59a48..18cb9a3b7f 100644 --- a/SRC/tagged/storage/MapOfTaggedObjectsIter.h +++ b/SRC/tagged/storage/MapOfTaggedObjectsIter.h @@ -47,8 +47,8 @@ class MapOfTaggedObjectsIter: public TaggedObjectIter MapOfTaggedObjectsIter(MapOfTaggedObjects &theComponents); virtual ~MapOfTaggedObjectsIter(); - virtual void reset(void); - virtual TaggedObject *operator()(void); + void reset() final; + TaggedObject *operator()() final; private: std::map *theMap; From 69ca653209563a4f3af38ef01734421a4fb05ae8 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:38:49 -0800 Subject: [PATCH 010/161] Update MapOfTaggedObjectsIter.cpp --- SRC/tagged/storage/MapOfTaggedObjectsIter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SRC/tagged/storage/MapOfTaggedObjectsIter.cpp b/SRC/tagged/storage/MapOfTaggedObjectsIter.cpp index 9ead624fba..8c81656bcd 100644 --- a/SRC/tagged/storage/MapOfTaggedObjectsIter.cpp +++ b/SRC/tagged/storage/MapOfTaggedObjectsIter.cpp @@ -35,7 +35,6 @@ typedef std::map MAP_TAGGED; typedef MAP_TAGGED::value_type MAP_TAGGED_TYPE; typedef MAP_TAGGED::iterator MAP_TAGGED_ITERATOR; -// MapOfTaggedObjectsIter(SingleDomain &theDomain): // constructor that takes the model, just the basic iter MapOfTaggedObjectsIter::MapOfTaggedObjectsIter(MapOfTaggedObjects &theComponents) { @@ -49,7 +48,7 @@ MapOfTaggedObjectsIter::~MapOfTaggedObjectsIter() } void -MapOfTaggedObjectsIter::reset(void) +MapOfTaggedObjectsIter::reset() { currentComponent = theMap->begin(); } From e51e7f3aa86fbb5eed5a64bd150da67166f1b1db Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:39:06 -0800 Subject: [PATCH 011/161] Update ArrayOfTaggedObjects.h --- SRC/tagged/storage/ArrayOfTaggedObjects.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/SRC/tagged/storage/ArrayOfTaggedObjects.h b/SRC/tagged/storage/ArrayOfTaggedObjects.h index 1b13e7892b..0072a4e15b 100644 --- a/SRC/tagged/storage/ArrayOfTaggedObjects.h +++ b/SRC/tagged/storage/ArrayOfTaggedObjects.h @@ -36,7 +36,8 @@ // ArrayOfTaggedObjects. ArrayOfTaggedObjects is a storage class. The class // is responsible for holding and providing access to objects of type // TaggedObject. The data structure used to hold the objects is a simple -// array of pointers. As a one dimensional array is used certain ideas are tried +// array of pointers. +// As a one dimensional array is used certain ideas are tried // to improve performance: (1) if the array needs to be larger to hold more // components, the array size is doubled and (2) when adding/retrieving components, // the array location given by the components tag is first checked. @@ -56,19 +57,20 @@ class ArrayOfTaggedObjects : public TaggedObjectStorage // public methods to populate a domain int setSize(int newSize); bool addComponent(TaggedObject *newComponent); -// bool allowMutltipleTags = false); TaggedObject *removeComponent(int tag); - int getNumComponents(void) const; + int getNumComponents() const; TaggedObject *getComponentPtr(int tag); TaggedObjectIter &getComponents(); + using Iterator = ArrayOfTaggedObjectsIter; + ArrayOfTaggedObjectsIter getIter(); - virtual TaggedObjectStorage *getEmptyCopy(void); + virtual TaggedObjectStorage *getEmptyCopy(); virtual void clearAll(bool invokeDestructor = true); - - void Print(OPS_Stream &s, int flag =0); + + void Print(OPS_Stream &s, int flag); friend class ArrayOfTaggedObjectsIter; protected: From 4e6ad26962ed44e5c4bd5ba97a07a1767956cd2c Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:39:12 -0800 Subject: [PATCH 012/161] Update ArrayOfTaggedObjectsIter.cpp --- SRC/tagged/storage/ArrayOfTaggedObjectsIter.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/SRC/tagged/storage/ArrayOfTaggedObjectsIter.cpp b/SRC/tagged/storage/ArrayOfTaggedObjectsIter.cpp index d3cacfb612..84014a568f 100644 --- a/SRC/tagged/storage/ArrayOfTaggedObjectsIter.cpp +++ b/SRC/tagged/storage/ArrayOfTaggedObjectsIter.cpp @@ -51,14 +51,14 @@ ArrayOfTaggedObjectsIter::~ArrayOfTaggedObjectsIter() } void -ArrayOfTaggedObjectsIter::reset(void) +ArrayOfTaggedObjectsIter::reset() { - currIndex = 0; - numDone = 0; + currIndex = 0; + numDone = 0; } TaggedObject * -ArrayOfTaggedObjectsIter::operator()(void) +ArrayOfTaggedObjectsIter::operator()() { // check if we still have elements in the model // if not return 0, indicating we are done @@ -81,6 +81,3 @@ ArrayOfTaggedObjectsIter::operator()(void) } return (0); } - - - From 5804878d656ae30d479d0b114b0e3d3f702e0c75 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:43:51 -0800 Subject: [PATCH 013/161] Refactor FrameSolidSection3d for shear alignment and Poisson effects Introduces shear_align matrix and related parameter handling to FrameSolidSection3d, refactors tangent assembly and fiber state management, and adds support for Poisson effects in state determination. Also updates JSON printing, copy constructor, and parameter update logic to include shear alignment, and improves code structure for clarity and extensibility. --- SRC/material/Frame/FrameSolidSection3d.cpp | 579 +++++++++++++++------ SRC/material/Frame/FrameSolidSection3d.h | 54 +- 2 files changed, 451 insertions(+), 182 deletions(-) diff --git a/SRC/material/Frame/FrameSolidSection3d.cpp b/SRC/material/Frame/FrameSolidSection3d.cpp index 614a285c58..00922fb171 100644 --- a/SRC/material/Frame/FrameSolidSection3d.cpp +++ b/SRC/material/Frame/FrameSolidSection3d.cpp @@ -47,17 +47,22 @@ ID FrameSolidSection3d::code(nsr); FrameSolidSection3d::FrameSolidSection3d(int tag, int num): FrameSection(tag, SEC_TAG_FrameSolidSection3d), + s(), e(), e_wrap(e), s_wrap(s), + shear_align{}, + centroid{}, + nubar(0.0), parameterID(0), dedh(nsr), fibers(new std::vector), - K_init(new Tangent) + K_init(new Tangent), + fiber_state(FiberState::Clean) { - code(inx) = SECTION_RESPONSE_P; - code(iny) = SECTION_RESPONSE_VY; - code(inz) = SECTION_RESPONSE_VZ; - code(imx) = SECTION_RESPONSE_T; - code(imy) = SECTION_RESPONSE_MY; - code(imz) = SECTION_RESPONSE_MZ; + code(inx) = FrameStress::N; + code(iny) = FrameStress::Vy; + code(inz) = FrameStress::Vz; + code(imx) = FrameStress::T; + code(imy) = FrameStress::My; + code(imz) = FrameStress::Mz; code(iwx) = FrameStress::Bimoment; code(iwy) = FrameStress::By; code(iwz) = FrameStress::Bz; @@ -68,19 +73,25 @@ FrameSolidSection3d::FrameSolidSection3d(int tag, int num): wagner = getenv("Wagner") != nullptr; } -// constructor for blank object that recvSelf needs to be invoked upon + +// for recvSelf FrameSolidSection3d::FrameSolidSection3d(): FrameSection(0, SEC_TAG_FrameSolidSection3d), + s(), e(), e_wrap(e), s_wrap(s), + shear_align{}, + centroid{}, + nubar(0.0), parameterID(0), dedh(nsr), - fibers(new std::vector) + fibers(new std::vector), + fiber_state(FiberState::Clean) { - code(inx) = SECTION_RESPONSE_P; - code(iny) = SECTION_RESPONSE_VY; - code(inz) = SECTION_RESPONSE_VZ; - code(imx) = SECTION_RESPONSE_T; - code(imy) = SECTION_RESPONSE_MY; - code(imz) = SECTION_RESPONSE_MZ; + code(inx) = FrameStress::N; + code(iny) = FrameStress::Vy; + code(inz) = FrameStress::Vz; + code(imx) = FrameStress::T; + code(imy) = FrameStress::My; + code(imz) = FrameStress::Mz; code(iwx) = FrameStress::Bimoment; code(iwy) = FrameStress::By; code(iwz) = FrameStress::Bz; @@ -90,6 +101,31 @@ FrameSolidSection3d::FrameSolidSection3d(): wagner = getenv("Wagner") != nullptr; } +// Used in getCopy to create an element instance from a reference instance +FrameSolidSection3d::FrameSolidSection3d(const FrameSolidSection3d &other) + : FrameSection(other.getTag(), other.getClassTag()), + K_pres(other.K_pres), + K_init(other.K_init), + fibers(other.fibers), + s(), + e(), + s_wrap(s), + e_wrap(e), + shear_align(other.shear_align), + centroid(other.centroid), + wagner(other.wagner), + fiber_state(FiberState::Clean), + parameterID(0) +{ + materials.reserve(other.materials.size()); + for (int i = 0; i < other.materials.size(); i++) + materials.push_back(other.materials[i]->getCopy("BeamFiber")); + // materials[i] = other.materials[i]->getCopy("BeamFiber"); + + this->revertToStart(); +} + + int FrameSolidSection3d::getIntegral(Field field, State state, double& value) const { @@ -175,7 +211,8 @@ FrameSolidSection3d::addFiber(NDMaterial& theMat, if (materials[materials.size()-1] == nullptr) return -1; - + + fiber_state = FiberState::Dirty; return materials.size()-1; } @@ -197,10 +234,98 @@ FrameSolidSection3d::setTrialSectionDeformation(const Vector &e_trial) return stateDetermination(K_pres, &s, &e, CurrentTangent); } + +FrameSection* +FrameSolidSection3d::getFrameCopy() +{ + + double area = 0.0; + if (fiber_state == FiberState::Dirty) { + nubar = 0.0; + const int nf = fibers->size(); + centroid.zero(); + for (int i = 0; i < nf; i++) { + NDMaterial &theMat = *materials[i]; + auto & fiber = (*fibers)[i]; + const Matrix & tangent = theMat.getInitialTangent(); + double nu = tangent(0,0)/(2.0*tangent(1,1)) - 1.0; + area += fiber.area; + nubar += nu*fiber.area; + centroid[1] += fiber.r[1]*fiber.area; + centroid[2] += fiber.r[2]*fiber.area; + } + centroid /= area; + nubar /= area; + } + if (!(getenv("Align"))) { + fiber_state = FiberState::Clean; + } + + if (fiber_state == FiberState::Dirty) { + const VectorND<2> rc { + centroid[1], + centroid[2] + }; + const int nf = fibers->size(); + double do_poisson = shear_align.norm() != 0.0; + MatrixND<2,2> H{}, HF{}; + for (int i = 0; i < nf; i++) { + NDMaterial &theMat = *materials[i]; + auto & fiber = (*fibers)[i]; + auto & w = fiber.warp; + const VectorND<2> r {fiber.r[1], fiber.r[2]}; + const Matrix & tangent = theMat.getInitialTangent(); + double nu = tangent(0,0)/(2.0*tangent(1,1)) - 1.0; + nu *= do_poisson; + MatrixND<2,2> Bb{}; + // -(dev ror)Xi + Bb.addTensorProduct(r, r, -nu); + Bb.addDiagonal(0.5*r.dot(r)*nu); + // + roc + Bb.addTensorProduct(r, rc, nu); + for (int j=0; j<2; j++) { + for (int k=0; k<2; k++) { + Bb(j,k) += w[1+k][1+j]; + } + } + HF.addMatrix(Bb, fiber.area*tangent(1,1)); + // HF.addTensorProduct(r-rc, r-rc, fiber.area*tangent(0,0)); + H.addMatrixTransposeProduct(1.0, Bb, Bb, fiber.area*tangent(1,1)); + } + Cholesky<2,false> chol(H); + MatrixND<2,2> Hi{}; + chol.invert(Hi); + MatrixND<2,2> X = Hi*HF.transpose(); + + for (int i=0; i<2; i++) + for (int j=0; j<2; j++) + shear_align(i+1,j+1) = X(i,j)*nubar; + + for (int k=0; k U {{w[1][1], w[1][2], + w[2][1], w[2][2]}}; + MatrixND<2,2> UX = U*X; + VectorND<2> xu = X^(VectorND<2>{w[1][0], w[2][0]}); + for (int i=0; i<2; i++) { + fiber.warp[i+1][0] = xu(i) - fiber.r[i+1]; + for (int j=0; j<2; j++) + fiber.warp[i+1][j+1] = UX(j,i) - double(i==j); + } + } + + fiber_state = FiberState::Clean; + } + return new FrameSolidSection3d(*this); +} + int FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, const VectorND * const e_trial, int tangentFlag) { + const bool conj_poisson = getenv("ConjPoisson") != nullptr; + const Vector3D gamma { e_trial? (*e_trial)(inx) : 0.0, e_trial? (*e_trial)(iny) : 0.0, @@ -222,8 +347,12 @@ FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons e_trial? (*e_trial)(ivz) : 0.0 }; + if (s_trial != nullptr) + s_trial->zero(); + K.zero(); + // integrate over fibers int res = 0; const int nf = fibers->size(); for (int i = 0; i < nf; i++) { @@ -231,10 +360,17 @@ FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons NDMaterial &theMat = *materials[i]; auto & fiber = (*fibers)[i]; auto & w = fiber.warp; - - const Vector3D r = fiber.r; + const Vector3D& r = fiber.r; double tr2 = 0; + Matrix3D Wb{}; + // -(dev ror)Xi + Wb.addTensorProduct(r, shear_align^r, -1.0); + Wb.addMatrix(shear_align, 0.5*r.dot(r)); + // + roc + Wb.addTensorProduct(r, shear_align^centroid, 1.0); + for (int j=0; j<3; j++) Wb(0,j) = (Wb(j,0) = 0.0); // No axial Poisson effect + if (e_trial != nullptr) { // Form material strain Vector3D eps = gamma + kappa.cross(r); @@ -243,6 +379,23 @@ FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons for (int j=1; j<3; j++) eps[j] += w[k][j]*alpha[k]; } + // Poisson effect + eps += Wb*gamma; + // if (eps.norm() != 0.0) { + // Vector3D eps_gamma = gamma + Wb*gamma; + // Vector3D eps_kappa = kappa.cross(r); + + // for (int k=1; k* s_trial, cons const Matrix &tangent = tangentFlag==CurrentTangent - ? theMat.getTangent() - : theMat.getInitialTangent(); + ? theMat.getTangent() + : theMat.getInitialTangent(); Matrix3D C{}; C.addMatrix(tangent, fiber.area); @@ -268,31 +421,50 @@ FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons }}; const Matrix3D iodw {{ - 0.0, w[0][1], w[0][2], - 0.0, w[1][1], w[1][2], - 0.0, w[2][1], w[2][2] + 0.0, w[0][1], w[0][2], + 0.0, w[1][1], w[1][2], + 0.0, w[2][1], w[2][2] }}; + const Matrix3D CWb = C*Wb; + const Matrix3D Ciow = C*iow; + const Matrix3D Ciodw = C*iodw; + Matrix3D Crx{}; + Crx.addMatrixSpinProduct( C, r, -1.0); + + { + K.nn.addMatrix(C, 1.0); + K.nn.addMatrix(CWb, 1.0); + K.nw.addMatrix(Ciow, 1.0); + K.nm.addMatrix(Crx, 1.0); + K.nv.addMatrix(Ciodw, 1.0); + if (conj_poisson) { + K.nv.addMatrixTransposeProduct(1.0, Wb, Ciodw, 1.0); + K.nm.addMatrixTransposeProduct(1.0, Wb, Crx, 1.0); + K.nn.addMatrixTransposeProduct(1.0, Wb, C+CWb, 1.0); + K.nw.addMatrixTransposeProduct(1.0, Wb, Ciow, 1.0); + } + } - K.nn.addMatrix(C, 1.0); { - Matrix3D rxC{}; - rxC.addSpinMatrixProduct(r, C, 1.0); - K.mm.addMatrixSpinProduct(rxC, r, -1.0); - K.mn.addMatrix(rxC, 1.0); - K.mw.addMatrixProduct(rxC, iow, 1.0); - K.mv.addMatrixProduct(rxC, iodw, 1.0); + K.mn.addSpinMatrixProduct(r, C, 1.0); + K.mn.addSpinMatrixProduct(r, CWb, 1.0); + K.mm.addSpinMatrixProduct(r, Crx, 1.0); + K.mw.addSpinMatrixProduct(r, Ciow, 1.0); + K.mv.addSpinMatrixProduct(r, Ciodw, 1.0); } { - Matrix3D Ciow{}; - Ciow.addMatrixProduct(C, iow, 1.0); - K.nw.addMatrix(Ciow, 1.0); + K.wn.addTranspose(Ciow, 1.0); + K.wn.addMatrixTransposeProduct(1.0, iow, CWb, 1.0); + K.wm.addMatrixTransposeProduct(1.0, iow, Crx, 1.0); K.ww.addMatrixTransposeProduct(1.0, iow, Ciow, 1.0); + K.wv.addMatrixTransposeProduct(1.0, iow, Ciodw, 1.0); } { - Matrix3D Ciodw{}; - Ciodw.addMatrixProduct(C, iodw, 1.0); - K.nv.addMatrix(Ciodw, 1.0); + K.vn.addTranspose(Ciodw, 1.0); + K.vn.addMatrixTransposeProduct(1.0, iodw, CWb, 1.0); + K.vm.addMatrixTransposeProduct(1.0, iodw, Crx, 1.0); + K.vw.addMatrixTransposeProduct(1.0, iodw, Ciow, 1.0); K.vv.addMatrixTransposeProduct(1.0, iodw, Ciodw, 1.0); } @@ -301,23 +473,24 @@ FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons // const Vector &stress = theMat.getStress(); - if (wagner && e_trial != nullptr) { + if (wagner && (e_trial != nullptr)) { constexpr Matrix3D ioi {{ 1, 0, 0 , 0, 0, 0 , 0, 0, 0 }}; - Matrix3D ioiC = ioi*C; - K.mn.addMatrix(ioiC, tr2); - // - K.mm.addSpinMatrixProduct(r, ioiC.transpose(), tr2); - K.mm.addMatrixSpinProduct(ioiC, r, -tr2); - K.mm.addMatrixProduct(ioiC, ioi, tr2*tr2); - - // Geometric part, equivalent to Kmm.addMatrix(ioi, r2*stress(0)); - if (kappa[0] != 0) [[likely]] - K.mm(0,0) += tr2/kappa[0]*stress(0)*fiber.area; - - K.mw.addMatrixProduct(ioiC, iow, tr2); - K.mv.addMatrixProduct(ioiC, iodw, tr2); + Matrix3D ioiC = ioi*C; + K.mn.addMatrix(ioiC, tr2); + K.nm.addTranspose(ioiC, tr2); + // + K.mm.addSpinMatrixProduct(r, ioiC.transpose(), tr2); + K.mm.addMatrixSpinProduct(ioiC, r, -tr2); + K.mm.addMatrixProduct(ioiC, ioi, tr2*tr2); + + // Geometric part, equivalent to Kmm.addMatrix(ioi, r2*stress(0)); + if (kappa[0] != 0) [[likely]] + K.mm(0,0) += (tr2/kappa[0])*stress(0)*fiber.area; + + K.mw.addMatrixProduct(ioiC, iow, tr2); + K.mv.addMatrixProduct(ioiC, iodw, tr2); } if (s_trial != nullptr) { @@ -344,95 +517,103 @@ FrameSolidSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons if (wagner && e_trial != nullptr) (*s_trial)(imx) += tr2*sig0; + + if (conj_poisson) { + // Poisson effect + (*s_trial)(iny) += Wb(1,1)*sig1 + Wb(2,1)*sig2; + (*s_trial)(inz) += Wb(1,2)*sig1 + Wb(2,2)*sig2; + } } } return res; } + const Vector& FrameSolidSection3d::getSectionDeformation() { return e_wrap; } -const Matrix& -FrameSolidSection3d::getInitialTangent() -{ - static double kInitial[nsr*nsr]; - static Matrix ksi(kInitial, nsr, nsr); - - ksi.Zero(); - this->stateDetermination(*K_init, nullptr, nullptr, InitialTangent); - - ksi.Zero(); - ksi.Assemble(K_init->nn, 0, 0, 1.0); - ksi.Assemble(K_init->nw, 0, 6, 1.0); - ksi.Assemble(K_init->nv, 0, 9, 1.0); - ksi.Assemble(K_init->mn, 3, 0, 1.0); - ksi.Assemble(K_init->mm, 3, 3, 1.0); - ksi.Assemble(K_init->mw, 3, 6, 1.0); - ksi.Assemble(K_init->mv, 3, 9, 1.0); - ksi.Assemble(K_init->ww, 6, 6, 1.0); - ksi.Assemble(K_init->vv, 9, 9, 1.0); - - ksi.AssembleTranspose(K_init->nw, 6, 0, 1.0); - ksi.AssembleTranspose(K_init->nv, 9, 0, 1.0); - ksi.AssembleTranspose(K_init->mn, 0, 3, 1.0); - ksi.AssembleTranspose(K_init->mw, 6, 3, 1.0); - ksi.AssembleTranspose(K_init->mv, 9, 3, 1.0); - return ksi; -} - const Matrix& FrameSolidSection3d::getSectionTangent() { #ifndef SEES_SECTION_THREADS - static Matrix K_wrap(nsr, nsr); + static MatrixND K; + static Matrix K_wrap(K); + // K_wrap.setData(K); #endif - K_wrap.Zero(); - K_wrap.Assemble(K_pres.nn, 0, 0, 1.0); - K_wrap.Assemble(K_pres.nw, 0, 6, 1.0); - K_wrap.Assemble(K_pres.nv, 0, 9, 1.0); - K_wrap.Assemble(K_pres.mn, 3, 0, 1.0); - K_wrap.Assemble(K_pres.mm, 3, 3, 1.0); - K_wrap.Assemble(K_pres.mw, 3, 6, 1.0); - K_wrap.Assemble(K_pres.mv, 3, 9, 1.0); - K_wrap.Assemble(K_pres.ww, 6, 6, 1.0); - K_wrap.Assemble(K_pres.vv, 9, 9, 1.0); - - K_wrap.AssembleTranspose(K_pres.nw, 6, 0, 1.0); - K_wrap.AssembleTranspose(K_pres.nv, 9, 0, 1.0); - K_wrap.AssembleTranspose(K_pres.mn, 0, 3, 1.0); - K_wrap.AssembleTranspose(K_pres.mw, 6, 3, 1.0); - K_wrap.AssembleTranspose(K_pres.mv, 9, 3, 1.0); + + K.zero(); + K.assemble(K_pres.nn, 0, 0, 1.0); + K.assemble(K_pres.nm, 0, 3, 1.0); + K.assemble(K_pres.nw, 0, 6, 1.0); + K.assemble(K_pres.nv, 0, 9, 1.0); + + K.assemble(K_pres.mn, 3, 0, 1.0); + K.assemble(K_pres.mm, 3, 3, 1.0); + K.assemble(K_pres.mw, 3, 6, 1.0); + K.assemble(K_pres.mv, 3, 9, 1.0); + + K.assemble(K_pres.wn, 6, 0, 1.0); + K.assemble(K_pres.wm, 6, 3, 1.0); + K.assemble(K_pres.ww, 6, 6, 1.0); + K.assemble(K_pres.wv, 6, 9, 1.0); + + // + K.assemble(K_pres.vn, 9, 0, 1.0); + K.assemble(K_pres.vm, 9, 3, 1.0); + K.assemble(K_pres.vw, 9, 6, 1.0); + K.assemble(K_pres.vv, 9, 9, 1.0); + + // K.assembleTranspose(K_pres.mn, 0, 3, 1.0); // nm + // K.assembleTranspose(K_pres.nw, 6, 0, 1.0); + // K.assembleTranspose(K_pres.mw, 6, 3, 1.0); + // // K.assembleTranspose(K_pres.nv, 9, 0, 1.0); + // K.assembleTranspose(K_pres.mv, 9, 3, 1.0); // vm + // K.assembleTranspose(K_pres.wv, 9, 6, 1.0); // vw return K_wrap; } -const Vector& -FrameSolidSection3d::getStressResultant() +const Matrix& +FrameSolidSection3d::getInitialTangent() { - return s_wrap; + static MatrixND ksi; + static Matrix wrap(ksi); //, nsr, nsr); + + ksi.zero(); + this->stateDetermination(K_pres, nullptr, nullptr, InitialTangent); + + ksi.zero(); + ksi.assemble(K_pres.nn, 0, 0, 1.0); + ksi.assemble(K_pres.mn, 3, 0, 1.0); + ksi.assemble(K_pres.nw, 0, 6, 1.0); + ksi.assemble(K_pres.nv, 0, 9, 1.0); + ksi.assemble(K_pres.mn, 3, 0, 1.0); + ksi.assemble(K_pres.mm, 3, 3, 1.0); + ksi.assemble(K_pres.mw, 3, 6, 1.0); + ksi.assemble(K_pres.mv, 3, 9, 1.0); + ksi.assemble(K_pres.ww, 6, 6, 1.0); + ksi.assemble(K_pres.vv, 9, 9, 1.0); + ksi.assembleTranspose(K_pres.nw, 6, 0, 1.0); + ksi.assembleTranspose(K_pres.nv, 9, 0, 1.0); + ksi.assembleTranspose(K_pres.mn, 0, 3, 1.0); + ksi.assembleTranspose(K_pres.mw, 6, 3, 1.0); + ksi.assembleTranspose(K_pres.mv, 9, 3, 1.0); + return wrap; } -FrameSection* -FrameSolidSection3d::getFrameCopy() -{ - FrameSolidSection3d *theCopy = new FrameSolidSection3d(); - theCopy->setTag(this->getTag()); - for (auto& material: materials) - theCopy->materials.push_back(material->getCopy("BeamFiber")); +const Vector& +FrameSolidSection3d::getStressResultant() +{ + return s_wrap; +} - theCopy->fibers = fibers; - theCopy->e = e; - theCopy->parameterID = parameterID; - theCopy->K_init = K_init; - return theCopy; -} const ID& FrameSolidSection3d::getType() @@ -440,12 +621,14 @@ FrameSolidSection3d::getType() return code; } + int FrameSolidSection3d::getOrder() const { return nsr; } + int FrameSolidSection3d::commitState() { @@ -472,6 +655,7 @@ FrameSolidSection3d::revertToLastCommit() return err; } + int FrameSolidSection3d::revertToStart() { @@ -480,13 +664,15 @@ FrameSolidSection3d::revertToStart() err += material->revertToStart(); s.zero(); + e.zero(); err += this->stateDetermination(K_pres, &s, nullptr, CurrentTangent); return err; } + int -FrameSolidSection3d::sendSelf(int commitTag, Channel &theChannel) +FrameSolidSection3d::sendSelf(int commitTag, Channel &) { return -1; } @@ -498,63 +684,10 @@ FrameSolidSection3d::recvSelf(int , Channel &, return -1; } -void -FrameSolidSection3d::Print(OPS_Stream &s, int flag) -{ - const int nf = fibers->size(); - if (flag == OPS_PRINT_PRINTMODEL_JSON) { - s << OPS_PRINT_JSON_MATE_INDENT << "{"; - s << "\"name\": " << this->getTag() << ", "; - s << "\"type\": \"" << this->getClassType() << "\", "; - - double mass; - if (this->FrameSection::getIntegral(Field::Density, State::Init, mass) == 0) - s << "\"mass\": " << mass; - - s << "\"fibers\": [\n"; - - for (int i = 0; i < nf; i++) { - s << OPS_PRINT_JSON_MATE_INDENT << "\t{\"location\": [" - << (*fibers)[i].r[1] << ", " - << (*fibers)[i].r[2] << "], "; - s << "\"area\": " << (*fibers)[i].area << ", "; - s << "\"warp\": ["; - for (int j = 0; j < nwm; j++) { - s << "["; - for (int k = 0; k < 3; k++) { - s << (*fibers)[i].warp[j][k]; - if (k < 2) - s << ", "; - } - s << "]"; - if (j < nwm-1) - s << ", "; - } - s << "], "; - - s << "\"material\": " << materials[i]->getTag(); - if (i < nf - 1) - s << "},\n"; - else - s << "}\n"; - } - s << OPS_PRINT_JSON_MATE_INDENT << "]}"; - return; - } - - else if (flag == 1) { - for (int i = 0; i < nf; i++) { - auto & fiber = (*fibers)[i]; - s << "\nLocation (y,z) = " << fiber.r[1] << ' ' << fiber.r[2]; - s << "\nArea = " << fiber.area << endln; - materials[i]->Print(s, flag); - } - } -} Response* FrameSolidSection3d::setResponse(const char **argv, int argc, - OPS_Stream &output) + OPS_Stream &output) { Response *theResponse = nullptr; @@ -678,6 +811,28 @@ FrameSolidSection3d::setParameter(const char **argv, int argc, Parameter ¶m) return param.addObject(Param::FiberFieldBase+fiberID*100+field, this); } + if (strcmp(argv[0], "shift_shear") == 0) { + // ... shift_shear i j + if (argc < 3) { + opserr << "FrameSolidSection3d::setParameter - i, j, value are required\n"; + return -1; + } + int i = atoi(argv[1]); + int j = atoi(argv[2]); + if ((i == 1) && (j == 1)) + return param.addObject(Param::ShearAlignYY, this); + else if ((i == 2) && (j == 2)) + return param.addObject(Param::ShearAlignZZ, this); + else if ((i == 1) && (j == 2)) + return param.addObject(Param::ShearAlignYZ, this); + else if ((i == 2) && (j == 1)) + return param.addObject(Param::ShearAlignZY, this); + else { + opserr << "FrameSolidSection3d::setParameter - invalid i, j: " << i << ", " << j << "\n"; + return -1; + } + } + // Check if the parameter belongs to the material if (strstr(argv[0], "material") != 0) { @@ -710,6 +865,23 @@ int FrameSolidSection3d::updateParameter(int paramID, Information &info) { + if (paramID == Param::ShearAlignYY) { + shear_align(1,1) = info.theDouble; + return 0; + } + else if (paramID == Param::ShearAlignZZ) { + shear_align(2,2) = info.theDouble; + return 0; + } + else if (paramID == Param::ShearAlignYZ) { + shear_align(1,2) = info.theDouble; + return 0; + } + else if (paramID == Param::ShearAlignZY) { + shear_align(2,1) = info.theDouble; + return 0; + } + if (paramID >= Param::FiberFieldBase) { int fiberID = (paramID - Param::FiberFieldBase) / 100; int field = (paramID - Param::FiberFieldBase) % 100; @@ -763,7 +935,6 @@ FrameSolidSection3d::updateParameter(int paramID, Information &info) return 0; } - return -1; } @@ -862,11 +1033,12 @@ FrameSolidSection3d::getStressResultantSensitivity(int gradIndex, bool condition dasdh(2,4) = 0; dasdh(1,5) = -dzdh[i]; dasdh(2,5) = dydh[i]; - +#if 0 // removed to eliminate implicit cast from MatrixND to Matrix static Matrix tmpMatrix(nsr,nsr); tmpMatrix.addMatrixTripleProduct(0.0, as, tangent, dasdh, 1.0); ds.addMatrixVector(1.0, tmpMatrix, e, A); +#endif } return ds; @@ -881,6 +1053,7 @@ FrameSolidSection3d::getInitialTangentSensitivity(int gradIndex) return dksdh; } + int FrameSolidSection3d::commitSensitivity(const Vector& defSens, int gradIndex, int numGrads) @@ -923,3 +1096,73 @@ FrameSolidSection3d::commitSensitivity(const Vector& defSens, return 0; } + + +void +FrameSolidSection3d::Print(OPS_Stream &s, int flag) +{ + const int nf = fibers->size(); + if (flag == OPS_PRINT_PRINTMODEL_JSON) { + s << OPS_PRINT_JSON_MATE_INDENT << "{"; + s << "\"name\": " << this->getTag() << ", "; + s << "\"type\": \"" << this->getClassType() << "\", "; + + double mass; + if (this->FrameSection::getIntegral(Field::Density, State::Init, mass) == 0) + s << "\"mass\": " << mass << ", "; + + + s << "\"shear_align\": ["; + for (int i = 1; i < 3; i++) { + s << "["; + for (int j = 1; j < 3; j++) { + s << shear_align(i,j); + if (j < 2) + s << ", "; + } + s << "]"; + if (i < 2) + s << ", "; + } + s << "], "; + + s << "\"fibers\": [\n"; + + for (int i = 0; i < nf; i++) { + s << OPS_PRINT_JSON_MATE_INDENT << "\t{\"location\": [" + << (*fibers)[i].r[1] << ", " + << (*fibers)[i].r[2] << "], "; + s << "\"area\": " << (*fibers)[i].area << ", "; + s << "\"warp\": ["; + for (int j = 0; j < nwm; j++) { + s << "["; + for (int k = 0; k < 3; k++) { + s << (*fibers)[i].warp[j][k]; + if (k < 2) + s << ", "; + } + s << "]"; + if (j < nwm-1) + s << ", "; + } + s << "], "; + + s << "\"material\": " << materials[i]->getTag(); + if (i < nf - 1) + s << "},\n"; + else + s << "}\n"; + } + s << OPS_PRINT_JSON_MATE_INDENT << "]}"; + return; + } + + else if (flag == 1) { + for (int i = 0; i < nf; i++) { + auto & fiber = (*fibers)[i]; + s << "\nLocation (y,z) = " << fiber.r[1] << ' ' << fiber.r[2]; + s << "\nArea = " << fiber.area << endln; + materials[i]->Print(s, flag); + } + } +} diff --git a/SRC/material/Frame/FrameSolidSection3d.h b/SRC/material/Frame/FrameSolidSection3d.h index b95571e501..5bb0fcbd6c 100644 --- a/SRC/material/Frame/FrameSolidSection3d.h +++ b/SRC/material/Frame/FrameSolidSection3d.h @@ -27,6 +27,7 @@ #include #include #include +#include class NDMaterial; class Response; @@ -37,6 +38,9 @@ class FrameSolidSection3d : public FrameSection public: FrameSolidSection3d(); FrameSolidSection3d(int tag, int numFibers); + private: + FrameSolidSection3d(const FrameSolidSection3d &); + public: ~FrameSolidSection3d(); int addFiber(NDMaterial&, double area, double y, double z=0.0); @@ -58,13 +62,15 @@ class FrameSolidSection3d : public FrameSection int revertToLastCommit() override; int revertToStart() override; - FrameSection *getFrameCopy(); - const ID &getType(); - int getOrder () const; + FrameSection *getFrameCopy() override; + const ID &getType() override; + int getOrder () const override; + // MovableObject int sendSelf(int tag, Channel &) override; int recvSelf(int tag, Channel &, FEM_ObjectBroker &) override; - void Print(OPS_Stream &s, int flag = 0) override; + // TaggedObject + void Print(OPS_Stream &s, int flag) override; Response *setResponse(const char **argv, int argc, OPS_Stream &) override; int getResponse(int responseID, Information &) override; @@ -84,11 +90,6 @@ class FrameSolidSection3d : public FrameSection constexpr static int nsr = 12; constexpr static int nwm = 3; // Number of warping modes - FrameSection::Tangent K_pres; - std::shared_ptr K_init; - - int stateDetermination(Tangent& K, VectorND* s_trial, const VectorND * const e_trial, int tangentFlag); - struct Param { enum : int { FiberWarpX=0, @@ -104,6 +105,10 @@ class FrameSolidSection3d : public FrameSection FiberZ, FiberArea, alpha, + ShearAlignYY, + ShearAlignZZ, + ShearAlignYZ, + ShearAlignZY, FiberFieldBase=10000 }; }; @@ -129,6 +134,25 @@ class FrameSolidSection3d : public FrameSection ivy, ivz }; + + struct Tangent { + OpenSees::MatrixND<3,3> nn, nm, nw, nv, + mn, mm, mw, mv, + wn, wm, ww, wv, + vn, vm, vw, vv; + void zero() { + nn.zero(); nm.zero(); nw.zero(); nv.zero(); + mn.zero(); mm.zero(); mw.zero(); mv.zero(); + wn.zero(); wm.zero(); ww.zero(); wv.zero(); + vn.zero(); vm.zero(); vw.zero(); vv.zero(); + } + }; + + Tangent K_pres; + std::shared_ptr K_init; + + int stateDetermination(Tangent& K, VectorND* s_trial, const VectorND * const e_trial, int tangentFlag); + struct FiberData { // NOTE: this may be faster if qualified with const, but this would @@ -140,21 +164,23 @@ class FrameSolidSection3d : public FrameSection // std::array wmix{{{0}}}; OpenSees::VectorND<3> r; }; - std::shared_ptr> fibers; + const std::shared_ptr> fibers; std::vector materials; VectorND s, e; Vector s_wrap, e_wrap; - + Matrix3D shear_align; Vector3D centroid; - double yBar; // Section centroid - double zBar; // Section centroid + double nubar; + enum class FiberState { + Dirty, Clean + } fiber_state; bool wagner; + int parameterID; static ID code; - int parameterID; Vector dedh; }; From cfdef4723b2a8abf5067be7f3df6097f9e60fe69 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:46:28 -0800 Subject: [PATCH 014/161] Delete Makefile --- SRC/tagged/storage/Makefile | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 SRC/tagged/storage/Makefile diff --git a/SRC/tagged/storage/Makefile b/SRC/tagged/storage/Makefile deleted file mode 100644 index 61538238ec..0000000000 --- a/SRC/tagged/storage/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -include ../../../Makefile.def - -OBJS = ArrayOfTaggedObjects.o ArrayOfTaggedObjectsIter.o \ - MapOfTaggedObjectsIter.o MapOfTaggedObjects.o - -# Compilation control - -all: $(OBJS) - -test: main.o - $(LINKER) $(LINKFLAGS) main.o \ - $(FE_LIBRARY) $(MACHINE_LINKLIBS) \ - $(MACHINE_NUMERICAL_LIBS) $(MACHINE_SPECIFIC_LIBS) \ - -o test - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o test - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. From f5846d5ccfdd811b0319d559e08a3981ab170fa3 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:46:30 -0800 Subject: [PATCH 015/161] Delete Makefile --- SRC/tagged/Makefile | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 SRC/tagged/Makefile diff --git a/SRC/tagged/Makefile b/SRC/tagged/Makefile deleted file mode 100644 index 3a93585481..0000000000 --- a/SRC/tagged/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -include ../../Makefile.def - -OBJS = TaggedObject.o - -# Compilation control - -all: $(OBJS) - @$(CD) $(FE)/tagged/storage; $(MAKE); - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - @$(CD) $(FE)/tagged/storage; $(MAKE) clean; - -wipe: spotless - @$(CD) $(FE)/tagged/storage; $(MAKE) wipe; - -# DO NOT DELETE THIS LINE -- make depend depends on it. - - From c6a1bf80b37656c6d770492107e50eb3d0ed0389 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:47:10 -0800 Subject: [PATCH 016/161] Delete Makefile --- SRC/recorder/Makefile | 47 ------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 SRC/recorder/Makefile diff --git a/SRC/recorder/Makefile b/SRC/recorder/Makefile deleted file mode 100644 index 714baae4e6..0000000000 --- a/SRC/recorder/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -include ../../Makefile.def - -ifeq ($(GRAPHICS), NONE) -GRAPHIC_OBJECTS = -else -GRAPHIC_OBJECTS = FilePlotter.o AlgorithmIncrements.o -endif - -OBJS = Recorder.o \ - DatastoreRecorder.o \ - ElementRecorder.o \ - ElementRecorderRMS.o \ - NodeRecorder.o \ - NodeRecorderRMS.o \ - EnvelopeElementRecorder.o \ - NormElementRecorder.o \ - NormEnvelopeElementRecorder.o \ - EnvelopeNodeRecorder.o \ - TclRecorderCommands.o \ - DriftRecorder.o \ - EnvelopeDriftRecorder.o \ - PatternRecorder.o \ - RemoveRecorder.o \ - DamageRecorder.o $(GRAPHIC_OBJECTS) \ - PVDRecorder.o MPCORecorder.o GmshRecorder.o \ - VTK_Recorder.o - - -# Compilation control - -all: $(OBJS) $(GRAPHIC_OBJECTS) - @$(CD) $(FE)/recorder/response; $(MAKE); - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - @$(CD) $(FE)/recorder/response; $(MAKE) wipe; - -wipe: spotless - - -# DO NOT DELETE THIS LINE -- make depend depends on it. From 7dbc2f7efbe882e3acb2443a4629deb5e6b880cc Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:47:13 -0800 Subject: [PATCH 017/161] Delete Makefile --- SRC/system_of_eqn/linearSOE/cg/Makefile | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 SRC/system_of_eqn/linearSOE/cg/Makefile diff --git a/SRC/system_of_eqn/linearSOE/cg/Makefile b/SRC/system_of_eqn/linearSOE/cg/Makefile deleted file mode 100644 index a401a04f7f..0000000000 --- a/SRC/system_of_eqn/linearSOE/cg/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -include ../../../../Makefile.def - -OBJS = ConjugateGradientSolver.o - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - @$(RM) $(RMFLAGS) - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. From b202f2a7882df4f1abc4449789f2fda288d655ec Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:51:32 -0800 Subject: [PATCH 018/161] Update ElasticBeam2d.cpp --- SRC/element/Frame/Elastic/ElasticBeam2d.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SRC/element/Frame/Elastic/ElasticBeam2d.cpp b/SRC/element/Frame/Elastic/ElasticBeam2d.cpp index ffaf629672..7a36c88104 100644 --- a/SRC/element/Frame/Elastic/ElasticBeam2d.cpp +++ b/SRC/element/Frame/Elastic/ElasticBeam2d.cpp @@ -325,14 +325,14 @@ ElasticBeam2d::getTangentStiff() q[0] += q0[0]; q[1] += q0[1]; q[2] += q0[2]; -#endif - return theCoordTransf->getGlobalStiffMatrix(kb, q); +#endif // TODO + return theCoordTransf->getGlobalStiffMatrix(Matrix(kb), q); } const Matrix & ElasticBeam2d::getInitialStiff() { -#if 0 +#if 0// TODO double L = theCoordTransf->getInitialLength(); double EoverL = E/L; @@ -353,7 +353,7 @@ ElasticBeam2d::getInitialStiff() kb(1,1) = 3.0*I*EoverL; } #endif - return theCoordTransf->getInitialGlobalStiffMatrix(kb); + return theCoordTransf->getInitialGlobalStiffMatrix(Matrix(kb)); } const Matrix & From d3089e8921da42c911bd97b13c9e30645079dc25 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 17:04:06 -0800 Subject: [PATCH 019/161] Update RankinIsometry.h --- .../Frame/Isometry/RankinIsometry.h | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h b/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h index 96bfcdfed3..59981fa27c 100644 --- a/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h @@ -109,12 +109,36 @@ class RankinIsometry : public AlignedIsometry Psi.template insert<6,0>(ex, -Ln); Psi.template insert<9,0>(Eye3, 1.0); #endif - Matrix3D B = Gamma^Psi; + const Matrix3D B = Gamma^Psi; Matrix3D A; B.invert(A); return Gamma*A.transpose()*NWL; } + MatrixND<3,6> + getRotationGradient(int node) final { + MatrixND<3,6> Gb{}; + + constexpr Vector3D axis{1, 0, 0}; + constexpr Matrix3D ix = Hat(axis); + + const double Ln = this->getLength(); + + if (node == 0) { + Gb.template insert<0,0>( ix, -1.0/Ln); + Gb(0,2) = n/Ln; + Gb(0,3) = 1.0; + Gb(0,4) = -n; + } + else if (node == nn-1) { + Gb.template insert<0,0>( ix, 1.0/Ln); + Gb(0,2) = -n/Ln; + Gb(0,3) = 0.0; + } + return Gb; + } + +private: MatrixND<3,6> getBasisVariation(int ie, int node) { @@ -145,29 +169,6 @@ class RankinIsometry : public AlignedIsometry return dei; } - MatrixND<3,6> - getRotationGradient(int node) final { - MatrixND<3,6> Gb{}; - - constexpr Vector3D axis{1, 0, 0}; - constexpr Matrix3D ix = Hat(axis); - - const double Ln = this->getLength(); - - if (node == 0) { - Gb.template insert<0,0>( ix, -1.0/Ln); - Gb(0,2) = n/Ln; - Gb(0,3) = 1.0; - Gb(0,4) = -n; - } - else if (node == nn-1) { - Gb.template insert<0,0>( ix, 1.0/Ln); - Gb(0,2) = -n/Ln; - Gb(0,3) = 0.0; - } - return Gb; - } - private: Vector3D q; double n = 0; From 1e71a95db6605d4612d1d384859c587abe10a2aa Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:15:43 -0800 Subject: [PATCH 020/161] silence some compiler warnings --- SRC/material/uniaxial/Bilin.cpp | 424 ++++++++++++++++---------------- 1 file changed, 209 insertions(+), 215 deletions(-) diff --git a/SRC/material/uniaxial/Bilin.cpp b/SRC/material/uniaxial/Bilin.cpp index f46a1db4da..0f58c2fd52 100644 --- a/SRC/material/uniaxial/Bilin.cpp +++ b/SRC/material/uniaxial/Bilin.cpp @@ -935,26 +935,24 @@ Bilin::setTrialStrain(double strain, double strainRate) //// energy CALCULATIONS --------------------------------------------- - if((flagstopdeg==0)&&(flagdeg==1)) { + if ((flagstopdeg==0)&&(flagdeg==1)) { - if((Enrgtot>=Enrgts)&&(Enrgts!=0.0)) { + if ((Enrgtot>=Enrgts)&&(Enrgts!=0.0)) { betas = 1.0; - } else if((Enrgtot>=Enrgtd)&&(Enrgtd!=0.0)) { + } else if ((Enrgtot>=Enrgtd)&&(Enrgtd!=0.0)) { betad = 1.0; } else { - if(LamdaS!=0.0) { - betas = pow((Enrgc/(Enrgts-Enrgtot)),Cs); - } - if(LamdaD!=0.0) { - betad = pow((Enrgc/(Enrgtd-Enrgtot)),Cd); - } + if (LamdaS!=0.0) + betas = pow((Enrgc/(Enrgts-Enrgtot)), Cs); + + if(LamdaD!=0.0) + betad = pow((Enrgc/(Enrgtd-Enrgtot)), Cd); - if(fabs(betas)>=1.0) { + if (fabs(betas)>=1.0) betas = 1.0; - } - if(fabs(betad)>=1.0) { + + if (fabs(betad)>=1.0) betad = 1.0; - } } //// Initialize energy of the cycle and Kstif for next loop ------- @@ -962,9 +960,9 @@ Bilin::setTrialStrain(double strain, double strainRate) ekexcurs = ekunload; //// Deteriorate parameters for the next half cycle - if(deltaD<0.0){ + if (deltaD<0.0){ - if(flagstopdeg == 0){ + if (flagstopdeg == 0){ fyNeg = fyNeg*(1-betas*PDNeg); //change the strain hardening ratio // Updated: Filipe Ribeiro and Andre Barbosa @@ -974,21 +972,22 @@ Bilin::setTrialStrain(double strain, double strainRate) alphaNeg=alphaNeg*(1-betas*PDNeg); //3rd - recompute the strain hardening ratio (updated) alphaNeg=(alphaNeg)/(1+nFactor*(1-alphaNeg)); // Updated: Filipe Ribeiro and Andre Barbosa - - fCapRefNeg=fCapRefNeg*(1-betad*PDNeg); - }else{ - fyNeg = fyNeg; - alphaNeg=alphaNeg; - fCapRefNeg=fCapRefNeg; + + fCapRefNeg=fCapRefNeg*(1-betad*PDNeg); + } else { + // CMP: Commented out to silcence -Wself-assign-field warnings + // fyNeg = fyNeg; + // alphaNeg=alphaNeg; + // fCapRefNeg=fCapRefNeg; } // When we reach post capping slope goes to zero due to residual - if(fyNeg>=KNeg*My_neg) { // If strength drops below residual + if (fyNeg >= KNeg*My_neg) { // If strength drops below residual fyNeg = KNeg*My_neg; //alphaNeg = 10^(-4); // This evaluates to -10 (bitwise XOR) - alphaNeg = 1.0e-4; + alphaNeg = 1.0e-4; fCapRefNeg = fyNeg; //capSlopeNeg = -pow(10.0,-6); - capSlopeNeg = -1.0e-6; + capSlopeNeg = -1.0e-6; flagstopdeg = 1; } else { //% Keep updating the post capping slope @@ -999,10 +998,10 @@ Bilin::setTrialStrain(double strain, double strainRate) capSlopeNeg=capSlopeNeg*(fabs((KNeg*My_neg-fyNeg)/(KNeg*My_neg-My_neg))); //3rd - recompute the post-capping ratio (updated) capSlopeNeg = capSlopeNeg/(1+nFactor*(1-capSlopeNeg)); // Updated: Filipe Ribeiro and Andre Barbosa - - if(capSlopeNeg >=0){ - //capSlopeNeg = -pow(10.0,-6); - capSlopeNeg = -1.0e-6; + + if(capSlopeNeg >=0){ + //capSlopeNeg = -pow(10.0,-6); + capSlopeNeg = -1.0e-6; } } @@ -1013,13 +1012,9 @@ Bilin::setTrialStrain(double strain, double strainRate) double dCap2Neg=(fCapRefNeg+ekhardNeg*dyNeg-fyNeg)/(ekhardNeg-capSlopeOrigNeg*Ke); //cpNeg=min(dCap1Neg,dCap2Neg); if (dCap1Neg=0) { - //capSlope = -pow(10.0,-6); - capSlope = -1.0e-6; + if(capSlope >=0) { + //capSlope = -pow(10.0,-6); + capSlope = -1.0e-6; } } dyPos = fyPos/Ke; @@ -1080,14 +1076,11 @@ Bilin::setTrialStrain(double strain, double strainRate) double dCap1Pos=fCapRefPos/(Ke-capSlopeOrig*Ke); double dCap2Pos=(fCapRefPos+ekhardPos*dyPos-fyPos)/(ekhardPos-capSlopeOrig*Ke); //cpPos=max(dCap1Pos,dCap2Pos); - if(dCap1Pos>dCap2Pos) - { - cpPos=dCap1Pos; - } + if (dCap1Pos>dCap2Pos) + cpPos=dCap1Pos; else - { - cpPos=dCap2Pos; - } + cpPos=dCap2Pos; + fCapPos = fCapRefPos + capSlopeOrig*Ke*cpPos; envelPosCap2(fyPos,alphaPos,capSlope,cpPos,dLimPos,fLimPos,ek,Ke,My_pos,KPos); @@ -1104,20 +1097,20 @@ Bilin::setTrialStrain(double strain, double strainRate) } // c Check the horizontal limit in case that dBound is reached after first neg slope - if ((d<0)&&(fabs(ek)<=1.0e-7)) { + if ((d<0) && (fabs(ek)<=1.0e-7)) { LN = 1; } - if ((d>0)&&(fabs(ek)<=1.0e-7)) { + if ((d>0) && (fabs(ek)<=1.0e-7)) { LP = 1; } - // c Update envelope values -------------------------------------------- + // Update envelope values -------------------------------------------- f1 = f; - // c Updating parameters for next cycle --------------------------------- + // Updating parameters for next cycle --------------------------------- ekP = ek; fP = f; dP = d; @@ -1130,116 +1123,116 @@ Bilin::setTrialStrain(double strain, double strainRate) return 0; } + double -Bilin::getStress(void) +Bilin::getStress() { - return (fP); + return fP; } double -Bilin::getTangent(void) +Bilin::getTangent() { - return (Tangent); + return Tangent; } double -Bilin::getInitialTangent(void) +Bilin::getInitialTangent() { - return (Ke); + return Ke; } - - double -Bilin::getStrain(void) +Bilin::getStrain() { - return (U); + return U; } int -Bilin::commitState(void) +Bilin::commitState() { commitCalledOnce = 1; //commit trial variables - CU=U; - CTangent=Tangent; - - CdNewLoadPos=dNewLoadPos; - CdNewLoadNeg=dNewLoadNeg; - Cflagdeg=flagdeg ; - Cflagstopdeg=flagstopdeg; - Cinterup=interup; - Ckon=kon; - CiNoFneg=iNoFneg; - CiNoFpos=iNoFpos; - CLP=LP; //fmk - CLN=LN; - CcapSlope=capSlope; - Cdmax=dmax; - Cdmin=dmin; - CEnrgtot=Enrgtot; - CEnrgc=Enrgc; - CfyPos=fyPos; - CfLimNeg=fLimNeg; - CfyNeg=fyNeg; - CekP=ekP; - Cekunload=ekunload; - Csp=sp; - Csn=sn; - CdP=dP; - CfP=fP; - Cek=ek; - CdLimPos=dLimPos; - CdLimNeg=dLimNeg; - CcpPos=cpPos; - CcpNeg=cpNeg; - CfLimPos=fLimPos; - Cekexcurs=ekexcurs; - CRSE=RSE; - CfPeakPos=fPeakPos; - CfPeakNeg=fPeakNeg; - CalphaNeg=alphaNeg; - CalphaPos=alphaPos; - CekhardNeg=ekhardNeg; - CekhardPos=ekhardPos; - CfCapRefPos=fCapRefPos; - CfCapRefNeg=fCapRefNeg; - CEnrgts=Enrgts; - CEnrgtk=Enrgtk; - CEnrgtd=Enrgtd; - CdyPos=dyPos; - CdyNeg=dyNeg; - CresSnHor=resSnHor; - Cfmax=fmax; - Cfmin=fmin; - CresSp=resSp; - CresSn=resSn; - CfCapPos=fCapPos; - CfCapNeg=fCapNeg; - CsnHor=snHor; - CspHor=spHor; - CresSpHor=resSpHor; - CsnEnv=snEnv; - CresSnEnv=resSnEnv; - CspEnv=spEnv; - CresSpEnv=resSpEnv; - CcapSlopeOrig=capSlopeOrig; - CcapSlopeNeg=capSlopeNeg; - CflagControlResponse=flagControlResponse; - CcapSlopeOrigNeg=capSlopeOrigNeg; - CcapSlopeNegMember=capSlopeNegMember; // Updated: Filipe Ribeiro and Andre Barbosa - CcapSlopeMember=capSlopeMember;// Updated: Filipe Ribeiro and Andre Barbosa - CKe=Ke; // Updated: Filipe Ribeiro and Andre Barbosa - CprodBeta=prodBeta; // Updated: Filipe Ribeiro and Andre Barbosa - return 0; + CU=U; + CTangent=Tangent; + + CdNewLoadPos=dNewLoadPos; + CdNewLoadNeg=dNewLoadNeg; + Cflagdeg=flagdeg ; + Cflagstopdeg=flagstopdeg; + Cinterup=interup; + Ckon=kon; + CiNoFneg=iNoFneg; + CiNoFpos=iNoFpos; + CLP=LP; //fmk + CLN=LN; + CcapSlope=capSlope; + Cdmax=dmax; + Cdmin=dmin; + CEnrgtot=Enrgtot; + CEnrgc=Enrgc; + CfyPos=fyPos; + CfLimNeg=fLimNeg; + CfyNeg=fyNeg; + CekP=ekP; + Cekunload=ekunload; + Csp=sp; + Csn=sn; + CdP=dP; + CfP=fP; + Cek=ek; + CdLimPos=dLimPos; + CdLimNeg=dLimNeg; + CcpPos=cpPos; + CcpNeg=cpNeg; + CfLimPos=fLimPos; + Cekexcurs=ekexcurs; + CRSE=RSE; + CfPeakPos=fPeakPos; + CfPeakNeg=fPeakNeg; + CalphaNeg=alphaNeg; + CalphaPos=alphaPos; + CekhardNeg=ekhardNeg; + CekhardPos=ekhardPos; + CfCapRefPos=fCapRefPos; + CfCapRefNeg=fCapRefNeg; + CEnrgts=Enrgts; + CEnrgtk=Enrgtk; + CEnrgtd=Enrgtd; + CdyPos=dyPos; + CdyNeg=dyNeg; + CresSnHor=resSnHor; + Cfmax=fmax; + Cfmin=fmin; + CresSp=resSp; + CresSn=resSn; + CfCapPos=fCapPos; + CfCapNeg=fCapNeg; + CsnHor=snHor; + CspHor=spHor; + CresSpHor=resSpHor; + CsnEnv=snEnv; + CresSnEnv=resSnEnv; + CspEnv=spEnv; + CresSpEnv=resSpEnv; + CcapSlopeOrig=capSlopeOrig; + CcapSlopeNeg=capSlopeNeg; + CflagControlResponse=flagControlResponse; + CcapSlopeOrigNeg=capSlopeOrigNeg; + CcapSlopeNegMember=capSlopeNegMember; // Updated: Filipe Ribeiro and Andre Barbosa + CcapSlopeMember=capSlopeMember;// Updated: Filipe Ribeiro and Andre Barbosa + CKe=Ke; // Updated: Filipe Ribeiro and Andre Barbosa + CprodBeta=prodBeta; // Updated: Filipe Ribeiro and Andre Barbosa + return 0; } + int -Bilin::revertToLastCommit(void) +Bilin::revertToLastCommit() { //the opposite of commit trial history variables U=CU; @@ -2061,27 +2054,26 @@ void Bilin::snCalc(void) } else { - resSn=resSnCap; + resSn=resSnCap; } - snEnv = sn; - resSnEnv = resSn; - if((LP==1)&&(fLimPos==0.0)) { - //call interPoint(snLim,resSnLim,dLimPos,fLimPos,0.d0,dP,fP,ekunload) - interPoint(snLim,resSnLim,dLimPos,fLimPos,0.0,dP,fP,ekunload); - if (snLimdresid) { -// call interPoint(snResid,resSnResid,dresid,Resid,ekresid,dP,fP,ekunload) - interPoint(snResid,resSnResid,dresid,Resid,ekresid,dP,fP,ekunload); - sn = snResid; - resSn = resSnResid; - } + if (sn>dresid) { + interPoint(snResid,resSnResid,dresid,Resid,ekresid,dP,fP,ekunload); + sn = snResid; + resSn = resSnResid; + } } @@ -2090,66 +2082,68 @@ Bilin::envelPosCap2(double fy,double alphaPos,double alphaCap,double cpDsp,doubl double& f,double& ek,double elstk,double fyieldPos,double Resfac) { - double dy = fy/elstk; - - double Res,rcap,dres; - if(dy<=cpDsp) { - Res = Resfac*fyieldPos; - rcap = fy+alphaPos*elstk*(cpDsp-dy); - dres = cpDsp+(Res-rcap)/(alphaCap*elstk); - - if (d<0.0){ - f = 0.0; - ek = 1.0e-7; - }else if (d<=dy) { - ek = elstk; - f = ek*d; - } else if(d<=cpDsp) { - ek = elstk*alphaPos; - f = fy+ek*(d-dy); - } else if(d<=dres) { - ek = alphaCap*elstk; - f = rcap+ek*(d-cpDsp); - } else { - ek = 1.0e-7; - f = Res+d*ek; - } -// c added by Dimitrios to account for fracture - if(d>=Thetau_pos) { - ek = 1.0e-7; - f = 1.0e-10; - d=Thetau_pos; - flagControlResponse=1; - } - } else if(dy>cpDsp) { - - rcap = elstk*cpDsp; - Res = Resfac*rcap; - dres = cpDsp+(Res-rcap)/(alphaCap*elstk); - - if (d<0.0) { - f = 0.0; - ek = 1.0e-7; - } else if(d<=cpDsp) { - ek = elstk; - f = ek*d; - } else if(d<=dres) { - ek = alphaCap*elstk; - f = rcap+ek*(d-cpDsp); - } else { - ek = 1.0e-7; - f = Res+d*ek; - } + double dy = fy/elstk; + + double Res,rcap,dres; + if(dy<=cpDsp) { + Res = Resfac*fyieldPos; + rcap = fy+alphaPos*elstk*(cpDsp-dy); + dres = cpDsp+(Res-rcap)/(alphaCap*elstk); + + if (d<0.0){ + f = 0.0; + ek = 1.0e-7; + } else if (d<=dy) { + ek = elstk; + f = ek*d; + } else if(d<=cpDsp) { + ek = elstk*alphaPos; + f = fy+ek*(d-dy); + } else if(d<=dres) { + ek = alphaCap*elstk; + f = rcap+ek*(d-cpDsp); + } else { + ek = 1.0e-7; + f = Res+d*ek; + } // c added by Dimitrios to account for fracture - if(d>=Thetau_pos) { - ek = 1.0e-7; - f = 1.0e-10; - d=Thetau_pos; - flagControlResponse=1; - } - - } else { - } + if(d>=Thetau_pos) { + ek = 1.0e-7; + f = 1.0e-10; + d=Thetau_pos; + flagControlResponse=1; + } + } + else if(dy > cpDsp) { + + rcap = elstk*cpDsp; + Res = Resfac*rcap; + dres = cpDsp+(Res-rcap)/(alphaCap*elstk); + + if (d<0.0) { + f = 0.0; + ek = 1.0e-7; + } else if(d<=cpDsp) { + ek = elstk; + f = ek*d; + } else if(d<=dres) { + ek = alphaCap*elstk; + f = rcap+ek*(d-cpDsp); + } else { + ek = 1.0e-7; + f = Res+d*ek; + } + // c added by Dimitrios to account for fracture + if(d>=Thetau_pos) { + ek = 1.0e-7; + f = 1.0e-10; + d=Thetau_pos; + flagControlResponse=1; + } + + } + else { + } } double Bilin::boundPos(void) From d9907fb8892442d5fd2ad85b8a3a27d58aadfb9a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:17:13 -0800 Subject: [PATCH 021/161] remove/consolidate LoadPatternIter class --- SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp | 1 - SRC/analysis/integrator/Dynamic/Newmark.cpp | 1 - SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp | 1 - SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp | 1 - SRC/analysis/integrator/Staged/StagedLoadControl.cpp | 1 - SRC/analysis/integrator/Staged/StagedNewmark.cpp | 1 - 6 files changed, 6 deletions(-) diff --git a/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp b/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp index 69bd014d67..1a46f1fcf5 100644 --- a/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp +++ b/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp @@ -28,7 +28,6 @@ // for sensitivity #include #include -#include #include #include diff --git a/SRC/analysis/integrator/Dynamic/Newmark.cpp b/SRC/analysis/integrator/Dynamic/Newmark.cpp index 901656d580..c77cc3a7c6 100644 --- a/SRC/analysis/integrator/Dynamic/Newmark.cpp +++ b/SRC/analysis/integrator/Dynamic/Newmark.cpp @@ -42,7 +42,6 @@ #include #include // for sensitivity #include -#include #include #include //Abbas diff --git a/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp b/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp index 3396148530..5a0497fdf0 100644 --- a/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp +++ b/SRC/analysis/integrator/Dynamic/NewmarkSO3.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp b/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp index ddbc68ef3f..f54f617e87 100644 --- a/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp +++ b/SRC/analysis/integrator/Dynamic/PFEMIntegrator.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include #include "sparseGEN/PFEMLinSOE.h" diff --git a/SRC/analysis/integrator/Staged/StagedLoadControl.cpp b/SRC/analysis/integrator/Staged/StagedLoadControl.cpp index 33db00e23a..ff208bd6ee 100644 --- a/SRC/analysis/integrator/Staged/StagedLoadControl.cpp +++ b/SRC/analysis/integrator/Staged/StagedLoadControl.cpp @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Staged/StagedNewmark.cpp b/SRC/analysis/integrator/Staged/StagedNewmark.cpp index bdccc3b163..8963b1b8a3 100644 --- a/SRC/analysis/integrator/Staged/StagedNewmark.cpp +++ b/SRC/analysis/integrator/Staged/StagedNewmark.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include From 49179899f68304cfef11c6f57c538098bca0853d Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:17:49 -0800 Subject: [PATCH 022/161] remove/consolidate LoadPatternIter class --- .../integrator/Static/HarmonicSteadyState.cpp | 1 - SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp | 11 ++++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp b/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp index df5a3343fe..4ad099752e 100644 --- a/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp +++ b/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp index 9db6e8616e..08b60f6b00 100644 --- a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp +++ b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -503,13 +502,13 @@ MinUnbalDispNorm::formTangDispSensitivity(Vector *dUhatdh,int gradNumber) Domain *theDomain = theModel->getDomainPtr(); LoadPatternIter &thePatterns = theDomain->getLoadPatterns(); - while((loadPatternPtr = thePatterns()) != nullptr) { + while ((loadPatternPtr = thePatterns()) != nullptr) { const Vector &randomLoads = loadPatternPtr->getExternalForceSensitivity(gradNumber); sizeRandomLoads = randomLoads.Size(); if (sizeRandomLoads == 1) { - // No random loads in this load pattern - continue; + // No random loads in this load pattern + continue; } // Random loads: add contributions to the 'B' vector numRandomLoads = (int)(sizeRandomLoads/2); @@ -528,14 +527,12 @@ MinUnbalDispNorm::formTangDispSensitivity(Vector *dUhatdh,int gradNumber) } if(theLinSOE->solve()<0) { - opserr<<"SOE failed to obtained dUhatdh "; + opserr << "SOE failed to obtained dUhatdh "; exit(-1); } (*dUhatdh)=theLinSOE->getX(); - - return dUhatdh; } From 5c5528d83652909f01718febd343f5d5ed9e6ff1 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:18:08 -0800 Subject: [PATCH 023/161] remove/consolidate LoadPatternIter class --- SRC/analysis/model/AnalysisModel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SRC/analysis/model/AnalysisModel.cpp b/SRC/analysis/model/AnalysisModel.cpp index 56cb98f258..cb46584f2f 100644 --- a/SRC/analysis/model/AnalysisModel.cpp +++ b/SRC/analysis/model/AnalysisModel.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -893,7 +892,7 @@ AnalysisModel::applyLoadGradient() // 2) Add external load sensitivity LoadPattern *pattern; - LoadPatternIter &thePatterns = myDomain->getLoadPatterns(); + auto &thePatterns = myDomain->getLoadPatterns(); while ((pattern = thePatterns()) != nullptr) pattern->applyLoadSensitivity(myDomain->getCurrentTime()); From 4d22a388f479277affb8b8eee3dd0ce6cdde92fd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:33:39 -0800 Subject: [PATCH 024/161] remove/consolidate LoadPatternIter class --- SRC/domain/partitioner/DomainPartitioner.cpp | 1 - SRC/recorder/RemoveRecorder.cpp | 1 - SRC/runtime/commands/modeling/printing.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/SRC/domain/partitioner/DomainPartitioner.cpp b/SRC/domain/partitioner/DomainPartitioner.cpp index 582fa22dac..563a324f42 100644 --- a/SRC/domain/partitioner/DomainPartitioner.cpp +++ b/SRC/domain/partitioner/DomainPartitioner.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #include #include diff --git a/SRC/recorder/RemoveRecorder.cpp b/SRC/recorder/RemoveRecorder.cpp index 90810292fc..30f3dff5c0 100644 --- a/SRC/recorder/RemoveRecorder.cpp +++ b/SRC/recorder/RemoveRecorder.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/runtime/commands/modeling/printing.cpp b/SRC/runtime/commands/modeling/printing.cpp index 1b393f0e27..b3f8e6b162 100644 --- a/SRC/runtime/commands/modeling/printing.cpp +++ b/SRC/runtime/commands/modeling/printing.cpp @@ -60,7 +60,6 @@ #include #include -#include #include From 77873b853a44d9c44b21cd074b81f25ea0da38a3 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:34:24 -0800 Subject: [PATCH 025/161] clean up --- SRC/material/Frame/FrameTraceSection3d.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SRC/material/Frame/FrameTraceSection3d.cpp b/SRC/material/Frame/FrameTraceSection3d.cpp index eaf7d73925..f553aab4e9 100644 --- a/SRC/material/Frame/FrameTraceSection3d.cpp +++ b/SRC/material/Frame/FrameTraceSection3d.cpp @@ -489,8 +489,8 @@ FrameTraceSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons 0, 0, 0 , 0, 0, 0 }}; const Matrix3D ioiC = ioi*C; - K.se.assemble(ioiC, 3, 0, tr2); // K.mn.addMatrix(ioiC, tr2); - K.se.assembleTranspose(ioiC, 0, 3, tr2); // K.nm.addTranspose(ioiC, tr2); + K.se.assemble(ioiC, 3, 0, tr2); + K.se.assembleTranspose(ioiC, 0, 3, tr2); // K.se.assemble(Hat(r)*ioiC.transpose() - ioiC*Hat(r), 3, 3, tr2); // K.mm.addSpinMatrixProduct(r, ioiC.transpose(), tr2); @@ -501,7 +501,6 @@ FrameTraceSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons // Geometric part, equivalent to Kmm.addMatrix(ioi, r2*stress(0)); if (kappa[0] != 0) [[likely]] K.se(3,3) += (tr2/kappa[0])*stress(0)*fiber.area; - // K.mm(0,0) += (tr2/kappa[0])*stress(0)*fiber.area; K.sw.assemble(ioiC*iow, 3, 0, tr2); // 6 // K.mw.addMatrixProduct(ioiC, iow, tr2); From b4ead579f357b1f576e41908a0f7ba0514b9c3fa Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 19:35:03 -0800 Subject: [PATCH 026/161] add static asserts --- SRC/matrix/MatrixND.tpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/SRC/matrix/MatrixND.tpp b/SRC/matrix/MatrixND.tpp index 5067d09a40..85a974f064 100644 --- a/SRC/matrix/MatrixND.tpp +++ b/SRC/matrix/MatrixND.tpp @@ -232,6 +232,7 @@ template inline int MatrixND::invert(MatrixND &M) const { static_assert(nr == nc, "Matrix must be square"); + static_assert(std::is_same_v, "Only double storage is supported"); int status = -1; if constexpr (nr == 2) { @@ -284,7 +285,9 @@ template int MatrixND::solve(const VectorND &V, VectorND &res) const noexcept { + static_assert(std::is_same_v, "Only double storage is supported"); static_assert(NR == NC); + if constexpr (NR < 6) { MatrixND Ainv; int status = this->invert(Ainv); @@ -312,8 +315,10 @@ template int MatrixND::solve(const MatrixND& M, MatrixND& X) const noexcept { + static_assert(std::is_same_v, "Only double storage is supported"); static_assert(NR == NC, "Matrix must be square."); static_assert(n == NR, "RHS row-count must match A."); + if constexpr (NR < 6) { MatrixND Ainv; int status = this->invert(Ainv); @@ -394,6 +399,8 @@ MatrixND::addMatrixProduct(const MatrixND& A, const MatrixND& B, double scale) noexcept { + static_assert(std::is_same_v, "Only double storage is supported"); + if constexpr (nr*nk < BlasSize) { // want: this += A * B * scale const double *ckjPtr = &B(0,0); @@ -445,6 +452,8 @@ MatrixND::setMatrixProduct(const MatrixND& B, } else { + static_assert(std::is_same_v, "Only double storage is supported"); + int m = nr, n = nc, k = nk; @@ -473,6 +482,8 @@ MatrixND::addMatrixProduct(const MatrixND& A, const MatT& } else { + static_assert(std::is_same_v, "Only double storage is supported"); + int m = nr, n = nc, k = nk; @@ -493,6 +504,8 @@ MatrixND::addMatrixProduct(double scale_this, const MatrixND& A, const MatT& B, double scale) { + static_assert(std::is_same_v, "Only double storage is supported"); + int m = nr, n = nc, k = nk; From 4c87516c998b8fb5ba39fe307d604abc16d79cc4 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 12 Jan 2026 20:47:29 -0800 Subject: [PATCH 027/161] Refactor domain pattern iteration and cleanup Replaces custom LoadPatternIter and related iteration logic with a generic TaggedIterator-based approach, removing now-unnecessary files and simplifying the Domain and LoadPattern interfaces. Updates method signatures for consistency, removes unused constructors, and cleans up code formatting and error messages. Also deletes obsolete Makefiles and legacy iteration headers/implementations. --- CMakeLists.txt | 4 + SRC/analysis/model/Makefile | 22 -- .../constraints/Pressure_Constraint.cpp | 1 - SRC/domain/domain/CMakeLists.txt | 1 - SRC/domain/domain/Domain.cpp | 310 ++++++------------ SRC/domain/domain/Domain.h | 48 ++- SRC/domain/domain/LoadCaseIter.h | 62 ---- SRC/domain/domain/Makefile | 26 -- SRC/domain/domain/NodeIter.h | 2 +- .../domain/single/SingleDomAllSP_Iter.cpp | 1 - .../domain/single/SingleDomAllSP_Iter.h | 3 +- SRC/domain/pattern/EarthquakePattern.cpp | 2 +- SRC/domain/pattern/EarthquakePattern.h | 9 +- SRC/domain/pattern/LoadPattern.cpp | 47 +-- SRC/domain/pattern/LoadPattern.h | 65 ++-- SRC/domain/pattern/LoadPatternIter.cpp | 76 ----- SRC/domain/pattern/LoadPatternIter.h | 42 +-- SRC/domain/pattern/LoadpatternIter | 0 SRC/domain/pattern/Makefile | 59 ---- SRC/domain/pattern/MultiSupportPattern.cpp | 30 +- SRC/domain/subdomain/Makefile | 27 -- SRC/domain/subdomain/ShadowSubdomain.cpp | 5 +- SRC/domain/subdomain/Subdomain.cpp | 45 --- SRC/domain/subdomain/Subdomain.h | 11 +- SRC/tagged/storage/ArrayOfTaggedObjects.h | 5 + .../storage/HashMapOfTaggedObjectsIter.cpp | 21 +- SRC/tagged/storage/MapOfTaggedObjects.cpp | 170 +++++----- SRC/tagged/storage/MapOfTaggedObjects.h | 11 +- 28 files changed, 333 insertions(+), 772 deletions(-) delete mode 100644 SRC/analysis/model/Makefile delete mode 100644 SRC/domain/domain/LoadCaseIter.h delete mode 100644 SRC/domain/domain/Makefile delete mode 100644 SRC/domain/pattern/LoadPatternIter.cpp delete mode 100644 SRC/domain/pattern/LoadpatternIter delete mode 100644 SRC/domain/pattern/Makefile delete mode 100644 SRC/domain/subdomain/Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b8bdeb11d..a5ba66acbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,6 +120,10 @@ elseif (WIN32) # NOTE: this will execute for both 32-bit and 64-bit builds. set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") endif() +if (CMAKE_BUILD_TYPE STREQUAL "RELEASE") + add_compile_definitions(XARA_RELEASE) +endif() + # Check for IPO and maybe use it; this can significantly slow down linking # and can be problematic on slow or memory constrained machines (e.g., my laptop) include(CheckIPOSupported) diff --git a/SRC/analysis/model/Makefile b/SRC/analysis/model/Makefile deleted file mode 100644 index 7d808cb05f..0000000000 --- a/SRC/analysis/model/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -include ../../../Makefile.def - -OBJS = AnalysisModel.o FE_EleIter.o DOF_GrpIter.o - -# Compilation control - -all: $(OBJS) - @$(CD) simple; $(MAKE); - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - @$(CD) simple; $(MAKE) wipe; - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/domain/constraints/Pressure_Constraint.cpp b/SRC/domain/constraints/Pressure_Constraint.cpp index 6da9738f91..1ecae6dc9d 100644 --- a/SRC/domain/constraints/Pressure_Constraint.cpp +++ b/SRC/domain/constraints/Pressure_Constraint.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/domain/domain/CMakeLists.txt b/SRC/domain/domain/CMakeLists.txt index 0ff039caad..459106974c 100644 --- a/SRC/domain/domain/CMakeLists.txt +++ b/SRC/domain/domain/CMakeLists.txt @@ -10,7 +10,6 @@ target_sources(OPS_Domain PUBLIC Domain.h ElementIter.h - LoadCaseIter.h MP_ConstraintIter.h NodeIter.h ParameterIter.h diff --git a/SRC/domain/domain/Domain.cpp b/SRC/domain/domain/Domain.cpp index 0c87f31f74..cb1e1de889 100644 --- a/SRC/domain/domain/Domain.cpp +++ b/SRC/domain/domain/Domain.cpp @@ -33,8 +33,9 @@ #include #include +#include + #include -#include #include #include #include @@ -48,15 +49,13 @@ #include #include -#include #include - -#include #include +#include +#include #include #include #include -#include #include #include @@ -78,6 +77,7 @@ double ops_Dt = 0.0; bool ops_InitialStateAnalysis = false; int ops_Creep = 0; + Domain::Domain() :theRecorders(0), numRecorders(0), currentTime(0.0), committedTime(0.0), dT(0.0), currentGeoTag(0), @@ -94,11 +94,11 @@ Domain::Domain() { // initialize the arrays for storing the domain components theElements = new MapOfTaggedObjects(); - theNodes = new MapOfTaggedObjects(); + theNodes = new NodeStorage(); theSPs = new MapOfTaggedObjects(); thePCs = new MapOfTaggedObjects(); theMPs = new MapOfTaggedObjects(); - theLoadPatterns = new MapOfTaggedObjects(); + theLoadPatterns = new PatternStorage(); theParameters = new MapOfTaggedObjects(); // initialize the iterators @@ -107,7 +107,7 @@ Domain::Domain() theSP_Iter = new SingleDomSP_Iter(theSPs); thePC_Iter = new SingleDomPC_Iter(thePCs); theMP_Iter = new SingleDomMP_Iter(theMPs); - theLoadPatternIter = new LoadPatternIter(theLoadPatterns); + theLoadPatternIter = new PatternIterator(theLoadPatterns); allSP_Iter = new SingleDomAllSP_Iter(*this); theParamIter = new SingleDomParamIter(theParameters); @@ -120,8 +120,11 @@ Domain::Domain() } -Domain::Domain(int numNodes, int numElements, int numSPs, int numMPs, - int numLoadPatterns) +Domain::Domain(int numNodes, + int numElements, + int numSPs, + int numMPs, + int numLoadPatterns) :theRecorders(0), numRecorders(0), currentTime(0.0), committedTime(0.0), dT(0.0), currentGeoTag(0), hasDomainChangedFlag(false), theDbTag(0), lastGeoSendTag(-1), @@ -133,130 +136,31 @@ Domain::Domain(int numNodes, int numElements, int numSPs, int numMPs, theModalDampingFactors(0), inclModalMatrix(false), lastChannel(0), paramIndex(0), paramSize(0), numParameters(0) { - // init the arrays for storing the domain components - theElements = new MapOfTaggedObjects(); - theNodes = new MapOfTaggedObjects(); - theSPs = new MapOfTaggedObjects(); - thePCs = new MapOfTaggedObjects(); - theMPs = new MapOfTaggedObjects(); - theLoadPatterns = new MapOfTaggedObjects(); - theParameters = new MapOfTaggedObjects(); - - // init the iters - theEleIter = new SingleDomEleIter(theElements); - theNodIter = new SingleDomNodIter(theNodes); - theSP_Iter = new SingleDomSP_Iter(theSPs); - thePC_Iter = new SingleDomPC_Iter(thePCs); - theMP_Iter = new SingleDomMP_Iter(theMPs); - theLoadPatternIter = new LoadPatternIter(theLoadPatterns); - allSP_Iter = new SingleDomAllSP_Iter(*this); - theParamIter = new SingleDomParamIter(theParameters); - - theBounds(0) = 0; - theBounds(1) = 0; - theBounds(2) = 0; - theBounds(3) = 0; - theBounds(4) = 0; - theBounds(5) = 0; -} - - -Domain::Domain(TaggedObjectStorage &theNodesStorage, - TaggedObjectStorage &theElementsStorage, - TaggedObjectStorage &theMPsStorage, - TaggedObjectStorage &theSPsStorage, - TaggedObjectStorage &theLoadPatternsStorage) -:theRecorders(0), numRecorders(0), - currentTime(0.0), committedTime(0.0), dT(0.0), - currentGeoTag(0), hasDomainChangedFlag(false), theDbTag(0), lastGeoSendTag(-1), - dbEle(0), dbNod(0), dbSPs(0), dbPCs(0), dbMPs(0), dbLPs(0), dbParam(0), - eleGraphBuiltFlag(false), nodeGraphBuiltFlag(false), theNodeGraph(nullptr), - theElementGraph(nullptr), - theElements(&theElementsStorage), - theNodes(&theNodesStorage), - theSPs(&theSPsStorage), - theMPs(&theMPsStorage), - theLoadPatterns(&theLoadPatternsStorage), - theRegions(nullptr), numRegions(0), commitTag(0), - initBounds(true), resetBounds(false), - theBounds(6), theEigenvalues(nullptr), theEigenvalueSetTime(0), - theModalDampingFactors(nullptr), inclModalMatrix(false), - lastChannel(0), - paramIndex(0), paramSize(0), numParameters(0) -{ - // check that the containers are empty - if (theElements->getNumComponents() != 0 || - theNodes->getNumComponents() != 0 || - theSPs->getNumComponents() != 0 || - theMPs->getNumComponents() != 0 || - theLoadPatterns->getNumComponents() != 0 ) { - - opserr << "Domain::Domain(&, & ...) - out of memory\n"; - } - // init the arrays for storing the domain components - thePCs = new MapOfTaggedObjects(); - - // init the iters - theEleIter = new SingleDomEleIter(theElements); - theNodIter = new SingleDomNodIter(theNodes); - theSP_Iter = new SingleDomSP_Iter(theSPs); - thePC_Iter = new SingleDomPC_Iter(thePCs); - theMP_Iter = new SingleDomMP_Iter(theMPs); - theLoadPatternIter = new LoadPatternIter(theLoadPatterns); - allSP_Iter = new SingleDomAllSP_Iter(*this); - theParameters = new MapOfTaggedObjects(); - theParamIter = new SingleDomParamIter(theParameters); - - theBounds(0) = 0.0; - theBounds(1) = 0.0; - theBounds(2) = 0.0; - theBounds(3) = 0.0; - theBounds(4) = 0.0; - theBounds(5) = 0.0; -} - -Domain::Domain(TaggedObjectStorage &theStorage) -:theRecorders(0), numRecorders(0), - currentTime(0.0), committedTime(0.0), dT(0.0), currentGeoTag(0), - hasDomainChangedFlag(false), theDbTag(0), lastGeoSendTag(-1), - dbEle(0), dbNod(0), dbSPs(0), dbPCs(0), dbMPs(0), dbLPs(0), dbParam(0), - eleGraphBuiltFlag(false), nodeGraphBuiltFlag(false), theNodeGraph(nullptr), - theElementGraph(nullptr), - theRegions(0), numRegions(0), commitTag(0),initBounds(true), resetBounds(false), - theBounds(6), theEigenvalues(0), theEigenvalueSetTime(0), - theModalDampingFactors(0), inclModalMatrix(false), - lastChannel(0), - paramIndex(0), paramSize(0), numParameters(0) -{ - // init the arrays for storing the domain components - theStorage.clearAll(); // clear the storage just in case populated - theElements = &theStorage; - theNodes = theStorage.getEmptyCopy(); - theSPs = theStorage.getEmptyCopy(); - thePCs = theStorage.getEmptyCopy(); - theMPs = theStorage.getEmptyCopy(); - theLoadPatterns = theStorage.getEmptyCopy(); - theParameters = theStorage.getEmptyCopy(); - - // init the iters + theElements = new MapOfTaggedObjects(); + theNodes = new NodeStorage(); + theSPs = new MapOfTaggedObjects(); + thePCs = new MapOfTaggedObjects(); + theMPs = new MapOfTaggedObjects(); + theLoadPatterns = new PatternStorage(); + theParameters = new MapOfTaggedObjects(); + + // init the iters theEleIter = new SingleDomEleIter(theElements); theNodIter = new SingleDomNodIter(theNodes); theSP_Iter = new SingleDomSP_Iter(theSPs); thePC_Iter = new SingleDomPC_Iter(thePCs); theMP_Iter = new SingleDomMP_Iter(theMPs); - theLoadPatternIter = new LoadPatternIter(theLoadPatterns); + theLoadPatternIter = new PatternIterator(theLoadPatterns); allSP_Iter = new SingleDomAllSP_Iter(*this); - theParamIter = new SingleDomParamIter(theParameters); - - theBounds(0) = 0.0; - theBounds(1) = 0.0; - theBounds(2) = 0.0; - theBounds(3) = 0.0; - theBounds(4) = 0.0; - theBounds(5) = 0.0; - - dbEle =0; dbNod =0; dbSPs =0; dbPCs = 0; dbMPs =0; dbLPs = 0; dbParam = 0; + theParamIter = new SingleDomParamIter(theParameters); + + theBounds(0) = 0; + theBounds(1) = 0; + theBounds(2) = 0; + theBounds(3) = 0; + theBounds(4) = 0; + theBounds(5) = 0; } @@ -273,8 +177,6 @@ Domain::~Domain() this->Domain::clearAll(); // delete all the storage objects - // SEGMENT FAULT WILL OCCUR IF THESE OBJECTS WERE NOT CONSTRUCTED - // USING NEW if (theElements != nullptr) delete theElements; @@ -1010,7 +912,7 @@ Domain::removeNode(int tag) // if not there return NULL if (mc == nullptr) - return nullptr; + return nullptr; // mark the domain has having changed this->domainChange(); @@ -1079,45 +981,46 @@ Domain::removeSP_Constraint(int theNode, int theDOF, int loadPatternTag) SP_Constraint * Domain::removeSP_Constraint(int tag) { - // remove the object from the container - TaggedObject *mc = theSPs->removeComponent(tag); - - // if not there return nullptr - if (mc == nullptr) - return nullptr; + // remove the object from the container + TaggedObject *mc = theSPs->removeComponent(tag); + + // if not there return nullptr + if (mc == nullptr) + return nullptr; - // mark the domain as having changed - this->domainChange(); - - // perform a downward cast, set the objects domain pointer to 0 - // and return the result of the cast - SP_Constraint *result = (SP_Constraint *)mc; - // result->setDomain(0); + // mark the domain as having changed + this->domainChange(); + + // perform a downward cast, set the objects domain pointer to 0 + // and return the result of the cast + SP_Constraint *result = (SP_Constraint *)mc; + // result->setDomain(0); - // should check that theLoad and result are the same - return result; + // should check that theLoad and result are the same + return result; } + Pressure_Constraint * Domain::removePressure_Constraint(int tag) { - // remove the object from the container - TaggedObject *mc = thePCs->removeComponent(tag); - - // if not there return nullptr - if (mc == nullptr) - return nullptr; + // remove the object from the container + TaggedObject *mc = thePCs->removeComponent(tag); + + // if not there return nullptr + if (mc == nullptr) + return nullptr; - // mark the domain as having changed - this->domainChange(); - - // perform a downward cast, set the objects domain pointer to 0 - // and return the result of the cast - Pressure_Constraint *result = (Pressure_Constraint *)mc; - // result->setDomain(0); - - // should check that theLoad and result are the same - return result; + // mark the domain as having changed + this->domainChange(); + + // perform a downward cast, set the objects domain pointer to 0 + // and return the result of the cast + Pressure_Constraint *result = (Pressure_Constraint *)mc; + // result->setDomain(0); + + // should check that theLoad and result are the same + return result; } MP_Constraint * @@ -1128,7 +1031,7 @@ Domain::removeMP_Constraint(int tag) // if not there return nullptr if (mc == nullptr) - return nullptr; + return nullptr; // mark the domain as having changed this->domainChange(); @@ -1320,16 +1223,16 @@ Domain::removeSP_Constraint(int tag, int loadPattern) ElementIter & Domain::getElements() { - theEleIter->reset(); - return *theEleIter; + theEleIter->reset(); + return *theEleIter; } NodeIter & Domain::getNodes() { - theNodIter->reset(); - return *theNodIter; + theNodIter->reset(); + return *theNodIter; } SP_ConstraintIter & @@ -1386,10 +1289,10 @@ Element * Domain::getElement(int tag) { TaggedObject *mc = theElements->getComponentPtr(tag); - + // if not there return 0 otherwise perform a cast and return that if (mc == 0) - return 0; + return 0; Element *result = (Element *)mc; return result; } @@ -1424,13 +1327,13 @@ Domain::getSP_Constraint(int tag) Pressure_Constraint * Domain::getPressure_Constraint(int tag) { - TaggedObject *mc = thePCs->getComponentPtr(tag); + TaggedObject *mc = thePCs->getComponentPtr(tag); - // if not there return 0 otherwise perform a cast and return that - if (mc == 0) - return 0; - Pressure_Constraint *result = (Pressure_Constraint *)mc; - return result; + // if not there return 0 otherwise perform a cast and return that + if (mc == 0) + return 0; + Pressure_Constraint *result = (Pressure_Constraint *)mc; + return result; } MP_Constraint * @@ -1467,7 +1370,6 @@ Domain::getParameterFromIndex(int index) opserr << "Domain::getParameterFromIndex -- index " << index << " out of bounds 0 ... " << numParameters-1 << endln; return 0; } - } int @@ -1502,19 +1404,19 @@ Domain::getLoadPattern(int tag) double -Domain::getCurrentTime(void) const +Domain::getCurrentTime() const { return currentTime; } double -Domain::getDT(void) const +Domain::getDT() const { return dT; } int -Domain::getCommitTag(void) const +Domain::getCommitTag() const { return commitTag; } @@ -1926,30 +1828,30 @@ Domain::commit(void) } int -Domain::revertToLastCommit(void) +Domain::revertToLastCommit() { - // - // first invoke revertToLastCommit on all nodes and elements in the domain - // - Node *nodePtr; - NodeIter &theNodeIter = this->getNodes(); - while ((nodePtr = theNodeIter()) != nullptr) - nodePtr->revertToLastCommit(); - - Element *elePtr; - ElementIter &theElemIter = this->getElements(); - while ((elePtr = theElemIter()) != nullptr) { - elePtr->revertToLastCommit(); - } + // + // first invoke revertToLastCommit on all nodes and elements in the domain + // + Node *nodePtr; + NodeIter &theNodeIter = this->getNodes(); + while ((nodePtr = theNodeIter()) != nullptr) + nodePtr->revertToLastCommit(); + + Element *elePtr; + ElementIter &theElemIter = this->getElements(); + while ((elePtr = theElemIter()) != nullptr) { + elePtr->revertToLastCommit(); + } - // set the current time and load factor in the domain to last committed - currentTime = committedTime; - dT = 0.0; + // set the current time and load factor in the domain to last committed + currentTime = committedTime; + dT = 0.0; - // apply load for the last committed time - this->applyLoad(currentTime); + // apply load for the last committed time + this->applyLoad(currentTime); - return this->update(); + return this->update(); } int @@ -3439,12 +3341,14 @@ Domain::calculateNodalReactions(int flag) // apply load again! (for case ele load removed and record before an analysis) this->applyLoad(committedTime); - Node *theNode; - Element *theElement; - NodeIter &theNodes = this->getNodes(); - while ((theNode = theNodes()) != nullptr) - theNode->resetReactionForce(flag); + { + Node *theNode; + NodeIter &theNodes = this->getNodes(); + while ((theNode = theNodes()) != nullptr) + theNode->resetReactionForce(flag); + } + Element *theElement; ElementIter &theElements = this->getElements(); while ((theElement = theElements()) != nullptr) if (theElement->isSubdomain() == false) diff --git a/SRC/domain/domain/Domain.h b/SRC/domain/domain/Domain.h index c6215376c3..90cabc873d 100644 --- a/SRC/domain/domain/Domain.h +++ b/SRC/domain/domain/Domain.h @@ -32,6 +32,8 @@ #include #include +#include +#include enum class NodeData: int; class Element; @@ -49,7 +51,6 @@ class NodeIter; class SP_ConstraintIter; class MP_ConstraintIter; class Pressure_ConstraintIter; -class LoadPatternIter; class ParameterIter; class SingleDomEleIter; @@ -67,7 +68,6 @@ class NodeGraph; class ElementGraph; class Channel; class FEM_ObjectBroker; - class TaggedObjectStorage; @@ -77,16 +77,13 @@ class Domain Domain(); Domain(int numNodes, int numElements, int numSPs, int numMPs, int numLoadPatterns); - Domain(TaggedObjectStorage &theNodesStorage, - TaggedObjectStorage &theElementsStorage, - TaggedObjectStorage &theMPsStorage, - TaggedObjectStorage &theSPsStorage, - TaggedObjectStorage &theLoadPatternsStorage); - - Domain(TaggedObjectStorage &theStorageType); - virtual ~Domain(); + + using NodeStorage = MapOfTaggedObjects; + using PatternStorage = MapOfTaggedObjects; + using PatternIterator = TaggedIterator; + // methods to populate a domain virtual bool addElement(Element *); virtual bool addNode(Node *); @@ -101,7 +98,7 @@ class Domain // methods to remove the components - virtual void clearAll(void); + virtual void clearAll(); virtual Element *removeElement(int tag); virtual Node *removeNode(int tag); virtual SP_Constraint *removeSP_Constraint(int tag); @@ -122,7 +119,7 @@ class Domain virtual ElementalLoad *removeElementalLoad(int tag, int loadPattern); virtual SP_Constraint *removeSP_Constraint(int tag, int loadPattern); virtual int removeSP_Constraint(int nodeTag, int dof, int loadPatternTag); - virtual LoadPatternIter &getLoadPatterns(); + virtual PatternIterator &getLoadPatterns(); virtual SP_ConstraintIter &getDomainAndLoadPatternSPs(); virtual void setLoadConstant(); virtual void unsetLoadConstant(); @@ -157,17 +154,17 @@ class Domain virtual int getNumSPs() const; virtual int getNumPCs() const; virtual int getNumMPs() const; - virtual int getNumLoadPatterns(void) const; - virtual int getNumParameters(void) const; - virtual const Vector &getPhysicalBounds(void); + virtual int getNumLoadPatterns() const; + virtual int getNumParameters() const; + virtual const Vector &getPhysicalBounds(); virtual const Vector *getNodeResponse(int nodeTag, NodeData responseType); virtual const Vector *getElementResponse(int eleTag, const char **argv, int argc); // methods to get element and node graphs - virtual Graph &getElementGraph(void); - virtual Graph &getNodeGraph(void); - virtual void clearElementGraph(void); - virtual void clearNodeGraph(void); + virtual Graph &getElementGraph(); + virtual Graph &getNodeGraph(); + virtual void clearElementGraph(); + virtual void clearNodeGraph(); // methods to update the domain virtual void setCommitTag(int newTag); @@ -233,10 +230,6 @@ class Domain virtual int calculateNodalReactions(int flag); -#if 0 - virtual int activateElements(const ID& elementList); - virtual int deactivateElements(const ID& elementList); -#endif protected: virtual int buildEleGraph(Graph *theEleGraph); @@ -263,19 +256,19 @@ class Domain Graph *theElementGraph; TaggedObjectStorage *theElements; - TaggedObjectStorage *theNodes; + NodeStorage* theNodes; TaggedObjectStorage *theSPs; TaggedObjectStorage *thePCs; TaggedObjectStorage *theMPs; - TaggedObjectStorage *theLoadPatterns; + PatternStorage *theLoadPatterns; TaggedObjectStorage *theParameters; SingleDomEleIter *theEleIter; - SingleDomNodIter *theNodIter; + SingleDomNodIter *theNodIter; SingleDomSP_Iter *theSP_Iter; SingleDomPC_Iter *thePC_Iter; SingleDomMP_Iter *theMP_Iter; - LoadPatternIter *theLoadPatternIter; + PatternIterator *theLoadPatternIter; SingleDomAllSP_Iter *allSP_Iter; SingleDomParamIter *theParamIter; @@ -304,5 +297,6 @@ class Domain int numParameters; }; +using LoadPatternIter = Domain::PatternIterator; #endif diff --git a/SRC/domain/domain/LoadCaseIter.h b/SRC/domain/domain/LoadCaseIter.h deleted file mode 100644 index 00c763dcba..0000000000 --- a/SRC/domain/domain/LoadCaseIter.h +++ /dev/null @@ -1,62 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:18 $ -// $Source: /usr/local/cvs/OpenSees/SRC/domain/domain/LoadCaseIter.h,v $ - - -// File: ~/domain/domain/LoadCaseIter.h -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the class definition for LoadCaseIter. -// LoadCaseIter is an abstract base class. A LoadCAseIter object is -// an iter for returning the elements of an object of class Domain. -// LoadCaseIters must be written for each subclass of Domain, hence the -// abstract base class. - -#ifndef LoadCaseIter_h -#define LoadCaseIter_h - -class LoadCase; - -class LoadCaseIter -{ - public: - LoadCaseIter() {}; - virtual ~LoadCaseIter() {}; - - virtual LoadCase *operator()(void) =0; - - protected: - - private: - -}; - -#endif - - - - - diff --git a/SRC/domain/domain/Makefile b/SRC/domain/domain/Makefile deleted file mode 100644 index 05754b5d70..0000000000 --- a/SRC/domain/domain/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../../../Makefile.def - -OBJS = Domain.o DomainModalProperties.o - -# Compilation control - -all: $(OBJS) - @$(CD) $(FE)/domain/domain/single; $(MAKE); - @$(CD) $(FE)/domain/domain/partitioned; $(MAKE); - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(CD) $(FE)/domain/domain/single; $(MAKE) wipe clean; - @$(CD) $(FE)/domain/domain/partitioned; $(MAKE) wipe clean; - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - @$(CD) $(FE)/domain/domain/single; $(MAKE) wipe; - @$(CD) $(FE)/domain/domain/partitioned; $(MAKE) wipe; - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/domain/domain/NodeIter.h b/SRC/domain/domain/NodeIter.h index cf45b39b62..58d12b071f 100644 --- a/SRC/domain/domain/NodeIter.h +++ b/SRC/domain/domain/NodeIter.h @@ -46,7 +46,7 @@ class NodeIter NodeIter() {}; virtual ~NodeIter() {}; - virtual Node *operator()(void) =0; + virtual Node *operator()() =0; protected: diff --git a/SRC/domain/domain/single/SingleDomAllSP_Iter.cpp b/SRC/domain/domain/single/SingleDomAllSP_Iter.cpp index e5d663408d..aba3314b7d 100644 --- a/SRC/domain/domain/single/SingleDomAllSP_Iter.cpp +++ b/SRC/domain/domain/single/SingleDomAllSP_Iter.cpp @@ -37,7 +37,6 @@ #include #include -#include #include #include #include diff --git a/SRC/domain/domain/single/SingleDomAllSP_Iter.h b/SRC/domain/domain/single/SingleDomAllSP_Iter.h index 97e403478a..fc25c59239 100644 --- a/SRC/domain/domain/single/SingleDomAllSP_Iter.h +++ b/SRC/domain/domain/single/SingleDomAllSP_Iter.h @@ -40,11 +40,10 @@ #define SingleDomAllSP_Iter_h #include - +#include class TaggedObjectStorage; class TaggedObjectIter; class Domain; -class LoadPatternIter; class LoadPatternSPIter; class LoadPattern; diff --git a/SRC/domain/pattern/EarthquakePattern.cpp b/SRC/domain/pattern/EarthquakePattern.cpp index 26fe335257..844f30c485 100644 --- a/SRC/domain/pattern/EarthquakePattern.cpp +++ b/SRC/domain/pattern/EarthquakePattern.cpp @@ -50,7 +50,7 @@ EarthquakePattern::~EarthquakePattern() { // invoke the destructor on all ground motions supplied for (int i=0; igetNodalLoads(); - while ((nodLoad = theNodalIter()) != nullptr) nodLoad->applyLoad(loadFactor); } @@ -713,7 +712,8 @@ int LoadPattern::recvSelf(int cTag, Channel &theChannel, if (theEle == 0) { opserr << "LoadPattern::recv - cannot create ElementalLoad with " "classTag " - << classTag << endln; + << classTag + << "\n"; return -2; } @@ -757,7 +757,8 @@ int LoadPattern::recvSelf(int cTag, Channel &theChannel, if (theSP == 0) { opserr << "LoadPattern::recv - cannot create SP_Constraint with " "classTag " - << classTag << endln; + << classTag + << "\n"; return -2; } theSP->setDbTag(dbTag); @@ -852,7 +853,8 @@ void LoadPattern::Print(OPS_Stream &s, int flag) else { s << "Load Pattern: " << this->getTag() << "\n"; - s << " Scale Factor: " << scaleFactor << endln; + s << " Scale Factor: " << scaleFactor + << "\n"; if (theSeries != 0) theSeries->Print(s, flag); s << " Nodal Loads: \n"; @@ -864,7 +866,9 @@ void LoadPattern::Print(OPS_Stream &s, int flag) } } -LoadPattern *LoadPattern::getCopy() + +LoadPattern * +LoadPattern::getCopy() { LoadPattern *theCopy = new LoadPattern(this->getTag()); @@ -875,7 +879,8 @@ LoadPattern *LoadPattern::getCopy() return theCopy; } -int LoadPattern::addMotion(GroundMotion &theMotion, int tag) +int +LoadPattern::addMotion(GroundMotion &theMotion, int tag) { opserr << "LoadPattern::addMotion() - cannot add GroundMotion - use " "MultiSupport Pattern instead\n"; @@ -924,9 +929,9 @@ void LoadPattern::applyLoadSensitivity(double pseudoTime) int LoadPattern::setParameter(const char **argv, int argc, Parameter ¶m) { - if (theSeries == 0) { + if (theSeries == nullptr) { opserr << "set/update/activate parameter is illegaly called in LoadPattern " - << endln; + << "\n"; return 0; } @@ -993,16 +998,17 @@ int LoadPattern::setParameter(const char **argv, int argc, Parameter ¶m) return -1; } -int LoadPattern::updateParameter(int parameterID, Information &info) +int +LoadPattern::updateParameter(int parameterID, Information &info) { if (theSeries == 0) { opserr << "set/update/activate parameter is illegaly called in LoadPattern " - << endln; + << "\n"; } opserr << "LoadPattern::updateParameter -- no parameters defined, this " "method should not be called" - << endln; + << "\n"; return 0; @@ -1055,14 +1061,14 @@ int LoadPattern::updateParameter(int parameterID, Information &info) int LoadPattern::activateParameter(int parameterID) { - if (theSeries == 0) { + if (theSeries == nullptr) { opserr << "set/update/activate parameter is illegaly called in LoadPattern " - << endln; + << "\n"; } opserr << "LoadPattern::activateParameter -- no parameters defined, this " "method should not be called" - << endln; + << "\n"; return 0; @@ -1117,7 +1123,7 @@ int LoadPattern::activateParameter(int parameterID) } } else { - opserr << "LoadPattern::gradient() -- error in identifier. " << endln; + opserr << "LoadPattern::gradient() -- error in identifier. " << "\n"; } } } @@ -1125,7 +1131,8 @@ int LoadPattern::activateParameter(int parameterID) */ } -const Vector &LoadPattern::getExternalForceSensitivity(int gradNumber) +const Vector & +LoadPattern::getExternalForceSensitivity(int gradNumber) { // THIS METHOD IS CURRENTLY ONLY USED FOR THE STATIC CASE @@ -1144,9 +1151,8 @@ const Vector &LoadPattern::getExternalForceSensitivity(int gradNumber) } // Prepare the vector identifying which loads are random. - NodalLoad *theNodalLoad = 0; + NodalLoad *theNodalLoad = nullptr; NodalLoadIter &theNodalIter = this->getNodalLoads(); - int i; // Loop through the nodal loads to pick up possible contributions int nodeNumber; @@ -1171,7 +1177,7 @@ const Vector &LoadPattern::getExternalForceSensitivity(int gradNumber) tempRandomLoads = (*randomLoads); delete randomLoads; randomLoads = new Vector(sizeRandomLoads + 2); - for (i = 0; i < sizeRandomLoads; i++) { + for (int i = 0; i < sizeRandomLoads; i++) { (*randomLoads)(i) = tempRandomLoads(i); } (*randomLoads)(sizeRandomLoads) = nodeNumber; @@ -1187,7 +1193,6 @@ int LoadPattern::saveLoadFactorSensitivity(double dlambdadh, int gradIndex, int numGrads) { - //opserr << "LoadPattern::savedlamdh " << gradIndex << ' ' << numGrads << endln; if (dLambdadh == 0) { dLambdadh = new Vector(numGrads); } @@ -1204,7 +1209,7 @@ int LoadPattern::saveLoadFactorSensitivity(double dlambdadh, int gradIndex, } else { opserr << "LoadPattern::saveLoadFactorSensitivity -- gradIndex out of bounds" - << endln; + << "\n"; return -1; } } diff --git a/SRC/domain/pattern/LoadPattern.h b/SRC/domain/pattern/LoadPattern.h index 6184137800..44df7d4ff5 100644 --- a/SRC/domain/pattern/LoadPattern.h +++ b/SRC/domain/pattern/LoadPattern.h @@ -33,7 +33,6 @@ // // What: "@(#) LoadPattern.h, revA" -// #include #include #include #include @@ -50,9 +49,7 @@ class SP_ConstraintIter; class TaggedObjectStorage; class GroundMotion; -class LoadPattern : - public TaggedObject, - public MovableObject +class LoadPattern : public TaggedObject, public MovableObject { public: LoadPattern(int tag, double fact = 1.0); @@ -62,43 +59,43 @@ class LoadPattern : virtual ~LoadPattern(); // method to set the associated TimeSeries and Domain - virtual void setTimeSeries(TimeSeries *theSeries); - virtual void setDomain(Domain *theDomain); + virtual void setDomain(Domain *); + void setTimeSeries(TimeSeries *); Domain* getDomain() {return theDomain;} + // methods to apply loads + virtual void applyLoad(double pseudoTime = 0.0); + void setLoadConstant(); + void unsetLoadConstant(); + double getLoadFactor(); + + // methods for o/p + virtual int sendSelf(int commitTag, Channel &); + virtual int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); + virtual void Print(OPS_Stream &s, int flag); + + // method to obtain a blank copy of the LoadPattern + virtual LoadPattern *getCopy(); + + // TODO: Move to subclass + virtual int addMotion(GroundMotion &theMotion, int tag); + virtual GroundMotion *getMotion(int tag); + + // TODO: Move to subclass // methods to add loads virtual bool addSP_Constraint(SP_Constraint *); virtual bool addNodalLoad(NodalLoad *); virtual bool addElementalLoad(ElementalLoad *); virtual NodalLoadIter &getNodalLoads(); virtual ElementalLoadIter &getElementalLoads(); - virtual SP_ConstraintIter &getSPs(); - + virtual SP_ConstraintIter &getSPs(); // methods to remove loads - virtual void clearAll(); virtual NodalLoad *removeNodalLoad(int tag); virtual ElementalLoad *removeElementalLoad(int tag); virtual SP_Constraint *removeSP_Constraint(int tag); + virtual void clearAll(); - // methods to apply loads - virtual void applyLoad(double pseudoTime = 0.0); - virtual void setLoadConstant(); - virtual void unsetLoadConstant(); - virtual double getLoadFactor(); - - // methods for o/p - virtual int sendSelf(int commitTag, Channel &theChannel); - virtual int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); - virtual void Print(OPS_Stream &s, int flag =0); - - // method to obtain a blank copy of the LoadPattern - virtual LoadPattern *getCopy(void); - - virtual int addMotion(GroundMotion &theMotion, int tag); - virtual GroundMotion *getMotion(int tag); - - // AddingSensitivity:BEGIN ////////////////////////////////////////// + // Sensitivity virtual void applyLoadSensitivity(double pseudoTime = 0.0); virtual int setParameter(const char **argv, int argc, Parameter ¶m); virtual int updateParameter(int parameterID, Information &info); @@ -108,9 +105,14 @@ class LoadPattern : virtual int saveLoadFactorSensitivity(double dlambdadh, int gradIndex, int numGrads); virtual double getLoadFactorSensitivity(int gradIndex); + protected: bool isConstant; // to indicate whether setConstant has been called - + + enum : int { + PATTERN_TAG_StaticPattern = 1000 + }; + private: double loadFactor; // current load factor double scaleFactor; // factor to scale load factor from time series @@ -130,15 +132,14 @@ class LoadPattern : NodalLoadIter *theNodIter; ElementalLoadIter *theEleIter; SingleDomSP_Iter *theSpIter; +// - // AddingSensitivity:BEGIN ////////////////////////////////////// Vector *randomLoads; bool RVisRandomProcessDiscretizer; Vector *dLambdadh; - // AddingSensitivity:END //////////////////////////////////////// + // int lastChannel; - Domain* theDomain; }; diff --git a/SRC/domain/pattern/LoadPatternIter.cpp b/SRC/domain/pattern/LoadPatternIter.cpp deleted file mode 100644 index 704f07d339..0000000000 --- a/SRC/domain/pattern/LoadPatternIter.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:19 $ -// $Source: /usr/local/cvs/OpenSees/SRC/domain/pattern/LoadPatternIter.cpp,v $ - - -// File: ~/domain/pattern/LoadPatternIter.C -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the method definitions for class -// LoadPatternIter. LoadPatternIter is a class for iterating through the -// Nodal loads of a load case. - -#include "LoadPatternIter.h" - -#include -#include -#include - - -// LoadPatternIter(SingleDomain &theDomain): -// constructor that takes the model, just the basic iter - -LoadPatternIter::LoadPatternIter(TaggedObjectStorage *theStorage) - :myIter(theStorage->getComponents()) -{ -} - - -LoadPatternIter::~LoadPatternIter() -{ -} - -void -LoadPatternIter::reset(void) -{ - myIter.reset(); -} - - -LoadPattern * -LoadPatternIter::operator()(void) -{ - // check if we still have elements in the model - // if not return 0, indicating we are done - TaggedObject *theComponent = myIter(); - if (theComponent == 0) - return 0; - else { - LoadPattern *result = (LoadPattern *)theComponent; - return result; - } -} - diff --git a/SRC/domain/pattern/LoadPatternIter.h b/SRC/domain/pattern/LoadPatternIter.h index 70b2de092c..a75aa8bab1 100644 --- a/SRC/domain/pattern/LoadPatternIter.h +++ b/SRC/domain/pattern/LoadPatternIter.h @@ -17,45 +17,27 @@ ** Filip C. Filippou (filippou@ce.berkeley.edu) ** ** ** ** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:19 $ -// $Source: /usr/local/cvs/OpenSees/SRC/domain/pattern/LoadPatternIter.h,v $ - - -// File: ~/domain/loadcase/LoadPatternIter.h -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A // // Description: This file contains the class definition for LoadPatternIter. // LoadPatternIter is an abstract base class. An LoadPatternIter is an // iter for returning the LoadPatterns of an object of class LoadCasse. // LoadPatternIters must be written for each subclass of LoadCase. +// +// Written: fmk +// Created: Fri Sep 20 15:27:47: 1996 +// Revision: A +// +// $Revision: 1.1.1.1 $ +// $Date: 2000-09-15 08:23:19 $ +// $Source: /usr/local/cvs/OpenSees/SRC/domain/pattern/LoadPatternIter.h,v $ +// +// File: ~/domain/loadcase/LoadPatternIter.h +// #ifndef LoadPatternIter_h #define LoadPatternIter_h class LoadPattern; -class TaggedObjectStorage; -class TaggedObjectIter; - -class LoadPatternIter -{ - public: - LoadPatternIter(TaggedObjectStorage *theStorage); - virtual ~LoadPatternIter(); - - virtual LoadPattern *operator()(void); - virtual void reset(void); - - protected: - - private: - TaggedObjectIter &myIter; - -}; - +#include #endif diff --git a/SRC/domain/pattern/LoadpatternIter b/SRC/domain/pattern/LoadpatternIter deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/SRC/domain/pattern/Makefile b/SRC/domain/pattern/Makefile deleted file mode 100644 index a0d6031e9a..0000000000 --- a/SRC/domain/pattern/Makefile +++ /dev/null @@ -1,59 +0,0 @@ -include ../../../Makefile.def - -ifeq ($(RELIABILITY), YES_RELIABILITY) - -RELIABILITY_OBJS = DiscretizedRandomProcessSeries.o \ - SimulatedRandomProcessSeries.o - -else - -RELIABILITY_OBJS = - -endif - -OBJS = $(RELIABILITY_OBJS) \ - EarthquakePattern.o \ - LinearSeries.o \ - LoadPattern.o \ - FireLoadPattern.o \ - LoadPatternIter.o \ - PathSeries.o \ - PathTimeSeries.o \ - PathTimeSeriesThermal.o \ - RectangularSeries.o \ - TimeSeries.o \ - TclPatternCommand.o \ - TrigSeries.o \ - ConstantSeries.o \ - UniformExcitation.o \ - TimeSeriesIntegrator.o \ - TrapezoidalTimeSeriesIntegrator.o \ - SimpsonTimeSeriesIntegrator.o \ - MultiSupportPattern.o \ - TclSeriesCommand.o \ - PulseSeries.o \ - TriangleSeries.o \ - TclSeriesIntegratorCommand.o \ - PeerMotion.o \ - PeerNGAMotion.o - -# Compilation control - -all: $(OBJS) - @$(CD) $(FE)/domain/pattern/drm; $(MAKE); - - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - @$(CD) $(FE)/domain/pattern/drm; $(MAKE) wipe; - - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/domain/pattern/MultiSupportPattern.cpp b/SRC/domain/pattern/MultiSupportPattern.cpp index 3f23fd3294..0a2cd33d3f 100644 --- a/SRC/domain/pattern/MultiSupportPattern.cpp +++ b/SRC/domain/pattern/MultiSupportPattern.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include MultiSupportPattern::MultiSupportPattern(int tag, int _classTag) @@ -192,8 +191,8 @@ MultiSupportPattern::sendSelf(int commitTag, Channel &theChannel) for (int j=0; jsendSelf(commitTag, theChannel) < 0) { - opserr << "MultiSupportPattern::sendSelf - ground motion failed in sendSelf\n"; - return -7; + opserr << "MultiSupportPattern::sendSelf - ground motion failed in sendSelf\n"; + return -7; } } } @@ -219,7 +218,7 @@ MultiSupportPattern::recvSelf(int commitTag, Channel &theChannel, if (theMotions != 0) { for (int i=0; isetDbTag(motionData(i*3+1)); int tag = motionData(i*3+2); if (theMotion->recvSelf(commitTag, theChannel, theBroker) < 0) { - opserr << "MultiSupportPattern::sendSelf - ground motion failed in recvSelf\n"; - return -7; + opserr << "MultiSupportPattern::sendSelf - ground motion failed in recvSelf\n"; + return -7; } theMotionTags[i] = tag; @@ -286,8 +280,8 @@ MultiSupportPattern::recvSelf(int commitTag, Channel &theChannel, void MultiSupportPattern::Print(OPS_Stream &s, int flag) { - s << "MultiSupportPattern tag: " << this->getTag() << - " numMotions: " << numMotions << endln; + s << "MultiSupportPattern tag: " << this->getTag() + << " numMotions: " << numMotions << "\n"; SP_Constraint *sp; SP_ConstraintIter &theIter = this->getSPs(); @@ -297,7 +291,7 @@ MultiSupportPattern::Print(OPS_Stream &s, int flag) } LoadPattern * -MultiSupportPattern::getCopy(void) +MultiSupportPattern::getCopy() { LoadPattern *theCopy = new MultiSupportPattern(this->getTag()); for (int i=0; isendVector(data); } -void ShadowSubdomain::setLoadConstant(void) +void ShadowSubdomain::setLoadConstant() { msgData(0) = ShadowActorSubdomain_setLoadConstant; diff --git a/SRC/domain/subdomain/Subdomain.cpp b/SRC/domain/subdomain/Subdomain.cpp index 9c1e74b401..f6224ba468 100644 --- a/SRC/domain/subdomain/Subdomain.cpp +++ b/SRC/domain/subdomain/Subdomain.cpp @@ -46,7 +46,6 @@ #include #include #include -//#include #include #include @@ -80,53 +79,9 @@ Subdomain::Subdomain(int tag) internalNodeIter = new SingleDomNodIter(internalNodes); externalNodeIter = new SingleDomNodIter(externalNodes); theNodIter = new SubdomainNodIter(*this); - - // check that space was available - if (internalNodes == 0 || externalNodes == 0 || - internalNodeIter == 0 || externalNodeIter == 0 || - theNodIter == 0) { - - opserr << "Subdomain::Subdomain() - ran out of memory\n"; - exit(-1); - } } -Subdomain::Subdomain(int tag, - TaggedObjectStorage &theInternalNodeStorage, - TaggedObjectStorage &theExternalNodeStorage, - TaggedObjectStorage &theElementsStorage, - TaggedObjectStorage &theLoadPatternsStorage, - TaggedObjectStorage &theMPsStorage, - TaggedObjectStorage &theSPsStorage) - :Element(tag,ELE_TAG_Subdomain), - Domain(theExternalNodeStorage, theElementsStorage, - theLoadPatternsStorage, - theMPsStorage,theSPsStorage), - mapBuilt(false),map(0),mappedVect(0),mappedMatrix(0), - internalNodes(&theInternalNodeStorage), - externalNodes(&theExternalNodeStorage), - realCost(0.0),cpuCost(0),pageCost(0), - theAnalysis(0), extNodes(0), theFEele(0) -{ - //thePartitionedModelBuilder = 0; - // realExternalNodes = new MapOfTaggedObjects(256); - - internalNodeIter = new SingleDomNodIter(internalNodes); - externalNodeIter = new SingleDomNodIter(externalNodes); - - // check that space was available - if (internalNodes == 0 || externalNodes == 0 || - internalNodeIter == 0 || externalNodeIter == 0 || - theNodIter == 0) { - - opserr << "Subdomain::Subdomain() - ran out of memory\n"; - exit(-1); - } - -} - - Subdomain::~Subdomain() { if (internalNodes != 0) diff --git a/SRC/domain/subdomain/Subdomain.h b/SRC/domain/subdomain/Subdomain.h index a605498223..9f49d57648 100644 --- a/SRC/domain/subdomain/Subdomain.h +++ b/SRC/domain/subdomain/Subdomain.h @@ -52,15 +52,6 @@ class Subdomain: public Element, public Domain { public: Subdomain(int tag); - - Subdomain(int tag, - TaggedObjectStorage &theInternalNodeStorage, - TaggedObjectStorage &theExternalNodeStorage, - TaggedObjectStorage &theElementsStorage, - TaggedObjectStorage &theLoadPatternsStorage, - TaggedObjectStorage &theMPsStorage, - TaggedObjectStorage &theSPsStorage); - virtual ~Subdomain(); // method added for parallel domain generation @@ -71,7 +62,7 @@ class Subdomain: public Element, public Domain virtual void clearAll(); virtual bool addNode(Node *); virtual Node *removeNode(int tag); - virtual NodeIter &getNodes(); + virtual NodeIter &getNodes(); virtual Node *getNode(int tag); virtual Node **getNodePtrs(); diff --git a/SRC/tagged/storage/ArrayOfTaggedObjects.h b/SRC/tagged/storage/ArrayOfTaggedObjects.h index 0072a4e15b..92d187b82d 100644 --- a/SRC/tagged/storage/ArrayOfTaggedObjects.h +++ b/SRC/tagged/storage/ArrayOfTaggedObjects.h @@ -66,6 +66,11 @@ class ArrayOfTaggedObjects : public TaggedObjectStorage using Iterator = ArrayOfTaggedObjectsIter; ArrayOfTaggedObjectsIter getIter(); + + Iterator& getIterRef() { + myIter.reset(); + return myIter; + } virtual TaggedObjectStorage *getEmptyCopy(); virtual void clearAll(bool invokeDestructor = true); diff --git a/SRC/tagged/storage/HashMapOfTaggedObjectsIter.cpp b/SRC/tagged/storage/HashMapOfTaggedObjectsIter.cpp index 826fbffd56..03410bc5bc 100644 --- a/SRC/tagged/storage/HashMapOfTaggedObjectsIter.cpp +++ b/SRC/tagged/storage/HashMapOfTaggedObjectsIter.cpp @@ -39,7 +39,7 @@ typedef MAP_TAGGED::iterator MAP_TAGGED_ITERATOR; // constructor that takes the model, just the basic iter HashMapOfTaggedObjectsIter::HashMapOfTaggedObjectsIter(HashMapOfTaggedObjects &theComponents) { - theMap = &(theComponents.theMap); + theMap = &(theComponents.theMap); } @@ -49,20 +49,21 @@ HashMapOfTaggedObjectsIter::~HashMapOfTaggedObjectsIter() } void -HashMapOfTaggedObjectsIter::reset(void) +HashMapOfTaggedObjectsIter::reset() { - currentComponent = theMap->begin(); + currentComponent = theMap->begin(); } + TaggedObject * -HashMapOfTaggedObjectsIter::operator()(void) +HashMapOfTaggedObjectsIter::operator()() { - if (currentComponent != theMap->end()) { - TaggedObject *result = (*currentComponent).second; - currentComponent++; - return result; - } else - return nullptr; + if (currentComponent != theMap->end()) { + TaggedObject *result = (*currentComponent).second; + currentComponent++; + return result; + } else + return nullptr; } diff --git a/SRC/tagged/storage/MapOfTaggedObjects.cpp b/SRC/tagged/storage/MapOfTaggedObjects.cpp index 2dd162a094..9f1c640dc1 100644 --- a/SRC/tagged/storage/MapOfTaggedObjects.cpp +++ b/SRC/tagged/storage/MapOfTaggedObjects.cpp @@ -32,64 +32,63 @@ // some typedefs that will be useful typedef Map MAP_TAGGED; -typedef MAP_TAGGED::value_type MAP_TAGGED_TYPE; -typedef MAP_TAGGED::iterator MAP_TAGGED_ITERATOR; MapOfTaggedObjects::MapOfTaggedObjects() -:myIter(*this) +: myIter(*this) { - // creates the iter with this as the argument + // creates the iter with this as the argument } MapOfTaggedObjects::~MapOfTaggedObjects() { - this->clearAll(); + this->clearAll(); } int MapOfTaggedObjects::setSize(int newSize) { - // no setSize for map template .. can only check enough space available - int maxSize = int(theMap.max_size()); - if (newSize > maxSize) { - opserr << "MapOfTaggedObjects::setSize - failed as map STL has a max size of " << maxSize << "\n"; - return -1; - } - - return 0; + // no setSize for map template .. can only check enough space available + int maxSize = int(theMap.max_size()); + if (newSize > maxSize) { + opserr << "MapOfTaggedObjects::setSize - failed as map STL has a max size of " << maxSize << "\n"; + return -1; + } + + return 0; } bool MapOfTaggedObjects::addComponent(TaggedObject *newComponent) { - MAP_TAGGED_ITERATOR theEle; + MAP_TAGGED::iterator theEle; int tag = newComponent->getTag(); // check if the ele already in map, if not we add - std::pair res = theMap.insert(MAP_TAGGED_TYPE(tag,newComponent)); + std::pair res = theMap.insert(MAP_TAGGED::value_type (tag,newComponent)); if (res.second == false) { - opserr << "MapOfTaggedObjects::addComponent - not adding as one with similar tag exists, tag: " << - tag << "\n"; + opserr << "MapOfTaggedObjects::addComponent - " + << "not adding as one with similar tag exists, tag: " + << tag << "\n"; return false; } /* theEle = theMap.find(tag); if (theEle == theMap.end()) { - theMap.insert(MAP_TAGGED_TYPE(tag,newComponent)); + theMap.insert(MAP_TAGGED::value_type (tag,newComponent)); // check if sucessfully added theEle = theMap.find(tag); if (theEle == theMap.end()) { - opserr << "MapOfTaggedObjects::addComponent - map STL failed to add object with tag : " << - newComponent->getTag() << "\n"; - return false; + opserr << "MapOfTaggedObjects::addComponent - map STL failed to add object with tag : " + << newComponent->getTag() << "\n"; + return false; } } else { opserr << "MapOfTaggedObjects::addComponent - not adding as one with similar tag exists, tag: " << - tag << "\n"; + tag << "\n"; return false; } */ @@ -101,117 +100,112 @@ MapOfTaggedObjects::addComponent(TaggedObject *newComponent) TaggedObject * MapOfTaggedObjects::removeComponent(int tag) { - TaggedObject *removed =0; - MAP_TAGGED_ITERATOR theEle; - - // return 0 if component does not exist, otherwise remove it - theEle = theMap.find(tag); - if (theEle == theMap.end()) // the object has not been added - return nullptr; - else { // the object exists so we remove it - removed = (*theEle).second; - int ok = int(theMap.erase(tag)); - if (ok != 1) { // ensure the map did remove the object - opserr << "MapOfTaggedObjects::removeComponent - map STL failed to remove object with tag " << - tag << "\n"; - return nullptr; - } + TaggedObject *removed =0; + MAP_TAGGED::iterator theEle; + + // return 0 if component does not exist, otherwise remove it + theEle = theMap.find(tag); + if (theEle == theMap.end()) // the object has not been added + return nullptr; + + else { // the object exists so we remove it + removed = (*theEle).second; + int ok = int(theMap.erase(tag)); + if (ok != 1) { // ensure the map did remove the object + opserr << "MapOfTaggedObjects::removeComponent - map STL failed to remove object with tag " << + tag << "\n"; + return nullptr; } + } - return removed; + return removed; } int -MapOfTaggedObjects::getNumComponents(void) const +MapOfTaggedObjects::getNumComponents() const { - return int(theMap.size()); + return int(theMap.size()); } TaggedObject * MapOfTaggedObjects::getComponentPtr(int tag) { - TaggedObject *removed = nullptr; - MAP_TAGGED_ITERATOR theEle; - - // return 0 if component does not exist, otherwise remove it - theEle = theMap.find(tag); - if (theEle == theMap.end()) - return nullptr; - else - removed = (*theEle).second; - - return removed; + TaggedObject *removed = nullptr; + MAP_TAGGED::iterator theEle; + + // return 0 if component does not exist, otherwise remove it + theEle = theMap.find(tag); + if (theEle == theMap.end()) + return nullptr; + else + removed = (*theEle).second; + + return removed; } TaggedObjectIter & MapOfTaggedObjects::getComponents() { - myIter.reset(); - return myIter; + myIter.reset(); + return myIter; } MapOfTaggedObjectsIter MapOfTaggedObjects::getIter() { - return MapOfTaggedObjectsIter(*this); + return MapOfTaggedObjectsIter(*this); } TaggedObjectStorage * -MapOfTaggedObjects::getEmptyCopy(void) +MapOfTaggedObjects::getEmptyCopy() { - MapOfTaggedObjects *theCopy = new MapOfTaggedObjects(); - - if (theCopy == nullptr) { - opserr << "MapOfTaggedObjects::getEmptyCopy-out of memory\n"; - } - - return theCopy; + return new MapOfTaggedObjects(); } + void MapOfTaggedObjects::clearAll(bool invokeDestructor) { - // invoke the destructor on all the tagged objects stored - if (invokeDestructor == true) { - MAP_TAGGED_ITERATOR p = theMap.begin(); - while (p != theMap.end()) { - delete (*p).second; - p++; - } + // invoke the destructor on all the tagged objects stored + if (invokeDestructor == true) { + MAP_TAGGED::iterator p = theMap.begin(); + while (p != theMap.end()) { + delete (*p).second; + p++; } + } - // now clear the map of all entries - theMap.clear(); + // now clear the map of all entries + theMap.clear(); } void MapOfTaggedObjects::Print(OPS_Stream &s, int flag) { - if (flag == OPS_PRINT_PRINTMODEL_JSON) { - int i = 0; - MAP_TAGGED_ITERATOR p = theMap.begin(); - while (p != theMap.end()) { - if (i++) - s << ",\n"; - ((*p).second)->Print(s, flag); - p++; - } - return; - } - - // s << "\nnumComponents: " << this->getNumComponents(); - // go through the array invoking Print on non-zero entries - MAP_TAGGED_ITERATOR p = theMap.begin(); + if (flag == OPS_PRINT_PRINTMODEL_JSON) { + int i = 0; + MAP_TAGGED::iterator p = theMap.begin(); while (p != theMap.end()) { - ((*p).second)->Print(s, flag); - p++; + if (i++) + s << ",\n"; + ((*p).second)->Print(s, flag); + p++; } + return; + } + + // go through the array invoking Print on non-zero entries + MAP_TAGGED::iterator p = theMap.begin(); + while (p != theMap.end()) { + ((*p).second)->Print(s, flag); + p++; + } } diff --git a/SRC/tagged/storage/MapOfTaggedObjects.h b/SRC/tagged/storage/MapOfTaggedObjects.h index a820471dd0..1ea8ee806e 100644 --- a/SRC/tagged/storage/MapOfTaggedObjects.h +++ b/SRC/tagged/storage/MapOfTaggedObjects.h @@ -60,18 +60,25 @@ class MapOfTaggedObjects : public TaggedObjectStorage bool addComponent(TaggedObject *newComponent); // bool allowMutltipleTags = false); TaggedObject *removeComponent(int tag); - int getNumComponents(void) const; + int getNumComponents() const; TaggedObject *getComponentPtr(int tag); TaggedObjectIter &getComponents(); + using Iterator = MapOfTaggedObjectsIter; MapOfTaggedObjectsIter getIter(); - TaggedObjectStorage *getEmptyCopy(void); + Iterator& getIterRef() { + myIter.reset(); + return myIter; + } + + TaggedObjectStorage *getEmptyCopy(); void clearAll(bool invokeDestructor = true); void Print(OPS_Stream &s, int flag =0); friend class MapOfTaggedObjectsIter; + protected: From ba7f5ea8cf0d62e02363f95636528c0050e0d5f0 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 13 Jan 2026 00:52:35 -0800 Subject: [PATCH 028/161] Create LoadCase.h --- SRC/domain/pattern/LoadCase.h | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 SRC/domain/pattern/LoadCase.h diff --git a/SRC/domain/pattern/LoadCase.h b/SRC/domain/pattern/LoadCase.h new file mode 100644 index 0000000000..5f2053aa57 --- /dev/null +++ b/SRC/domain/pattern/LoadCase.h @@ -0,0 +1,73 @@ +# pragma once +#include "LoadPattern.h" +#include +#include +#include +#include + +// case { +// pattern ... +//. +//. analyze +// } + + +class Domain; +class LoadPattern; + +class ElementalLoad; +class NodalLoad; +class SP_Constraint; +class SP_ConstraintIter; + +namespace OpenSees { +class LoadCase { +public: + LoadCase(Domain& domain); + + void clearAll(); + + // int domainChange(); // TODO + + void applyLoad(double pseudoTime); + void setLoadConstant(); + void unsetLoadConstant(); + + virtual int getNumLoadPatterns(void) const; + bool addLoadPattern(LoadPattern *); + LoadPattern* getLoadPattern(int tag); + LoadPattern* removeLoadPattern(int tag); + bool addSP_Constraint(SP_Constraint *, int loadPatternTag); + bool addNodalLoad(NodalLoad *, int loadPatternTag); + bool addElementalLoad(ElementalLoad *, int loadPatternTag); + NodalLoad *removeNodalLoad(int tag, int loadPattern); + ElementalLoad *removeElementalLoad(int tag, int loadPattern); + SP_Constraint *removeSP_Constraint(int tag, int loadPattern); + int removeSP_Constraint(int nodeTag, int dof, int loadPatternTag); + + using PatternStorage = MapOfTaggedObjects; + using PatternIterator = TaggedIterator; + PatternIterator &getLoadPatterns(); + + auto getConstraints() { + allSPs.clear(); + PatternIterator &thePatterns = this->getLoadPatterns(); + LoadPattern *lp; + while ((lp = thePatterns()) != nullptr) { + SP_ConstraintIter &spIter = lp->getSPs(); + SP_Constraint *sp; + while ((sp = spIter()) != nullptr) { + allSPs.push_back(sp); + } + } + return std::views::all(allSPs); + } + +private: + Domain& domain; + PatternStorage *theLoadPatterns; + PatternIterator *theLoadPatternIter; + std::vector allSPs; +}; + +} // namespace OpenSees \ No newline at end of file From f4f5b87fe644e02183aef659d2c7f05a57922efc Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 13 Jan 2026 00:52:37 -0800 Subject: [PATCH 029/161] Create LoadCase.cpp --- SRC/domain/pattern/LoadCase.cpp | 404 ++++++++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 SRC/domain/pattern/LoadCase.cpp diff --git a/SRC/domain/pattern/LoadCase.cpp b/SRC/domain/pattern/LoadCase.cpp new file mode 100644 index 0000000000..6681b58038 --- /dev/null +++ b/SRC/domain/pattern/LoadCase.cpp @@ -0,0 +1,404 @@ + + +#include "LoadCase.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace OpenSees; + +LoadCase::LoadCase(Domain& domain_) +: domain(domain_) +, theLoadPatterns(new PatternStorage()) +, theLoadPatternIter(new PatternIterator(theLoadPatterns)) +{ + +} + +void +LoadCase::clearAll() +{ + // clear the loads and constraints from any load pattern + PatternIterator &thePatterns = this->getLoadPatterns(); + LoadPattern *thePattern; + while ((thePattern = thePatterns()) != nullptr) + thePattern->clearAll(); +} + +bool +LoadCase::addLoadPattern(LoadPattern *load) +{ + // first check if a load pattern with a similar tag exists + int tag = load->getTag(); + TaggedObject *other = theLoadPatterns->getComponentPtr(tag); + if (other != nullptr) { + opserr << "LoadCase::addLoadPattern - cannot add as LoadPattern with tag " + << tag << " already exists in model\n"; + return false; + } + + int numSPs = 0; + SP_Constraint *theSP_Constraint; + SP_ConstraintIter &theSP_Constraints = load->getSPs(); + while ((theSP_Constraint = theSP_Constraints()) != nullptr) + numSPs++; + + // now we add the load pattern to the container for load patterns + bool result = theLoadPatterns->addComponent(load); + if (result == true) { + load->setDomain(&domain); + if (numSPs > 0) + domain.domainChange(); + } + else + opserr << "cannot add LoadPattern with tag " + << tag << " to the container\n"; + return result; +} + + +bool +LoadCase::addSP_Constraint(SP_Constraint *spConstraint, int pattern) +{ + + // now add it to the pattern + TaggedObject *thePattern = theLoadPatterns->getComponentPtr(pattern); + if (thePattern == nullptr) { + opserr << "LoadCase::addSP_Constraint - cannot add as pattern with tag " + << pattern << " does not exist in domain\n"; + + return false; + } + + LoadPattern *theLoadPattern = (LoadPattern *)thePattern; + bool result = theLoadPattern->addSP_Constraint(spConstraint); + if (result == false) { + opserr << "LoadCase::addSP_Constraint - " + << pattern << " pattern could not add the SP_Constraint\n"; + + return false; + } + + spConstraint->setDomain(&domain); + domain.domainChange(); + + return true; +} + +bool +LoadCase::addNodalLoad(NodalLoad *load, int pattern) +{ + int nodTag = load->getNodeTag(); + Node *res = domain.getNode(nodTag); + if (res == 0) { + opserr << "LoadCase::addNodalLoad() - no node with tag " + << nodTag << " exists in the model, not adding the nodal load " + << *load << "\n"; + return false; + } + + // now add it to the pattern + TaggedObject *thePattern = theLoadPatterns->getComponentPtr(pattern); + if (thePattern == nullptr) { + opserr << "LoadCase::addNodalLoad() - no pattern with tag " + << pattern << " in the model, not adding the nodal load " + << *load << "\n"; + + return false; + } + + LoadPattern *theLoadPattern = (LoadPattern *)thePattern; + bool result = theLoadPattern->addNodalLoad(load); + if (result == false) { + opserr << "LoadCase::addNodalLoad() - pattern with tag " + << pattern << " could not add the load " << *load + << "\n"; + + return false; + } + + load->setDomain(&domain); // done in LoadPattern::addNodalLoad() + //domain.domainChange(); // a nodal load does not change the domain + + return result; +} + + +bool +LoadCase::addElementalLoad(ElementalLoad *load, int pattern) +{ + // now add it to the pattern + TaggedObject *thePattern = theLoadPatterns->getComponentPtr(pattern); + if (thePattern == nullptr) { + opserr << "LoadCase::addElementalLoad() - no pattern with tag " << pattern + << "exits in the model, not adding the ele load " << *load << "\n"; + + return false; + } + LoadPattern *theLoadPattern = (LoadPattern *)thePattern; + + bool result = theLoadPattern->addElementalLoad(load); + if (result == false) { + opserr << "LoadCase::addElementalLoad() - no pattern with tag " << + pattern << "in the model, not adding the ele load" << *load << "\n"; + return false; + } + + + // load->setDomain(&domain); // done in LoadPattern::addElementalLoad() + domain.domainChange(); + return result; +} + + + +int +LoadCase::removeSP_Constraint(int theNode, int theDOF, int loadPatternTag) +{ + SP_Constraint *theSP = nullptr; + bool found = false; + int spTag = 0; + + { + LoadPattern *thePattern = this->getLoadPattern(loadPatternTag); + if (thePattern != nullptr) { + SP_ConstraintIter &theSPs = thePattern->getSPs(); + while ((found == false) && ((theSP = theSPs()) != 0)) { + int nodeTag = theSP->getNodeTag(); + int dof = theSP->getDOF_Number(); + if (nodeTag == theNode && dof == theDOF) { + spTag = theSP->getTag(); + found = true; + } + } + } + } + + if (found == true) + theSP = domain.removeSP_Constraint(spTag); + + // mark the domain has having changed regardless if SP constraint + // was there or not + domain.domainChange(); + + if (theSP != nullptr) { + delete theSP; + return 1; + } + + return 0; +} + +LoadPattern * +LoadCase::removeLoadPattern(int tag) +{ + // remove the object from the container + TaggedObject *obj = theLoadPatterns->removeComponent(tag); + + // if not there return nullptr + if (obj == nullptr) + return nullptr; + + // perform a downward cast, set the objects domain pointer to 0 + // and return the result of the cast + LoadPattern *result = (LoadPattern *)obj; + // result->setDomain(0); + + // + // now set the Domain pointer for all loads and SP constraints + // in the loadPattern to be 0 + // + + NodalLoad *theNodalLoad; + NodalLoadIter &theNodalLoads = result->getNodalLoads(); + while ((theNodalLoad = theNodalLoads()) != nullptr) { + // theNodalLoad->setDomain(0); + } + + ElementalLoad *theElementalLoad; + ElementalLoadIter &theElementalLoads = result->getElementalLoads(); + while ((theElementalLoad = theElementalLoads()) != nullptr) { + // theElementalLoad->setDomain(0); + } + + int numSPs = 0; + SP_Constraint *theSP_Constraint; + SP_ConstraintIter &theSP_Constraints = result->getSPs(); + while ((theSP_Constraint = theSP_Constraints()) != nullptr) { + numSPs++; + // theSP_Constraint->setDomain(0); + } + + // mark the domain has having changed if numSPs > 0 + // as the constraint handlers have to be redone + if (numSPs > 0) + domain.domainChange(); + + // finally return the load pattern + return result; +} + + +NodalLoad * +LoadCase::removeNodalLoad(int tag, int loadPattern) +{ + // remove the object from the container + LoadPattern *theLoadPattern = this->getLoadPattern(loadPattern); + + // if not there return 0 + if (theLoadPattern == nullptr) + return nullptr; + + return theLoadPattern->removeNodalLoad(tag); +} + + +ElementalLoad * +LoadCase::removeElementalLoad(int tag, int loadPattern) +{ + // remove the object from the container + LoadPattern *theLoadPattern = this->getLoadPattern(loadPattern); + + // if not there return nullptr + if (theLoadPattern == nullptr) + return nullptr; + + return theLoadPattern->removeElementalLoad(tag); +} + + +SP_Constraint * +LoadCase::removeSP_Constraint(int tag, int loadPattern) +{ + // remove the object from the container + LoadPattern *theLoadPattern = this->getLoadPattern(loadPattern); + + // if not there return 0 + if (theLoadPattern == 0) + return 0; + + SP_Constraint *theSP = theLoadPattern->removeSP_Constraint(tag); + if (theSP != 0) + domain.domainChange(); + + return theSP; +} + + + +LoadCase::PatternIterator & +LoadCase::getLoadPatterns() +{ + theLoadPatternIter->reset(); + return *theLoadPatternIter; +} + + +LoadPattern * +LoadCase::getLoadPattern(int tag) +{ + TaggedObject *mc = theLoadPatterns->getComponentPtr(tag); + // if not there return 0 otherwise perform a cast and return that + if (mc == 0) + return 0; + LoadPattern *result = (LoadPattern *)mc; + return result; +} + + +int +LoadCase::getNumLoadPatterns() const +{ + return theLoadPatterns->getNumComponents(); +} + + + +void +LoadCase::applyLoad(double scale) +{ +#if 0 // CMP: Keep this part in Domain + // set the current pseudo time in the domain to be newTime + currentTime = scale; + dT = currentTime - committedTime; + ops_Dt = dT; + + // + // first zero all loads + // + Node *nodePtr; + NodeIter &theNodeIter = domain.getNodes(); + while ((nodePtr = theNodeIter()) != nullptr) + nodePtr->zeroUnbalancedLoad(); + + Element *elePtr; + ElementIter &theElemIter = domain.getElements(); + while ((elePtr = theElemIter()) != nullptr) + if (elePtr->isSubdomain() == false) + elePtr->zeroLoad(); +#endif + + // + // now loop over load patterns, invoking applyLoad on them + // + LoadPattern *thePattern; + PatternIterator &thePatterns = this->getLoadPatterns(); + while((thePattern = thePatterns()) != nullptr) + thePattern->applyLoad(scale); + +#if 0 // CMP: Keep this part in Domain + // + // finally loop over the MP_Constraints and SP_Constraints + // + + MP_ConstraintIter &theMPs = this->getMPs(); + MP_Constraint *theMP; + while ((theMP = theMPs()) != nullptr) + theMP->applyConstraint(scale); + + SP_ConstraintIter &theSPs = this->getSPs(); + SP_Constraint *theSP; + while ((theSP = theSPs()) != nullptr) + theSP->applyConstraint(scale); +#endif +} + + +void +LoadCase::setLoadConstant() +{ + // loop over all the load patterns that are currently added to the domain + // getting them to set their loads as now constant + LoadPattern *thePattern; + PatternIterator &thePatterns = this->getLoadPatterns(); + while((thePattern = thePatterns()) != nullptr) + thePattern->setLoadConstant(); +} + + +void +LoadCase::unsetLoadConstant() +{ + // loop over all the load patterns that are currently added to the domain + // getting them to set their loads as now constant + LoadPattern *thePattern; + PatternIterator &thePatterns = this->getLoadPatterns(); + while((thePattern = thePatterns()) != nullptr) + thePattern->unsetLoadConstant(); +} + From 45a1a235658c7771896116a2a0af874cc96a806f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 13 Jan 2026 00:52:43 -0800 Subject: [PATCH 030/161] Update CMakeLists.txt --- SRC/domain/pattern/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/domain/pattern/CMakeLists.txt b/SRC/domain/pattern/CMakeLists.txt index e5ffda3a69..691cfe6448 100644 --- a/SRC/domain/pattern/CMakeLists.txt +++ b/SRC/domain/pattern/CMakeLists.txt @@ -8,13 +8,13 @@ target_sources(OPS_Domain PRIVATE EarthquakePattern.cpp LoadPattern.cpp - LoadPatternIter.cpp MultiSupportPattern.cpp UniformExcitation.cpp + LoadCase.cpp + StaticPattern.cpp PUBLIC EarthquakePattern.h LoadPattern.h - LoadPatternIter.h MultiSupportPattern.h UniformExcitation.h ) From 5b2009085c9f161a731887b32b6bb19704bb9971 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:42:15 -0800 Subject: [PATCH 031/161] Create StaticPattern.h --- SRC/domain/pattern/StaticPattern.h | 53 ++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 SRC/domain/pattern/StaticPattern.h diff --git a/SRC/domain/pattern/StaticPattern.h b/SRC/domain/pattern/StaticPattern.h new file mode 100644 index 0000000000..8995e8867f --- /dev/null +++ b/SRC/domain/pattern/StaticPattern.h @@ -0,0 +1,53 @@ +#pragma once +#include + +#include +#include +#include + +class Domain; +class NodalLoad; +class TimeSeries; +class ElementalLoad; +class SP_Constraint; +class NodalLoadIter; +class ElementalLoadIter; +class SingleDomSP_Iter; +class SP_ConstraintIter; +class TaggedObjectStorage; +class GroundMotion; + + +class StaticPattern : public LoadPattern +{ + public: + StaticPattern(int tag, double fact = 1.0); + ~StaticPattern() override; + +#if 0 + LoadPattern *getCopy() override; + bool addSP_Constraint(SP_Constraint *) final; + bool addNodalLoad(NodalLoad *) final; + bool addElementalLoad(ElementalLoad *) final; + NodalLoadIter &getNodalLoads() final; + ElementalLoadIter &getElementalLoads() final; + SP_ConstraintIter &getSPs() final; + // methods to remove loads + NodalLoad *removeNodalLoad(int tag) final; + ElementalLoad *removeElementalLoad(int tag) final; + SP_Constraint *removeSP_Constraint(int tag) final; + void clearAll(); +#endif +private: +#if 0 + // storage objects for the loads and constraints + TaggedObjectStorage *theNodalLoads; + TaggedObjectStorage *theElementalLoads; + TaggedObjectStorage *theSPs; + + // iterator objects for the objects added to the storage objects + NodalLoadIter *theNodIter; + ElementalLoadIter *theEleIter; + SingleDomSP_Iter *theSpIter; +#endif +}; \ No newline at end of file From cc329416acc3cbed6c144ca0629e6c10c0192caa Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:42:20 -0800 Subject: [PATCH 032/161] Create StaticPattern.cpp --- SRC/domain/pattern/StaticPattern.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 SRC/domain/pattern/StaticPattern.cpp diff --git a/SRC/domain/pattern/StaticPattern.cpp b/SRC/domain/pattern/StaticPattern.cpp new file mode 100644 index 0000000000..200cbfb526 --- /dev/null +++ b/SRC/domain/pattern/StaticPattern.cpp @@ -0,0 +1,12 @@ +#include "StaticPattern.h" + +StaticPattern::StaticPattern(int tag, double fact) + :LoadPattern(tag, PATTERN_TAG_StaticPattern, fact) +{ + +} + +StaticPattern::~StaticPattern() +{ +} + From 183e10045087e1b32a5ef7ce07e32405850b74b2 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 13 Jan 2026 10:56:14 -0800 Subject: [PATCH 033/161] Update LoadCase.h --- SRC/domain/pattern/LoadCase.h | 1 + 1 file changed, 1 insertion(+) diff --git a/SRC/domain/pattern/LoadCase.h b/SRC/domain/pattern/LoadCase.h index 5f2053aa57..3e4ee2ed28 100644 --- a/SRC/domain/pattern/LoadCase.h +++ b/SRC/domain/pattern/LoadCase.h @@ -4,6 +4,7 @@ #include #include #include +#include // case { // pattern ... From 7cb343f8b0c7cd9beb47a8053b4e01f3a00ced19 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:36:44 -0800 Subject: [PATCH 034/161] Remove unused iterators and simple model files Eliminated unused #include directives for DOF_GrpIter and FE_EleIter from integrator and numberer source files. Deleted SimpleDOF_Iter and SimpleFE_Iter classes and related files from the simple analysis model, as they are no longer referenced. --- .../integrator/Dynamic/AlphaOS/AlphaOS.cpp | 1 - .../Dynamic/AlphaOS/AlphaOSGeneralized.cpp | 2 - .../integrator/Dynamic/AlphaOS/AlphaOS_TP.cpp | 1 - SRC/analysis/integrator/Dynamic/GS4.cpp | 2 - .../integrator/Dynamic/HHTExplicit.cpp | 2 - SRC/analysis/integrator/Dynamic/Newmark.cpp | 2 - SRC/analysis/integrator/Dynamic/TRBDF2.cpp | 1 - .../integrator/Dynamic/WilsonTheta.cpp | 1 - .../Hybrid/CollocationHSIncrLimit.cpp | 1 - .../Hybrid/CollocationHSIncrReduct.cpp | 1 - .../integrator/Hybrid/HHTHSIncrLimit_TP.cpp | 1 - .../integrator/Hybrid/HHTHSIncrReduct.cpp | 1 - .../integrator/Hybrid/HHTHSIncrReduct_TP.cpp | 1 - .../Hybrid/NewmarkHSFixedNumIter.cpp | 1 - .../integrator/Static/DisplacementControl.cpp | 15 ++-- .../integrator/Static/HarmonicSteadyState.cpp | 2 - .../integrator/Static/MinUnbalDispNorm.cpp | 1 - .../integrator/TransientIntegrator.cpp | 2 - SRC/analysis/model/DOF_GrpIter.cpp | 10 +-- SRC/analysis/model/FE_EleIter.cpp | 18 ++-- SRC/analysis/model/numberer/PlainNumberer.cpp | 2 - SRC/analysis/model/simple/Makefile | 20 ----- SRC/analysis/model/simple/SimpleDOF_Iter.cpp | 85 ------------------- SRC/analysis/model/simple/SimpleDOF_Iter.h | 64 -------------- SRC/analysis/model/simple/SimpleFE_Iter.cpp | 84 ------------------ SRC/analysis/model/simple/SimpleFE_Iter.h | 64 -------------- 26 files changed, 20 insertions(+), 365 deletions(-) delete mode 100644 SRC/analysis/model/simple/Makefile delete mode 100644 SRC/analysis/model/simple/SimpleDOF_Iter.cpp delete mode 100644 SRC/analysis/model/simple/SimpleDOF_Iter.h delete mode 100644 SRC/analysis/model/simple/SimpleFE_Iter.cpp delete mode 100644 SRC/analysis/model/simple/SimpleFE_Iter.h diff --git a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS.cpp b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS.cpp index c10849847a..e40c829d29 100644 --- a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS.cpp +++ b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized.cpp b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized.cpp index c4d96cafc2..acd9afc936 100644 --- a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized.cpp +++ b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOSGeneralized.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS_TP.cpp b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS_TP.cpp index d47534a9a1..7c081f9516 100644 --- a/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS_TP.cpp +++ b/SRC/analysis/integrator/Dynamic/AlphaOS/AlphaOS_TP.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/GS4.cpp b/SRC/analysis/integrator/Dynamic/GS4.cpp index 86402b502c..9644a74959 100644 --- a/SRC/analysis/integrator/Dynamic/GS4.cpp +++ b/SRC/analysis/integrator/Dynamic/GS4.cpp @@ -19,12 +19,10 @@ #include #include #include -#include #include #include #include #include -#include #include // #include // for sensitivity diff --git a/SRC/analysis/integrator/Dynamic/HHTExplicit.cpp b/SRC/analysis/integrator/Dynamic/HHTExplicit.cpp index d825aa08db..dfa00b4117 100644 --- a/SRC/analysis/integrator/Dynamic/HHTExplicit.cpp +++ b/SRC/analysis/integrator/Dynamic/HHTExplicit.cpp @@ -30,12 +30,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/Newmark.cpp b/SRC/analysis/integrator/Dynamic/Newmark.cpp index c77cc3a7c6..a4ba1f7ad5 100644 --- a/SRC/analysis/integrator/Dynamic/Newmark.cpp +++ b/SRC/analysis/integrator/Dynamic/Newmark.cpp @@ -28,12 +28,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Dynamic/TRBDF2.cpp b/SRC/analysis/integrator/Dynamic/TRBDF2.cpp index 9c7aacbeaf..de6bf356ed 100644 --- a/SRC/analysis/integrator/Dynamic/TRBDF2.cpp +++ b/SRC/analysis/integrator/Dynamic/TRBDF2.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include // OPS_ADD_RUNTIME_VPV diff --git a/SRC/analysis/integrator/Dynamic/WilsonTheta.cpp b/SRC/analysis/integrator/Dynamic/WilsonTheta.cpp index a3c85d1b67..32e0df151f 100644 --- a/SRC/analysis/integrator/Dynamic/WilsonTheta.cpp +++ b/SRC/analysis/integrator/Dynamic/WilsonTheta.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/CollocationHSIncrLimit.cpp b/SRC/analysis/integrator/Hybrid/CollocationHSIncrLimit.cpp index 9bd4cd5872..cb236bde80 100644 --- a/SRC/analysis/integrator/Hybrid/CollocationHSIncrLimit.cpp +++ b/SRC/analysis/integrator/Hybrid/CollocationHSIncrLimit.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/CollocationHSIncrReduct.cpp b/SRC/analysis/integrator/Hybrid/CollocationHSIncrReduct.cpp index 33e3bf9192..513082224e 100755 --- a/SRC/analysis/integrator/Hybrid/CollocationHSIncrReduct.cpp +++ b/SRC/analysis/integrator/Hybrid/CollocationHSIncrReduct.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit_TP.cpp b/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit_TP.cpp index 035fda09f1..b04a54f46c 100644 --- a/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit_TP.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSIncrLimit_TP.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp b/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp index 3618ec1d29..024a872b1a 100755 --- a/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct_TP.cpp b/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct_TP.cpp index 4886696fa9..2aa6da4be5 100644 --- a/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct_TP.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct_TP.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Hybrid/NewmarkHSFixedNumIter.cpp b/SRC/analysis/integrator/Hybrid/NewmarkHSFixedNumIter.cpp index 055d061998..9f32ef5103 100755 --- a/SRC/analysis/integrator/Hybrid/NewmarkHSFixedNumIter.cpp +++ b/SRC/analysis/integrator/Hybrid/NewmarkHSFixedNumIter.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Static/DisplacementControl.cpp b/SRC/analysis/integrator/Static/DisplacementControl.cpp index bd5c9f5abd..80d509922b 100644 --- a/SRC/analysis/integrator/Static/DisplacementControl.cpp +++ b/SRC/analysis/integrator/Static/DisplacementControl.cpp @@ -40,13 +40,10 @@ #include #include #include -#include #include #include #include -#include #include -#include #include #include #include @@ -65,7 +62,9 @@ DisplacementControl::DisplacementControl(int node, int dof, theNode(node), theDof(dof), theIncrement(increment), theDomain(domain), theDofID(-1), deltaUhat(0), deltaUbar(0), deltaU(0), deltaUstep(0),dUhatdh(0), - phat(0), deltaLambdaStep(0.0), currentLambda(0.0), dLambdaStepDh(0.0),dUIJdh(0),Dlambdadh(0.0), + phat(0), + dUIJdh(0),Dlambdadh(0.0), + deltaLambdaStep(0.0), currentLambda(0.0), dLambdaStepDh(0.0), specNumIncrStep(numIncr), numIncrLastStep(numIncr), minIncrement(min), maxIncrement(max), // sensitivityFlag(0), @@ -261,9 +260,9 @@ int DisplacementControl::update(const Vector &dU) // update dU and dlambda - (*deltaUstep) += *deltaU; + (*deltaUstep) += *deltaU; deltaLambdaStep += dLambda; - currentLambda += dLambda; + currentLambda += dLambda; // update the model theModel->incrDisp(*deltaU); @@ -368,7 +367,7 @@ DisplacementControl::domainChanged() int numGrads = theDomain->getNumParameters(); if (dLAMBDAdh == 0 || dLAMBDAdh->Size() != (numGrads)) { - if (dLAMBDAdh != 0 ) + if (dLAMBDAdh != nullptr) delete dLAMBDAdh; dLAMBDAdh = new Vector(numGrads); } @@ -393,7 +392,7 @@ DisplacementControl::domainChanged() } if (haveLoad == 0) { - opserr << "WARNING DisplacementControl::domainChanged - zero reference load"; + opserr << "WARNING DisplacementControl: zero reference load\n"; return -1; } diff --git a/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp b/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp index 4ad099752e..1c5879175c 100644 --- a/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp +++ b/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp @@ -34,10 +34,8 @@ #include #include #include -#include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp index 08b60f6b00..f55f2463a3 100644 --- a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp +++ b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/SRC/analysis/integrator/TransientIntegrator.cpp b/SRC/analysis/integrator/TransientIntegrator.cpp index 66a2f67135..00c28b6cdb 100644 --- a/SRC/analysis/integrator/TransientIntegrator.cpp +++ b/SRC/analysis/integrator/TransientIntegrator.cpp @@ -33,8 +33,6 @@ #include #include #include -#include -#include TransientIntegrator::TransientIntegrator(int clasTag) : IncrementalIntegrator(clasTag) diff --git a/SRC/analysis/model/DOF_GrpIter.cpp b/SRC/analysis/model/DOF_GrpIter.cpp index a975a4c81e..c209941509 100644 --- a/SRC/analysis/model/DOF_GrpIter.cpp +++ b/SRC/analysis/model/DOF_GrpIter.cpp @@ -30,8 +30,6 @@ #include -// DOF_GrpIter(SingleDomain &theDomain): -// constructor that takes the model, just the basic iter DOF_GrpIter::DOF_GrpIter(TaggedObjectStorage *theStorage) :myIter(&(theStorage->getComponents())) @@ -47,7 +45,7 @@ DOF_GrpIter::~DOF_GrpIter() void DOF_GrpIter::reset(void) { - myIter->reset(); + myIter->reset(); } @@ -58,10 +56,10 @@ DOF_GrpIter::operator()(void) // if not return 0, indicating we are done TaggedObject *theComponent = (*myIter)(); if (theComponent == 0) - return 0; + return 0; else { - DOF_Group *result = (DOF_Group *)theComponent; - return result; + DOF_Group *result = (DOF_Group *)theComponent; + return result; } } diff --git a/SRC/analysis/model/FE_EleIter.cpp b/SRC/analysis/model/FE_EleIter.cpp index 998e49b213..0d0236450b 100644 --- a/SRC/analysis/model/FE_EleIter.cpp +++ b/SRC/analysis/model/FE_EleIter.cpp @@ -54,15 +54,15 @@ FE_EleIter::reset() FE_Element * FE_EleIter::operator()() { - // check if we still have elements in the model - // if not return 0, indicating we are done - TaggedObject *theComponent = (*myIter)(); - if (theComponent == 0) - return 0; - else { - FE_Element *result = (FE_Element *)theComponent; - return result; - } + // check if we still have elements in the model + // if not return 0, indicating we are done + TaggedObject *theComponent = (*myIter)(); + if (theComponent == nullptr) + return 0; + else { + FE_Element *result = (FE_Element *)theComponent; + return result; + } } diff --git a/SRC/analysis/model/numberer/PlainNumberer.cpp b/SRC/analysis/model/numberer/PlainNumberer.cpp index 111a5d3648..222c827ab7 100644 --- a/SRC/analysis/model/numberer/PlainNumberer.cpp +++ b/SRC/analysis/model/numberer/PlainNumberer.cpp @@ -36,9 +36,7 @@ #include #include -#include #include -#include #include #include #include diff --git a/SRC/analysis/model/simple/Makefile b/SRC/analysis/model/simple/Makefile deleted file mode 100644 index d6adddda65..0000000000 --- a/SRC/analysis/model/simple/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../../../../Makefile.def - -OBJS = - -# Compilation control - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/analysis/model/simple/SimpleDOF_Iter.cpp b/SRC/analysis/model/simple/SimpleDOF_Iter.cpp deleted file mode 100644 index 8b02359c88..0000000000 --- a/SRC/analysis/model/simple/SimpleDOF_Iter.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:17 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/model/simple/SimpleDOF_Iter.cpp,v $ - - -// File: ~/analysis/model/simple/SimpleDOF_Iter.C -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the method definitions for class -// SimpleDOF_Iter. SimpleDOF_Iter is a class for iterating through the -// DOF_Groups of an simple analysis model. - -#include "SimpleDOF_Iter.h" -#include "AnalysisModel.h" - - -// SimpleDOF_Iter(AnalysisModel *theModel): -// constructor that takes the model, just the basic iter - -SimpleDOF_Iter::SimpleDOF_Iter(AnalysisModel &theModel) - :myModel(theModel), currIndex(0), numDone(0) -{ -} - - -SimpleDOF_Iter::~SimpleDOF_Iter() -{ -} - -void -SimpleDOF_Iter::reset(void) -{ - currIndex = 0; - numDone = 0; -} - - -DOF_Group * -SimpleDOF_Iter::operator()(void) -{ - // check if we still have elements in the model - // if not return 0, indicating we are done - - if (numDone >= myModel.numDOF_Grp) - return 0; - - // search through domains ele list till we find the next element - while ((currIndex < myModel.sizeDOF) - && (myModel.theDOFs[currIndex] == 0)) - currIndex++; - - // if not at the end of the list return the element - if (currIndex < myModel.sizeDOF) { - DOF_Group *result = myModel.theDOFs[currIndex]; - numDone++; currIndex++; - return(result); - } - return (0); -} - - - diff --git a/SRC/analysis/model/simple/SimpleDOF_Iter.h b/SRC/analysis/model/simple/SimpleDOF_Iter.h deleted file mode 100644 index 70f3d74b41..0000000000 --- a/SRC/analysis/model/simple/SimpleDOF_Iter.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:17 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/model/simple/SimpleDOF_Iter.h,v $ - - -// File: ~/analysis/model/simple/SimpleDOF_Iter.h -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the class definition for SimpleDOF_Iter. -// SimpleDOF_Iter is an iter for returning the DOF_Groups of an object of class -// SimpleAnalysisModel. SimpleDOF_Iters must be written for each subclass of -// SimpleAnalusisModel, wherin the elements are stored differently. - -#ifndef SimpleDOF_Iter_h -#define SimpleDOF_Iter_h - -#include - -class AnalysisModel; - -class SimpleDOF_Iter: public DOF_GrpIter -{ - public: - SimpleDOF_Iter(AnalysisModel &theModel); - virtual ~SimpleDOF_Iter(); - - virtual void reset(void); - virtual DOF_Group *operator()(void); - - private: - AnalysisModel &myModel; - int currIndex; - int numDone; -}; - -#endif - - - - - diff --git a/SRC/analysis/model/simple/SimpleFE_Iter.cpp b/SRC/analysis/model/simple/SimpleFE_Iter.cpp deleted file mode 100644 index cb9f3180ed..0000000000 --- a/SRC/analysis/model/simple/SimpleFE_Iter.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:17 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/model/simple/SimpleFE_Iter.cpp,v $ - - -// File: ~/analysis/model/simple/SimpleFE_Iter.C -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the method definitions for class -// SimpleFE_Iter. SimpleFE_Iter is a class for iterating through the -// elements of an analysis model. - - -#include -#include - - -// SimpleFE_Iter(AnalysisModel &theModel): -// constructor that takes the model, just the basic iter - -SimpleFE_Iter::SimpleFE_Iter(AnalysisModel &theModel) - :myModel(theModel), currIndex(0), numDone(0) -{ -} - - -SimpleFE_Iter::~SimpleFE_Iter() -{ -} - -void -SimpleFE_Iter::reset(void) -{ - currIndex = 0; - numDone = 0; -} - -FE_Element * -SimpleFE_Iter::operator()(void) -{ - // check if we still have elements in the model - // if not return 0, indicating we are done - if (numDone >= myModel.numFE_Ele) - return 0; - - // search through domains ele list till we find the next element - while ((currIndex < myModel.sizeEle) - && (myModel.theFEs[currIndex] == 0)) - currIndex++; - - // if not at the end of the list return the element - if (currIndex < myModel.sizeEle) { - FE_Element *result = myModel.theFEs[currIndex]; - numDone++; currIndex++; - return(result); - } - return (0); -} - - - diff --git a/SRC/analysis/model/simple/SimpleFE_Iter.h b/SRC/analysis/model/simple/SimpleFE_Iter.h deleted file mode 100644 index e597507196..0000000000 --- a/SRC/analysis/model/simple/SimpleFE_Iter.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ - -// $Revision: 1.1.1.1 $ -// $Date: 2000-09-15 08:23:17 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/model/simple/SimpleFE_Iter.h,v $ - - -// File: ~/analysis/model/simple/SimpleFE_Iter.h -// -// Written: fmk -// Created: Fri Sep 20 15:27:47: 1996 -// Revision: A -// -// Description: This file contains the class definition for SimpleFE_Iter. -// SimpleFE_Iter is an iter for returning the elements of an object of class -// AnalysisModel. SimpleFE_Iters must be written for each subclass of -// SimpleAnalusis, wherin the elements are stored differently. - -#ifndef SimpleFE_Iter_h -#define SimpleFE_Iter_h - -#include - -class AnalysisModel; - -class SimpleFE_Iter: public FE_EleIter -{ - public: - SimpleFE_Iter(AnalysisModel &theModel); - virtual ~SimpleFE_Iter(); - - virtual void reset(void); - virtual FE_Element *operator()(void); - - private: - AnalysisModel &myModel; - int currIndex; - int numDone; -}; - -#endif - - - - - From d1cce6b3eaa96a20b9f1f007b9dd89a73adfca73 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:38:28 -0800 Subject: [PATCH 035/161] Refactor LoadControl argument parsing logic Replaces positional argument parsing in G3Parse_newLoadControl with ArgumentTracker and support for named options (-step, -iter, -min_step, -max_step). --- SRC/runtime/commands/analysis/integrator.cpp | 144 +++++++++++++++++-- 1 file changed, 132 insertions(+), 12 deletions(-) diff --git a/SRC/runtime/commands/analysis/integrator.cpp b/SRC/runtime/commands/analysis/integrator.cpp index a4dc41c9c9..1a3279e67c 100644 --- a/SRC/runtime/commands/analysis/integrator.cpp +++ b/SRC/runtime/commands/analysis/integrator.cpp @@ -22,6 +22,8 @@ #include #include #include "BasicAnalysisBuilder.h" +#include +#include // integrators #include @@ -259,6 +261,18 @@ G3Parse_newHSIntegrator(ClientData clientData, Tcl_Interp *interp, int argc, con int G3Parse_newLoadControl(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]) { + BasicAnalysisBuilder *builder = static_cast(clientData); + enum class Position: int { + StepSize, + EndRequired, + IterationTarget, + MinStepSize, + MaxStepSize, + End + }; + ArgumentTracker tracker; + std::set positional; + double dLambda; double minIncr, maxIncr; int numIter; @@ -267,25 +281,131 @@ G3Parse_newLoadControl(ClientData clientData, Tcl_Interp *interp, int argc, cons "dlamMin dlamMax>\n"; return TCL_ERROR;; } - if (Tcl_GetDouble(interp, argv[2], &dLambda) != TCL_OK) - return TCL_ERROR;; - if (argc > 5) { - if (Tcl_GetInt(interp, argv[3], &numIter) != TCL_OK) - return TCL_ERROR;; - if (Tcl_GetDouble(interp, argv[4], &minIncr) != TCL_OK) - return TCL_ERROR;; - if (Tcl_GetDouble(interp, argv[5], &maxIncr) != TCL_OK) - return TCL_ERROR;; - } else { + for (int i=2; i= argc) { + opserr << OpenSees::PromptValueError + << "parameter missing for -step" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (Tcl_GetDouble(interp, argv[i+1], &dLambda) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid -step value" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + i++; + tracker.consume(Position::StepSize); + } + else if (strcmp(argv[i], "-iter") == 0) { + if (i + 1 >= argc) { + opserr << OpenSees::PromptValueError + << "parameter missing for -iter" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (Tcl_GetInt(interp, argv[i+1], &numIter) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid -iter value" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + i++; + tracker.consume(Position::IterationTarget); + } + else if (strcmp(argv[i], "-min_step") == 0) { + if (i + 1 >= argc) { + opserr << OpenSees::PromptValueError + << "parameter missing for -min_step" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (Tcl_GetDouble(interp, argv[i+1], &minIncr) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid -min value" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + i++; + tracker.consume(Position::MinStepSize); + } + else if (strcmp(argv[i], "-max_step") == 0) { + if (i + 1 >= argc) { + opserr << OpenSees::PromptValueError + << "parameter missing for -max_step" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (Tcl_GetDouble(interp, argv[i+1], &maxIncr) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid -max_step value" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + i++; + tracker.consume(Position::MaxStepSize); + } + else { + positional.insert(i); + } + } + + for (int i: positional) { + if (tracker.current() == Position::EndRequired) + tracker.increment(); + + switch (tracker.current()) { + case Position::StepSize: + if (Tcl_GetDouble(interp, argv[i], &dLambda) != TCL_OK) + return TCL_ERROR; + break; + case Position::IterationTarget: + if (Tcl_GetInt(interp, argv[i], &numIter) != TCL_OK) + return TCL_ERROR; + break; + case Position::MinStepSize: + if (Tcl_GetDouble(interp, argv[i], &minIncr) != TCL_OK) + return TCL_ERROR; + break; + case Position::MaxStepSize: + if (Tcl_GetDouble(interp, argv[i], &maxIncr) != TCL_OK) + return TCL_ERROR; + break; + case Position::EndRequired: + // This shouldnt be reached; only here to silence compiler. + break; + case Position::End: + opserr << OpenSees::PromptValueError + << "unexpected parameter: " << argv[i] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + tracker.increment(); + } + + if (tracker.current() < Position::EndRequired) { + opserr << OpenSees::PromptValueError + << "missing required parameters for LoadControl integrator" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (tracker.contains(Position::MinStepSize)) minIncr = dLambda; + if (tracker.contains(Position::MaxStepSize)) maxIncr = dLambda; + if (tracker.contains(Position::IterationTarget)) numIter = 1; - } + StaticIntegrator *theStaticIntegrator = new LoadControl(dLambda, numIter, minIncr, maxIncr); - BasicAnalysisBuilder *builder = static_cast(clientData); builder->set(*theStaticIntegrator); return TCL_OK; From 482279ed10f7798ae79a47746a322deb62f1f28f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:39:42 -0800 Subject: [PATCH 036/161] Update plane.cpp --- SRC/runtime/commands/modeling/element/plane.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/runtime/commands/modeling/element/plane.cpp b/SRC/runtime/commands/modeling/element/plane.cpp index 2f3da0b800..d42f618a81 100644 --- a/SRC/runtime/commands/modeling/element/plane.cpp +++ b/SRC/runtime/commands/modeling/element/plane.cpp @@ -122,13 +122,13 @@ TclBasicBuilder_addFourNodeQuad(ClientData clientData, Tcl_Interp *interp, Tcl_S if (argc < 6) { opserr << OpenSees::PromptValueError << "insufficient arguments for element " << argv[1] - << "\n"; + << OpenSees::SignalMessageEnd; return TCL_ERROR; } if (Tcl_GetInt(interp, argv[2], &tag) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid element tag " << argv[2] - << "\n"; + << OpenSees::SignalMessageEnd; return TCL_ERROR; } int nen = -1; From f8571b69de6a580ef8fc723bc2e298101183d23d Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:40:28 -0800 Subject: [PATCH 037/161] Update Field.h --- SRC/Field.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/SRC/Field.h b/SRC/Field.h index a56bf2b03f..41354403ae 100644 --- a/SRC/Field.h +++ b/SRC/Field.h @@ -17,11 +17,6 @@ enum class Field { DensityZZ, DensityXY, DensityXZ, - DensityCentroidXX, - DensityCentroidYY, - DensityCentroidZZ, - DensityCentroidXY, - DensityCentroidXZ, PolarInertia, // NOTE: not J0; this includes density From eb56d7909361c20e9745d5268f604dbe59067ae5 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:40:56 -0800 Subject: [PATCH 038/161] Update LoadPattern.h --- SRC/domain/pattern/LoadPattern.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/domain/pattern/LoadPattern.h b/SRC/domain/pattern/LoadPattern.h index 44df7d4ff5..f20dbd0e6f 100644 --- a/SRC/domain/pattern/LoadPattern.h +++ b/SRC/domain/pattern/LoadPattern.h @@ -126,12 +126,12 @@ class LoadPattern : public TaggedObject, public MovableObject // storage objects for the loads and constraints TaggedObjectStorage *theNodalLoads; TaggedObjectStorage *theElementalLoads; - TaggedObjectStorage *theSPs; + TaggedObjectStorage *theSPs; // iterator objects for the objects added to the storage objects NodalLoadIter *theNodIter; ElementalLoadIter *theEleIter; - SingleDomSP_Iter *theSpIter; + SingleDomSP_Iter *theSpIter; // Vector *randomLoads; From 1303dce4617a8ab64785adee46054cc9abbbaec2 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:41:09 -0800 Subject: [PATCH 039/161] Update EulerFrame3d.cpp --- SRC/element/Frame/EulerFrame3d.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/SRC/element/Frame/EulerFrame3d.cpp b/SRC/element/Frame/EulerFrame3d.cpp index 3dfca99662..76068839eb 100644 --- a/SRC/element/Frame/EulerFrame3d.cpp +++ b/SRC/element/Frame/EulerFrame3d.cpp @@ -976,18 +976,18 @@ EulerFrame3d::getBasicForceGrad(int gradNumber) for (int j = 0; j < nsr; j++) { double sensi = ds[j]*wti; switch(scheme[j]) { - case SECTION_RESPONSE_P: + case FrameStress::N: dqdh(0) += sensi; break; - case SECTION_RESPONSE_MZ: + case FrameStress::Mz: dqdh(1) += (xi6-4.0)*sensi; dqdh(2) += (xi6-2.0)*sensi; break; - case SECTION_RESPONSE_MY: + case FrameStress::My: dqdh(3) += (xi6-4.0)*sensi; dqdh(4) += (xi6-2.0)*sensi; break; - case SECTION_RESPONSE_T: + case FrameStress::T: dqdh(5) += sensi; break; default: @@ -1072,18 +1072,18 @@ EulerFrame3d::commitSensitivity(int gradNumber, int numGrads) for (int j = 0; j < nsr; j++) { switch(scheme[j]) { - case SECTION_RESPONSE_P: + case FrameStress::N: e[j] = jsx*dvdh(0) + d1oLdh*v(0); break; - case SECTION_RESPONSE_MZ: + case FrameStress::Mz: e[j] = jsx*((xi6-4.0)*dvdh(1) + (xi6-2.0)*dvdh(2)) + d1oLdh*((xi6-4.0)*v(1) + (xi6-2.0)*v(2)); break; - case SECTION_RESPONSE_MY: + case FrameStress::My: e[j] = jsx*((xi6-4.0)*dvdh(3) + (xi6-2.0)*dvdh(4)) + d1oLdh*((xi6-4.0)*v(3) + (xi6-2.0)*v(4)); break; - case SECTION_RESPONSE_T: + case FrameStress::T: e[j] = jsx*dvdh(5) + d1oLdh*v(5); break; From 647a14d12fd1cb6de9ede8873e133d96aafaa222 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:42:34 -0800 Subject: [PATCH 040/161] Update linalg.hh --- SRC/runtime/commands/utilities/linalg.hh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/SRC/runtime/commands/utilities/linalg.hh b/SRC/runtime/commands/utilities/linalg.hh index 5674718228..413ebc8d95 100644 --- a/SRC/runtime/commands/utilities/linalg.hh +++ b/SRC/runtime/commands/utilities/linalg.hh @@ -21,23 +21,23 @@ proc verify {cmd {value ""} {reference ""} {tolerance 1e-12} {about ""}} { if {$cmd == "error"} { set check [expr abs(($value - $reference)/$reference)] if {$check > $tolerance} { - puts " \033\[31mFAIL\033\[0m: | $value - $reference | = $check > $tolerance" - error "$about" + puts " \033\[31mFAIL\033\[0m: | $value - $reference | = $check > $tolerance" + error "$about" } else { - puts " \033\[32mPASS\033\[0m "; # " $value $reference $about" + puts " \033\[32mPASS\033\[0m $value $check $about" } } elseif {$cmd == "value"} { - if {abs($value - $reference) > $tolerance} { set check [expr abs($value - $reference)] - puts " \033\[31mFAIL\033\[0m($about): | $value - $reference | = $check > $tolerance" - error "$about" + if {abs($value - $reference) > $tolerance} { + puts " \033\[31mFAIL\033\[0m($about): | $value - $reference | = $check > $tolerance" + error "$about" } else { - puts " \033\[32mPASS\033\[0m "; # "$value $reference $about" + puts " \033\[32mPASS\033\[0m $value $check $about" } } else { - # value or "about" - puts " $value" + # "about" + puts " $value" } } From 9b1b98fd359ebd8fdc0ee0778281244efb06deb8 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 00:45:34 -0800 Subject: [PATCH 041/161] Update frames.cpp --- .../commands/modeling/element/frames.cpp | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/SRC/runtime/commands/modeling/element/frames.cpp b/SRC/runtime/commands/modeling/element/frames.cpp index 51e004fec3..54f6a315d0 100644 --- a/SRC/runtime/commands/modeling/element/frames.cpp +++ b/SRC/runtime/commands/modeling/element/frames.cpp @@ -35,6 +35,16 @@ #endif #define strcmp strcasecmp +// Maximum number of integration points. +// Large values can noticeably impact compile time. +#ifdef _DEBUG + #define MAX_NIP 8 +#elif defined(XARA_RELEASE) + #define MAX_NIP 30 +#else + #define MAX_NIP 15 +#endif + // Parsing #include #include @@ -303,8 +313,14 @@ CreateFrame(ModelRegistry& builder, else if ((strstr(name, "Force") != 0) || (strcmp(name, "MixedFrame") == 0)) { if (strcmp(name, "ForceDeltaFrame") == 0 || options.geom_flag) { + if (sections.size() > MAX_NIP) { + opserr << OpenSees::PromptValueError + << "too many sections for ForceDeltaFrame3d: " << static_cast(sections.size()) + << OpenSees::SignalMessageEnd; + return nullptr; + } if (!options.shear_flag) - static_loop<2,6>([&](auto nip) constexpr { + static_loop<2,MAX_NIP>([&](auto nip) constexpr { if (nip.value == sections.size()) theElement = new ForceDeltaFrame3d(tag, nodes, sections, beamIntegr, *tb, @@ -316,7 +332,7 @@ CreateFrame(ModelRegistry& builder, ); }); else - static_loop<2,6>([&](auto nip) constexpr { + static_loop<2,MAX_NIP>([&](auto nip) constexpr { if (nip.value == sections.size()) theElement = new ForceDeltaFrame3d(tag, nodes, sections, beamIntegr, *tb, @@ -329,7 +345,7 @@ CreateFrame(ModelRegistry& builder, }); } else { int ndf = builder.getNDF(); - if (sections.size() > 30) { + if (sections.size() > MAX_NIP) { opserr << OpenSees::PromptValueError << "too many sections for ForceFrame3d: " << static_cast(sections.size()) << OpenSees::SignalMessageEnd; @@ -338,7 +354,7 @@ CreateFrame(ModelRegistry& builder, static_loop<0, 3>([&](auto nwm) constexpr { if (nwm.value + 6 == ndf) { if (!options.shear_flag) { - static_loop<2,30>([&](auto nip) constexpr { + static_loop<2,MAX_NIP>([&](auto nip) constexpr { if (nip.value == sections.size()) theElement = new ForceFrame3d(tag, nodes, @@ -350,7 +366,7 @@ CreateFrame(ModelRegistry& builder, }); } else { - static_loop<2,30>([&](auto nip) constexpr { + static_loop<2,MAX_NIP>([&](auto nip) constexpr { if (nip.value == sections.size()) theElement = new ForceFrame3d(tag, nodes, From 229c0489d5fed7f3406be5a834991589bea193bb Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:51:15 -0800 Subject: [PATCH 042/161] Remove redundant semicolons after return statements Cleaned up unnecessary double semicolons following return statements in integrator.cpp. --- SRC/runtime/commands/analysis/integrator.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SRC/runtime/commands/analysis/integrator.cpp b/SRC/runtime/commands/analysis/integrator.cpp index 1a3279e67c..51821ea7d2 100644 --- a/SRC/runtime/commands/analysis/integrator.cpp +++ b/SRC/runtime/commands/analysis/integrator.cpp @@ -219,17 +219,17 @@ G3Parse_newHSIntegrator(ClientData clientData, Tcl_Interp *interp, int argc, con if (argc < 3) { opserr << "WARNING integrator HSConstraint " " \n"; - return TCL_ERROR;; + return TCL_ERROR; } if (argc >= 3 && Tcl_GetDouble(interp, argv[2], &arcLength) != TCL_OK) - return TCL_ERROR;; + return TCL_ERROR; if (argc >= 4 && Tcl_GetDouble(interp, argv[3], &psi_u) != TCL_OK) - return TCL_ERROR;; + return TCL_ERROR; if (argc >= 5 && Tcl_GetDouble(interp, argv[4], &psi_f) != TCL_OK) - return TCL_ERROR;; + return TCL_ERROR; if (argc == 6 && Tcl_GetDouble(interp, argv[5], &u_ref) != TCL_OK) - return TCL_ERROR;; + return TCL_ERROR; // Create the integrator StaticIntegrator* theStaticIntegrator = nullptr; @@ -279,7 +279,7 @@ G3Parse_newLoadControl(ClientData clientData, Tcl_Interp *interp, int argc, cons if (argc < 3) { opserr << "WARNING incorrect # args - integrator LoadControl dlam \n"; - return TCL_ERROR;; + return TCL_ERROR; } for (int i=2; i Date: Fri, 16 Jan 2026 14:51:39 -0800 Subject: [PATCH 043/161] Update FrameTransformBuilder.hpp --- .../transform/FrameTransformBuilder.hpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp index d44355a5e5..5e6a29856b 100644 --- a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp +++ b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp @@ -39,7 +39,6 @@ class FrameTransformBuilder : public TaggedObject { : ndm(ndm), TaggedObject(t), vz{{0, 0, 0}}, offsets{}, offset_flags(0) { - // strncpy(name, n, 128); snprintf(name, sizeof(name), "%s", n); // offset_flags |= LogIter; } @@ -73,7 +72,7 @@ class FrameTransformBuilder : public TaggedObject { if constexpr (ndf == 6) return new SouzaFrameTransf (tag, vz, offset_array, offset_flags); else - return nullptr; + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); } else if (strstr(name, "PDelta") != nullptr) @@ -91,17 +90,14 @@ class FrameTransformBuilder : public TaggedObject { return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); } else if (strcmp(name, "Corotational03") == 0) - { - if (getenv("Crisfield02")) - return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); - - return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); - } + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); else if (strcmp(name, "Corotational04") == 0) - { - return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); - } + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); + + else if (strcmp(name, "Corotational05") == 0) + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); + return nullptr; } From a37cda2f2bc961780f4623a5c90c5cd25e0adf0a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:52:30 -0800 Subject: [PATCH 044/161] Update ArrayOfTaggedObjects.cpp --- SRC/tagged/storage/ArrayOfTaggedObjects.cpp | 403 ++++++++++---------- 1 file changed, 197 insertions(+), 206 deletions(-) diff --git a/SRC/tagged/storage/ArrayOfTaggedObjects.cpp b/SRC/tagged/storage/ArrayOfTaggedObjects.cpp index 35295db529..39af9f7e40 100644 --- a/SRC/tagged/storage/ArrayOfTaggedObjects.cpp +++ b/SRC/tagged/storage/ArrayOfTaggedObjects.cpp @@ -44,18 +44,14 @@ ArrayOfTaggedObjects::ArrayOfTaggedObjects(int size) positionLastNoFitEntry(0),fitFlag(true), theComponents(0), myIter(*this) { - // get the components array from the heap - theComponents = new TaggedObject *[size]; - - // check we obtained enough memory and set the array size - if (theComponents == 0) { - opserr << "ArrayOfTaggedObjects::ArrayOfTaggedObjects - failed to allocate an array of size " << size << endln; - } else + // get the components array from the heap + theComponents = new TaggedObject *[size]; + sizeComponentArray = size; - // 0 the array - for (int i=0; i sizeComponentArray) { - opserr << "ArrayOfTaggedObjects::setSize - invalid size " << newSize << endln; - return -1; - } - - if (newSize < 2) newSize = 2; // make 2 the min size; - - // get an array of pointers from the heap - // NOTE: cannot use TaggedObject **newArray = new (TaggedObject *)[newSize]; - // with digital cxx compiler!!!! - TaggedObject **newArray = new TaggedObject *[newSize]; - - if (newArray == 0) { - // cannot increase size to newSize, keep as is and return error - opserr << "ArrayOfTaggedObjects::setSize - failed to allocate an array of size " << newSize << endln; - return -2; - } - - // - // we got the space we needed .. now we populate the new array - // trying to put everything in nicely, i.e. in location given by obj tags. - // + // check a valid size + if (newSize < 0 && newSize > sizeComponentArray) { + opserr << "ArrayOfTaggedObjects::setSize - invalid size " << newSize << endln; + return -1; + } + + if (newSize < 2) + newSize = 2; // make 2 the min size; + + // get an array of pointers from the heap + // NOTE: cannot use TaggedObject **newArray = new (TaggedObject *)[newSize]; + // with digital cxx compiler!!!! + TaggedObject **newArray = new TaggedObject *[newSize]; + + // + // we got the space we needed .. now we populate the new array + // trying to put everything in nicely, i.e. in location given by obj tags. + // + + // first zero the new array + for (int i=0; iaddComponent(oldArray[j]) == false) { - // this should never happen - but in case it does - opserr << "SERIOUS ERROR: ArrayOfTaggedObjects::setSize() - we have lost a component with tag: " << - oldArray[j]->getTag() << endln; - error = -3; - } - } + sizeComponentArray = newSize; + for (int i=0; i<=positionLastEntry; i++) + theComponents[i] = oldArray[i]; + } + else { + // we will see if the components fit in well this time + + // reset the parameters for the new array + numComponents = 0; + sizeComponentArray = newSize; + positionLastEntry = 0; + positionLastNoFitEntry = 0; + fitFlag = true; + + // now add all the componets of the old array into the new one + // we add using addComponent() to see if false fitFlag will now be true + for (int j=0; j<=oldArrayLastEntry; j++) + if (oldArray[j] != 0) + if (this->addComponent(oldArray[j]) == false) { + // this should never happen - but in case it does + opserr << "SERIOUS ERROR: ArrayOfTaggedObjects::setSize() - we have lost a component with tag: " << + oldArray[j]->getTag() << endln; + error = -3; + } + } - // delete the old array - if (oldArray != 0) - delete [] oldArray; - - return error; + // delete the old array + if (oldArray != 0) + delete [] oldArray; + + return error; } bool ArrayOfTaggedObjects::addComponent(TaggedObject *newComponent) { - // check to see that no other component already exists + // check to see that no other component already exists // if (allowMultiple == false) { - TaggedObject *other = this->getComponentPtr(newComponent->getTag()); - if (other != 0) { - opserr << "WARNING ArrayOfTaggedObjects::addComponent() - component" << - " with tag already exists, not adding component with tag: " << - newComponent->getTag() << endln; - return false; - } -// } - - // check to see if size of current array is big enough. if not resize. - if (numComponents == sizeComponentArray) - if (this->setSize(2*numComponents) < 0) { - opserr << "ArrayOfTaggedObjects::addComponent()- failed to enlarge the array with size" << - 2*numComponents << endln; - return false; - } - - // we try to the Component in nicely, i.e. in - // position given by the newComponents Tag - - int newComponentTag = newComponent->getTag(); - - if ((newComponentTag >= 0) && (newComponentTag < sizeComponentArray)) { - if (theComponents[newComponentTag] == 0) { // it will go in nicely - theComponents[newComponentTag] = newComponent; - numComponents ++; - if (newComponentTag > positionLastEntry) - positionLastEntry = newComponentTag; - return true; - } + TaggedObject *other = this->getComponentPtr(newComponent->getTag()); + if (other != 0) { + opserr << "WARNING ArrayOfTaggedObjects::addComponent() - component" << + " with tag already exists, not adding component with tag: " << + newComponent->getTag() << endln; + return false; + } +// } + + // check to see if size of current array is big enough. if not resize. + if (numComponents == sizeComponentArray) + if (this->setSize(2*numComponents) < 0) { + opserr << "ArrayOfTaggedObjects::addComponent()- failed to enlarge the array with size" << + 2*numComponents << endln; + return false; } + + // we try to the Component in nicely, i.e. in + // position given by the newComponents Tag + + int newComponentTag = newComponent->getTag(); + + if ((newComponentTag >= 0) && (newComponentTag < sizeComponentArray)) { + if (theComponents[newComponentTag] == 0) { // it will go in nicely + theComponents[newComponentTag] = newComponent; + numComponents ++; + if (newComponentTag > positionLastEntry) + positionLastEntry = newComponentTag; + return true; + } + } - // it won't go in nicely, so put wherever we can get it in - while (theComponents[positionLastNoFitEntry] != 0 && - positionLastNoFitEntry < sizeComponentArray ) - positionLastNoFitEntry++; + // it won't go in nicely, so put wherever we can get it in + while (theComponents[positionLastNoFitEntry] != 0 && + positionLastNoFitEntry < sizeComponentArray ) + positionLastNoFitEntry++; - // just in case we don't get a location .. though we should!! - if (positionLastNoFitEntry == sizeComponentArray) { - opserr << "ArrayOfTaggedObjects::addComponent() - could not - find a vacant spot after enlarging!!\n"; - return false; - } - - theComponents[positionLastNoFitEntry] = newComponent; - numComponents++; - if (positionLastNoFitEntry > positionLastEntry) - positionLastEntry = positionLastNoFitEntry; - fitFlag = false; - - return true; // o.k. + // just in case we don't get a location.. though we should!! + if (positionLastNoFitEntry == sizeComponentArray) { + opserr << "ArrayOfTaggedObjects::addComponent() - could not - find a vacant spot after enlarging!!\n"; + return false; + } + + theComponents[positionLastNoFitEntry] = newComponent; + numComponents++; + if (positionLastNoFitEntry > positionLastEntry) + positionLastEntry = positionLastNoFitEntry; + fitFlag = false; + + return true; // o.k. } + TaggedObject * ArrayOfTaggedObjects::removeComponent(int tag) { - TaggedObject *removed; + TaggedObject *removed; + + // first check to see if object is located at pos given by tag + if ((tag >= 0) && (tag < sizeComponentArray)) { + // if all objects in nicely then has to be at location given by tag + if (fitFlag == true) { + removed = theComponents[tag]; + theComponents[tag] = 0; + + // if the object is there decrement numComponents added and + // check if need to reset positionLastEntry marker + if (removed != 0) { + numComponents--; + + if (positionLastEntry == tag) { + for (int i = positionLastEntry; i>=0; i--) + if (theComponents[i] != 0) { + positionLastEntry = i; + i = -1; // break out of loop + } + } + } + return removed; + } + else // it still may be at nice location so do as above + if (theComponents[tag] != 0) + if ((theComponents[tag]->getTag()) == tag) { + removed = theComponents[tag]; + theComponents[tag] = 0; + if (positionLastEntry == tag) { + for (int i = positionLastEntry; i>=0; i--) + if (theComponents[i] != 0) { + positionLastEntry = i; + i = -1; // break out of loop + } + } + positionLastNoFitEntry = 0; + numComponents--; + return removed; + } + } + + // else we have to look through array until we find it or + // reach lastPosition used + for (int i=0; i<=positionLastEntry; i++) + if (theComponents[i] != 0) + if (theComponents[i]->getTag() == tag) { - // first check to see if object is located at pos given by tag - if ((tag >= 0) && (tag < sizeComponentArray)) { - - // if all objects in nicely then has to be at location given by tag - if (fitFlag == true) { - removed = theComponents[tag]; - theComponents[tag] = 0; - - // if the object is there decrement numComponents added and - // check if need to reset positionLastEntry marker - if (removed != 0) { - numComponents--; - - if (positionLastEntry == tag) { - for (int i = positionLastEntry; i>=0; i--) - if (theComponents[i] != 0) { - positionLastEntry = i; - i = -1; // break out of loop - } - } - } - return removed; - } else // it still may be at nice location so do as above - if (theComponents[tag] != 0) - if ((theComponents[tag]->getTag()) == tag) { - removed = theComponents[tag]; - theComponents[tag] = 0; - if (positionLastEntry == tag) { - for (int i = positionLastEntry; i>=0; i--) - if (theComponents[i] != 0) { - positionLastEntry = i; - i = -1; // break out of loop - } - } - positionLastNoFitEntry = 0; - numComponents--; - return removed; - } - } + // we found the component so do as above again + // and then return a pointer to the component + removed = theComponents[i]; + theComponents[i] = 0; + if (positionLastEntry == i) { + for (int j = positionLastEntry; j>=0; j--) + if (theComponents[j] != 0) { + positionLastEntry = j; + j = -1; // break out of loop + } + } + positionLastNoFitEntry = 0; + numComponents--; + return removed; + } - // else we have to look through array until we find it or - // reach lastPosition used - for (int i=0; i<=positionLastEntry; i++) - if (theComponents[i] != 0) - if (theComponents[i]->getTag() == tag) { - - // we found the component so do as above again - // and then return a pointer to the component - removed = theComponents[i]; - theComponents[i] = 0; - if (positionLastEntry == i) { - for (int j = positionLastEntry; j>=0; j--) - if (theComponents[j] != 0) { - positionLastEntry = j; - j = -1; // break out of loop - } - } - positionLastNoFitEntry = 0; - numComponents--; - return removed; - } - - // if get here the object is not stored in the array - return 0; + // if get here the object is not stored in the array + return 0; } int @@ -297,9 +290,9 @@ ArrayOfTaggedObjects::getComponentPtr(int tag) // else we have to look through array until we find it or // reach lastPosition used for (int i=0; i<=positionLastEntry; i++) - if (theComponents[i] != 0) - if (theComponents[i]->getTag() == tag) - return theComponents[i]; + if (theComponents[i] != 0) + if (theComponents[i]->getTag() == tag) + return theComponents[i]; // its not in the array return 0; @@ -309,29 +302,29 @@ ArrayOfTaggedObjects::getComponentPtr(int tag) TaggedObjectIter & ArrayOfTaggedObjects::getComponents() { - // reset the iter to point to first component and then return - // a reference to the iter - myIter.reset(); - return myIter; + // reset the iter to point to first component and then return + // a reference to the iter + myIter.reset(); + return myIter; } ArrayOfTaggedObjectsIter ArrayOfTaggedObjects::getIter() { - // return a new iter to the components, more expensive to use - // this iter as two memory calls to heap .. needed if user needs - // to have multiple iters running in same code segment! - return ArrayOfTaggedObjectsIter(*this); + // return a new iter to the components, more expensive to use + // this iter as two memory calls to heap .. needed if user needs + // to have multiple iters running in same code segment! + return ArrayOfTaggedObjectsIter(*this); } TaggedObjectStorage * ArrayOfTaggedObjects::getEmptyCopy() { - ArrayOfTaggedObjects *theCopy = new ArrayOfTaggedObjects(sizeComponentArray); + ArrayOfTaggedObjects *theCopy = new ArrayOfTaggedObjects(sizeComponentArray); - return theCopy; + return theCopy; } void @@ -376,5 +369,3 @@ ArrayOfTaggedObjects::Print(OPS_Stream &s, int flag) theComponents[i]->Print(s, flag); } - - From 5e8743c7e5bdbfc42936e0176057dfa1198dbdbc Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:15:03 -0800 Subject: [PATCH 045/161] Refactor pattern and constraint handling in loading commands Replaces legacy pattern handling with StaticPattern and MultiSupportPattern, updates pattern selection and error reporting, and introduces a new `constrain` command for translation constraints with optional rotation. Removes deprecated TclPatternCommand.cpp, updates related command implementations, and improves error messages and argument parsing for pattern and constraint commands. --- SRC/domain/pattern/StaticPattern.cpp | 120 ++++- SRC/domain/pattern/StaticPattern.h | 31 +- SRC/runtime/commands/domain/element.cpp | 4 +- .../domain/loading/drm/TclPatternCommand.cpp | 439 ---------------- .../commands/domain/loading/element_load.cpp | 35 +- .../commands/domain/loading/groundMotion.cpp | 4 +- .../commands/domain/loading/pattern.cpp | 56 +- SRC/runtime/commands/modeling/commands.h | 2 + SRC/runtime/commands/modeling/constraint.cpp | 488 ++++++++++++++---- SRC/runtime/runtime/CMakeLists.txt | 5 +- SRC/runtime/runtime/ModelRegistry.cpp | 13 +- SRC/runtime/runtime/ModelRegistry.h | 41 +- 12 files changed, 634 insertions(+), 604 deletions(-) delete mode 100644 SRC/runtime/commands/domain/loading/drm/TclPatternCommand.cpp diff --git a/SRC/domain/pattern/StaticPattern.cpp b/SRC/domain/pattern/StaticPattern.cpp index 200cbfb526..c6ba2f644a 100644 --- a/SRC/domain/pattern/StaticPattern.cpp +++ b/SRC/domain/pattern/StaticPattern.cpp @@ -1,12 +1,130 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +//===----------------------------------------------------------------------===// +// #include "StaticPattern.h" +#include +#include +#include +#include +#include +#include +#include +#include StaticPattern::StaticPattern(int tag, double fact) - :LoadPattern(tag, PATTERN_TAG_StaticPattern, fact) + : LoadPattern(tag, PATTERN_TAG_StaticPattern, fact) + , currentGeoTag(0) + , lastGeoSendTag(-1) + , theNodalLoads(new MapOfTaggedObjects()) + , theElementalLoads(new MapOfTaggedObjects()) + , theSPs(new MapOfTaggedObjects()) + , theNodIter(new NodalLoadIter(theNodalLoads)) + , theEleIter(new ElementalLoadIter(theElementalLoads)) + , theSpIter(new SingleDomSP_Iter(theSPs)) { } StaticPattern::~StaticPattern() { + delete theNodalLoads; + delete theElementalLoads; + delete theSPs; + delete theNodIter; + delete theEleIter; + delete theSpIter; } +#if 0 +bool +StaticPattern::addNodalLoad(NodalLoad *load) +{ + Domain *theDomain = this->getDomain(); + + bool result = theNodalLoads->addComponent(load); + + if (result != true) { + opserr << "WARNING: LoadPattern::addNodalLoad() - load could not be added\n"; + return result; + } + + if (theDomain != nullptr) + load->setDomain(theDomain); + + load->setLoadPatternTag(this->getTag()); + currentGeoTag++; + + return result; +} + + +bool +StaticPattern::addElementalLoad(ElementalLoad *load) +{ + Domain *theDomain = this->getDomain(); + + bool result = theElementalLoads->addComponent(load); + if (result == true) { + if (theDomain != 0) + load->setDomain(theDomain); + load->setLoadPatternTag(this->getTag()); + currentGeoTag++; + } else + opserr << "WARNING: LoadPattern::addElementalLoad() - load could not be " + "added\n"; + + return result; +} + + +NodalLoad * +StaticPattern::removeNodalLoad(int tag) +{ + TaggedObject *obj = theNodalLoads->removeComponent(tag); + if (obj == 0) + return 0; + NodalLoad *result = (NodalLoad *)obj; + result->setDomain(nullptr); + currentGeoTag++; + return result; +} + + +ElementalLoad * +StaticPattern::removeElementalLoad(int tag) +{ + TaggedObject *obj = theElementalLoads->removeComponent(tag); + if (obj == 0) + return 0; + + ElementalLoad *result = (ElementalLoad *)obj; + result->setDomain(nullptr); + currentGeoTag++; + return result; +} + + +NodalLoadIter & +LoadPattern::getNodalLoads() +{ + theNodIter->reset(); + return *theNodIter; +} + +ElementalLoadIter & +LoadPattern::getElementalLoads() +{ + theEleIter->reset(); + return *theEleIter; +} + +#endif \ No newline at end of file diff --git a/SRC/domain/pattern/StaticPattern.h b/SRC/domain/pattern/StaticPattern.h index 8995e8867f..6a6dc4004d 100644 --- a/SRC/domain/pattern/StaticPattern.h +++ b/SRC/domain/pattern/StaticPattern.h @@ -1,3 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +//===----------------------------------------------------------------------===// +// #pragma once #include @@ -27,27 +39,34 @@ class StaticPattern : public LoadPattern #if 0 LoadPattern *getCopy() override; bool addSP_Constraint(SP_Constraint *) final; + SP_ConstraintIter &getSPs() final; + SP_Constraint *removeSP_Constraint(int tag) final; +private: + TaggedObjectStorage *theSPs; + +#endif +#if 0 bool addNodalLoad(NodalLoad *) final; bool addElementalLoad(ElementalLoad *) final; NodalLoadIter &getNodalLoads() final; - ElementalLoadIter &getElementalLoads() final; - SP_ConstraintIter &getSPs() final; + ElementalLoadIter &getElementalLoads() final; + // methods to remove loads NodalLoad *removeNodalLoad(int tag) final; ElementalLoad *removeElementalLoad(int tag) final; - SP_Constraint *removeSP_Constraint(int tag) final; void clearAll(); #endif private: -#if 0 // storage objects for the loads and constraints TaggedObjectStorage *theNodalLoads; TaggedObjectStorage *theElementalLoads; - TaggedObjectStorage *theSPs; + TaggedObjectStorage *theSPs; // iterator objects for the objects added to the storage objects NodalLoadIter *theNodIter; ElementalLoadIter *theEleIter; SingleDomSP_Iter *theSpIter; -#endif + + int currentGeoTag; + int lastGeoSendTag; }; \ No newline at end of file diff --git a/SRC/runtime/commands/domain/element.cpp b/SRC/runtime/commands/domain/element.cpp index b2888aeb2d..bddb808192 100644 --- a/SRC/runtime/commands/domain/element.cpp +++ b/SRC/runtime/commands/domain/element.cpp @@ -473,8 +473,8 @@ getEleClassTags(ClientData clientData, Tcl_Interp *interp, int argc, sprintf(buffer, "%d ", theEle->getClassTag()); Tcl_AppendResult(interp, buffer, NULL); } - - } else if (argc == 2) { + } + else if (argc == 2) { int eleTag; if (Tcl_GetInt(interp, argv[1], &eleTag) != TCL_OK) { diff --git a/SRC/runtime/commands/domain/loading/drm/TclPatternCommand.cpp b/SRC/runtime/commands/domain/loading/drm/TclPatternCommand.cpp deleted file mode 100644 index 27e408e423..0000000000 --- a/SRC/runtime/commands/domain/loading/drm/TclPatternCommand.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** ****************************************************************** */ -// -// Description: This file contains the function invoked when the user invokes -// the Pattern command in the interpreter. It is invoked by the -// TclBasicBuilder_addPattern function in the TclBasicBuilder.C file. Current -// valid Pattern types are: -// -// Written: fmk -// Created: 07/99 -// -// Modified: fmk 11/00 - removed TimeSeries stuff from file, now an external -// procedure -// -// Modified: Nov. 2002, Zhaohui Yang and Boris Jeremic added Plastic Bowl -// loading (aka Domain Reduction Method) commands -// -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -extern SimulationInformation simulationInfo; -extern const char *getInterpPWD(Tcl_Interp *interp); // interpreter.cpp - -LoadPattern *theTclLoadPattern = 0; -MultiSupportPattern *theTclMultiSupportPattern = 0; - -extern TimeSeriesIntegrator *TclDispatch_newSeriesIntegrator(ClientData clientData, - Tcl_Interp *interp, - TCL_Char *arg); - -extern TimeSeries *TclSeriesCommand(ClientData clientData, Tcl_Interp *interp, - TCL_Char *arg); - -int -TclPatternCommand(ClientData clientData, Tcl_Interp *interp, int argc, - TCL_Char **argv, Domain *theDomain) -{ - LoadPattern *thePattern = nullptr; - - // make sure at least one other argument to contain integrator - if (argc < 4) { - opserr << OpenSees::PromptValueError << "invalid command - want: pattern type "; - opserr << " {list of load and sp constraints commands}\n"; - opserr - << " valid types: Plain, UniformExcitation, MultiSupport\n"; - return TCL_ERROR; - } - - TimeSeries *theSeries = nullptr; - int patternID = 0; - - if (Tcl_GetInt(interp, argv[2], &patternID) != TCL_OK) { - opserr << "WARNING invalid patternID: pattern type " << argv[2] - << "\n"; - return TCL_ERROR; - } - - int commandEndMarker = 0; - - if (strcmp(argv[1], "Plain") == 0) { - - thePattern = new LoadPattern(patternID); - theSeries = TclSeriesCommand(clientData, interp, argv[3]); - - if (theSeries == nullptr) { - - opserr << "WARNING - problem creating TimeSeries for LoadPattern "; - opserr << patternID << "\n"; - - // clean up the memory and return an error - if (thePattern != nullptr) - delete thePattern; - - if (theSeries != nullptr) - delete theSeries; - - return TCL_ERROR; - } - - thePattern->setTimeSeries(theSeries); - - } - - else if (strcmp(argv[1], "UniformExcitation") == 0) { - - int dir; - - if (Tcl_GetInt(interp, argv[3], &dir) != TCL_OK) { - opserr << "WARNING invalid patternID: pattern type " << argv[2] - << "\n"; - return TCL_ERROR; - } - - dir--; // subtract 1 for c indexing - - TimeSeries *accelSeries = nullptr; - TimeSeries *velSeries = nullptr; - TimeSeries *dispSeries = nullptr; - TimeSeriesIntegrator *seriesIntegrator = nullptr; - double vel0 = 0.0; - - int currentArg = 4; - bool doneSeries = false; - while (currentArg < argc - 1 && doneSeries == false) { - - if ((strcmp(argv[currentArg], "-vel0") == 0) || - (strcmp(argv[currentArg], "-initialVel") == 0)) { - - currentArg++; - if ((currentArg < argc) && - (Tcl_GetDouble(interp, argv[currentArg], &vel0) != TCL_OK)) { - opserr << "WARNING invalid vel0: pattern type UniformExcitation\n"; - return TCL_ERROR; - } - - currentArg++; - } - - else if ((strcmp(argv[currentArg], "-accel") == 0) || - (strcmp(argv[currentArg], "-acceleration") == 0)) { - - currentArg++; - accelSeries = TclSeriesCommand(clientData, interp, argv[currentArg]); - if (accelSeries == 0) { - opserr << "WARNING invalid accel series: pattern UniformExcitation " - "-accel \n"; - return TCL_ERROR; - } - - currentArg++; - - } else if ((strcmp(argv[currentArg], "-vel") == 0) || - (strcmp(argv[currentArg], "-velocity") == 0)) { - - currentArg++; - velSeries = TclSeriesCommand(clientData, interp, argv[currentArg]); - - if (velSeries == nullptr) { - opserr << "WARNING invalid vel series: " << argv[currentArg]; - opserr << " pattern UniformExcitation -vel {series}\n"; - return TCL_ERROR; - } - - currentArg++; - - } else if ((strcmp(argv[currentArg], "-disp") == 0) || - (strcmp(argv[currentArg], "-displacement") == 0)) { - - currentArg++; - dispSeries = TclSeriesCommand(clientData, interp, argv[currentArg]); - - if (dispSeries == nullptr) { - opserr << "WARNING invalid vel series: " << argv[currentArg]; - opserr << " pattern UniformExcitation -vel {series}\n"; - return TCL_ERROR; - } - - currentArg++; - } else if ((strcmp(argv[currentArg], "-int") == 0) || - (strcmp(argv[currentArg], "-integrator") == 0)) { - - currentArg++; - seriesIntegrator = - TclDispatch_newSeriesIntegrator(clientData, interp, argv[currentArg]); - if (seriesIntegrator == nullptr) { - opserr << "WARNING invalid series integrator: " << argv[currentArg]; - opserr << " - pattern UniformExcitation -int {Series Integrator}\n"; - return TCL_ERROR; - } - currentArg++; - } - - else - doneSeries = true; - } - - if (dispSeries == 0 && velSeries == 0 && accelSeries == 0) { - opserr << "WARNING invalid series, want - pattern UniformExcitation"; - opserr << "-disp {dispSeries} -vel {velSeries} -accel {accelSeries} "; - opserr << "-int {Series Integrator}\n"; - return TCL_ERROR; - } - - GroundMotion *theMotion = - new GroundMotion(dispSeries, velSeries, accelSeries, seriesIntegrator); - - if (theMotion == 0) { - opserr << "WARNING ran out of memory creating ground motion - pattern " - "UniformExcitation "; - opserr << patternID << "\n"; - - return TCL_ERROR; - } - - // create the UniformExcitation Pattern - thePattern = new UniformExcitation(*theMotion, dir, patternID, vel0); - - // Added by MHS to prevent call to Tcl_Eval at end of this function - commandEndMarker = currentArg; - } - - else if (strcmp(argv[1], "Uniform") == 0) { - - // First search for file name and time step - int numInputs = argc; - TCL_Char *accelFileName = 0; - double dt = 0.0; - for (int i = 5; i < argc; ++i) { - if (strcmp(argv[i], "-accel") == 0 && i + 2 < argc) { - // Read the input file name - accelFileName = argv[i + 1]; - - // Read the time interval - if (Tcl_GetDouble(interp, argv[i + 2], &dt) != TCL_OK) { - opserr << "WARNING problem reading ground motion " - << "time interval - pattern UniformExcitation: " << patternID - << "\n"; - return TCL_ERROR; - } - numInputs -= 3; - } - } - - if (numInputs < 5) { - opserr << "WARNING insufficient number of arguments - want: pattern "; - opserr << "UniformExcitation " << patternID << " dir factor\n"; - return TCL_ERROR; - } - - int dir; - if (Tcl_GetInt(interp, argv[3], &dir) != TCL_OK) { - - char inputDir; - inputDir = argv[3][0]; - switch (inputDir) { - case 'X': - case 'x': - case '1': // Global X - dir = 0; - break; - case 'Y': - case 'y': - case '2': // Global Y - dir = 1; - break; - case 'Z': - case 'z': - case '3': // Global Z - dir = 2; - break; - default: - opserr << "WARNING cannot read direction for excitation \n"; - opserr << "UniformExcitation " << patternID << " dir factor" << "\n"; - return TCL_ERROR; - break; - } - } else - dir--; // change to c++ indexing - - double factor; - if (Tcl_GetDouble(interp, argv[4], &factor) != TCL_OK) { - opserr << "WARNING insufficient number of arguments - want: pattern "; - opserr << "UniformExcitation " << patternID << " dir factor\n"; - return TCL_ERROR; - } - - GroundMotionRecord *theMotion; - - // read in the ground motion - if (accelFileName == 0) { - opserr << "WARNING -- No ground motion data provided\n"; - opserr << "UniformExcitation tag: " << patternID << "\n"; - return TCL_ERROR; - } - - theMotion = new GroundMotionRecord(accelFileName, dt, factor); - - if (theMotion == 0) { - opserr << "WARNING ran out of memory creating ground motion - pattern " - "UniformExcitation "; - opserr << patternID << "\n"; - return TCL_ERROR; - } - - const char *pwd = getInterpPWD(interp); - simulationInfo.addInputFile(accelFileName, pwd); - - // create the UniformExcitation Pattern - thePattern = new UniformExcitation(*theMotion, dir, patternID); - - if (thePattern == 0) { - opserr << "WARNING ran out of memory creating load pattern - pattern " - "UniformExcitation "; - opserr << patternID << "\n"; - - // clean up memory allocated up to this point and return an error - if (theMotion != 0) - delete theMotion; - - return TCL_ERROR; - } - } - - else if ((strcmp(argv[1], "MultipleSupportExcitation") == 0) || - (strcmp(argv[1], "MultipleSupport") == 0) || - (strcmp(argv[1], "MultiSupport") == 0)) { - - theTclMultiSupportPattern = new MultiSupportPattern(patternID); - thePattern = theTclMultiSupportPattern; - - if (thePattern == 0) { - opserr << "WARNING ran out of memory creating load pattern - pattern " - "MultipleSupportExcitation "; - opserr << patternID << "\n"; - } - commandEndMarker = 2; - } - - // Added Joey Yang and Boris Jeremic at UC Davis 10/31/2002 - - //////// //////// ///////// ////////// ///// // DRMLoadPattern add BEGIN - else if (strcmp(argv[1], "DRMLoadPattern") == 0) { - TCL_Char *InputDataFileName = 0; - - if ((strcmp(argv[2], "-inputdata") == 0) || - (strcmp(argv[2], "-InputData") == 0)) { - InputDataFileName = argv[3]; - } - - // now parse the input file name to extract the pattern input data - std::ifstream ifile(InputDataFileName); - int num_steps; - ifile >> num_steps; - double dt; - ifile >> dt; - int steps_cached; - ifile >> steps_cached; - double *ele_d = new double[3]; - ifile >> ele_d[0]; - ifile >> ele_d[1]; - ifile >> ele_d[2]; - double *drm_box_crds = new double[6]; - for (int i = 0; i < 6; ++i) - ifile >> drm_box_crds[i]; - int n1; - ifile >> n1; - int n2; - ifile >> n2; - - std::string inps; - int nf = 6; - char **files = new char *[nf]; - int *f_d = new int[3 * (nf - 1)]; - int ne1, ne2; - for (int i = 0; i < nf; ++i) { - ifile >> inps; - files[i] = (char *)inps.c_str(); - if (i < (nf - 1)) { - ifile >> ne1; - ifile >> ne2; - f_d[3 * i] = (ne1 + 1) * (ne2 + 1); - f_d[3 * i + 1] = ne1; - f_d[3 * i + 2] = ne2; - } - } - - Mesh3DSubdomain *myMesher = new Mesh3DSubdomain(theDomain); - PlaneDRMInputHandler *patternhandler = new PlaneDRMInputHandler( - 1.0, files, nf, dt, 0, num_steps, f_d, 15, n1, n2, drm_box_crds, - drm_box_crds, ele_d, myMesher, steps_cached, theDomain); - DRMLoadPattern *ptr = new DRMLoadPattern(1, 1.0, patternhandler, theDomain); - ptr->setMaps(); - thePattern = ptr; - - } // end else if DRMLoadPattern - - ///////// ///////// ///////// //////// ////// // DRMLoadPattern add END - - else { - opserr << "WARNING unknown pattern type " << argv[1]; - opserr << " - want: pattern patternType " << patternID; - opserr << " \t valid types: Plain, UniformExcitation, " - "MultiSupportExciatation \n"; - return TCL_ERROR; - } - - // now add the load pattern to the modelBuilder - if (theDomain->addLoadPattern(thePattern) == false) { - opserr << "WARNING could not add load pattern to the domain " - << *thePattern; - delete thePattern; // free up the memory, pattern destroys the time series - return TCL_ERROR; - } - - theTclLoadPattern = thePattern; - - // use TCL_Eval to evaluate the list of load and single point constraint - // commands - if (commandEndMarker < (argc - 1)) { - if (Tcl_Eval(interp, argv[argc - 1]) != TCL_OK) { - opserr << "WARNING - error reading load pattern information in { } "; - return TCL_ERROR; - } - } - - theTclMultiSupportPattern = 0; - - return TCL_OK; -} diff --git a/SRC/runtime/commands/domain/loading/element_load.cpp b/SRC/runtime/commands/domain/loading/element_load.cpp index d853707389..e5c7f7b7b9 100644 --- a/SRC/runtime/commands/domain/loading/element_load.cpp +++ b/SRC/runtime/commands/domain/loading/element_load.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include int TclCommand_addFrameLoad(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, @@ -61,7 +61,7 @@ TclCommand_addFrameLoad(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc ArgumentTracker tracker; - LoadPattern *pattern = builder->getEnclosingPattern(); + LoadPattern *pattern = builder->getCurrentPattern(); // eleLoad FrameForce $shape -n $n -offset $r -pattern $pattern -basis $basis -ele $ele @@ -91,24 +91,30 @@ TclCommand_addFrameLoad(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc for (int i=0; igetDomain()->getLoadPattern(ptag); if (pattern == nullptr) { - opserr << OpenSees::PromptValueError << "pattern " << argv[i+1] << " not found\n"; + opserr << OpenSees::PromptValueError + << "pattern " << argv[i+1] << " not found\n"; return TCL_ERROR; } i++; } else if (strcmp(argv[i], "-basis") == 0) { if (i == argc-1) { - opserr << OpenSees::PromptValueError << "-basis paramter missing required argument\n"; + opserr << OpenSees::PromptValueError + << "-basis paramter missing required argument\n"; return TCL_ERROR; } if (strcmp(argv[i+1], "global") == 0) @@ -120,7 +126,8 @@ TclCommand_addFrameLoad(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc basis = FrameLoad::Director; else { opserr << OpenSees::PromptValueError - << "unknown basis for FrameLoad " << argv[i+1] << "\n"; + << "unknown basis for FrameLoad " << argv[i+1] + << "\n"; return TCL_ERROR; } i++; @@ -128,24 +135,28 @@ TclCommand_addFrameLoad(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc else if (strcmp(argv[i], "-force") == 0) { if (i == argc-1) { - opserr << OpenSees::PromptValueError << "-force paramter missing required argument\n"; + opserr << OpenSees::PromptValueError + << "-force paramter missing required argument\n"; return TCL_ERROR; } int list_argc; TCL_Char **list_argv; if (Tcl_SplitList(interp, argv[i+1], &list_argc, &list_argv) != TCL_OK) { - opserr << OpenSees::PromptValueError << "force parameter expected list of floats\n"; + opserr << OpenSees::PromptValueError + << "force parameter expected list of floats\n"; return TCL_ERROR; } if (list_argc != 3) { - opserr << OpenSees::PromptValueError << "force parameter expected list of 3 floats\n"; + opserr << OpenSees::PromptValueError + << "force parameter expected list of 3 floats\n"; Tcl_Free((char *) list_argv); return TCL_ERROR; } Vector3D force; for (int j = 0; j < 3; j++) { if (Tcl_GetDouble(interp, list_argv[j], &force[j]) != TCL_OK) { - opserr << OpenSees::PromptValueError << "force argument expected list of 3 floats\n"; + opserr << OpenSees::PromptValueError + << "force argument expected list of 3 floats\n"; Tcl_Free((char *) list_argv); return TCL_ERROR; } @@ -403,7 +414,7 @@ TclCommand_addElementalLoad(ClientData clientData, Tcl_Interp *interp, // If -pattern wasnt given explicitly, see if there is one // activated in the builder if (explicitPatternPassed == false) { - LoadPattern *theTclLoadPattern = builder->getEnclosingPattern(); + LoadPattern *theTclLoadPattern = builder->getCurrentPattern(); if (theTclLoadPattern == nullptr) { opserr << OpenSees::PromptValueError << "no current load pattern\n"; return TCL_ERROR; diff --git a/SRC/runtime/commands/domain/loading/groundMotion.cpp b/SRC/runtime/commands/domain/loading/groundMotion.cpp index e82defa3e5..bc30bba379 100644 --- a/SRC/runtime/commands/domain/loading/groundMotion.cpp +++ b/SRC/runtime/commands/domain/loading/groundMotion.cpp @@ -48,8 +48,8 @@ TclCommand_addGroundMotion(ClientData clientData, Tcl_Interp *interp, int argc, TCL_Char ** const argv) { - MultiSupportPattern* pattern = - (MultiSupportPattern *)Tcl_GetAssocData(interp,"theTclMultiSupportPattern", NULL); + ModelRegistry *builder = static_cast(clientData); + MultiSupportPattern* pattern = builder->getCurrentPattern(); if (pattern == nullptr) { opserr << "ERROR no multi-support pattern\n"; diff --git a/SRC/runtime/commands/domain/loading/pattern.cpp b/SRC/runtime/commands/domain/loading/pattern.cpp index 4013c0e598..33d7482d2d 100644 --- a/SRC/runtime/commands/domain/loading/pattern.cpp +++ b/SRC/runtime/commands/domain/loading/pattern.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -93,7 +94,8 @@ TclCommand_addPattern(ClientData clientData, // make sure at least one other argument to contain integrator if (argc < 3) { - opserr << OpenSees::PromptValueError << "invalid command - want: pattern type "; + opserr << OpenSees::PromptValueError + << "invalid command - want: pattern type "; opserr << " {list of load and sp constraints commands}\n"; opserr << " valid types: Plain, UniformExcitation, MultiSupport\n"; return TCL_ERROR; @@ -138,20 +140,24 @@ TclCommand_addPattern(ClientData clientData, } } - thePattern = new LoadPattern(patternID, fact); + StaticPattern* theStaticPattern = new StaticPattern(patternID, fact); theSeries = TclSeriesCommand(clientData, interp, series_arg); if (theSeries == nullptr) { - opserr << OpenSees::PromptValueError << "problem creating TimeSeries for LoadPattern " - << patternID << "\n"; + opserr << OpenSees::PromptValueError + << "problem creating TimeSeries for LoadPattern " + << patternID + << OpenSees::SignalMessageEnd; // clean up the memory and return an error - if (thePattern != nullptr) - delete thePattern; + if (theStaticPattern != nullptr) + delete theStaticPattern; return TCL_ERROR; } - thePattern->setTimeSeries(theSeries); + theStaticPattern->setTimeSeries(theSeries); + builder->setCurrentPattern(theStaticPattern); + thePattern = theStaticPattern; } else if (strcmp(argv[1], "UniformExcitation") == 0) { @@ -275,6 +281,7 @@ TclCommand_addPattern(ClientData clientData, // create the UniformExcitation Pattern thePattern = new UniformExcitation(*theMotion, dir, patternID, vel0, fact); + builder->setCurrentPattern(thePattern); // Added by MHS to prevent call to Tcl_Eval at end of this function commandEndMarker = currentArg+1; } @@ -357,8 +364,7 @@ TclCommand_addPattern(ClientData clientData, // Create the UniformExcitation Pattern thePattern = new UniformExcitation(*theMotion, dir, patternID); - Tcl_SetAssocData(interp,"theTclMultiSupportPattern", NULL, (ClientData)0); - + builder->setCurrentPattern(thePattern); } else if ((strcmp(argv[1], "MultipleSupportExcitation") == 0) || @@ -366,9 +372,8 @@ TclCommand_addPattern(ClientData clientData, (strcmp(argv[1], "MultiSupport") == 0)) { MultiSupportPattern *theTclMultiSupportPattern = new MultiSupportPattern(patternID); - Tcl_SetAssocData(interp,"theTclMultiSupportPattern", NULL, (ClientData)theTclMultiSupportPattern); + builder->setCurrentPattern(theTclMultiSupportPattern); thePattern = theTclMultiSupportPattern; - // commandEndMarker = 2; } @@ -427,9 +432,8 @@ TclCommand_addPattern(ClientData clientData, new DRMLoadPattern(1, 1.0, patternhandler, domain); ptr->setMaps(); thePattern = ptr; - theTclMultiSupportPattern = 0; - Tcl_SetAssocData(interp,"theTclMultiSupportPattern", NULL, (ClientData)0); - } else { + } + else { // TCL_Char * ifp = 0; double INVALID = 0.7111722273337; @@ -695,8 +699,6 @@ TclCommand_addPattern(ClientData clientData, thePattern = new DRMLoadPatternWrapper(patternID, factor, files, nf, dt, num_steps, f_d, 15, n1, n2, drm_box_crds, ele_d, steps_cached); - // theTclMultiSupportPattern = 0; - Tcl_SetAssocData(interp,"theTclMultiSupportPattern", NULL, (ClientData)0); commandEndMarker = c_arg+1; } @@ -739,9 +741,9 @@ TclCommand_addPattern(ClientData clientData, #endif else { - opserr << OpenSees::PromptValueError << "unknown pattern type " << argv[1]; - opserr << " \t valid types: Plain, UniformExcitation, " - "MultiSupportExciatation \n"; + opserr << OpenSees::PromptValueError + << "unknown pattern type " << argv[1] + << OpenSees::SignalMessageEnd; return TCL_ERROR; } @@ -754,11 +756,10 @@ TclCommand_addPattern(ClientData clientData, return TCL_ERROR; } - - builder->setEnclosingPattern(thePattern); - + // // use TCL_Eval to evaluate the list of load and single point constraint // commands + // if (commandEndMarker < argc) { // Set the Pattern for "sp" command @@ -778,7 +779,6 @@ TclCommand_addPattern(ClientData clientData, return TCL_ERROR; } - Tcl_SetAssocData(interp,"theTclMultiSupportPattern", NULL, (ClientData)0); // info.clientData = (ClientData)builder; // Tcl_SetCommandInfo(interp, "sp", &info); @@ -797,7 +797,7 @@ TclCommand_addNodalLoad(ClientData clientData, Tcl_Interp *interp, int argc, TCL // TODO ModelRegistry *builder = static_cast(clientData); - LoadPattern *theTclLoadPattern = builder->getEnclosingPattern(); + StaticPattern *theTclLoadPattern = builder->getCurrentPattern(); int nodeLoadTag = builder->getNodalLoadTag(); int ndf = builder->getNDF(); // argc - 2; @@ -809,14 +809,18 @@ TclCommand_addNodalLoad(ClientData clientData, Tcl_Interp *interp, int argc, TCL if (true) { if (argc < (2 + ndf)) { - opserr << OpenSees::PromptValueError << "expected " << ndf << " forces\n"; + opserr << OpenSees::PromptValueError + << "expected " << ndf << " forces" + << OpenSees::SignalMessageEnd; return TCL_ERROR; } // get the id of the node int nodeId; if (Tcl_GetInt(interp, argv[1], &nodeId) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid nodeId: " << argv[1]; + opserr << OpenSees::PromptValueError + << "invalid nodeId: " << argv[1] + << OpenSees::SignalMessageEnd; return TCL_ERROR; } diff --git a/SRC/runtime/commands/modeling/commands.h b/SRC/runtime/commands/modeling/commands.h index 32101815e6..3e62d180dd 100644 --- a/SRC/runtime/commands/modeling/commands.h +++ b/SRC/runtime/commands/modeling/commands.h @@ -58,6 +58,7 @@ extern Tcl_CmdProc TclCommand_addYieldSurface_BC; // Constraints extern Tcl_CmdProc TclCommand_addMP; extern Tcl_CmdProc TclCommand_addSP; +extern Tcl_CmdProc TclCommand_constrain; extern Tcl_CmdProc TclCommand_addHomogeneousBC; extern Tcl_CmdProc TclCommand_addHomogeneousBC_X; extern Tcl_CmdProc TclCommand_addHomogeneousBC_Y; @@ -151,6 +152,7 @@ constexpr ModelBuilderCommands[] = { {"rigidLink", TclCommand_RigidLink}, {"sp", TclCommand_addSP}, + {"constrain", TclCommand_constrain}, {"groundMotion", TclCommand_addGroundMotion}, {"imposedMotion", TclCommand_addImposedMotionSP}, {"imposedSupportMotion", TclCommand_addImposedMotionSP}, diff --git a/SRC/runtime/commands/modeling/constraint.cpp b/SRC/runtime/commands/modeling/constraint.cpp index b8fc88daa2..33d28dd636 100644 --- a/SRC/runtime/commands/modeling/constraint.cpp +++ b/SRC/runtime/commands/modeling/constraint.cpp @@ -21,9 +21,10 @@ #include #include #include +#include #include - +#include #include #include #include @@ -143,6 +144,9 @@ int TclCommand_addHomogeneousBC_X(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, TCL_Char ** const argv) { + assert(clientData != nullptr); + ModelRegistry *builder = static_cast(clientData); + int ndf = argc - 2; if (strcmp(argv[argc-2],"-tol") == 0) ndf -= 2; @@ -185,8 +189,6 @@ TclCommand_addHomogeneousBC_X(ClientData clientData, Tcl_Interp *interp, } - assert(clientData != nullptr); - ModelRegistry *builder = static_cast(clientData); // TODO: Why not add SP to Domain directly? builder->addSP_Constraint(0, xLoc, fixity, tol); @@ -233,7 +235,9 @@ TclCommand_addHomogeneousBC_Y(ClientData clientData, Tcl_Interp *interp, if (argc >= (4 + ndf)) { if (strcmp(argv[2+ndf],"-tol") == 0) if (Tcl_GetDouble(interp, argv[3+ndf], &tol) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid tol specified - fixY " << yLoc << OpenSees::SignalMessageEnd; + opserr << OpenSees::PromptValueError + << "invalid tol specified - fixY " + << yLoc << OpenSees::SignalMessageEnd; return TCL_ERROR; } } @@ -272,7 +276,8 @@ TclCommand_addHomogeneousBC_Z(ClientData clientData, Tcl_Interp *interp, ID fixity(ndf); for (int i=0; igetEnclosingPattern(); + LoadPattern *theTclLoadPattern = nullptr; + if ((theTclLoadPattern = builder->getCurrentPattern())) + ; + else if ((theTclLoadPattern = builder->getCurrentPattern())) + ; + else { + opserr << OpenSees::PromptValueError + << "no current load pattern supports single point constraints\n"; + return TCL_ERROR; + } // check number of arguments if (argc < 4) { @@ -450,7 +465,8 @@ TclCommand_addEqualDOF_MP(ClientData clientData, Tcl_Interp *interp, // Check number of arguments if (argc < 4) { - opserr << OpenSees::PromptValueError << "bad command - want: equalDOF RnodeID? CnodeID? DOF1? DOF2? ..."; + opserr << OpenSees::PromptValueError + << "bad command - want: equalDOF RnodeID? CnodeID? DOF1? DOF2? ..."; return TCL_ERROR; } @@ -510,94 +526,366 @@ TclCommand_addEqualDOF_MP(ClientData clientData, Tcl_Interp *interp, return TCL_OK; } + +int +TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, + Tcl_Size argc, TCL_Char ** const argv) +{ + ModelRegistry *builder = static_cast(clientData); + Domain *theDomain = (builder != nullptr) ? builder->getDomain() : nullptr; + + // Usage: + // constrain Translation Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}> + // constrain Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}> + // + // where v is a rotation vector (axis * angle in radians), R = Exp(Hat(v)), + // and the enforced relation is Uc = R * Ur on the selected DOFs. + + Tcl_Size argi = 1; + + // Optional keyword "Translation" + if (argc > argi && + (std::strcmp(argv[argi], "Translation") == 0 || + std::strcmp(argv[argi], "translation") == 0)) { + ++argi; + } + + if (argc - argi < 3) { + opserr << OpenSees::PromptValueError + << "insufficient arguments.\n" + << "Usage: constrain Translation Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}>" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + int RnodeID = 0, CnodeID = 0; + + if (Tcl_GetInt(interp, argv[argi + 0], &RnodeID) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid RnodeID: " << argv[argi + 0] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (Tcl_GetInt(interp, argv[argi + 1], &CnodeID) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid CnodeID: " << argv[argi + 1] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + Node *theRetainedNode = theDomain->getNode(RnodeID); + Node *theConstrainedNode = theDomain->getNode(CnodeID); + if (theRetainedNode == nullptr || theConstrainedNode == nullptr) { + opserr << OpenSees::PromptValueError + << "Retained or Constrained node does not exist in the Domain: " + << RnodeID << " " << CnodeID + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + // Parse DOF list argument (a Tcl list in one argv slot) + Tcl_Size listSize = 0; + const char **listDOF = nullptr; + if (Tcl_SplitList(interp, argv[argi + 2], &listSize, &listDOF) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid dof list: " << argv[argi + 2] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + if (listSize <= 0) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "empty dof list" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + const int numDOF = static_cast(listSize); + + // Prepare IDs and store 0-based indices of requested DOFs + ID rDOF(numDOF); + ID cDOF(numDOF); + std::vector dofIdx(numDOF, -1); + + // For a "Translation" constraint, we strongly prefer DOFs to be within the + // coordinate dimension (2D -> {1,2}, 3D -> {1,2,3}). + const int dimR = theRetainedNode->getCrds().Size(); + const int dimC = theConstrainedNode->getCrds().Size(); + const int dim = (dimR < dimC) ? dimR : dimC; + + if (dim < 1) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "node coordinate dimension is invalid" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + for (int i = 0; i < numDOF; ++i) { + int dof1 = 0; + if (Tcl_GetInt(interp, listDOF[i], &dof1) != TCL_OK) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "invalid dof value: " << listDOF[i] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + if (dof1 <= 0) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "dof values must be >= 1, got: " << dof1 + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + const int d = dof1 - 1; // 0-based + + // Translation DOFs should live in [0, dim-1] + if (d < 0 || d >= dim) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "Translation constraint DOF out of range for node dimension. " + << "Got dof=" << dof1 << " but node dimension is " << dim + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + // Check duplicates + for (int k = 0; k < i; ++k) { + if (dofIdx[k] == d) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "duplicate dof in list: " << dof1 + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + } + + dofIdx[i] = d; + cDOF(i) = d; + rDOF(i) = d; + } + + Tcl_Free((char*)listDOF); + + // Parse optional -rotate {v1 v2 v3} + bool doRotate = false; + double vx = 0.0, vy = 0.0, vz = 0.0; + + for (Tcl_Size a = argi + 3; a < argc; ++a) { + if (strcmp(argv[a], "-rotate") == 0 || strcmp(argv[a], "-rot") == 0) { + if (a + 1 >= argc) { + opserr << OpenSees::PromptValueError + << "missing vector after -rotate" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + if (strcmp(argv[a + 1], "None") == 0) { + argi++; + continue; // no rotation + } + + Tcl_Size nvec = 0; + const char **vec = nullptr; + if (Tcl_SplitList(interp, argv[a + 1], &nvec, &vec) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid -rotate vector list: " << argv[a + 1] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (nvec != 3) { + Tcl_Free((char*)vec); + opserr << OpenSees::PromptValueError + << "-rotate expects 3 components {v1 v2 v3}" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + if (Tcl_GetDouble(interp, vec[0], &vx) != TCL_OK || + Tcl_GetDouble(interp, vec[1], &vy) != TCL_OK || + Tcl_GetDouble(interp, vec[2], &vz) != TCL_OK) { + Tcl_Free((char*)vec); + opserr << OpenSees::PromptValueError + << "invalid -rotate vector components: " << argv[a + 1] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + Tcl_Free((char*)vec); + doRotate = true; + ++a; // skip the vector argument + } else { + opserr << OpenSees::PromptValueError + << "unknown option: " << argv[a] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + } + + // Build constraint matrix Ccr such that Uc = Ccr * Ur + Matrix Ccr(numDOF, numDOF); + Ccr.Zero(); + + if (!doRotate) { + // Identity -> equalDOF behavior on the selected DOFs + for (int i = 0; i < numDOF; ++i) + Ccr(i, i) = 1.0; + } else { + + // For 2D models, reject rotation vectors with x or y components + if (dim == 2 && (std::fabs(vx) > 1e-14 || std::fabs(vy) > 1e-14)) { + opserr << OpenSees::PromptValueError + << "2D Translation constraint only supports rotation about global Z. " + << "Use -rotate {0 0 theta} (theta in radians)." + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + // Compute 3x3 rotation R = Exp(Hat(v)) using Rodrigues’ formula + double R[3][3]; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + R[i][j] = (i == j) ? 1.0 : 0.0; + + const double theta = std::sqrt(vx*vx + vy*vy + vz*vz); + if (theta > 1e-14) { + const double kx = vx / theta; + const double ky = vy / theta; + const double kz = vz / theta; + + const double st = std::sin(theta); + const double ct = std::cos(theta); + const double omc = 1.0 - ct; + + R[0][0] = ct + kx*kx*omc; + R[0][1] = kx*ky*omc - kz*st; + R[0][2] = kx*kz*omc + ky*st; + + R[1][0] = ky*kx*omc + kz*st; + R[1][1] = ct + ky*ky*omc; + R[1][2] = ky*kz*omc - kx*st; + + R[2][0] = kz*kx*omc - ky*st; + R[2][1] = kz*ky*omc + kx*st; + R[2][2] = ct + kz*kz*omc; + } + + // Fill submatrix of R corresponding to requested DOFs + for (int i = 0; i < numDOF; ++i) { + const int ii = dofIdx[i]; // 0..(dim-1) + for (int j = 0; j < numDOF; ++j) { + const int jj = dofIdx[j]; + Ccr(i, j) = R[ii][jj]; + } + } + } + + // Create and add MP constraint + MP_Constraint *theMP = new MP_Constraint(RnodeID, CnodeID, Ccr, cDOF, rDOF); + + if (theDomain->addMP_Constraint(theMP) == false) { + opserr << OpenSees::PromptValueError + << "could not add MP_Constraint to domain" + << OpenSees::SignalMessageEnd; + delete theMP; + return TCL_ERROR; + } + + Tcl_SetObjResult(interp, Tcl_NewIntObj(theMP->getTag())); + return TCL_OK; +} + + #if 0 int TclCommand_addEqualDOF_MP_Mixed(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, TCL_Char ** const argv) { - // Ensure the destructor has not been called - ModelRegistry *builder = static_cast(clientData); + // Ensure the destructor has not been called + ModelRegistry *builder = static_cast(clientData); - if (theTclBuilder == 0 || clientData == 0) { - opserr << OpenSees::PromptValueError << "builder has been destroyed - equalDOF \n"; - return TCL_ERROR; - } + if (theTclBuilder == 0 || clientData == 0) { + opserr << OpenSees::PromptValueError << "builder has been destroyed - equalDOF \n"; + return TCL_ERROR; + } - // Check number of arguments - if (argc < 4) { - opserr << OpenSees::PromptValueError << "bad command - want: equalDOFmixed RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ... ..."; - return TCL_ERROR; - } + // Check number of arguments + if (argc < 4) { + opserr << OpenSees::PromptValueError << "bad command - want: equalDOFmixed RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ... ..."; + return TCL_ERROR; + } - // Read in the node IDs and the DOF - int RnodeID, CnodeID, dofIDR, dofIDC, numDOF; + // Read in the node IDs and the DOF + int RnodeID, CnodeID, dofIDR, dofIDC, numDOF; - if (Tcl_GetInt(interp, argv[1], &RnodeID) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid RnodeID: " << argv[1] - << " equalDOF RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ..."; - return TCL_ERROR; - } - if (Tcl_GetInt(interp, argv[2], &CnodeID) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid CnodeID: " << argv[2] - << " equalDOF RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ..."; - return TCL_ERROR; - } + if (Tcl_GetInt(interp, argv[1], &RnodeID) != TCL_OK) { + opserr << OpenSees::PromptValueError << "invalid RnodeID: " << argv[1] + << " equalDOF RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ..."; + return TCL_ERROR; + } + if (Tcl_GetInt(interp, argv[2], &CnodeID) != TCL_OK) { + opserr << OpenSees::PromptValueError << "invalid CnodeID: " << argv[2] + << " equalDOF RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ..."; + return TCL_ERROR; + } - if (Tcl_GetInt(interp, argv[3], &numDOF) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid numDOF: " << argv[2] - << " equalDOF RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ..."; - return TCL_ERROR; - } + if (Tcl_GetInt(interp, argv[3], &numDOF) != TCL_OK) { + opserr << OpenSees::PromptValueError << "invalid numDOF: " << argv[2] + << " equalDOF RnodeID? CnodeID? numDOF? RDOF1? CDOF1? ..."; + return TCL_ERROR; + } - // The number of DOF to be coupled - // int numDOF = argc - 3; - - // The constraint matrix ... U_c = C_cr * U_r - Matrix Ccr (numDOF, numDOF); - Ccr.Zero(); - - // The vector containing the retained and constrained DOFs - ID rDOF (numDOF); - ID cDOF (numDOF); - - int i, j, k; - // Read the degrees of freedom which are to be coupled - for (i = 4, j = 5, k = 0; k < numDOF; i+=2, j+=2, k++) { - if (Tcl_GetInt(interp, argv[i], &dofIDR) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid dofID: " << argv[3] - << " equalDOF RnodeID? CnodeID? DOF1? DOF2? ..."; - return TCL_ERROR; - } - if (Tcl_GetInt(interp, argv[j], &dofIDC) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid dofID: " << argv[3] - << " equalDOF RnodeID? CnodeID? DOF1? DOF2? ..."; - return TCL_ERROR; - } - - dofIDR -= 1; // Decrement for 0-based indexing - dofIDC -= 1; - if (dofIDC < 0 || dofIDR < 0) { - opserr << OpenSees::PromptValueError << "invalid dofID: " << argv[i] - << " must be >= 1"; - return TCL_ERROR; - } - rDOF(k) = dofIDR; - cDOF(k) = dofIDC; - Ccr(k,k) = 1.0; - } + // The number of DOF to be coupled + // int numDOF = argc - 3; - // Create the multi-point constraint - MP_Constraint *theMP = new MP_Constraint (RnodeID, CnodeID, Ccr, cDOF, rDOF); + // The constraint matrix ... U_c = C_cr * U_r + Matrix Ccr (numDOF, numDOF); + Ccr.Zero(); - // Add the multi-point constraint to the domain - if (theTclDomain->addMP_Constraint (theMP) == false) { - opserr << OpenSees::PromptValueError << "could not add equalDOF MP_Constraint to domain "; - delete theMP; - return TCL_ERROR; - } + // The vector containing the retained and constrained DOFs + ID rDOF (numDOF); + ID cDOF (numDOF); - Tcl_SetObjResult(interp, Tcl_NewIntObj(theMP->getTag())); - return TCL_OK; + int i, j, k; + // Read the degrees of freedom which are to be coupled + for (i = 4, j = 5, k = 0; k < numDOF; i+=2, j+=2, k++) { + if (Tcl_GetInt(interp, argv[i], &dofIDR) != TCL_OK) { + opserr << OpenSees::PromptValueError << "invalid dofID: " << argv[3] + << " equalDOF RnodeID? CnodeID? DOF1? DOF2? ..."; + return TCL_ERROR; + } + if (Tcl_GetInt(interp, argv[j], &dofIDC) != TCL_OK) { + opserr << OpenSees::PromptValueError << "invalid dofID: " << argv[3] + << " equalDOF RnodeID? CnodeID? DOF1? DOF2? ..."; + return TCL_ERROR; + } + + dofIDR -= 1; // Decrement for 0-based indexing + dofIDC -= 1; + if (dofIDC < 0 || dofIDR < 0) { + opserr << OpenSees::PromptValueError << "invalid dofID: " << argv[i] + << " must be >= 1"; + return TCL_ERROR; + } + rDOF(k) = dofIDR; + cDOF(k) = dofIDC; + Ccr(k,k) = 1.0; + } + + // Create the multi-point constraint + MP_Constraint *theMP = new MP_Constraint (RnodeID, CnodeID, Ccr, cDOF, rDOF); + + // Add the multi-point constraint to the domain + if (theTclDomain->addMP_Constraint (theMP) == false) { + opserr << OpenSees::PromptValueError << "could not add equalDOF MP_Constraint to domain "; + delete theMP; + return TCL_ERROR; + } + + Tcl_SetObjResult(interp, Tcl_NewIntObj(theMP->getTag())); + return TCL_OK; } #endif @@ -606,17 +894,15 @@ int TclCommand_addImposedMotionSP(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, TCL_Char ** const argv) { - // TODO: Cleanup - G3_Runtime* rt = G3_getRuntime(interp); - Domain *domain = G3_getDomain(rt); - - // ModelRegistry *theTclBuilder = G3_getSafeBuilder(G3_getRuntime(interp)); - // ModelRegistry *builder = static_cast(clientData); + assert(clientData != nullptr); + ModelRegistry *builder = static_cast(clientData); + Domain* domain = builder->getDomain(); // check number of arguments if (argc < 4) { - opserr << OpenSees::PromptValueError << "bad command - want: imposedMotion nodeId dofID gMotionID\n"; + opserr << OpenSees::PromptValueError + << "bad command - want: imposedMotion nodeId dofID gMotionID\n"; return TCL_ERROR; } @@ -624,14 +910,17 @@ TclCommand_addImposedMotionSP(ClientData clientData, Tcl_Interp *interp, int nodeId, dofId, gMotionID; if (Tcl_GetInt(interp, argv[1], &nodeId) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid nodeId: " << argv[1] - << " - imposedMotion nodeId dofID gMotionID" << "\n"; + opserr << OpenSees::PromptValueError + << "invalid nodeId: " << argv[1] + << " - imposedMotion nodeId dofID gMotionID" + << "\n"; return TCL_ERROR; } if (Tcl_GetInt(interp, argv[2], &dofId) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid dofId: " << argv[2] - << " - imposedMotion " << nodeId << " dofID gMotionID\n"; + << " - imposedMotion " << nodeId << " dofID gMotionID" + << "\n"; return TCL_ERROR; } dofId--; // DECREMENT THE DOF VALUE BY 1 TO GO TO OUR C++ INDEXING @@ -653,19 +942,20 @@ TclCommand_addImposedMotionSP(ClientData clientData, Tcl_Interp *interp, // Node *theNode = domain->getNode(nodeId); if (theNode == nullptr) { - opserr << OpenSees::PromptValueError << "invalid node " << argv[2] << " node not found\n "; + opserr << OpenSees::PromptValueError + << "invalid node " << argv[2] << " node not found\n "; return -1; } int nDof = theNode->getNumberDOF(); if (dofId < 0 || dofId >= nDof) { - opserr << OpenSees::PromptValueError << "invalid dofId: " << argv[2] << " dof specified cannot be <= 0 or greater than num dof at nod\n "; + opserr << OpenSees::PromptValueError + << "invalid dofId: " << argv[2] << " dof specified cannot be <= 0 or greater than num dof at nod\n "; return -2; } - MultiSupportPattern *thePattern = - (MultiSupportPattern*)Tcl_GetAssocData(interp, "theTclMultiSupportPattern", NULL); - if (thePattern == 0) { + MultiSupportPattern *thePattern = builder->getCurrentPattern(); + if (thePattern == nullptr) { opserr << "ERROR no multi-support pattern found\n"; return TCL_ERROR; } @@ -681,7 +971,9 @@ TclCommand_addImposedMotionSP(ClientData clientData, Tcl_Interp *interp, } if (thePattern->addSP_Constraint(theSP) == false) { - opserr << OpenSees::PromptValueError << "could not add SP_Constraint to pattern "; + opserr << OpenSees::PromptValueError + << "could not add SP_Constraint to pattern " + << OpenSees::SignalMessageEnd; delete theSP; return TCL_ERROR; } diff --git a/SRC/runtime/runtime/CMakeLists.txt b/SRC/runtime/runtime/CMakeLists.txt index 755a8cef69..e45ac7626d 100644 --- a/SRC/runtime/runtime/CMakeLists.txt +++ b/SRC/runtime/runtime/CMakeLists.txt @@ -8,12 +8,13 @@ target_sources(OPS_Runtime PRIVATE BasicAnalysisBuilder.cpp - ModelRegistry.cpp + ModelRegistry.cpp + analysis/EigenSolve.cpp TclPackageClassBroker.cpp PUBLIC BasicAnalysisBuilder.h - ModelRegistry.h + ModelRegistry.h TclPackageClassBroker.h ) diff --git a/SRC/runtime/runtime/ModelRegistry.cpp b/SRC/runtime/runtime/ModelRegistry.cpp index e3d327c45f..706ff7ca12 100644 --- a/SRC/runtime/runtime/ModelRegistry.cpp +++ b/SRC/runtime/runtime/ModelRegistry.cpp @@ -36,6 +36,7 @@ #include // For TCL_OK/ERROR +using OpenSees::LoadCase; ModelRegistry::ModelRegistry(Domain &domain, int NDM, int NDF) @@ -125,18 +126,6 @@ ModelRegistry::addSP_Constraint(int axisDirn, double axisValue, const ID &fixity return theDomain->addSP_Constraint(axisDirn, axisValue, fixityCodes, tol); } -LoadPattern * -ModelRegistry::getEnclosingPattern() -{ - return tclEnclosingPattern; -} - -int -ModelRegistry::setEnclosingPattern(LoadPattern* pat) -{ - tclEnclosingPattern = pat; - return 1; -} int ModelRegistry::getCurrentSectionBuilder(int& tag) diff --git a/SRC/runtime/runtime/ModelRegistry.h b/SRC/runtime/runtime/ModelRegistry.h index e22c372149..71063f406b 100644 --- a/SRC/runtime/runtime/ModelRegistry.h +++ b/SRC/runtime/runtime/ModelRegistry.h @@ -27,15 +27,18 @@ #include #include #include - +#include #include - +#include +#include class LoadPattern; +class StaticPattern; class MultiSupportPattern; class OPS_Stream; class ID; class Domain; + class ModelRegistry { public: @@ -79,11 +82,38 @@ class ModelRegistry { return findFreeTag(typeid(T).name(), tag); } + int getCurrentSectionBuilder(int&); void setCurrentSectionBuilder(int); - LoadPattern* getEnclosingPattern(); - int setEnclosingPattern(LoadPattern*); + OpenSees::LoadCase& getLoadCase(); + int setLoadCase(std::string& name); + int newLoadCase(std::string& name); + + template + T* getCurrentPattern() { + if constexpr (std::is_same::value) { + return static_pattern; + } + else if constexpr (std::is_same::value) { + return multi_pattern; + } + else if constexpr (std::is_same::value) { + return tclEnclosingPattern; + } + } + + template + int setCurrentPattern(T* pattern) { + if constexpr (std::is_same::value) { + static_pattern = pattern; + } + else if constexpr (std::is_same::value) { + multi_pattern = pattern; + } + tclEnclosingPattern = static_cast(pattern); + return 0; + } int incrNodalLoadTag(); int decrNodalLoadTag(); @@ -118,12 +148,15 @@ class ModelRegistry { // previously extern variables LoadPattern *tclEnclosingPattern = nullptr; + StaticPattern* static_pattern = nullptr; + MultiSupportPattern* multi_pattern = nullptr; bool section_builder_is_set = false; int current_section_builder = 0; // OBJECT CONTAINERS std::unordered_map> m_registry; + std::unordered_map m_cases; }; From bb67d057993e5ae98337a25c8429701a4f1764e3 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:18:10 -0800 Subject: [PATCH 046/161] Create EigenSolve.h --- SRC/runtime/runtime/analysis/EigenSolve.h | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 SRC/runtime/runtime/analysis/EigenSolve.h diff --git a/SRC/runtime/runtime/analysis/EigenSolve.h b/SRC/runtime/runtime/analysis/EigenSolve.h new file mode 100644 index 0000000000..dae22617c7 --- /dev/null +++ b/SRC/runtime/runtime/analysis/EigenSolve.h @@ -0,0 +1,27 @@ +class AnalysisModel; +class LinearSOE; +class ConstraintHandler; + +class EigenSolve { +public: + struct Options { + int solver = 0; + enum ProblemType { + None, + Standard, + Generalized + } problem = None; + int numMode = 0; + double shift = 0.0; + }; + + int solve(AnalysisModel&, + LinearSOE&, + ConstraintHandler&, + const Options&); +private: + int setup(AnalysisModel&, + LinearSOE&, + const Options&); + int clean(); +}; \ No newline at end of file From 8dd0bb7fd2588d41361331e4b1c42ee131bb6d7b Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:18:13 -0800 Subject: [PATCH 047/161] Create EigenSolve.cpp --- SRC/runtime/runtime/analysis/EigenSolve.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 SRC/runtime/runtime/analysis/EigenSolve.cpp diff --git a/SRC/runtime/runtime/analysis/EigenSolve.cpp b/SRC/runtime/runtime/analysis/EigenSolve.cpp new file mode 100644 index 0000000000..8ef8756caf --- /dev/null +++ b/SRC/runtime/runtime/analysis/EigenSolve.cpp @@ -0,0 +1,17 @@ +#include "EigenSolve.h" +#include +#include +#include +#include +#include +#include +#include + +int +EigenSolve::solve(AnalysisModel& model, + LinearSOE& soe, + ConstraintHandler& handler, + const Options& options) +{ + return 0; +} \ No newline at end of file From 71e5f267c293e36a82ef7ae3603afd3bd7c8b06b Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:20:03 -0800 Subject: [PATCH 048/161] Update CMakeLists.txt --- SRC/analysis/model/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/SRC/analysis/model/CMakeLists.txt b/SRC/analysis/model/CMakeLists.txt index 4b2f7da118..0dcafab86b 100644 --- a/SRC/analysis/model/CMakeLists.txt +++ b/SRC/analysis/model/CMakeLists.txt @@ -7,8 +7,6 @@ target_sources(OPS_Analysis PRIVATE AnalysisModel.cpp - # FE_EleIter.cpp - # DOF_GrpIter.cpp PUBLIC AnalysisModel.h FE_EleIter.h From 538c28584e606b4e69a8344c319d2668fdf30f02 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:21:09 -0800 Subject: [PATCH 049/161] Update FE_EleIter.h --- SRC/analysis/model/FE_EleIter.h | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/SRC/analysis/model/FE_EleIter.h b/SRC/analysis/model/FE_EleIter.h index e66a02f5ee..4235d89be4 100644 --- a/SRC/analysis/model/FE_EleIter.h +++ b/SRC/analysis/model/FE_EleIter.h @@ -42,22 +42,6 @@ class TaggedObjectIter; class TaggedObjectStorage; class FE_Element; -#if 0 -class FE_EleIter -{ - public: - FE_EleIter(); - FE_EleIter(TaggedObjectStorage *); - virtual ~FE_EleIter(); - virtual void reset(void); - virtual FE_Element *operator()(void); - - protected: - - private: - TaggedObjectIter *myIter; -}; -#endif #endif From 58606673608f9dbb03f7e07f0c9c809437dbd704 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:21:12 -0800 Subject: [PATCH 050/161] Update DOF_GrpIter.h --- SRC/analysis/model/DOF_GrpIter.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/SRC/analysis/model/DOF_GrpIter.h b/SRC/analysis/model/DOF_GrpIter.h index cd38753bf1..25f14b110f 100644 --- a/SRC/analysis/model/DOF_GrpIter.h +++ b/SRC/analysis/model/DOF_GrpIter.h @@ -38,22 +38,5 @@ class DOF_Group; class TaggedObjectStorage; class TaggedObjectIter; -#if 0 -class DOF_GrpIter -{ - public: - DOF_GrpIter(); - DOF_GrpIter(TaggedObjectStorage *); - virtual ~DOF_GrpIter(); - - virtual void reset(void); - virtual DOF_Group *operator()(void); - - protected: - - private: - TaggedObjectIter *myIter; -}; -#endif #endif From 90b80f0472cd30a172865b016e1548d5335a9cec Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:26:26 -0800 Subject: [PATCH 051/161] Delete Makefile --- SRC/analysis/dof_grp/Makefile | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 SRC/analysis/dof_grp/Makefile diff --git a/SRC/analysis/dof_grp/Makefile b/SRC/analysis/dof_grp/Makefile deleted file mode 100644 index e218cb0d3d..0000000000 --- a/SRC/analysis/dof_grp/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../../../Makefile.def - -OBJS = DOF_Group.o LagrangeDOF_Group.o TransformationDOF_Group.o - -# Compilation control - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. From 770353283bb67faa96597eaa717aae733be2c6fb Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:26:29 -0800 Subject: [PATCH 052/161] Delete Makefile --- SRC/analysis/fe_ele/transformation/Makefile | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 SRC/analysis/fe_ele/transformation/Makefile diff --git a/SRC/analysis/fe_ele/transformation/Makefile b/SRC/analysis/fe_ele/transformation/Makefile deleted file mode 100644 index a02695e61e..0000000000 --- a/SRC/analysis/fe_ele/transformation/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -include ../../../../Makefile.def - -OBJS = TransformationFE.o - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - - -# DO NOT DELETE THIS LINE -- make depend depends on it. From d0658ac5819363287a3fd8a8649787cd81280eec Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:27:08 -0800 Subject: [PATCH 053/161] Update MP_Constraint.cpp --- SRC/domain/constraints/MP_Constraint.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/SRC/domain/constraints/MP_Constraint.cpp b/SRC/domain/constraints/MP_Constraint.cpp index 15e64fe586..2666e21dab 100644 --- a/SRC/domain/constraints/MP_Constraint.cpp +++ b/SRC/domain/constraints/MP_Constraint.cpp @@ -58,12 +58,7 @@ MP_Constraint::MP_Constraint(int nodeRetain, int nodeConstr, numMPs++; constrDOF = new ID(constrainedDOF); - retainDOF = new ID(retainedDOF); - if (constrDOF == 0 || constrainedDOF.Size() != constrDOF->Size() || - retainDOF == 0 || retainedDOF.Size() != retainDOF->Size()) { - opserr << "MP_Constraint::MP_Constraint - ran out of memory 1\n"; - exit(-1); - } + retainDOF = new ID(retainedDOF); // resize initial state Uc0.resize(constrDOF->Size()); From f738ec143b18aa0394f3b5e4bfc2eca39252e1a0 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 12:19:51 -0800 Subject: [PATCH 054/161] Remove displaySelf methods and clean up element interfaces Deleted all displaySelf methods and related Renderer includes from element classes, simplifying the interface and removing unused visualization code. Updated method signatures for sendSelf, recvSelf, and Print to use consistent argument lists and removed Makefiles for deleted or refactored modules. --- SRC/domain/node/Makefile | 20 ----- .../Bearing/elastomeric/LeadRubberY.cpp | 12 --- SRC/element/Bearing/elastomeric/LeadRubberY.h | 5 +- SRC/element/Bearing/elastomeric/Makefile | 31 -------- .../Bearing/friction/RJWatsonEQS3d.cpp | 35 -------- SRC/element/Bearing/friction/RJWatsonEQS3d.h | 1 - .../Bearing/friction/SingleFPSimple3d.cpp | 35 -------- .../Bearing/friction/SingleFPSimple3d.h | 7 +- .../friction/TripleFrictionPendulum.cpp | 34 -------- SRC/element/Plane/Nine_Four_Node_QuadUP.cpp | 61 -------------- SRC/element/Plane/Nine_Four_Node_QuadUP.h | 12 +-- SRC/element/Truss/CorotTruss.cpp | 16 ---- SRC/element/Truss/CorotTruss.h | 9 +-- SRC/element/community/UWelements/SSPbrick.cpp | 44 ----------- SRC/element/community/UWelements/SSPbrick.h | 15 ++-- SRC/element/mefi/MEFI.cpp | 32 -------- SRC/element/mefi/MEFI.h | 13 ++- SRC/element/mvlem/E_SFI.cpp | 79 ------------------- SRC/element/mvlem/E_SFI.h | 7 +- SRC/element/mvlem/MVLEM.cpp | 78 ------------------ SRC/element/mvlem/MVLEM.h | 3 +- SRC/element/mvlem/Makefile | 21 ----- SRC/element/mvlem/SFI_MVLEM.cpp | 79 ------------------- SRC/element/mvlem/SFI_MVLEM.h | 21 +++-- 24 files changed, 38 insertions(+), 632 deletions(-) delete mode 100644 SRC/domain/node/Makefile delete mode 100644 SRC/element/Bearing/elastomeric/Makefile delete mode 100644 SRC/element/mvlem/Makefile diff --git a/SRC/domain/node/Makefile b/SRC/domain/node/Makefile deleted file mode 100644 index f9915cccb3..0000000000 --- a/SRC/domain/node/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../../../Makefile.def - -OBJS = Node.o NodalLoad.o - -# Compilation control - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/element/Bearing/elastomeric/LeadRubberY.cpp b/SRC/element/Bearing/elastomeric/LeadRubberY.cpp index aeff8fad31..f0715c4674 100755 --- a/SRC/element/Bearing/elastomeric/LeadRubberY.cpp +++ b/SRC/element/Bearing/elastomeric/LeadRubberY.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -1088,17 +1087,6 @@ int LeadRubberY::recvSelf(int commitTag, Channel &rChannel, } -int LeadRubberY::displaySelf(Renderer &theViewer, - int displayMode, float fact, const char **modes, int numMode) -{ - static Vector v1(3); - static Vector v2(3); - - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - return theViewer.drawLine(v1, v2, 1.0, 1.0, this->getTag()); -} void LeadRubberY::Print(OPS_Stream &s, int flag) diff --git a/SRC/element/Bearing/elastomeric/LeadRubberY.h b/SRC/element/Bearing/elastomeric/LeadRubberY.h index 5ab24b84aa..ae9ac51119 100644 --- a/SRC/element/Bearing/elastomeric/LeadRubberY.h +++ b/SRC/element/Bearing/elastomeric/LeadRubberY.h @@ -81,9 +81,8 @@ class LeadRubberY : public Element const Vector &getResistingForceIncInertia(); // Public methods for element output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); void Print(OPS_Stream &s, int flag); // Public methods for element recorder diff --git a/SRC/element/Bearing/elastomeric/Makefile b/SRC/element/Bearing/elastomeric/Makefile deleted file mode 100644 index 8a55417fb3..0000000000 --- a/SRC/element/Bearing/elastomeric/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -include ../../../Makefile.def - -OBJS = ElastomericBearingPlasticity2d.o \ - ElastomericBearingPlasticity3d.o \ - ElastomericBearingBoucWen2d.o \ - ElastomericBearingBoucWen3d.o \ - ElastomericBearingBoucWenMod3d.o \ - ElastomericBearingUFRP2d.o \ - ElastomericX.o \ - HDR.o \ - LeadRubberX.o \ - TclElastomericBearingBoucWenCommand.o \ - TclElastomericBearingUFRPCommand.o \ - TclElastomericBearingPlasticityCommand.o - -# Compilation control - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/element/Bearing/friction/RJWatsonEQS3d.cpp b/SRC/element/Bearing/friction/RJWatsonEQS3d.cpp index 4820b07c7f..3efd69bcce 100644 --- a/SRC/element/Bearing/friction/RJWatsonEQS3d.cpp +++ b/SRC/element/Bearing/friction/RJWatsonEQS3d.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -793,40 +792,6 @@ int RJWatsonEQS3d::recvSelf(int commitTag, Channel &rChannel, } -int RJWatsonEQS3d::displaySelf(Renderer &theViewer, - int displayMode, float fact, const char **modes, int numMode) -{ - int errCode = 0; - - // get coordinates - const Vector& end1Crd = theNodes[0]->getCrds(); - const Vector& end2Crd = theNodes[1]->getCrds(); - Vector xp = end2Crd - end1Crd; - - // get displaced coordinates for ends - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - // get displacement vector for rotation - static Vector r2(6); - theNodes[1]->getDisplayRots(r2, fact, displayMode); - - // calculate coordinates of intermediate point - for (int i = 0; i < 2; i++) { - v3(0) = v1(0) + v2(0) - end2Crd(0) + xp(1) * r2(2) - xp(2) * r2(1); - v3(1) = v1(1) + v2(1) - end2Crd(1) - xp(0) * r2(2) + xp(2) * r2(0); - v3(2) = v1(2) + v2(2) - end2Crd(2) + xp(0) * r2(1) - xp(1) * r2(0); - } - - errCode += theViewer.drawLine(v1, v3, 1.0, 1.0, this->getTag(), 0); - errCode += theViewer.drawLine(v3, v2, 1.0, 1.0, this->getTag(), 0); - - return errCode; -} - void RJWatsonEQS3d::Print(OPS_Stream &s, int flag) { diff --git a/SRC/element/Bearing/friction/RJWatsonEQS3d.h b/SRC/element/Bearing/friction/RJWatsonEQS3d.h index 4017a73c84..654153aa2a 100644 --- a/SRC/element/Bearing/friction/RJWatsonEQS3d.h +++ b/SRC/element/Bearing/friction/RJWatsonEQS3d.h @@ -91,7 +91,6 @@ class RJWatsonEQS3d : public Element // public methods for element output int sendSelf(int commitTag, Channel &theChannel); int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); void Print(OPS_Stream &s, int flag = 0); Response *setResponse(const char **argv, int argc, OPS_Stream &s); diff --git a/SRC/element/Bearing/friction/SingleFPSimple3d.cpp b/SRC/element/Bearing/friction/SingleFPSimple3d.cpp index 279f9d905d..335d00bef2 100755 --- a/SRC/element/Bearing/friction/SingleFPSimple3d.cpp +++ b/SRC/element/Bearing/friction/SingleFPSimple3d.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -799,40 +798,6 @@ int SingleFPSimple3d::recvSelf(int commitTag, Channel &rChannel, } -int SingleFPSimple3d::displaySelf(Renderer &theViewer, - int displayMode, float fact, const char **modes, int numMode) -{ - int errCode = 0; - - // get coordinates - const Vector& end1Crd = theNodes[0]->getCrds(); - const Vector& end2Crd = theNodes[1]->getCrds(); - Vector xp = end2Crd - end1Crd; - - // get displaced coordinates for ends - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - // get displacement vector for rotation - static Vector r2(6); - theNodes[1]->getDisplayRots(r2, fact, displayMode); - - // calculate coordinates of intermediate point - for (int i = 0; i < 2; i++) { - v3(0) = v1(0) + v2(0) - end2Crd(0) + xp(1) * r2(2) - xp(2) * r2(1); - v3(1) = v1(1) + v2(1) - end2Crd(1) - xp(0) * r2(2) + xp(2) * r2(0); - v3(2) = v1(2) + v2(2) - end2Crd(2) + xp(0) * r2(1) - xp(1) * r2(0); - } - - errCode += theViewer.drawLine(v1, v3, 1.0, 1.0, this->getTag(), 0); - errCode += theViewer.drawLine(v3, v2, 1.0, 1.0, this->getTag(), 0); - - return errCode; -} - void SingleFPSimple3d::Print(OPS_Stream &s, int flag) { diff --git a/SRC/element/Bearing/friction/SingleFPSimple3d.h b/SRC/element/Bearing/friction/SingleFPSimple3d.h index a1f356900b..73b3b5393e 100755 --- a/SRC/element/Bearing/friction/SingleFPSimple3d.h +++ b/SRC/element/Bearing/friction/SingleFPSimple3d.h @@ -85,10 +85,9 @@ class SingleFPSimple3d : public Element const Vector &getResistingForceIncInertia(); // public methods for element output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); - void Print(OPS_Stream &s, int flag = 0); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); + void Print(OPS_Stream &s, int flag); Response *setResponse(const char **argv, int argc, OPS_Stream &s); int getResponse(int responseID, Information &eleInformation); diff --git a/SRC/element/Bearing/friction/TripleFrictionPendulum.cpp b/SRC/element/Bearing/friction/TripleFrictionPendulum.cpp index 3ecd4e9fe1..8c7eaf25d6 100644 --- a/SRC/element/Bearing/friction/TripleFrictionPendulum.cpp +++ b/SRC/element/Bearing/friction/TripleFrictionPendulum.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -874,39 +873,6 @@ int TripleFrictionPendulum::recvSelf(int commitTag, Channel &theChannel, FEM_Obj } -int TripleFrictionPendulum::displaySelf(Renderer &theViewer, - int displayMode, float fact, const char **modes, int numMode) -{ - int errCode = 0; - - // get coordinates - const Vector& end1Crd = theNodes[0]->getCrds(); - const Vector& end2Crd = theNodes[1]->getCrds(); - Vector xp = end2Crd - end1Crd; - - // get displaced coordinates for ends - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - // get displacement vector for rotation - static Vector r2(6); - theNodes[1]->getDisplayRots(r2, fact, displayMode); - - // calculate coordinates of intermediate point - for (int i = 0; i < 2; i++) { - v3(0) = v1(0) + v2(0) - end2Crd(0) + xp(1) * r2(2) - xp(2) * r2(1); - v3(1) = v1(1) + v2(1) - end2Crd(1) - xp(0) * r2(2) + xp(2) * r2(0); - v3(2) = v1(2) + v2(2) - end2Crd(2) + xp(0) * r2(1) - xp(1) * r2(0); - } - - errCode += theViewer.drawLine(v1, v3, 1.0, 1.0, this->getTag(), 0); - errCode += theViewer.drawLine(v3, v2, 1.0, 1.0, this->getTag(), 0); - - return errCode; -} void TripleFrictionPendulum::Print(OPS_Stream &s, int flag) diff --git a/SRC/element/Plane/Nine_Four_Node_QuadUP.cpp b/SRC/element/Plane/Nine_Four_Node_QuadUP.cpp index e8230e965b..81fb213285 100644 --- a/SRC/element/Plane/Nine_Four_Node_QuadUP.cpp +++ b/SRC/element/Plane/Nine_Four_Node_QuadUP.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -929,66 +928,6 @@ NineFourNodeQuadUP::Print(OPS_Stream &s, int flag) s << "\t\tGauss point " << i+1 << ": " << theMaterial[i]->getStress(); } -int -NineFourNodeQuadUP::displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode) -{ - // get the end point display coords - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - static Vector v4(3); - static Vector v5(3); - static Vector v6(3); - static Vector v7(3); - static Vector v8(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - theNodes[2]->getDisplayCrds(v3, fact, displayMode); - theNodes[3]->getDisplayCrds(v4, fact, displayMode); - theNodes[4]->getDisplayCrds(v5, fact, displayMode); - theNodes[5]->getDisplayCrds(v6, fact, displayMode); - theNodes[6]->getDisplayCrds(v7, fact, displayMode); - theNodes[7]->getDisplayCrds(v8, fact, displayMode); - // place values in coords matrix - static Matrix coords(8, 3); - for (int i = 0; i < 3; i++) { - coords(0, i) = v1(i); - coords(1, i) = v5(i); - coords(2, i) = v2(i); - coords(3, i) = v6(i); - coords(4, i) = v3(i); - coords(5, i) = v7(i); - coords(6, i) = v4(i); - coords(7, i) = v8(i); - } - // set the quantity to be displayed at the nodes; - // if displayMode is 1 through 8 we will plot material stresses otherwise 0.0 - static Vector values(8); - if (displayMode < 8 && displayMode > 0) { - const Vector& stress1 = theMaterial[0]->getStress(); - const Vector& stress2 = theMaterial[1]->getStress(); - const Vector& stress3 = theMaterial[2]->getStress(); - const Vector& stress4 = theMaterial[3]->getStress(); - const Vector& stress5 = theMaterial[4]->getStress(); - const Vector& stress6 = theMaterial[5]->getStress(); - const Vector& stress7 = theMaterial[6]->getStress(); - const Vector& stress8 = theMaterial[7]->getStress(); - values(0) = stress1(displayMode - 1); - values(1) = stress5(displayMode - 1); - values(2) = stress2(displayMode - 1); - values(3) = stress6(displayMode - 1); - values(4) = stress3(displayMode - 1); - values(5) = stress7(displayMode - 1); - values(6) = stress4(displayMode - 1); - values(7) = stress8(displayMode - 1); - } - else { - for (int i = 0; i < 8; i++) - values(i) = 0.0; - } - // draw the polygon - return theViewer.drawPolygon(coords, values, this->getTag()); -} Response* NineFourNodeQuadUP::setResponse(const char **argv, int argc, OPS_Stream &output) diff --git a/SRC/element/Plane/Nine_Four_Node_QuadUP.h b/SRC/element/Plane/Nine_Four_Node_QuadUP.h index 8cbaf3bc1d..e4af8ecfe2 100644 --- a/SRC/element/Plane/Nine_Four_Node_QuadUP.h +++ b/SRC/element/Plane/Nine_Four_Node_QuadUP.h @@ -16,9 +16,6 @@ #ifndef NineFourNodeQuadUP_h #define NineFourNodeQuadUP_h -#ifndef _bool_h -#include -#endif #include #include @@ -40,8 +37,7 @@ class NineFourNodeQuadUP : public Element NineFourNodeQuadUP(); virtual ~NineFourNodeQuadUP(); - const char *getClassType(void) const {return "NineFourNodeQuadUP";}; - static constexpr const char* class_name = "NineFourNodeQuadUP"; + const char *getClassType(void) const {return "NineFourNodeQuadUP";} int getNumExternalNodes(void) const; const ID &getExternalNodes(void); Node **getNodePtrs(void); @@ -68,10 +64,8 @@ class NineFourNodeQuadUP : public Element const Vector &getResistingForceIncInertia(void); // public methods for element output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker - &theBroker); - int displaySelf(Renderer &, int mode, float fact, const char **displayModes=0, int numModes=0); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); void Print(OPS_Stream &, int flag) final; Response *setResponse(const char **argv, int argc, OPS_Stream &s); diff --git a/SRC/element/Truss/CorotTruss.cpp b/SRC/element/Truss/CorotTruss.cpp index f2b2116e43..e2961c0d63 100644 --- a/SRC/element/Truss/CorotTruss.cpp +++ b/SRC/element/Truss/CorotTruss.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -764,22 +763,7 @@ CorotTruss::recvSelf(int commitTag, Channel& theChannel, FEM_ObjectBroker& theBr return 0; } -int -CorotTruss::displaySelf(Renderer& theViewer, int displayMode, float fact, const char** modes, - int numMode) -{ - // ensure setDomain() worked - if (Ln == 0.0) - return 0; - static Vector v1(3); - static Vector v2(3); - - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - return theViewer.drawLine(v1, v2, 1.0, 1.0, this->getTag()); -} void CorotTruss::Print(OPS_Stream& s, int flag) diff --git a/SRC/element/Truss/CorotTruss.h b/SRC/element/Truss/CorotTruss.h index 9269b9911d..4680729330 100644 --- a/SRC/element/Truss/CorotTruss.h +++ b/SRC/element/Truss/CorotTruss.h @@ -80,13 +80,12 @@ class CorotTruss : public Element { int addInertiaLoadToUnbalance(const Vector& accel); const Vector& getResistingForce(void); - const Vector& getResistingForceIncInertia(void); + const Vector& getResistingForceIncInertia(); // public methods for element output - int sendSelf(int commitTag, Channel& theChannel); - int recvSelf(int commitTag, Channel& theChannel, FEM_ObjectBroker& theBroker); - int displaySelf(Renderer&, int mode, float fact, const char** displayModes = 0, int numModes = 0); - void Print(OPS_Stream& s, int flag = 0); + int sendSelf(int commitTag, Channel& ); + int recvSelf(int commitTag, Channel&, FEM_ObjectBroker&); + void Print(OPS_Stream& s, int flag); Response* setResponse(const char** argv, int argc, OPS_Stream& s); int getResponse(int responseID, Information& eleInformation); diff --git a/SRC/element/community/UWelements/SSPbrick.cpp b/SRC/element/community/UWelements/SSPbrick.cpp index 8cb774760f..fbbeb55d6b 100644 --- a/SRC/element/community/UWelements/SSPbrick.cpp +++ b/SRC/element/community/UWelements/SSPbrick.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -911,49 +910,6 @@ SSPbrick::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBrok return 0; } -int -SSPbrick::displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode) -{ - // vertex display coordinate vectors - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - static Vector v4(3); - static Vector v5(3); - static Vector v6(3); - static Vector v7(3); - static Vector v8(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - theNodes[2]->getDisplayCrds(v3, fact, displayMode); - theNodes[3]->getDisplayCrds(v4, fact, displayMode); - theNodes[4]->getDisplayCrds(v5, fact, displayMode); - theNodes[5]->getDisplayCrds(v6, fact, displayMode); - theNodes[6]->getDisplayCrds(v7, fact, displayMode); - theNodes[7]->getDisplayCrds(v8, fact, displayMode); - - // add to coord matrix - static Matrix coords(8, 3); - int i; - for (i = 0; i < 3; i++) { - coords(0, i) = v1(i); - coords(1, i) = v2(i); - coords(2, i) = v3(i); - coords(3, i) = v4(i); - coords(4, i) = v5(i); - coords(5, i) = v6(i); - coords(6, i) = v7(i); - coords(7, i) = v8(i); - } - - // get color vector - static Vector values(8); - for (i = 0; i < 8; i++) - values(i) = 1.0; - - // draw cube - return theViewer.drawCube(coords, values, this->getTag()); -} void SSPbrick::Print(OPS_Stream &s, int flag) diff --git a/SRC/element/community/UWelements/SSPbrick.h b/SRC/element/community/UWelements/SSPbrick.h index f3cbc092ca..737f7727ad 100644 --- a/SRC/element/community/UWelements/SSPbrick.h +++ b/SRC/element/community/UWelements/SSPbrick.h @@ -63,10 +63,10 @@ class SSPbrick : public Element void setDomain(Domain *theDomain); // public methods to set the state of the element - int commitState(void); - int revertToLastCommit(void); - int revertToStart(void); - int update(void); + int commitState(); + int revertToLastCommit(); + int revertToStart(); + int update(); // public methods to obtain stiffness, mass, damping, and residual info const Matrix &getTangentStiff(void); @@ -80,10 +80,9 @@ class SSPbrick : public Element const Vector &getResistingForceIncInertia(void); // public methods for element output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); - void Print(OPS_Stream &s, int flag =0); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); + void Print(OPS_Stream &s, int flag); Response *setResponse(const char **argv, int argc, OPS_Stream &eleInfo); int getResponse(int responseID, Information &eleInformation); diff --git a/SRC/element/mefi/MEFI.cpp b/SRC/element/mefi/MEFI.cpp index 17ff9165ef..65d875110f 100644 --- a/SRC/element/mefi/MEFI.cpp +++ b/SRC/element/mefi/MEFI.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -706,37 +705,6 @@ MEFI::Print(OPS_Stream &s, int flag) }//end Print -int -MEFI::displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode) -{ - //get the end point display coords - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - static Vector v4(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - theNodes[2]->getDisplayCrds(v3, fact, displayMode); - theNodes[3]->getDisplayCrds(v4, fact, displayMode); - - //place values in coords matrix - static Matrix coords(4, 3); - for (int i = 0; i < 3; i++) { - coords(0, i) = v1(i); - coords(1, i) = v2(i); - coords(2, i) = v3(i); - coords(3, i) = v4(i); - } - - static Vector values(4); - for (int i = 0; i < 4; i++) { - values(i) = 0.0; - } - - // draw the polygon - return theViewer.drawPolygon(coords, values, this->getTag()); - -}//end displaySelf Response* MEFI::setResponse(const char **argv, int argc, OPS_Stream &output) { diff --git a/SRC/element/mefi/MEFI.h b/SRC/element/mefi/MEFI.h index 265eb0f7f2..f2930d96d3 100644 --- a/SRC/element/mefi/MEFI.h +++ b/SRC/element/mefi/MEFI.h @@ -9,7 +9,7 @@ // points and weights of the classical finite element formulation of membrane elements to resemble strips (fibers), similarly to macroscopic elements. // // Reference: -// 1.- López, C. N., Rojas, F., & Massone, L. M. (2022). Membrane fiber element for reinforced concrete walls – the benefits of macro and micro modeling approaches. Engineering Structures, 254, 113819. +// 1.- L�pez, C. N., Rojas, F., & Massone, L. M. (2022). Membrane fiber element for reinforced concrete walls � the benefits of macro and micro modeling approaches. Engineering Structures, 254, 113819. // // Source: /usr/local/cvs/OpenSees/SRC/element/mefi/MEFI.h // @@ -67,15 +67,12 @@ class MEFI : public Element const Vector &getResistingForceIncInertia(void); // public methods for element output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker - &theBroker); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); - int displaySelf(Renderer &, int mode, float fact, const char **displayModes=0, int numModes=0); - void Print(OPS_Stream &s, int flag =0); + void Print(OPS_Stream &s, int flag); - Response *setResponse(const char **argv, int argc, - OPS_Stream &s); + Response *setResponse(const char **argv, int argc, OPS_Stream &s); int getResponse(int responseID, Information &eleInformation); diff --git a/SRC/element/mvlem/E_SFI.cpp b/SRC/element/mvlem/E_SFI.cpp index 90b881fe3c..951332b208 100644 --- a/SRC/element/mvlem/E_SFI.cpp +++ b/SRC/element/mvlem/E_SFI.cpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -712,84 +711,6 @@ int E_SFI::recvSelf(int commitTag, Channel& theChannel, FEM_ObjectBroker& theBro return 0; } -// Display model -int E_SFI::displaySelf(Renderer& theViewer, int displayMode, float fact, const char** modes, int numMode) -{ - // Get the end points of the beam for the display factor - static Vector v1(3); - static Vector v2(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - // determine the deformation - rotation - other is taken from v1, v2 - static Vector r1(1); - theNodes[0]->getDisplayRots(r1, fact, displayMode); - - // Displaying wall axis - int error = 0; - Vector RGB(3); - RGB(0) = 0.0; - RGB(1) = 1.0; - RGB(2) = 0.0; - error += theViewer.drawLine(v1, v2, RGB, RGB, 1, 1); - - // Displaying Panels - for (int panel = 0; panel < m; panel++) // loop over m panels - { - Matrix NodePLotCrds(m, 13); // (panel id, x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4) - - // first set the quantity to be displayed at the nodes; - // if displayMode is 1 through 3 we will plot material stresses otherwise 0.0 - static Vector values(1); // values to be plotted (either epsX, epsY, gammaXY) - if (displayMode < 4 && displayMode > 0) { - const Vector& stress = theMaterial[panel]->getStrain(); - values(0) = stress(displayMode - 1); - } - else { - values(0) = 0.0; - } - - // Panel nodes - NodePLotCrds(panel, 0) = panel + 1; // panel id - // Local node 1 - bottom left - NodePLotCrds(panel, 1) = v1(0) + x[panel] - b[panel] / 2.0; // x - NodePLotCrds(panel, 2) = v1(1) + (x[panel] - b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 3) = v1(2); // z - // Local node 2 - bottom right - NodePLotCrds(panel, 4) = v1(0) + x[panel] + b[panel] / 2.0; // x - NodePLotCrds(panel, 5) = v1(1) + (x[panel] + b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 6) = v1(2); // z - // Local node 3 - top left - NodePLotCrds(panel, 7) = v2(0) + x[panel] + b[panel] / 2.0; // x - NodePLotCrds(panel, 8) = v2(1) + (x[panel] + b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 9) = v2(2); // z - // Local node 4 - top right - NodePLotCrds(panel, 10) = v2(0) + x[panel] - b[panel] / 2.0; // x - NodePLotCrds(panel, 11) = v2(1) + (x[panel] - b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 12) = v2(2); // z - - Matrix coords(4, 3); // Temporary coordinates for plotting - - coords(0, 0) = NodePLotCrds(panel, 1); // node 1 x - coords(1, 0) = NodePLotCrds(panel, 4); // node 2 x - coords(2, 0) = NodePLotCrds(panel, 7); // node 3 x - coords(3, 0) = NodePLotCrds(panel, 10); // node 4 x - - coords(0, 1) = NodePLotCrds(panel, 2); // node 1 y - coords(1, 1) = NodePLotCrds(panel, 5); // node 2 y - coords(2, 1) = NodePLotCrds(panel, 8); // node 3 y - coords(3, 1) = NodePLotCrds(panel, 11); // node 4 y - - coords(0, 2) = NodePLotCrds(panel, 3); // node 1 z - coords(1, 2) = NodePLotCrds(panel, 6); // node 2 z - coords(2, 2) = NodePLotCrds(panel, 9); // node 3 z - coords(3, 2) = NodePLotCrds(panel, 12); // node 4 z - - error += theViewer.drawPolygon(coords, values); - } - - return error; -} // Print Element Information void E_SFI::Print(OPS_Stream& s, int flag) diff --git a/SRC/element/mvlem/E_SFI.h b/SRC/element/mvlem/E_SFI.h index e8c59be386..90fac17af3 100644 --- a/SRC/element/mvlem/E_SFI.h +++ b/SRC/element/mvlem/E_SFI.h @@ -80,11 +80,10 @@ class E_SFI : public Element const Vector &getResistingForceIncInertia(void); // public methods for output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); - void Print(OPS_Stream &s, int flag =0); + void Print(OPS_Stream &s, int flag); Response *setResponse(const char **argv, int argc, OPS_Stream &s); int getResponse(int responseID, Information &eleInformation); diff --git a/SRC/element/mvlem/MVLEM.cpp b/SRC/element/mvlem/MVLEM.cpp index f91cf4cc5e..72bbd313a6 100755 --- a/SRC/element/mvlem/MVLEM.cpp +++ b/SRC/element/mvlem/MVLEM.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include @@ -1250,83 +1249,6 @@ MVLEM::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker) return res; } -// Display model -int MVLEM::displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode) -{ - // Get the end points of the beam for the display factor - static Vector v1(3); - static Vector v2(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - // determine the deformation - rotation - other is taken from v1, v2 - static Vector r1(1); - theNodes[0]->getDisplayRots(r1, fact, displayMode); - - // Displaying wall axis - int error = 0; - Vector RGB(3); - RGB(0) = 0.0; - RGB(1) = 1.0; - RGB(2) = 0.0; - error += theViewer.drawLine(v1, v2, RGB, RGB, 1, 1); - - // Displaying Panels - for (int panel = 0; panel < m; panel++) // loop over m panels - { - Matrix NodePLotCrds(m, 13); // (panel id, x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4) - - // first set the quantity to be displayed at the nodes; - // if displayMode is 1 through 3 we will plot material stresses otherwise 0.0 - static Vector values(1); // values to be plotted (either epsX, epsY, gammaXY) - if (displayMode < 4 && displayMode > 0) { - values(0) = theMaterialsConcrete[panel]->getStrain(); - } - else { - values(0) = 0.0; - } - - // Fiber nodes - NodePLotCrds(panel, 0) = panel + 1; // panel id - // Local node 1 - bottom left - NodePLotCrds(panel, 1) = v1(0) + x[panel] - b[panel] / 2.0; // x - NodePLotCrds(panel, 2) = v1(1) + (x[panel] - b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 3) = v1(2); // z - // Local node 2 - bottom right - NodePLotCrds(panel, 4) = v1(0) + x[panel] + b[panel] / 2.0; // x - NodePLotCrds(panel, 5) = v1(1) + (x[panel] + b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 6) = v1(2); // z - // Local node 3 - top left - NodePLotCrds(panel, 7) = v2(0) + x[panel] + b[panel] / 2.0; // x - NodePLotCrds(panel, 8) = v2(1) + (x[panel] + b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 9) = v2(2); // z - // Local node 4 - top right - NodePLotCrds(panel, 10) = v2(0) + x[panel] - b[panel] / 2.0; // x - NodePLotCrds(panel, 11) = v2(1) + (x[panel] - b[panel] / 2.0) * r1(0); // y - NodePLotCrds(panel, 12) = v2(2); // z - - Matrix coords(4, 3); // Temporary coordinates for plotting - - coords(0, 0) = NodePLotCrds(panel, 1); // node 1 x - coords(1, 0) = NodePLotCrds(panel, 4); // node 2 x - coords(2, 0) = NodePLotCrds(panel, 7); // node 3 x - coords(3, 0) = NodePLotCrds(panel, 10); // node 4 x - - coords(0, 1) = NodePLotCrds(panel, 2); // node 1 y - coords(1, 1) = NodePLotCrds(panel, 5); // node 2 y - coords(2, 1) = NodePLotCrds(panel, 8); // node 3 y - coords(3, 1) = NodePLotCrds(panel, 11); // node 4 y - - coords(0, 2) = NodePLotCrds(panel, 3); // node 1 z - coords(1, 2) = NodePLotCrds(panel, 6); // node 2 z - coords(2, 2) = NodePLotCrds(panel, 9); // node 3 z - coords(3, 2) = NodePLotCrds(panel, 12); // node 4 z - - error += theViewer.drawPolygon(coords, values); - } - - return error; -} void MVLEM::Print(OPS_Stream &s, int flag) diff --git a/SRC/element/mvlem/MVLEM.h b/SRC/element/mvlem/MVLEM.h index f175699ba2..e869b2ab51 100644 --- a/SRC/element/mvlem/MVLEM.h +++ b/SRC/element/mvlem/MVLEM.h @@ -82,9 +82,8 @@ class MVLEM : public Element { // public methods for output int sendSelf(int commitTag, Channel &theChannel); int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); - void Print(OPS_Stream &s, int flag = 0); + void Print(OPS_Stream &s, int flag); Response *setResponse(const char **argv, int argc, OPS_Stream &s); int getResponse(int responseID, Information &eleInformation); diff --git a/SRC/element/mvlem/Makefile b/SRC/element/mvlem/Makefile deleted file mode 100644 index 7ecddeee01..0000000000 --- a/SRC/element/mvlem/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../../../Makefile.def - -OBJS = MVLEM.o \ - SFI_MVLEM.o \ - MVLEM_3D.o \ - SFI_MVLEM_3D.o - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/element/mvlem/SFI_MVLEM.cpp b/SRC/element/mvlem/SFI_MVLEM.cpp index 09c160b35c..3f7079855a 100644 --- a/SRC/element/mvlem/SFI_MVLEM.cpp +++ b/SRC/element/mvlem/SFI_MVLEM.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -847,84 +846,6 @@ int SFI_MVLEM::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &th return 0; } -// Display model -int SFI_MVLEM::displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode) -{ - // Get the end points of the beam for the display factor - static Vector v1(3); - static Vector v2(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - - // determine the deformation - rotation - other is taken from v1, v2 - static Vector r1(1); - theNodes[0]->getDisplayRots(r1, fact, displayMode); - - // Displaying wall axis - int error = 0; - Vector RGB(3); - RGB(0) = 0.0; - RGB(1) = 1.0; - RGB(2) = 0.0; - error += theViewer.drawLine (v1, v2, RGB, RGB, 1, 1); - - // Displaying Panels - for (int panel=0; panel < m; panel++) // loop over m panels - { - Matrix NodePLotCrds(m,13); // (panel id, x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4) - - // first set the quantity to be displayed at the nodes; - // if displayMode is 1 through 3 we will plot material stresses otherwise 0.0 - static Vector values(1); // values to be plotted (either epsX, epsY, gammaXY) - if (displayMode < 4 && displayMode > 0) { - const Vector& stress = theMaterial[panel]->getStrain(); - values(0) = stress(displayMode - 1); - } - else { - values(0) = 0.0; - } - - // Panel nodes - NodePLotCrds(panel,0) = panel+1; // panel id - // Local node 1 - bottom left - NodePLotCrds(panel,1) = v1(0) + x[panel]-b[panel]/2.0; // x - NodePLotCrds(panel,2) = v1(1) + (x[panel]-b[panel]/2.0)*r1(0); // y - NodePLotCrds(panel,3) = v1(2); // z - // Local node 2 - bottom right - NodePLotCrds(panel,4) = v1(0) + x[panel]+b[panel]/2.0; // x - NodePLotCrds(panel,5) = v1(1) + (x[panel]+b[panel]/2.0)* r1(0); // y - NodePLotCrds(panel,6) = v1(2); // z - // Local node 3 - top left - NodePLotCrds(panel,7) = v2(0) + x[panel]+b[panel]/2.0; // x - NodePLotCrds(panel,8) = v2(1) +(x[panel]+b[panel]/2.0)* r1(0); // y - NodePLotCrds(panel,9) = v2(2); // z - // Local node 4 - top right - NodePLotCrds(panel,10) = v2(0) + x[panel]-b[panel]/2.0; // x - NodePLotCrds(panel,11) = v2(1) + (x[panel]-b[panel]/2.0)* r1(0); // y - NodePLotCrds(panel,12) = v2(2); // z - - Matrix coords(4,3); // Temporary coordinates for plotting - - coords(0,0) = NodePLotCrds(panel,1); // node 1 x - coords(1,0) = NodePLotCrds(panel,4); // node 2 x - coords(2,0) = NodePLotCrds(panel,7); // node 3 x - coords(3,0) = NodePLotCrds(panel,10); // node 4 x - - coords(0,1) = NodePLotCrds(panel,2); // node 1 y - coords(1,1) = NodePLotCrds(panel,5); // node 2 y - coords(2,1) = NodePLotCrds(panel,8); // node 3 y - coords(3,1) = NodePLotCrds(panel,11); // node 4 y - - coords(0,2) = NodePLotCrds(panel,3); // node 1 z - coords(1,2) = NodePLotCrds(panel,6); // node 2 z - coords(2,2) = NodePLotCrds(panel,9); // node 3 z - coords(3,2) = NodePLotCrds(panel,12); // node 4 z - - error += theViewer.drawPolygon (coords, values); - } - - return error; -} // Print Element Information void SFI_MVLEM::Print(OPS_Stream &s, int flag) diff --git a/SRC/element/mvlem/SFI_MVLEM.h b/SRC/element/mvlem/SFI_MVLEM.h index a08c44d4ce..1f4fae912d 100644 --- a/SRC/element/mvlem/SFI_MVLEM.h +++ b/SRC/element/mvlem/SFI_MVLEM.h @@ -80,23 +80,22 @@ class SFI_MVLEM : public Element int update(void); // public methods to obtain stiffness, mass, damping and residual information - const Matrix &getTangentStiff(void); - const Matrix &getInitialStiff(void); - const Matrix &getDamp(void); - const Matrix &getMass(void); + const Matrix &getTangentStiff(); + const Matrix &getInitialStiff(); + const Matrix &getDamp(); + const Matrix &getMass(); - void zeroLoad(void); + void zeroLoad(); int addLoad(ElementalLoad *theLoad, double loadFactor); int addInertiaLoadToUnbalance(const Vector &accel); - const Vector &getResistingForce(void); - const Vector &getResistingForceIncInertia(void); + const Vector &getResistingForce(); + const Vector &getResistingForceIncInertia(); // public methods for output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); - void Print(OPS_Stream &s, int flag =0); + void Print(OPS_Stream &s, int flag); Response *setResponse(const char **argv, int argc, OPS_Stream &s); int getResponse(int responseID, Information &eleInformation); From 173d7068c0f58220633c5dae1df958fd05c3451d Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 12:22:32 -0800 Subject: [PATCH 055/161] Update constraint.cpp --- SRC/runtime/commands/modeling/constraint.cpp | 124 ++++++++----------- 1 file changed, 52 insertions(+), 72 deletions(-) diff --git a/SRC/runtime/commands/modeling/constraint.cpp b/SRC/runtime/commands/modeling/constraint.cpp index 33d28dd636..62f6034e91 100644 --- a/SRC/runtime/commands/modeling/constraint.cpp +++ b/SRC/runtime/commands/modeling/constraint.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -531,11 +532,11 @@ int TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, Tcl_Size argc, TCL_Char ** const argv) { + assert(clientData != nullptr); ModelRegistry *builder = static_cast(clientData); - Domain *theDomain = (builder != nullptr) ? builder->getDomain() : nullptr; + Domain *domain = builder->getDomain(); // Usage: - // constrain Translation Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}> // constrain Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}> // // where v is a rotation vector (axis * angle in radians), R = Exp(Hat(v)), @@ -543,14 +544,7 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, Tcl_Size argi = 1; - // Optional keyword "Translation" - if (argc > argi && - (std::strcmp(argv[argi], "Translation") == 0 || - std::strcmp(argv[argi], "translation") == 0)) { - ++argi; - } - - if (argc - argi < 3) { + if (argc < 3) { opserr << OpenSees::PromptValueError << "insufficient arguments.\n" << "Usage: constrain Translation Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}>" @@ -558,8 +552,10 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } + // + // Read tags for the retained and constrained nodes + // int RnodeID = 0, CnodeID = 0; - if (Tcl_GetInt(interp, argv[argi + 0], &RnodeID) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid RnodeID: " << argv[argi + 0] @@ -574,8 +570,8 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } - Node *theRetainedNode = theDomain->getNode(RnodeID); - Node *theConstrainedNode = theDomain->getNode(CnodeID); + Node *theRetainedNode = domain->getNode(RnodeID); + Node *theConstrainedNode = domain->getNode(CnodeID); if (theRetainedNode == nullptr || theConstrainedNode == nullptr) { opserr << OpenSees::PromptValueError << "Retained or Constrained node does not exist in the Domain: " @@ -584,7 +580,8 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } - // Parse DOF list argument (a Tcl list in one argv slot) + // Parse DOF list argument. This is a Tcl list in one argv slot: + // {d1 d2 ...} Tcl_Size listSize = 0; const char **listDOF = nullptr; if (Tcl_SplitList(interp, argv[argi + 2], &listSize, &listDOF) != TCL_OK) { @@ -608,20 +605,27 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, ID cDOF(numDOF); std::vector dofIdx(numDOF, -1); - // For a "Translation" constraint, we strongly prefer DOFs to be within the - // coordinate dimension (2D -> {1,2}, 3D -> {1,2,3}). - const int dimR = theRetainedNode->getCrds().Size(); - const int dimC = theConstrainedNode->getCrds().Size(); - const int dim = (dimR < dimC) ? dimR : dimC; - + + + // Check that nodes have valid spatial dimension + int dim = theRetainedNode->getCrds().Size(); if (dim < 1) { Tcl_Free((char*)listDOF); opserr << OpenSees::PromptValueError - << "node coordinate dimension is invalid" - << OpenSees::SignalMessageEnd; + << "node coordinate dimension is invalid" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + // Ensure both nodes have the same dimension + if (dim != theConstrainedNode->getCrds().Size()) { + Tcl_Free((char*)listDOF); + opserr << OpenSees::PromptValueError + << "retained and constrained node coordinate dimensions do not match" + << OpenSees::SignalMessageEnd; return TCL_ERROR; } + // Parse and validate DOF indices for (int i = 0; i < numDOF; ++i) { int dof1 = 0; if (Tcl_GetInt(interp, listDOF[i], &dof1) != TCL_OK) { @@ -639,6 +643,7 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } + // Convert to 0-based index const int d = dof1 - 1; // 0-based // Translation DOFs should live in [0, dim-1] @@ -646,7 +651,8 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, Tcl_Free((char*)listDOF); opserr << OpenSees::PromptValueError << "Translation constraint DOF out of range for node dimension. " - << "Got dof=" << dof1 << " but node dimension is " << dim + << "Got dof=" << dof1 + << " but node dimension is " << dim << OpenSees::SignalMessageEnd; return TCL_ERROR; } @@ -669,12 +675,14 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, Tcl_Free((char*)listDOF); + // // Parse optional -rotate {v1 v2 v3} + // bool doRotate = false; - double vx = 0.0, vy = 0.0, vz = 0.0; + Vector3D v{}; // rotation vector for (Tcl_Size a = argi + 3; a < argc; ++a) { - if (strcmp(argv[a], "-rotate") == 0 || strcmp(argv[a], "-rot") == 0) { + if (strcmp(argv[a], "-rotate") == 0) { if (a + 1 >= argc) { opserr << OpenSees::PromptValueError << "missing vector after -rotate" @@ -690,7 +698,7 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, const char **vec = nullptr; if (Tcl_SplitList(interp, argv[a + 1], &nvec, &vec) != TCL_OK) { opserr << OpenSees::PromptValueError - << "invalid -rotate vector list: " << argv[a + 1] + << "invalid rotate vector list: " << argv[a + 1] << OpenSees::SignalMessageEnd; return TCL_ERROR; } @@ -703,12 +711,12 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } - if (Tcl_GetDouble(interp, vec[0], &vx) != TCL_OK || - Tcl_GetDouble(interp, vec[1], &vy) != TCL_OK || - Tcl_GetDouble(interp, vec[2], &vz) != TCL_OK) { + if (Tcl_GetDouble(interp, vec[0], &v[0]) != TCL_OK || + Tcl_GetDouble(interp, vec[1], &v[1]) != TCL_OK || + Tcl_GetDouble(interp, vec[2], &v[2]) != TCL_OK) { Tcl_Free((char*)vec); opserr << OpenSees::PromptValueError - << "invalid -rotate vector components: " << argv[a + 1] + << "invalid rotate vector components: " << argv[a + 1] << OpenSees::SignalMessageEnd; return TCL_ERROR; } @@ -716,7 +724,8 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, Tcl_Free((char*)vec); doRotate = true; ++a; // skip the vector argument - } else { + } + else { opserr << OpenSees::PromptValueError << "unknown option: " << argv[a] << OpenSees::SignalMessageEnd; @@ -724,7 +733,9 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, } } + // // Build constraint matrix Ccr such that Uc = Ccr * Ur + // Matrix Ccr(numDOF, numDOF); Ccr.Zero(); @@ -732,60 +743,29 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, // Identity -> equalDOF behavior on the selected DOFs for (int i = 0; i < numDOF; ++i) Ccr(i, i) = 1.0; - } else { - - // For 2D models, reject rotation vectors with x or y components - if (dim == 2 && (std::fabs(vx) > 1e-14 || std::fabs(vy) > 1e-14)) { - opserr << OpenSees::PromptValueError - << "2D Translation constraint only supports rotation about global Z. " - << "Use -rotate {0 0 theta} (theta in radians)." - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } + } + else { + // Compute 3x3 rotation R = Exp(v) using Rodrigues’ formula + Matrix3D R = ExpSO3(v); - // Compute 3x3 rotation R = Exp(Hat(v)) using Rodrigues’ formula - double R[3][3]; - for (int i = 0; i < 3; ++i) - for (int j = 0; j < 3; ++j) - R[i][j] = (i == j) ? 1.0 : 0.0; - - const double theta = std::sqrt(vx*vx + vy*vy + vz*vz); - if (theta > 1e-14) { - const double kx = vx / theta; - const double ky = vy / theta; - const double kz = vz / theta; - - const double st = std::sin(theta); - const double ct = std::cos(theta); - const double omc = 1.0 - ct; - - R[0][0] = ct + kx*kx*omc; - R[0][1] = kx*ky*omc - kz*st; - R[0][2] = kx*kz*omc + ky*st; - - R[1][0] = ky*kx*omc + kz*st; - R[1][1] = ct + ky*ky*omc; - R[1][2] = ky*kz*omc - kx*st; - - R[2][0] = kz*kx*omc - ky*st; - R[2][1] = kz*ky*omc + kx*st; - R[2][2] = ct + kz*kz*omc; - } + opserr << "R = " << Matrix(R); // Fill submatrix of R corresponding to requested DOFs for (int i = 0; i < numDOF; ++i) { const int ii = dofIdx[i]; // 0..(dim-1) for (int j = 0; j < numDOF; ++j) { const int jj = dofIdx[j]; - Ccr(i, j) = R[ii][jj]; + Ccr(i, j) = R(ii, jj); } } } - // Create and add MP constraint + opserr << "Ccr = " << Ccr; + + // Create and add MP (multi-point) constraint MP_Constraint *theMP = new MP_Constraint(RnodeID, CnodeID, Ccr, cDOF, rDOF); - if (theDomain->addMP_Constraint(theMP) == false) { + if (domain->addMP_Constraint(theMP) == false) { opserr << OpenSees::PromptValueError << "could not add MP_Constraint to domain" << OpenSees::SignalMessageEnd; From 42ee10e2a305047d22b6a5be1e616b09d451971c Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 18 Jan 2026 15:05:13 -0800 Subject: [PATCH 056/161] Update constraint.cpp --- SRC/runtime/commands/modeling/constraint.cpp | 119 ++++--------------- 1 file changed, 21 insertions(+), 98 deletions(-) diff --git a/SRC/runtime/commands/modeling/constraint.cpp b/SRC/runtime/commands/modeling/constraint.cpp index 62f6034e91..7b936daaac 100644 --- a/SRC/runtime/commands/modeling/constraint.cpp +++ b/SRC/runtime/commands/modeling/constraint.cpp @@ -580,100 +580,17 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } - // Parse DOF list argument. This is a Tcl list in one argv slot: - // {d1 d2 ...} - Tcl_Size listSize = 0; - const char **listDOF = nullptr; - if (Tcl_SplitList(interp, argv[argi + 2], &listSize, &listDOF) != TCL_OK) { - opserr << OpenSees::PromptValueError - << "invalid dof list: " << argv[argi + 2] - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - if (listSize <= 0) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "empty dof list" - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - - const int numDOF = static_cast(listSize); + const int numDOF = builder->getNDF(); // Prepare IDs and store 0-based indices of requested DOFs ID rDOF(numDOF); ID cDOF(numDOF); - std::vector dofIdx(numDOF, -1); - - - - // Check that nodes have valid spatial dimension - int dim = theRetainedNode->getCrds().Size(); - if (dim < 1) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "node coordinate dimension is invalid" - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - // Ensure both nodes have the same dimension - if (dim != theConstrainedNode->getCrds().Size()) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "retained and constrained node coordinate dimensions do not match" - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - - // Parse and validate DOF indices - for (int i = 0; i < numDOF; ++i) { - int dof1 = 0; - if (Tcl_GetInt(interp, listDOF[i], &dof1) != TCL_OK) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "invalid dof value: " << listDOF[i] - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - if (dof1 <= 0) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "dof values must be >= 1, got: " << dof1 - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - // Convert to 0-based index - const int d = dof1 - 1; // 0-based - - // Translation DOFs should live in [0, dim-1] - if (d < 0 || d >= dim) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "Translation constraint DOF out of range for node dimension. " - << "Got dof=" << dof1 - << " but node dimension is " << dim - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - - // Check duplicates - for (int k = 0; k < i; ++k) { - if (dofIdx[k] == d) { - Tcl_Free((char*)listDOF); - opserr << OpenSees::PromptValueError - << "duplicate dof in list: " << dof1 - << OpenSees::SignalMessageEnd; - return TCL_ERROR; - } - } - - dofIdx[i] = d; - cDOF(i) = d; - rDOF(i) = d; + for (int i=0; i= argc) { opserr << OpenSees::PromptValueError @@ -748,20 +665,26 @@ TclCommand_constrain(ClientData clientData, Tcl_Interp *interp, // Compute 3x3 rotation R = Exp(v) using Rodrigues’ formula Matrix3D R = ExpSO3(v); - opserr << "R = " << Matrix(R); - - // Fill submatrix of R corresponding to requested DOFs - for (int i = 0; i < numDOF; ++i) { - const int ii = dofIdx[i]; // 0..(dim-1) - for (int j = 0; j < numDOF; ++j) { - const int jj = dofIdx[j]; - Ccr(i, j) = R(ii, jj); + switch (builder->getNDM()) { + case 3: { + // Map R into the 6x6 Ccr for 3D problems + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + Ccr(i, j) = R(i, j); + for (int i = 3; i < 6; ++i) + for (int j = 3; j < 6; ++j) + Ccr(i, j) = R(i - 3, j - 3); + break; + } + default: { + opserr << OpenSees::PromptValueError + << "constrain command - rotation only implemented for 3D problems" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; } } } - opserr << "Ccr = " << Ccr; - // Create and add MP (multi-point) constraint MP_Constraint *theMP = new MP_Constraint(RnodeID, CnodeID, Ccr, cDOF, rDOF); From afcc78d8165112db4154a4abd9ba3bc6207e57d9 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:35:22 -0800 Subject: [PATCH 057/161] Remove displaySelf from N4BiaxialTruss and fix rigid_links Removed the displaySelf method and related Renderer include from N4BiaxialTruss, and updated the header accordingly. Also fixed a bug in rigid_links.cpp where the constrained node was not properly checked for null, and corrected indentation in a conditional block. --- SRC/element/Truss/N4BiaxialTruss.cpp | 53 --------------------- SRC/element/Truss/N4BiaxialTruss.h | 13 +++-- SRC/runtime/commands/domain/rigid_links.cpp | 4 +- 3 files changed, 8 insertions(+), 62 deletions(-) diff --git a/SRC/element/Truss/N4BiaxialTruss.cpp b/SRC/element/Truss/N4BiaxialTruss.cpp index fbae96fef7..c172c78f5b 100644 --- a/SRC/element/Truss/N4BiaxialTruss.cpp +++ b/SRC/element/Truss/N4BiaxialTruss.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -1019,58 +1018,6 @@ N4BiaxialTruss::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &t } -int -N4BiaxialTruss::displaySelf(Renderer &theViewer, int displayMode, float fact, const char **modes, int numMode) -{ - // ensure setDomain() worked - if (L == 0.0) - return 0; - - // get display coordinates - static Vector v1(3); - static Vector v2(3); - static Vector v3(3); - static Vector v4(3); - theNodes[0]->getDisplayCrds(v1, fact, displayMode); - theNodes[1]->getDisplayCrds(v2, fact, displayMode); - theNodes[2]->getDisplayCrds(v3, fact, displayMode); - theNodes[3]->getDisplayCrds(v4, fact, displayMode); - - // determine color and draw lines - int retVal = 0; - if (displayMode == 1 || displayMode == 2) { - // compute the strain and axial force in the member - double force1, force2; - if (L == 0.0) { - strain_1 = 0.0; - strain_2 = 0.0; - force1 = 0.0; - force2 = 0.0; - } - else { - this->computeCurrentStrainBiaxial(); - theMaterial_1->setTrialStrain(strain_1); - theMaterial_2->setTrialStrain(strain_2); - force1 = A * theMaterial_1->getStress(); - force2 = A * theMaterial_2->getStress(); - } - if (displayMode == 2) {// use the strain as the drawing measure - retVal += theViewer.drawLine(v1, v2, (float)strain_1, (float)strain_1); - retVal += theViewer.drawLine(v3, v4, (float)strain_2, (float)strain_2); - } - else { // otherwise use the axial force as measure - retVal += theViewer.drawLine(v1, v2, (float)force1, (float)force1); - retVal += theViewer.drawLine(v3, v4, (float)force2, (float)force2); - } - - } - else { - retVal += theViewer.drawLine(v1, v2, 1.0, 1.0); - retVal += theViewer.drawLine(v3, v4, 1.0, 1.0); - } - return retVal; -} - void N4BiaxialTruss::Print(OPS_Stream &s, int flag) { diff --git a/SRC/element/Truss/N4BiaxialTruss.h b/SRC/element/Truss/N4BiaxialTruss.h index 877d24d0c9..8d8c14c5ec 100644 --- a/SRC/element/Truss/N4BiaxialTruss.h +++ b/SRC/element/Truss/N4BiaxialTruss.h @@ -68,7 +68,7 @@ class N4BiaxialTruss : public Element const Matrix &getDamp(void); const Matrix &getMass(void); - void zeroLoad(void); + void zeroLoad(); int addLoad(ElementalLoad *theLoad, double loadFactor); int addInertiaLoadToUnbalance(const Vector &accel); @@ -76,10 +76,9 @@ class N4BiaxialTruss : public Element const Vector &getResistingForceIncInertia(void); // public methods for element output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker); - int displaySelf(Renderer &, int mode, float fact, const char **displayModes=0, int numModes=0); - void Print(OPS_Stream &s, int flag =0); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); + void Print(OPS_Stream &s, int flag); Response *setResponse(const char **argv, int argc, OPS_Stream &s); int getResponse(int responseID, Information &eleInformation); @@ -87,8 +86,8 @@ class N4BiaxialTruss : public Element protected: private: - int computeCurrentStrainBiaxial(void); - int computeCurrentStrainRate(void); + int computeCurrentStrainBiaxial(); + int computeCurrentStrainRate(); // private attributes - a copy for each object of the class UniaxialMaterial *theMaterial_1; // pointer to a material for the 1 direction diff --git a/SRC/runtime/commands/domain/rigid_links.cpp b/SRC/runtime/commands/domain/rigid_links.cpp index ff42b164d3..2cbc59394c 100644 --- a/SRC/runtime/commands/domain/rigid_links.cpp +++ b/SRC/runtime/commands/domain/rigid_links.cpp @@ -53,7 +53,7 @@ createLinearRigidBeam(Domain &theDomain, int ret_tag, int con_tag) } Node *nodeC = theDomain.getNode(con_tag); - if (nodeR == nullptr) { + if (nodeC == nullptr) { opserr << OpenSees::PromptValueError << "constrained node " << con_tag << " not in domain\n"; return CONSTRAINT_ERROR; @@ -109,7 +109,7 @@ createLinearRigidBeam(Domain &theDomain, int ret_tag, int con_tag) mat(0,2) = -deltaY; mat(1,2) = deltaX; - } else if (dimR == 3 && numDOF == 6) { + } else if (dimR == 3 && numDOF == 6) { double deltaX = crdC(0) - crdR(0); double deltaY = crdC(1) - crdR(1); double deltaZ = crdC(2) - crdR(2); From 1b889b4934a410ca26cae8155911d164912b2e8a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:35:29 -0800 Subject: [PATCH 058/161] Delete Makefile --- SRC/element/mefi/Makefile | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 SRC/element/mefi/Makefile diff --git a/SRC/element/mefi/Makefile b/SRC/element/mefi/Makefile deleted file mode 100644 index 64292cbd62..0000000000 --- a/SRC/element/mefi/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -include ../../../Makefile.def - -OBJS = MEFI.o - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. From bf815b99b9664cc7c92c2f8c4bac4cfd55e79873 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:37:47 -0800 Subject: [PATCH 059/161] Update LoadPattern.cpp --- SRC/domain/pattern/LoadPattern.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/SRC/domain/pattern/LoadPattern.cpp b/SRC/domain/pattern/LoadPattern.cpp index e941ffc6db..56c2527058 100644 --- a/SRC/domain/pattern/LoadPattern.cpp +++ b/SRC/domain/pattern/LoadPattern.cpp @@ -229,19 +229,22 @@ LoadPattern::addSP_Constraint(SP_Constraint *theSp) return result; } -NodalLoadIter &LoadPattern::getNodalLoads() +NodalLoadIter & +LoadPattern::getNodalLoads() { theNodIter->reset(); return *theNodIter; } -ElementalLoadIter &LoadPattern::getElementalLoads() +ElementalLoadIter & +LoadPattern::getElementalLoads() { theEleIter->reset(); return *theEleIter; } -SP_ConstraintIter &LoadPattern::getSPs() +SP_ConstraintIter & +LoadPattern::getSPs() { theSpIter->reset(); return *theSpIter; From c3231f5bbf3dc27e75611bd8e2f1365ba1e1d348 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:38:30 -0800 Subject: [PATCH 060/161] Update MixedFrame3d.cpp --- SRC/element/Frame/MixedFrame3d.cpp | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/SRC/element/Frame/MixedFrame3d.cpp b/SRC/element/Frame/MixedFrame3d.cpp index b1e2205afc..54e3b2cd82 100644 --- a/SRC/element/Frame/MixedFrame3d.cpp +++ b/SRC/element/Frame/MixedFrame3d.cpp @@ -1227,31 +1227,31 @@ MixedFrame3d::getSectionTangent(int sec, int type, MatrixNDgetSectionDeformation(); int order = sections[i]->getOrder(); for (int j = 0; j < order; j++) { - if (code(j) == SECTION_RESPONSE_MZ) + if (code(j) == FrameStress::Mz) kappaz[i] += e(j); - if (code(j) == SECTION_RESPONSE_MY) + if (code(j) == FrameStress::My) kappay[i] += e(j); } } From 90526a21b8a6c29fee17d10c1f1d63cad6cc4cbd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:39:26 -0800 Subject: [PATCH 061/161] Update MP_Joint3D.h --- SRC/element/Joint/MP_Joint3D.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/SRC/element/Joint/MP_Joint3D.h b/SRC/element/Joint/MP_Joint3D.h index 162b9aba5d..e879f95547 100644 --- a/SRC/element/Joint/MP_Joint3D.h +++ b/SRC/element/Joint/MP_Joint3D.h @@ -64,15 +64,14 @@ class MP_Joint3D : public MP_Constraint const ID &getRetainedDOFs(void) const; int applyConstraint(double pseudoTime); bool isTimeVarying(void) const; - const Matrix &getConstraint(void); - void setDomain(Domain *theDomain); + const Matrix &getConstraint(void); + void setDomain(Domain *theDomain); // methods for output - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); - void Print(OPS_Stream &s, int flag =0); + void Print(OPS_Stream &s, int flag); protected: From 44b603f7909f0cc05a3f9af1cfbe2783fbcae104 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:39:41 -0800 Subject: [PATCH 062/161] Update SP_Constraint.h --- SRC/domain/constraints/SP_Constraint.h | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/SRC/domain/constraints/SP_Constraint.h b/SRC/domain/constraints/SP_Constraint.h index 928bf7772f..0e48847d2a 100644 --- a/SRC/domain/constraints/SP_Constraint.h +++ b/SRC/domain/constraints/SP_Constraint.h @@ -52,23 +52,22 @@ class SP_Constraint : public DomainComponent // destructor virtual ~SP_Constraint(); - virtual int getNodeTag(void) const; - virtual int getDOF_Number(void) const; + virtual int getNodeTag() const; + virtual int getDOF_Number() const; virtual int applyConstraint(double loadFactor); - virtual double getValue(void); - virtual double getInitialValue(void); - virtual bool isHomogeneous(void) const; + virtual double getValue(); + virtual double getInitialValue(); + virtual bool isHomogeneous() const; virtual void setLoadPatternTag(int loadPaternTag); - virtual int getLoadPatternTag(void) const; - + virtual int getLoadPatternTag() const; + // Inherited - virtual void setDomain(Domain* theDomain); + virtual void setDomain(Domain*); - virtual int sendSelf(int commitTag, Channel &theChannel); - virtual int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); + virtual int sendSelf(int commitTag, Channel &); + virtual int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); - virtual void Print(OPS_Stream &s, int flag =0); + virtual void Print(OPS_Stream &s, int flag=0); protected: int nodeTag; // to identify the node in the model From 40f8eb560bc8e3f632dc2562658595809eb81071 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 19 Jan 2026 02:39:51 -0800 Subject: [PATCH 063/161] Update MP_Constraint.h --- SRC/domain/constraints/MP_Constraint.h | 37 +++++++++++++------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/SRC/domain/constraints/MP_Constraint.h b/SRC/domain/constraints/MP_Constraint.h index d951b4fa5b..75aa29107f 100644 --- a/SRC/domain/constraints/MP_Constraint.h +++ b/SRC/domain/constraints/MP_Constraint.h @@ -54,16 +54,16 @@ class MP_Constraint : public DomainComponent MP_Constraint(int classTag ); // Arash MP_Constraint(int nodeRetain, - int nodeConstr, - ID &constrainedDOF, - ID &retainedDOF, - int classTag); + int nodeConstr, + ID &constrainedDOF, + ID &retainedDOF, + int classTag); MP_Constraint(int nodeRetain, - int nodeConstr, - Matrix &constrnt, - ID &constrainedDOF, - ID &retainedDOF); + int nodeConstr, + Matrix &constrnt, + ID &constrainedDOF, + ID &retainedDOF); // destructor virtual ~MP_Constraint(); @@ -72,20 +72,19 @@ class MP_Constraint : public DomainComponent void setDomain(Domain* theDomain); // method to get information about the constraint - virtual int getNodeRetained(void) const; - virtual int getNodeConstrained(void) const; - virtual const ID &getConstrainedDOFs(void) const; - virtual const ID &getRetainedDOFs(void) const; + virtual int getNodeRetained() const; + virtual int getNodeConstrained() const; + virtual const ID &getConstrainedDOFs() const; + virtual const ID &getRetainedDOFs() const; virtual int applyConstraint(double pseudoTime); - virtual bool isTimeVarying(void) const; - virtual const Matrix &getConstraint(void); - virtual const Vector &getConstrainedDOFsInitialDisplacement(void) const; - virtual const Vector &getRetainedDOFsInitialDisplacement(void) const; + virtual bool isTimeVarying() const; + virtual const Matrix &getConstraint(); + virtual const Vector &getConstrainedDOFsInitialDisplacement() const; + virtual const Vector &getRetainedDOFsInitialDisplacement() const; // methods for output - virtual int sendSelf(int commitTag, Channel &theChannel); - virtual int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); + virtual int sendSelf(int commitTag, Channel &); + virtual int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &theBroker); virtual void Print(OPS_Stream &s, int flag =0); From 8bbe304a27db8bb4625c27afcdcf5e6e0845f74a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:27:01 -0800 Subject: [PATCH 064/161] Update Prism.h --- SRC/element/Frame/Prism.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/SRC/element/Frame/Prism.h b/SRC/element/Frame/Prism.h index 06b8e456cd..e82243871c 100644 --- a/SRC/element/Frame/Prism.h +++ b/SRC/element/Frame/Prism.h @@ -4,6 +4,14 @@ namespace OpenSees { namespace Frame { +struct Release { + enum { + None = 0, + My = 1 << 3, + Mz = 1 << 4, + } i,j; +}; + // TODO: Maybe make this public under ElasticFrameSection struct Prism { // n-n From c277c88b5ee4aea7a073a0c745ce1000d3515840 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:27:37 -0800 Subject: [PATCH 065/161] Update ForceBeamColumn3d.cpp --- SRC/element/Frame/Other/Force/ForceBeamColumn3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SRC/element/Frame/Other/Force/ForceBeamColumn3d.cpp b/SRC/element/Frame/Other/Force/ForceBeamColumn3d.cpp index 56da9abeaa..764fc2dbb0 100644 --- a/SRC/element/Frame/Other/Force/ForceBeamColumn3d.cpp +++ b/SRC/element/Frame/Other/Force/ForceBeamColumn3d.cpp @@ -2448,7 +2448,7 @@ ForceBeamColumn3d::Print(OPS_Stream &s, int flag) } if (flag == OPS_PRINT_PRINTMODEL_JSON) { - s << "\t\t\t{"; + s << OPS_PRINT_JSON_ELEM_INDENT << "{"; s << "\"name\": " << this->getTag() << ", "; s << "\"type\": \"ForceBeamColumn3d\", "; s << "\"nodes\": [" << connectedExternalNodes(0) << ", " << connectedExternalNodes(1) << "], "; From 647bfbc6faff853fc4c4b734000b232860e0815f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:28:05 -0800 Subject: [PATCH 066/161] Update ZeroLength.cpp --- SRC/element/Point/ZeroLength.cpp | 95 ++++++++++++++++---------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/SRC/element/Point/ZeroLength.cpp b/SRC/element/Point/ZeroLength.cpp index b39f6432fd..11fbf7ac2e 100644 --- a/SRC/element/Point/ZeroLength.cpp +++ b/SRC/element/Point/ZeroLength.cpp @@ -1251,50 +1251,50 @@ ZeroLength::setUp( int Nd1, int Nd2, const Vector &x, const Vector &yp ) { - // ensure the connectedExternalNode ID is of correct size & set values - if (connectedExternalNodes.Size() != 2) - opserr << "FATAL ZeroLength::setUp - failed to create an ID of correct size\n"; - - connectedExternalNodes(0) = Nd1; - connectedExternalNodes(1) = Nd2; + // ensure the connectedExternalNode ID is of correct size & set values + if (connectedExternalNodes.Size() != 2) + opserr << "FATAL ZeroLength::setUp - failed to create an ID of correct size\n"; + + connectedExternalNodes(0) = Nd1; + connectedExternalNodes(1) = Nd2; int i; - for (i=0; i<2; i++) - theNodes[i] = 0; - - // check that vectors for orientation are correct size - if ( x.Size() != 3 || yp.Size() != 3 ) - opserr << "FATAL ZeroLength::setUp - incorrect dimension of orientation vectors\n"; - - // establish orientation of element for the transformation matrix - // z = x cross yp - Vector z(3); - z(0) = x(1)*yp(2) - x(2)*yp(1); - z(1) = x(2)*yp(0) - x(0)*yp(2); - z(2) = x(0)*yp(1) - x(1)*yp(0); - - // y = z cross x - Vector y(3); - y(0) = z(1)*x(2) - z(2)*x(1); - y(1) = z(2)*x(0) - z(0)*x(2); - y(2) = z(0)*x(1) - z(1)*x(0); - - // compute length(norm) of vectors - double xn = x.Norm(); - double yn = y.Norm(); - double zn = z.Norm(); - - // check valid x and y vectors, i.e. not parallel and of zero length - if (xn == 0 || yn == 0 || zn == 0) { - opserr << "FATAL ZeroLength::setUp - invalid vectors to constructor\n"; - } - - // create transformation matrix of direction cosines - for ( i=0; i<3; i++ ) { - transformation(0,i) = x(i)/xn; - transformation(1,i) = y(i)/yn; - transformation(2,i) = z(i)/zn; - } + for (i=0; i<2; i++) + theNodes[i] = 0; + + // check that vectors for orientation are correct size + if ( x.Size() != 3 || yp.Size() != 3 ) + opserr << "FATAL ZeroLength::setUp - incorrect dimension of orientation vectors\n"; + + // establish orientation of element for the transformation matrix + // z = x cross yp + Vector z(3); + z(0) = x(1)*yp(2) - x(2)*yp(1); + z(1) = x(2)*yp(0) - x(0)*yp(2); + z(2) = x(0)*yp(1) - x(1)*yp(0); + + // y = z cross x + Vector y(3); + y(0) = z(1)*x(2) - z(2)*x(1); + y(1) = z(2)*x(0) - z(0)*x(2); + y(2) = z(0)*x(1) - z(1)*x(0); + + // compute length(norm) of vectors + double xn = x.Norm(); + double yn = y.Norm(); + double zn = z.Norm(); + + // check valid x and y vectors, i.e. not parallel and of zero length + if (xn == 0 || yn == 0 || zn == 0) { + opserr << "FATAL ZeroLength::setUp - invalid vectors to constructor\n"; + } + + // create transformation matrix of direction cosines + for ( i=0; i<3; i++ ) { + transformation(0,i) = x(i)/xn; + transformation(1,i) = y(i)/yn; + transformation(2,i) = z(i)/zn; + } } @@ -1303,11 +1303,12 @@ ZeroLength::setUp( int Nd1, int Nd2, void ZeroLength::checkDirection( ID &dir ) const { - for ( int i=0; i 5 ) { - opserr << "WARNING ZeroLength::checkDirection - incorrect direction " << dir(i) << " is set to 0\n"; - dir(i) = 0; - } + for ( int i=0; i 5 ) { + opserr << "WARNING ZeroLength::checkDirection - incorrect direction " + << dir(i) << " is set to 0\n"; + dir(i) = 0; + } } From 27a53fba43484803d53a3b86cb9107e34486c77e Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:31:04 -0800 Subject: [PATCH 067/161] Update UVCmultiaxial.cpp --- SRC/material/plastic/UVCmultiaxial.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/SRC/material/plastic/UVCmultiaxial.cpp b/SRC/material/plastic/UVCmultiaxial.cpp index fd4d7aba80..0d9550fbe5 100644 --- a/SRC/material/plastic/UVCmultiaxial.cpp +++ b/SRC/material/plastic/UVCmultiaxial.cpp @@ -29,21 +29,19 @@ OPS_ADD_RUNTIME_VPV(OPS_UVCmultiaxial) << "\n"; numUVCmultiaxial++; } - NDMaterial* theMaterial = 0; // Parameters for parsing - const unsigned int N_TAGS = 1; - const unsigned int N_BASIC_PROPERTIES = 5; - const unsigned int N_UPDATED_PROPERTIES = 2; - const unsigned int N_PARAM_PER_BACK = 2; - const unsigned int MAX_BACKSTRESSES = 8; - const unsigned int BACKSTRESS_SPACE = MAX_BACKSTRESSES * N_PARAM_PER_BACK; + static constexpr unsigned int N_TAGS = 1; + static constexpr unsigned int N_BASIC_PROPERTIES = 5; + static constexpr unsigned int N_UPDATED_PROPERTIES = 2; + static constexpr unsigned int N_PARAM_PER_BACK = 2; + static constexpr unsigned int MAX_BACKSTRESSES = 8; + static constexpr unsigned int BACKSTRESS_SPACE = MAX_BACKSTRESSES * N_PARAM_PER_BACK; std::string inputInstructions = "Invalid args, want:\n" "nDMaterial UVCmultiaxial " "tag? E? nu? fy? QInf? b? DInf? a? " - "N? C1? gamma1? \n" - "Note: to neglect the updated model, set DInf = 0.0"; + "N? C1? gamma1? \n"; // Containers for the inputs int nInputsToRead; @@ -101,6 +99,7 @@ OPS_ADD_RUNTIME_VPV(OPS_UVCmultiaxial) } // Allocate the material + NDMaterial* theMaterial = 0; theMaterial = new UVCmultiaxial(materialTag[0], basicProps[0], basicProps[1], basicProps[2], basicProps[3], basicProps[4], updProps[0], updProps[1], cK, gammaK); @@ -364,8 +363,7 @@ UVCmultiaxial::calculateStiffness(double consistParam, double stressRelativeNorm double Hkin = 0.; for (unsigned int i = 0; i < nBackstresses; ++i) { double eK = calculateEk(i); - Hkin += - cK[i] * eK - std::sqrt(2. / 3.) * gammaK[i] * eK * dotprod6(flowNormal, alphaKConverged[i]); + Hkin += cK[i]*eK - std::sqrt(2. / 3.) * gammaK[i] * eK * dotprod6(flowNormal, alphaKConverged[i]); } beta = 1.0 + (Hkin + Hiso) / (3.0 * shearModulus); From 296a8eb6738bafd9b813450a726ce61b3779e9ec Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:31:20 -0800 Subject: [PATCH 068/161] Update J2PlateFibre.cpp --- SRC/material/plastic/J2PlateFibre.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SRC/material/plastic/J2PlateFibre.cpp b/SRC/material/plastic/J2PlateFibre.cpp index a27436d98b..697f068641 100644 --- a/SRC/material/plastic/J2PlateFibre.cpp +++ b/SRC/material/plastic/J2PlateFibre.cpp @@ -80,9 +80,9 @@ void * OPS_ADD_RUNTIME_VPV(OPS_J2PlateFibreMaterial) } J2PlateFibre::J2PlateFibre -(int tag, double e, double g, double sy, double hi, double hk): +(int tag, double e, double v, double sy, double hi, double hk): NDMaterial(tag, ND_TAG_J2PlateFibre), - E(e), nu(g), sigmaY(sy), Hiso(hi), Hkin(hk), + E(e), nu(v), sigmaY(sy), Hiso(hi), Hkin(hk), parameterID(0), SHVs(0), Tepsilon(5), dg_n1(0.0) { epsPn[0] = 0.0; @@ -491,7 +491,7 @@ J2PlateFibre::commitState() } int -J2PlateFibre::revertToLastCommit (void) +J2PlateFibre::revertToLastCommit() { epsPn1[0] = epsPn[0]; epsPn1[1] = epsPn[1]; From a55ba836fc80285ea82b36a94743949a9dca5649 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:31:54 -0800 Subject: [PATCH 069/161] Update TclPackageClassBroker.h --- SRC/runtime/runtime/TclPackageClassBroker.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/SRC/runtime/runtime/TclPackageClassBroker.h b/SRC/runtime/runtime/TclPackageClassBroker.h index 2f1d483827..2a8388c94a 100644 --- a/SRC/runtime/runtime/TclPackageClassBroker.h +++ b/SRC/runtime/runtime/TclPackageClassBroker.h @@ -27,9 +27,6 @@ class TclPackageClassBroker : public FEM_ObjectBroker { Actor *getNewActor(int classTag, Channel *theChannel); - PartitionedModelBuilder *getPtrNewPartitionedModelBuilder(Subdomain &theSub, - int classTag); - GraphNumberer *getPtrNewGraphNumberer(int classTag); // methods to get new modelling class objects @@ -86,7 +83,7 @@ class TclPackageClassBroker : public FEM_ObjectBroker { DomainSolver *getNewDomainSolver(void); DomainDecompositionAnalysis *getNewDomainDecompAnalysis(int classTag, - Subdomain &theDomain); + Subdomain &); Subdomain *getSubdomainPtr(int classTag); From 5f78e8a47568338f5284bbcafc1c4177d281afc9 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:31:58 -0800 Subject: [PATCH 070/161] Update TclPackageClassBroker.cpp --- SRC/runtime/runtime/TclPackageClassBroker.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/SRC/runtime/runtime/TclPackageClassBroker.cpp b/SRC/runtime/runtime/TclPackageClassBroker.cpp index 1ee863903c..cca3795956 100644 --- a/SRC/runtime/runtime/TclPackageClassBroker.cpp +++ b/SRC/runtime/runtime/TclPackageClassBroker.cpp @@ -552,23 +552,6 @@ TclPackageClassBroker::getNewActor(int classTag, Channel *theChannel) } } -PartitionedModelBuilder * -TclPackageClassBroker::getPtrNewPartitionedModelBuilder(Subdomain &theSubdomain, - int classTag) -{ - switch (classTag) { - /* - case PartitionedModelBuilder_TAGS_PartitionedQuick2dFrameModel: - return new PartitionedQuick2dFrame(theSubdomain); - */ - - default: - opserr << "TclPackageClassBroker::getPtrNewPartitionedModelBuilder - "; - opserr << " - no PartitionedModelBuilder type exists for class tag "; - opserr << classTag << "\n"; - return 0; - } -} GraphNumberer * TclPackageClassBroker::getPtrNewGraphNumberer(int classTag) @@ -674,7 +657,6 @@ TclPackageClassBroker::getNewElement(int classTag) DISPATCH(ZeroLengthContactASDimplex); - DISPATCH(Joint2D); DISPATCH(TwoNodeLink); DISPATCH(LinearElasticSpring); @@ -1045,6 +1027,7 @@ TclPackageClassBroker::getNewUniaxialMaterial(int classTag) case MAT_TAG_ENTMaterial: return new ENTMaterial(); + #if defined(OPSDEF_UNIAXIAL_FEDEAS) case MAT_TAG_FedeasBond1: return new FedeasBond1Material(); From a39fd2812cfee2f97f2a93aec6014628298f1e0c Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:35:11 -0800 Subject: [PATCH 071/161] Update analysis.cpp --- SRC/runtime/commands/analysis/analysis.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SRC/runtime/commands/analysis/analysis.cpp b/SRC/runtime/commands/analysis/analysis.cpp index c51e699b8f..dc29cecae8 100644 --- a/SRC/runtime/commands/analysis/analysis.cpp +++ b/SRC/runtime/commands/analysis/analysis.cpp @@ -311,6 +311,7 @@ eigenAnalysis(ClientData clientData, else if ((strcmp(argv[loc], "genBandArpack") == 0) || (strcmp(argv[loc], "-genBandArpack") == 0) || + (strcmp(argv[loc], "-bandGenArpack") == 0) || (strcmp(argv[loc], "genBandArpackEigen") == 0) || (strcmp(argv[loc], "-genBandArpackEigen") == 0)) typeSolver = EigenSOE_TAGS_ArpackSOE; @@ -341,7 +342,9 @@ eigenAnalysis(ClientData clientData, return TCL_ERROR; } } - + else if (strcmp(argv[loc], "-solver")==0) { + ; + } else { opserr << "Unknown option: " << argv[loc] << OpenSees::SignalMessageEnd; From 399caa2b27b7c7918865d38b7d42092a87f77550 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:35:41 -0800 Subject: [PATCH 072/161] Update BeamIntegration.h --- SRC/quadrature/Frame/BeamIntegration.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SRC/quadrature/Frame/BeamIntegration.h b/SRC/quadrature/Frame/BeamIntegration.h index f15542318e..75d59099cf 100644 --- a/SRC/quadrature/Frame/BeamIntegration.h +++ b/SRC/quadrature/Frame/BeamIntegration.h @@ -38,7 +38,7 @@ class BeamIntegration : public MovableObject virtual void getSectionLocations(int nIP, double L, double *xi) const = 0; virtual void getSectionWeights(int nIP, double L, double *wt) const = 0; - virtual BeamIntegration *getCopy(void) = 0; + virtual BeamIntegration *getCopy() = 0; // // @@ -100,16 +100,16 @@ class BeamIntegrationRule : public TaggedObject BeamIntegrationRule(int tag, BeamIntegration* bi, const ID& stags) :TaggedObject(tag),theInt(bi),secTags(stags){} - ~BeamIntegrationRule(){ - if (theInt != 0) - delete theInt; + ~BeamIntegrationRule() { + if (theInt != 0) + delete theInt; } BeamIntegration* getBeamIntegration(){return theInt;} const ID& getSectionTags() const {return secTags;} void Print(OPS_Stream &s, int flag) { - theInt->Print(s); + theInt->Print(s, flag); } private: BeamIntegration* theInt; From f21b38a32f0c157efeff6a5ce0937193ea0ad570 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:36:29 -0800 Subject: [PATCH 073/161] Delete Makefile --- SRC/analysis/fe_ele/Makefile | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 SRC/analysis/fe_ele/Makefile diff --git a/SRC/analysis/fe_ele/Makefile b/SRC/analysis/fe_ele/Makefile deleted file mode 100644 index 9d7136b2d4..0000000000 --- a/SRC/analysis/fe_ele/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -include ../../../Makefile.def - -OBJS = FE_Element.o - -# Compilation control - -all: $(OBJS) - @$(CD) $(FE)/analysis/fe_ele/penalty; $(MAKE); - @$(CD) $(FE)/analysis/fe_ele/lagrange; $(MAKE); - @$(CD) $(FE)/analysis/fe_ele/transformation; $(MAKE); - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - @$(CD) $(FE)/analysis/fe_ele/penalty; $(MAKE) wipe; - @$(CD) $(FE)/analysis/fe_ele/lagrange; $(MAKE) wipe; - @$(CD) $(FE)/analysis/fe_ele/transformation; $(MAKE) wipe; - - -# DO NOT DELETE THIS LINE -- make depend depends on it. From d28b9689ace6ed4ab5165c5c6cbe19ab6381f42a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:36:32 -0800 Subject: [PATCH 074/161] Delete Makefile --- SRC/analysis/fe_ele/lagrange/Makefile | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 SRC/analysis/fe_ele/lagrange/Makefile diff --git a/SRC/analysis/fe_ele/lagrange/Makefile b/SRC/analysis/fe_ele/lagrange/Makefile deleted file mode 100644 index de40c6de54..0000000000 --- a/SRC/analysis/fe_ele/lagrange/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../../../../Makefile.def - -OBJS = LagrangeMP_FE.o LagrangeSP_FE.o - -# Compilation control - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - - -# DO NOT DELETE THIS LINE -- make depend depends on it. From 818dd8bdf744e07a2737bc293704a1b83381a562 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:36:34 -0800 Subject: [PATCH 075/161] Delete Makefile --- SRC/analysis/fe_ele/penalty/Makefile | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 SRC/analysis/fe_ele/penalty/Makefile diff --git a/SRC/analysis/fe_ele/penalty/Makefile b/SRC/analysis/fe_ele/penalty/Makefile deleted file mode 100644 index 15d4bcd7ea..0000000000 --- a/SRC/analysis/fe_ele/penalty/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../../../../Makefile.def - -OBJS = PenaltySP_FE.o PenaltyMP_FE.o - -# Compilation control - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - - -# DO NOT DELETE THIS LINE -- make depend depends on it. From 1801d88f1e42b4160d388025b7e13b33022e6e79 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:37:09 -0800 Subject: [PATCH 076/161] Create ElementFE.h --- SRC/analysis/fe_ele/ElementFE.h | 121 ++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 SRC/analysis/fe_ele/ElementFE.h diff --git a/SRC/analysis/fe_ele/ElementFE.h b/SRC/analysis/fe_ele/ElementFE.h new file mode 100644 index 0000000000..1264b286f4 --- /dev/null +++ b/SRC/analysis/fe_ele/ElementFE.h @@ -0,0 +1,121 @@ +/* ****************************************************************** ** +** OpenSees - Open System for Earthquake Engineering Simulation ** +** Pacific Earthquake Engineering Research Center ** +** ** +** ** +** (C) Copyright 1999, The Regents of the University of California ** +** All Rights Reserved. ** +** ** +** Commercial use of this program without express permission of the ** +** University of California, Berkeley, is strictly prohibited. See ** +** file 'COPYRIGHT' in main directory for information on usage and ** +** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** +** ** +** Developed by: ** +** Frank McKenna (fmckenna@ce.berkeley.edu) ** +** Gregory L. Fenves (fenves@ce.berkeley.edu) ** +** Filip C. Filippou (filippou@ce.berkeley.edu) ** +** ** +** ****************************************************************** */ +// +// Description: This file contains the class definition for ElementFE. +// +// Written: fmk +// Created: 11/96 +// Revision: A +// +#ifndef ElementFE_h +#define ElementFE_h + +#include +#include + +class Vector; +class Matrix; +class Element; +class Integrator; +class StaticIntegrator; +class AnalysisModel; + + +class ElementFE: public FE_Element +{ + public: + ElementFE(int tag, Element *); + virtual ~ElementFE(); + + // public methods for setting/obtaining mapping information + virtual const ID &getDOFtags() const; + virtual const ID &getID() const; + int setID(AnalysisModel &) override; + + // methods to form and obtain the tangent and residual + const Matrix &getTangent(Integrator *) override; + const Vector &getResidual(Integrator *) override; + + // methods called by integrator to build tangent + virtual void zeroTangent() ; + void addKtToTang(double fact = 1.0) override; + void addKiToTang(double fact = 1.0) override; + void addCtoTang (double fact = 1.0) override; + void addMtoTang (double fact = 1.0) override; + virtual void addKpToTang(double fact = 1.0, int numP = 0); + virtual int storePreviousK(int numP); + + // methods used by integrator to build residual + virtual void zeroResidual(); + virtual void addRtoResidual(double fact = 1.0); + virtual void addRIncInertiaToResidual(double fact); + + // methods for ele-by-ele strategies + virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); + virtual const Vector &getK_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + virtual void addM_Force(const Vector &accel, double fact = 1.0); + virtual void addD_Force(const Vector &vel, double fact = 1.0); + virtual void addK_Force(const Vector &disp, double fact = 1.0); + + virtual int updateElement(); + + virtual Integrator *getLastIntegrator(); + virtual const Vector &getLastResponse(); + Element *getElement() override; + + virtual void Print(OPS_Stream&, int flag) {return;}; + + virtual void addResistingForceSensitivity(int gradNumber, double fact = 1.0); + virtual void addM_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); + virtual void addD_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); + virtual int commitSensitivity (int gradNum, int numGrads); + + protected: + void addLocalM_Force(const Vector &accel, double fact = 1.0); + void addLocalD_Force(const Vector &vel, double fact = 1.0); + void addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, double fact = 1.0); + void addLocalD_ForceSensitivity(int gradNumber, const Vector &vel, double fact = 1.0); + + // protected variables - a copy for each object of the class + ID myDOF_Groups; + ID myID; + + private: + // private variables - a copy for each object of the class + int numDOF; + Element *myEle; + Vector *theResidual; + Matrix *theTangent; + Integrator *theIntegrator; // need for Subdomain + + // + // static variables + // + static Matrix **theMatrices; // array of pointers to class wide matrices + static Vector **theVectors; // array of pointers to class widde vectors + static int numFEs; // number of objects + +}; + +#endif + From f05e57f01d8b23010728476fef55e0e8b29110cc Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:38:07 -0800 Subject: [PATCH 077/161] Delete Makefile --- SRC/analysis/handler/Makefile | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 SRC/analysis/handler/Makefile diff --git a/SRC/analysis/handler/Makefile b/SRC/analysis/handler/Makefile deleted file mode 100644 index de8e94a0e0..0000000000 --- a/SRC/analysis/handler/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -include ../../../Makefile.def - -OBJS = ConstraintHandler.o PlainHandler.o \ - PenaltyConstraintHandler.o LagrangeConstraintHandler.o \ - TransformationConstraintHandler.o PenaltyHandlerNoHomoSPMultipliers.o - -# Compilation control -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. From f12734b30cda7638460af76cd0c6b6291ad413dd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:33:53 -0800 Subject: [PATCH 078/161] Update ExactFrame3d.tpp --- SRC/element/Frame/ExactFrame3d.tpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/SRC/element/Frame/ExactFrame3d.tpp b/SRC/element/Frame/ExactFrame3d.tpp index 687216aaeb..198af5fce4 100644 --- a/SRC/element/Frame/ExactFrame3d.tpp +++ b/SRC/element/Frame/ExactFrame3d.tpp @@ -304,8 +304,8 @@ ExactFrame3d::update() // // - Matrix3D dR = ExpSO3(theta); - Matrix3D R = dR*pres[i].rotation; + const Matrix3D dR = ExpSO3(theta); + const Matrix3D R = dR*pres[i].rotation; pres[i].rotation = R; @@ -315,8 +315,9 @@ ExactFrame3d::update() // pres[i].curvature = omega + TanSO3(theta, 'R')*dtheta; pres[i].curvature = omega + TExpSO3(theta)*dtheta; - Vector3D gamma = (R^dx) - D; - Vector3D kappa = R^pres[i].curvature; + const Vector3D gamma = (R^dx) - D; + const Vector3D kappa = R^pres[i].curvature; + VectorND e { gamma[0], gamma[1], gamma[2], From aca002f261ac9e0d6bc747a2c7368a59e6736fec Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:35:35 -0800 Subject: [PATCH 079/161] Create ElementFE.cpp --- SRC/analysis/fe_ele/ElementFE.cpp | 714 ++++++++++++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 SRC/analysis/fe_ele/ElementFE.cpp diff --git a/SRC/analysis/fe_ele/ElementFE.cpp b/SRC/analysis/fe_ele/ElementFE.cpp new file mode 100644 index 0000000000..f2df7edb83 --- /dev/null +++ b/SRC/analysis/fe_ele/ElementFE.cpp @@ -0,0 +1,714 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// +// +// Purpose: This file contains the code for implementing the methods +// of the ElementFE class interface. +// +// Written: cmp +// Created: Jan 2026 +// Revision: A +// +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NUM_DOF 64 + +// static variables initialisation +Matrix **ElementFE::theMatrices; // pointers to class wide matrices +Vector **ElementFE::theVectors; // pointers to class widde vectors +int ElementFE::numFEs(0); // number of objects + + +// constructor that take the corresponding model element. +ElementFE::ElementFE(int tag, Element *ele) + : FE_Element(tag, (ele->getExternalNodes()).Size(), ele->getNumDOF()) + , myID(ele->getNumDOF()), + numDOF(ele->getNumDOF()), myEle(ele), + theResidual(nullptr), theTangent(nullptr), theIntegrator(nullptr) +{ + assert(numDOF > 0); + + // get elements domain & check it is valid + Domain *theDomain = ele->getDomain(); + assert(theDomain != nullptr); + + // keep a pointer to all DOF_Groups + int numGroups = ele->getNumExternalNodes(); + const ID &nodes = ele->getExternalNodes(); + + for (int i=0; igetNode(nodes(i)); + assert(nodePtr != nullptr); + + DOF_Group *dofGrpPtr = nodePtr->getDOF_GroupPtr(); + assert(dofGrpPtr != nullptr); + myDOF_Groups(i) = dofGrpPtr->getTag(); + } + + // if this is the first ElementFE we now + // create the arrays used to store pointers to class wide + // matrix and vector objects used to return tangent and residual + if (numFEs == 0) { + theMatrices = new Matrix *[MAX_NUM_DOF+1]; + theVectors = new Vector *[MAX_NUM_DOF+1]; + + for (int i=0; i MAX_NUM_DOF) { + if (theTangent != nullptr) + delete theTangent; + if (theResidual != nullptr) + delete theResidual; + } + + // if this is the last ElementFE, clean up the + // storage for the matrix and vector objects + if (numFEs == 0) { + for (int i=0; igetID(); + + for (int j=0; jformEleTangent(this); + + return *theTangent; + +} + + +void +ElementFE::zeroTangent() +{ + assert(myEle != nullptr); + theTangent->Zero(); +} + + +void +ElementFE::addKtToTang(double fact) +{ + assert (myEle != nullptr); + + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle->getTangentStiff(),fact); +} + + +void +ElementFE::addCtoTang(double fact) +{ + assert (myEle != nullptr); + + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle->getDamp(),fact); +} + + +void +ElementFE::addMtoTang(double fact) +{ + if (myEle != nullptr) { + + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle->getMass(),fact); + } +} + + +void +ElementFE::addKiToTang(double fact) +{ + // check for a quick return + if (fact == 0.0) + return; + + else // if (myEle->isSubdomain() == false) + theTangent->addMatrix(myEle->getInitialStiff(), fact); +} + + +void +ElementFE::addKpToTang(double fact, int numP) +{ + if (myEle != nullptr) { + // check for a quick return + if (fact == 0.0) + return; + + else if (myEle->isSubdomain() == false) { + const Matrix *thePrevMat = myEle->getPreviousK(numP); + if (thePrevMat != nullptr) + theTangent->addMatrix(*thePrevMat, fact); + + } + } +} + +int +ElementFE::storePreviousK(int numP) +{ + int res = 0; + if (myEle != nullptr) + res = myEle->storePreviousK(numP); + + return res; +} + +// +// RESIDUAL +// +const Vector & +ElementFE::getResidual(Integrator *theNewIntegrator) +{ + theIntegrator = theNewIntegrator; + + if (theIntegrator == nullptr) + return *theResidual; + + assert(myEle != nullptr); + + theNewIntegrator->formEleResidual(this); + return *theResidual; +} + +void +ElementFE::zeroResidual() +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + theResidual->Zero(); +} + + +void +ElementFE::addRtoResidual(double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + else { + const Vector &eleResisting = myEle->getResistingForce(); + theResidual->addVector(1.0, eleResisting, -fact); + } +} + + +void +ElementFE::addRIncInertiaToResidual(double fact) +{ + assert(myEle != nullptr); + + // check for a quick return + if (fact == 0.0) + return; + + else { + const Vector &eleResisting = myEle->getResistingForceIncInertia(); + theResidual->addVector(1.0, eleResisting, -fact); + } +} + + +const Vector & +ElementFE::getTangForce(const Vector &disp, double fact) +{ + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + // form the tangent again and then add the force + theIntegrator->formEleTangent(this); + theResidual->addMatrixVector(*theTangent,tmp,fact); + + return *theResidual; +} + + + +const Vector & +ElementFE::getK_Force(const Vector &disp, double fact) +{ + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); + + return *theResidual; +} + + +const Vector & +ElementFE::getKi_Force(const Vector &disp, double fact) +{ + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getInitialStiff(), tmp, fact); + + return *theResidual; +} + +const Vector & +ElementFE::getM_Force(const Vector &disp, double fact) +{ + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getMass(), tmp, fact); + + return *theResidual; +} + +const Vector & +ElementFE::getC_Force(const Vector &disp, double fact) +{ + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); + + return *theResidual; +} + + +Integrator * +ElementFE::getLastIntegrator() +{ + return theIntegrator; +} + + +const Vector & +ElementFE::getLastResponse() +{ + assert(myEle != nullptr); + + if (theIntegrator != nullptr) { + if (theIntegrator->getLastResponse(*theResidual,myID) < 0) { + opserr << "WARNING ElementFE::getLastResponse()"; + opserr << " - the Integrator had problems with getLastResponse()\n"; + } + } + else { + theResidual->Zero(); + opserr << "WARNING ElementFE::getLastResponse()"; + opserr << " No Integrator yet passed\n"; + } + + Vector &result = *theResidual; + return result; +} + +void +ElementFE::addM_Force(const Vector &accel, double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = accel(loc); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(1.0, myEle->getMass(), tmp, fact); +} + +void +ElementFE::addD_Force(const Vector &accel, double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = accel(loc); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); +} + +void +ElementFE::addK_Force(const Vector &disp, double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(loc); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); +} + + + +void +ElementFE::addLocalM_Force(const Vector &accel, double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + theResidual->addMatrixVector(myEle->getMass(), accel, fact); +} + +void +ElementFE::addLocalD_Force(const Vector &accel, double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + if (theResidual->addMatrixVector(myEle->getDamp(), accel, fact) < 0){ + opserr << "WARNING ElementFE::addLocalD_Force() - "; + opserr << "- addMatrixVector returned error\n"; + } +} + + +Element * +ElementFE::getElement() +{ + return myEle; +} + + +// AddingSensitivity:BEGIN ///////////////////////////////// +void +ElementFE::addResistingForceSensitivity(int gradNumber, double fact) +{ + theResidual->addVector(1.0, myEle->getResistingForceSensitivity(gradNumber), -fact); +} + +void +ElementFE::addM_ForceSensitivity(int gradNumber, const Vector &vect, double fact) +{ + // Get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) { + tmp(i) = vect(loc); + } else { + tmp(i) = 0.0; + } + } + theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber),tmp,fact); +} + +void +ElementFE::addD_ForceSensitivity(int gradNumber, const Vector &vect, double fact) +{ + assert(myEle != nullptr); + + // check for a quick return + if (fact == 0.0) + return; + + if (myEle->isSubdomain() == false) { + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = vect(loc); + else + tmp(i) = 0.0; + } + theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), tmp, fact); + } + else { + opserr << "WARNING ElementFE::addD_ForceSensitivity() - "; + opserr << "- this should not be called on a Subdomain!\n"; + } +} + +void +ElementFE::addLocalD_ForceSensitivity(int gradNumber, const Vector &accel, double fact) +{ + // check for a quick return + if (fact == 0.0) + return; + theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), accel, fact); + +} + + +void +ElementFE::addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, double fact) +{ + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + if (theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber), accel, fact) < 0) { + opserr << "WARNING ElementFE::addLocalD_ForceSensitivity() - "; + opserr << "- addMatrixVector returned error\n"; + } +} + + + + + +int +ElementFE::commitSensitivity(int gradNum, int numGrads) +{ + myEle->commitSensitivity(gradNum, numGrads); + return 0; +} + +// AddingSensitivity:END //////////////////////////////////// + + +int +ElementFE::updateElement() +{ + if (myEle != nullptr) + return myEle->update(); + return 0; +} From fff5ce4beee9e2ea1943e7cb6a670874839bad05 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:35:39 -0800 Subject: [PATCH 080/161] Update ElementFE.h --- SRC/analysis/fe_ele/ElementFE.h | 47 ++++++++++++++------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/SRC/analysis/fe_ele/ElementFE.h b/SRC/analysis/fe_ele/ElementFE.h index 1264b286f4..cd784c2ba6 100644 --- a/SRC/analysis/fe_ele/ElementFE.h +++ b/SRC/analysis/fe_ele/ElementFE.h @@ -1,27 +1,22 @@ -/* ****************************************************************** ** -** OpenSees - Open System for Earthquake Engineering Simulation ** -** Pacific Earthquake Engineering Research Center ** -** ** -** ** -** (C) Copyright 1999, The Regents of the University of California ** -** All Rights Reserved. ** -** ** -** Commercial use of this program without express permission of the ** -** University of California, Berkeley, is strictly prohibited. See ** -** file 'COPYRIGHT' in main directory for information on usage and ** -** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. ** -** ** -** Developed by: ** -** Frank McKenna (fmckenna@ce.berkeley.edu) ** -** Gregory L. Fenves (fenves@ce.berkeley.edu) ** -** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** -** ****************************************************************** */ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// // // Description: This file contains the class definition for ElementFE. // -// Written: fmk -// Created: 11/96 +// Written: cmp +// Created: Jan 2026 // Revision: A // #ifndef ElementFE_h @@ -42,19 +37,18 @@ class ElementFE: public FE_Element { public: ElementFE(int tag, Element *); - virtual ~ElementFE(); + ~ElementFE() override; // public methods for setting/obtaining mapping information - virtual const ID &getDOFtags() const; - virtual const ID &getID() const; int setID(AnalysisModel &) override; + const ID &getID() const override; // methods to form and obtain the tangent and residual const Matrix &getTangent(Integrator *) override; const Vector &getResidual(Integrator *) override; // methods called by integrator to build tangent - virtual void zeroTangent() ; + void zeroTangent() override; void addKtToTang(double fact = 1.0) override; void addKiToTang(double fact = 1.0) override; void addCtoTang (double fact = 1.0) override; @@ -96,8 +90,7 @@ class ElementFE: public FE_Element void addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, double fact = 1.0); void addLocalD_ForceSensitivity(int gradNumber, const Vector &vel, double fact = 1.0); - // protected variables - a copy for each object of the class - ID myDOF_Groups; + // protected variables - a copy for each object of the class ID myID; private: From bc1931c54c097082df034d7a58d7083c57a85f81 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:36:18 -0800 Subject: [PATCH 081/161] Create SubdomainFE.h --- SRC/analysis/fe_ele/SubdomainFE.h | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 SRC/analysis/fe_ele/SubdomainFE.h diff --git a/SRC/analysis/fe_ele/SubdomainFE.h b/SRC/analysis/fe_ele/SubdomainFE.h new file mode 100644 index 0000000000..a7339d1a75 --- /dev/null +++ b/SRC/analysis/fe_ele/SubdomainFE.h @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// +// +// Description: This file contains the class definition for SubdomainFE. +// +// Written: fmk +// Created: 11/96 +// Revision: A +// +#ifndef SubdomainFE_h +#define SubdomainFE_h + +#include +#include + +class Vector; +class Matrix; +class Element; +class Integrator; +class StaticIntegrator; +class AnalysisModel; + + +class SubdomainFE: public FE_Element +{ + public: + SubdomainFE(int tag, Element *theElement); + ~SubdomainFE() override; + + // public methods for setting/obtaining mapping information + virtual int setID(AnalysisModel &); + virtual const ID &getID() const; + + // methods to form and obtain the tangent and residual + virtual const Matrix &getTangent(Integrator *); + virtual const Vector &getResidual(Integrator *); + + // methods called by integrator to build tangent + virtual void zeroTangent() ; + virtual void addKtToTang(double fact = 1.0) ; + virtual void addKiToTang(double fact = 1.0) ; + virtual void addCtoTang (double fact = 1.0) ; + virtual void addMtoTang (double fact = 1.0) ; + virtual void addKpToTang(double fact = 1.0, int numP = 0); + virtual int storePreviousK(int numP); + + // methods used by integrator to build residual + virtual void zeroResidual(); + virtual void addRtoResidual(double fact = 1.0); + virtual void addRIncInertiaToResidual(double fact); + + // methods for ele-by-ele strategies + virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); + virtual const Vector &getK_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + virtual void addM_Force(const Vector &accel, double fact = 1.0); + virtual void addD_Force(const Vector &vel, double fact = 1.0); + virtual void addK_Force(const Vector &disp, double fact = 1.0); + + virtual int updateElement(); + + virtual Integrator *getLastIntegrator(); + virtual const Vector &getLastResponse(); + virtual Element *getElement(); + + virtual void Print(OPS_Stream&, int flag) {return;} + + virtual void addResistingForceSensitivity(int gradNumber, double fact = 1.0); + virtual void addM_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); + virtual void addD_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); + virtual int commitSensitivity (int gradNum, int numGrads); + + protected: + // protected variables - a copy for each object of the class + ID myID; + + private: + // private variables - a copy for each object of the class + int numDOF; + Element *myEle; + Vector *theResidual; + Matrix *theTangent; + Integrator *theIntegrator; // need for Subdomain + + // + // static variables + // + static Matrix **theMatrices; // array of pointers to class wide matrices + static Vector **theVectors; // array of pointers to class widde vectors + static int numFEs; // number of objects + +}; + +#endif + From 08968a1173cac81729c25f90336894185779b648 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:36:21 -0800 Subject: [PATCH 082/161] Create SubdomainFE.cpp --- SRC/analysis/fe_ele/SubdomainFE.cpp | 708 ++++++++++++++++++++++++++++ 1 file changed, 708 insertions(+) create mode 100644 SRC/analysis/fe_ele/SubdomainFE.cpp diff --git a/SRC/analysis/fe_ele/SubdomainFE.cpp b/SRC/analysis/fe_ele/SubdomainFE.cpp new file mode 100644 index 0000000000..1c15657e0f --- /dev/null +++ b/SRC/analysis/fe_ele/SubdomainFE.cpp @@ -0,0 +1,708 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// +// +// Purpose: This file contains the code for implementing the methods +// of the SubdomainFE class interface. +// +// Written: fmk +// Created: 11/96 +// Revision: A +// +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NUM_DOF 64 + +// static variables initialisation +Matrix **SubdomainFE::theMatrices; // pointers to class wide matrices +Vector **SubdomainFE::theVectors; // pointers to class widde vectors +int SubdomainFE::numFEs(0); // number of objects + + +// constructor that take the corresponding model element. +SubdomainFE::SubdomainFE(int tag, Element *ele) + : FE_Element(tag, (ele->getExternalNodes()).Size(), ele->getNumDOF()) + , myID(ele->getNumDOF()), + numDOF(ele->getNumDOF()), myEle(ele), + theResidual(nullptr), theTangent(nullptr), theIntegrator(nullptr) +{ + assert(numDOF > 0); + opserr << "SubdomainFE::SubdomainFE - called\n"; + + // get elements domain & check it is valid + Domain *theDomain = ele->getDomain(); + assert(theDomain != nullptr); + + // keep a pointer to all DOF_Groups + int numGroups = ele->getNumExternalNodes(); + const ID &nodes = ele->getExternalNodes(); + + for (int i=0; igetNode(nodes(i)); + assert(nodePtr != nullptr); + + DOF_Group *dofGrpPtr = nodePtr->getDOF_GroupPtr(); + assert(dofGrpPtr != nullptr); + myDOF_Groups(i) = dofGrpPtr->getTag(); + } + + // if this is the first SubdomainFE we now + // create the arrays used to store pointers to class wide + // matrix and vector objects used to return tangent and residual + if (numFEs == 0) { + theMatrices = new Matrix *[MAX_NUM_DOF+1]; + theVectors = new Vector *[MAX_NUM_DOF+1]; + + for (int i=0; isetFE_ElementPtr(this); + } + + // increment number of SubdomainFEs by 1 + numFEs++; +} + + + + + +SubdomainFE::~SubdomainFE() +{ + // decrement number of SubdomainFEs + numFEs--; + + // delete tangent and residual if created specially + if (numDOF > MAX_NUM_DOF) { + if (theTangent != nullptr) + delete theTangent; + if (theResidual != nullptr) + delete theResidual; + } + + // if this is the last SubdomainFE, clean up the + // storage for the matrix and vector objects + if (numFEs == 0) { + for (int i=0; igetID(); + + for (int j=0; jcomputeTang(); + return theSub->getTang(); + } +#endif +} + +void +SubdomainFE::zeroTangent() +{ + opserr << "This should not be called on a Subdomain!\n"; +} + + +void +SubdomainFE::addKtToTang(double fact) +{ + opserr << "WARNING FE_Element::addKToTang() - "; + opserr << "- this should not be called on a Subdomain!\n"; +} + + +void +SubdomainFE::addCtoTang(double fact) +{ +#ifdef OLD_FE + assert (myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle->getDamp(),fact); +#endif +} + + +void +SubdomainFE::addMtoTang(double fact) +{ +#ifdef OLD_FE + if (myEle != nullptr) { + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle->getMass(),fact); + } +#endif +} + + +void +SubdomainFE::addKiToTang(double fact) +{ +#ifdef OLD_FE + if (myEle != nullptr) { + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + else // if (myEle->isSubdomain() == false) + theTangent->addMatrix(myEle->getInitialStiff(), fact); + } +#endif +} + + +void +SubdomainFE::addKpToTang(double fact, int numP) +{ +#ifdef OLD_FE + if (myEle != nullptr) { + // check for a quick return + if (fact == 0.0) + return; + + else if (myEle->isSubdomain() == false) { + const Matrix *thePrevMat = myEle->getPreviousK(numP); + if (thePrevMat != nullptr) + theTangent->addMatrix(*thePrevMat, fact); + + } else { + opserr << "WARNING SubdomainFE::addKpToTang() - "; + opserr << "- this should not be called on a Subdomain!\n"; + } + } +#endif +} + +int +SubdomainFE::storePreviousK(int numP) +{ + int res = 0; + if (myEle != nullptr) + res = myEle->storePreviousK(numP); + + return res; +} + +// +// RESIDUAL +// +const Vector & +SubdomainFE::getResidual(Integrator *theNewIntegrator) +{ + theIntegrator = theNewIntegrator; + +#ifdef OLD_FE + if (theIntegrator == nullptr) + return *theResidual; + + assert(myEle != nullptr); + + if (myEle->isSubdomain() == false) { + theNewIntegrator->formEleResidual(this); + return *theResidual; + + } else { + Subdomain *theSub = (Subdomain *)myEle; + theSub->computeResidual(); + return theSub->getResistingForce(); + } +#else + return *theResidual; +#endif +} + +void +SubdomainFE::zeroResidual() +{ +#ifdef OLD_FE + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + theResidual->Zero(); +#endif +} + + +void +SubdomainFE::addRtoResidual(double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + else { + const Vector &eleResisting = myEle->getResistingForce(); + theResidual->addVector(1.0, eleResisting, -fact); + } +#endif +} + + +void +SubdomainFE::addRIncInertiaToResidual(double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + else { + const Vector &eleResisting = myEle->getResistingForceIncInertia(); + theResidual->addVector(1.0, eleResisting, -fact); + } +#endif +} + + +const Vector & +SubdomainFE::getTangForce(const Vector &disp, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + if (myEle->isSubdomain() == false) { + // form the tangent again and then add the force + theIntegrator->formEleTangent(this); + theResidual->addMatrixVector(*theTangent,tmp,fact); + + } else { + theResidual->addMatrixVector(((Subdomain *)myEle)->getTang(),tmp,fact); + } +#endif + return *theResidual; +} + + + +const Vector & +SubdomainFE::getK_Force(const Vector &disp, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); +#endif + return *theResidual; +} + + +const Vector & +SubdomainFE::getKi_Force(const Vector &disp, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getInitialStiff(), tmp, fact); +#endif + return *theResidual; +} + +const Vector & +SubdomainFE::getM_Force(const Vector &disp, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getMass(), tmp, fact); +#endif + return *theResidual; +} + +const Vector & +SubdomainFE::getC_Force(const Vector &disp, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + + // zero out the force vector + theResidual->Zero(); + + // check for a quick return + if (fact == 0.0) + return *theResidual; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(myID(i)); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); +#endif + return *theResidual; +} + + +Integrator * +SubdomainFE::getLastIntegrator() +{ + return theIntegrator; +} + + +const Vector & +SubdomainFE::getLastResponse() +{ +#ifndef OLD_FE + assert(myEle != nullptr); + + if (theIntegrator != nullptr) { + if (theIntegrator->getLastResponse(*theResidual,myID) < 0) { + opserr << "WARNING SubdomainFE::getLastResponse()"; + opserr << " - the Integrator had problems with getLastResponse()\n"; + } + } + else { + theResidual->Zero(); + opserr << "WARNING SubdomainFE::getLastResponse()"; + opserr << " No Integrator yet passed\n"; + } +#endif + Vector &result = *theResidual; + return result; +} + +void +SubdomainFE::addM_Force(const Vector &accel, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = accel(loc); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(1.0, myEle->getMass(), tmp, fact); +#endif +} + +void +SubdomainFE::addD_Force(const Vector &accel, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = accel(loc); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); +#endif +} + +void +SubdomainFE::addK_Force(const Vector &disp, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + assert(myEle->isSubdomain() == false); + + // check for a quick return + if (fact == 0.0) + return; + + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = disp(loc); + else + tmp(i) = 0.0; + } + + theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); +#endif +} + + + + + +Element * +SubdomainFE::getElement() +{ + return myEle; +} + + +// AddingSensitivity:BEGIN ///////////////////////////////// +void +SubdomainFE::addResistingForceSensitivity(int gradNumber, double fact) +{ + theResidual->addVector(1.0, myEle->getResistingForceSensitivity(gradNumber), -fact); +} + +void +SubdomainFE::addM_ForceSensitivity(int gradNumber, const Vector &vect, double fact) +{ + // Get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) { + tmp(i) = vect(loc); + } else { + tmp(i) = 0.0; + } + } + if (theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber),tmp,fact) < 0) { + opserr << "WARNING SubdomainFE::addM_ForceSensitivity() - "; + opserr << "- addMatrixVector returned error\n"; + } +} + +void +SubdomainFE::addD_ForceSensitivity(int gradNumber, const Vector &vect, double fact) +{ +#ifdef OLD_FE + assert(myEle != nullptr); + + // check for a quick return + if (fact == 0.0) + return; + + if (myEle->isSubdomain() == false) { + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = vect(loc); + else + tmp(i) = 0.0; + } + if (theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), tmp, fact) < 0){ + opserr << "WARNING SubdomainFE::addD_ForceSensitivity() - "; + opserr << "- addMatrixVector returned error\n"; + } + } + else { + opserr << "WARNING SubdomainFE::addD_ForceSensitivity() - "; + opserr << "- this should not be called on a Subdomain!\n"; + } +#endif +} + + + + + +int +SubdomainFE::commitSensitivity(int gradNum, int numGrads) +{ + myEle->commitSensitivity(gradNum, numGrads); + return 0; +} + +// AddingSensitivity:END //////////////////////////////////// + + +int +SubdomainFE::updateElement() +{ + if (myEle != nullptr) + return myEle->update(); + return 0; +} From 1edce8c537df079cfd3ed00fbc7efd1499fa3b01 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:36:35 -0800 Subject: [PATCH 083/161] Update CrdTransf.h --- SRC/coordTransformation/CrdTransf.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/SRC/coordTransformation/CrdTransf.h b/SRC/coordTransformation/CrdTransf.h index d716b2970f..9e5e110391 100644 --- a/SRC/coordTransformation/CrdTransf.h +++ b/SRC/coordTransformation/CrdTransf.h @@ -97,7 +97,4 @@ class CrdTransf: public TaggedObject, public MovableObject private: }; -// some additional methods related to prototypes created for copy constructors -extern ID OPS_getAllCrdTransfTags(); - #endif From eb335f924a820b51fda7cd071c93117cf93b48f1 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:38:01 -0800 Subject: [PATCH 084/161] Remove unused transpose matrices in MixedFrame3d Eliminated transformNaturalCoordsT, nd1T, and nd2T matrices and their related code from MixedFrame3d. Updated all relevant computations to use the appropriate operator (^) for transposition and multiplication, simplifying the code and reducing memory usage. --- SRC/element/Frame/MixedFrame3d.cpp | 75 ++++++------------------------ SRC/element/Frame/MixedFrame3d.h | 13 ++---- 2 files changed, 19 insertions(+), 69 deletions(-) diff --git a/SRC/element/Frame/MixedFrame3d.cpp b/SRC/element/Frame/MixedFrame3d.cpp index 54e3b2cd82..4da15d5a73 100644 --- a/SRC/element/Frame/MixedFrame3d.cpp +++ b/SRC/element/Frame/MixedFrame3d.cpp @@ -77,7 +77,6 @@ Matrix MixedFrame3d::theMatrix(NEGD, NEGD); Vector MixedFrame3d::theVector(NEGD); Matrix MixedFrame3d::transformNaturalCoords(NDM_NATURAL_WITH_TORSION, NDM_NATURAL_WITH_TORSION); -Matrix MixedFrame3d::transformNaturalCoordsT(NDM_NATURAL_WITH_TORSION, NDM_NATURAL_WITH_TORSION); Vector* MixedFrame3d::ei_trial = nullptr; @@ -85,8 +84,6 @@ Vector* MixedFrame3d::si_trial = nullptr; MatrixND* MixedFrame3d::nldhat = nullptr; MatrixND* MixedFrame3d::nd1 = nullptr; MatrixND* MixedFrame3d::nd2 = nullptr; -MatrixND* MixedFrame3d::nd1T = nullptr; -MatrixND* MixedFrame3d::nd2T = nullptr; // Constructor which takes the unique element tag, sections, @@ -206,13 +203,6 @@ MixedFrame3d::MixedFrame3d(int tag, std::array& nodes, transformNaturalCoords(3, 2) = 1; transformNaturalCoords(4, 4) = 1; transformNaturalCoords(5, 5) = 1; - transformNaturalCoordsT.Zero(); - transformNaturalCoordsT(0, 0) = 1; - transformNaturalCoordsT(1, 1) = 1; - transformNaturalCoordsT(3, 2) = 1; - transformNaturalCoordsT(2, 3) = 1; - transformNaturalCoordsT(4, 4) = 1; - transformNaturalCoordsT(5, 5) = 1; } if (ei_trial == nullptr) @@ -225,15 +215,6 @@ MixedFrame3d::MixedFrame3d(int tag, std::array& nodes, nd1 = new MatrixND[MAX_NUM_SECTIONS]; if (nd2 == nullptr) nd2 = new MatrixND[MAX_NUM_SECTIONS]; - if (nd1T == nullptr) - nd1T = new MatrixND[MAX_NUM_SECTIONS]{}; - if (nd2T == nullptr) - nd2T = new MatrixND[MAX_NUM_SECTIONS]{}; - -//for (int i = 0; i < MAX_NUM_SECTIONS; i++) { -// nd1T[i] = Matrix(NDM_NATURAL, NDM_SECTION); -// nd2T[i] = Matrix(NDM_NATURAL, NDM_SECTION); -//} } @@ -332,13 +313,6 @@ MixedFrame3d::MixedFrame3d() transformNaturalCoords(3, 2) = 1; transformNaturalCoords(4, 4) = -1; transformNaturalCoords(5, 5) = 1; - transformNaturalCoordsT.Zero(); - transformNaturalCoordsT(0, 0) = 1; - transformNaturalCoordsT(1, 1) = 1; - transformNaturalCoordsT(3, 2) = -1; - transformNaturalCoordsT(2, 3) = 1; - transformNaturalCoordsT(4, 4) = -1; - transformNaturalCoordsT(5, 5) = 1; } if (ei_trial == nullptr) @@ -351,10 +325,6 @@ MixedFrame3d::MixedFrame3d() nd1 = new MatrixND[MAX_NUM_SECTIONS]; if (nd2 == nullptr) nd2 = new MatrixND[MAX_NUM_SECTIONS]; - if (nd1T == nullptr) - nd1T = new MatrixND[MAX_NUM_SECTIONS]{}; - if (nd2T == nullptr) - nd2T = new MatrixND[MAX_NUM_SECTIONS]{}; } @@ -536,13 +506,6 @@ MixedFrame3d::revertToStart() nldhat[i] = this->getNld_hat(i, myZeros, L0, geom_flag); nd1[i] = this->getNd1(i, myZeros, L0, geom_flag); nd2[i] = this->getNd2(i, 0, L0); - - for (int j = 0; j < NDM_SECTION; j++) { - for (int k = 0; k < NDM_NATURAL; k++) { - nd1T[i](k, j) = nd1[i](j, k); - nd2T[i](k, j) = nd2[i](j, k); - } - } } // Set initial and committed section flexibility and GJ @@ -572,11 +535,11 @@ MixedFrame3d::revertToStart() MatrixND Kg{}; for (int i = 0; i < numSections; i++) { - G += L0 * wt[i] * nd1T[i] * nldhat[i]; - G2 += L0 * wt[i] * nd2T[i] * nldhat[i]; - H += L0 * wt[i] * nd1T[i] * fs_trial[i] * nd1[i]; - H12 += L0 * wt[i] * nd1T[i] * fs_trial[i] * nd2[i]; - H22 += L0 * wt[i] * nd2T[i] * fs_trial[i] * nd2[i]; + G += L0 * wt[i] * (nd1[i] ^ nldhat[i]); + G2 += L0 * wt[i] * (nd2[i] ^ nldhat[i]); + H += L0 * wt[i] * (nd1[i] ^ (fs_trial[i] * nd1[i])); + H12 += L0 * wt[i] * (nd1[i] ^ (fs_trial[i] * nd2[i])); + H22 += L0 * wt[i] * (nd2[i] ^ (fs_trial[i] * nd2[i])); // Md is zero since deformations are zero Kg.addMatrix(this->getKg(i, 0.0, L0), L0 * wt[i]); } @@ -619,7 +582,7 @@ MixedFrame3d::revertToStart() kv(5, 5) = GJ / L0; // Torsional Stiffness GJ/L ke_past = kv; - Matrix kvOpenSees = transformNaturalCoordsT * Matrix(kv) * transformNaturalCoords; + Matrix kvOpenSees = transformNaturalCoords^(Matrix(kv) * transformNaturalCoords); if (Ki == nullptr) Ki = new Matrix(NEGD, NEGD); @@ -664,7 +627,7 @@ MixedFrame3d::getTangentStiff() if (state_flag == 0) this->revertToStart(); - Matrix ktOpenSees = transformNaturalCoordsT * Matrix(kv) * transformNaturalCoords; + Matrix ktOpenSees = transformNaturalCoords ^ Matrix(kv) * transformNaturalCoords; return crdTransf->getGlobalStiffMatrix(ktOpenSees, qe_pres); } @@ -730,14 +693,6 @@ MixedFrame3d::update() } else { nd2[i] = this->getNd2(i, qe_pres(0), L); } - - // Transpose of shape functions - for (int j = 0; j < NDM_SECTION; j++) { - for (int k = 0; k < NDM_NATURAL; k++) { - nd1T[i](k, j) = nd1[i](j, k); - nd2T[i](k, j) = nd2[i](j, k); - } - } } // Update natural force @@ -793,14 +748,14 @@ MixedFrame3d::update() Kg.zero(); for (int i = 0; i < numSections; i++) { - V = V + L0*wt[i] * nd1T[i]*(ei_trial[i] - es_trial[i] - + V += L0*wt[i] * nd1[i]^(ei_trial[i] - es_trial[i] - fs_trial[i] * (si_trial[i] - sr_trial[i])); - V2 = V2 + L0 * wt[i] * nd2T[i] * (ei_trial[i] - es_trial[i]); - G = G + L0 * wt[i] * nd1T[i] * nldhat[i]; - G2 = G2 + L0 * wt[i] * nd2T[i] * nldhat[i]; - H = H + L0 * wt[i] * nd1T[i] * fs_trial[i] * nd1[i]; - H12 = H12 + L0 * wt[i] * nd1T[i] * fs_trial[i] * nd2[i]; - H22 = H22 + L0 * wt[i] * nd2T[i] * fs_trial[i] * nd2[i]; + V2 = V2 + L0*wt[i] * (nd2[i] ^ (ei_trial[i] - es_trial[i])); + G = G + L0*wt[i] * (nd1[i] ^ nldhat[i]); + G2 = G2 + L0*wt[i] * (nd2[i] ^ nldhat[i]); + H = H + L0*wt[i] * (nd1[i] ^ (fs_trial[i] * nd1[i])); + H12 = H12 + L0*wt[i] * (nd1[i] ^ (fs_trial[i] * nd2[i])); + H22 = H22 + L0*wt[i] * (nd2[i] ^ (fs_trial[i] * nd2[i])); if (!geom_flag) { // sr_trial[i][0] is the axial load, P @@ -843,7 +798,7 @@ MixedFrame3d::update() qe_pres(i) = internalForce[i]; qe_pres(5) = torsionalForce; // Add in torsional force - qe_pres = transformNaturalCoordsT * qe_pres; + qe_pres = transformNaturalCoords^qe_pres; // Compute the stiffness matrix without the torsion term MatrixND K_temp; diff --git a/SRC/element/Frame/MixedFrame3d.h b/SRC/element/Frame/MixedFrame3d.h index a771ffc30b..a316deadbe 100644 --- a/SRC/element/Frame/MixedFrame3d.h +++ b/SRC/element/Frame/MixedFrame3d.h @@ -30,7 +30,8 @@ class MixedFrame3d : public FiniteElement<2,3,6> { // constructors MixedFrame3d(int tag, std::array& nodes, - int numSections, FrameSection** sectionPtrs, + int numSections, + FrameSection** sectionPtrs, BeamIntegration& bi, CrdTransf& coordTransf, double density, @@ -38,16 +39,13 @@ class MixedFrame3d : public FiniteElement<2,3,6> { int geom_flag = true); MixedFrame3d(); - ~MixedFrame3d(); const char* getClassType() const { return "MixedFrame3d"; - }; - - + } int setNodes(); // (Domain* theDomain); @@ -73,7 +71,7 @@ class MixedFrame3d : public FiniteElement<2,3,6> { int recvSelf(int cTag, Channel&, FEM_ObjectBroker&); // TaggedObject - void Print(OPS_Stream& s, int flag = 0); + void Print(OPS_Stream& s, int flag); Response* setResponse(const char** argv, int argc, OPS_Stream& output); int getResponse(int responseID, Information& info); @@ -160,7 +158,6 @@ class MixedFrame3d : public FiniteElement<2,3,6> { static Matrix theMatrix; static Vector theVector; static Matrix transformNaturalCoords; - static Matrix transformNaturalCoordsT; // matrix to transform the natural coordinates from what the coordinate transformation uses and what the element uses // These variable are always recomputed, so there is no need to store them for each instance of the element @@ -169,8 +166,6 @@ class MixedFrame3d : public FiniteElement<2,3,6> { static MatrixND* nldhat; static MatrixND* nd1; static MatrixND* nd2; - static MatrixND* nd1T; - static MatrixND* nd2T; double wt[MAX_NUM_SECTIONS]; // weights of sections or gauss points of integration points double xi[MAX_NUM_SECTIONS]; From 5848d10ffab75a57748df880f7df577cf4910c50 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:38:34 -0800 Subject: [PATCH 085/161] Refactor ZeroLength element command error messages --- SRC/element/Point/commands.cpp | 52 ++++++++++++++-------------------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/SRC/element/Point/commands.cpp b/SRC/element/Point/commands.cpp index 629f2b157f..ab1d4f8678 100644 --- a/SRC/element/Point/commands.cpp +++ b/SRC/element/Point/commands.cpp @@ -38,6 +38,11 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg ModelRegistry* builder = (ModelRegistry*)clientData; Domain* domain = builder->getDomain(); + // Syntax: + // element ZeroLength eleTag? iNode? jNode? + // -mat matID1? ... -dir dirMat1? .. + // <-orient x1? x2? x3? y1? y2? y3?> + // the spatial dimension of the problem int ndm = builder->getNDM(); @@ -52,9 +57,7 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg // a quick check on number of args if (argc < 9) { opserr << "WARNING too few arguments " - << "want - element ZeroLength eleTag? iNode? jNode? " - << "-mat matID1? ... -dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + << "\n"; return TCL_ERROR; } @@ -62,27 +65,21 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg // get the ele tag if (Tcl_GetInt(interp, argv[2], &eleTag) != TCL_OK) { opserr << "WARNING invalied eleTag " << argv[2] - << "- element ZeroLength eleTag? iNode? jNode? -mat matID1? ... " - "-dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + << "\n"; return TCL_ERROR; } // get the two end nodes if (Tcl_GetInt(interp, argv[3], &iNode) != TCL_OK) { opserr << "WARNING invalied iNode " << argv[3] - << "- element ZeroLength eleTag? iNode? jNode? " - << "-mat matID1? ... -dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + << "\n"; return TCL_ERROR; } if (Tcl_GetInt(interp, argv[4], &jNode) != TCL_OK) { opserr << "WARNING invalid jNode " << argv[4] - << "- element ZeroLength eleTag? iNode? jNode? " - << "-mat matID1? ... -dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + << "\n"; return TCL_ERROR; } @@ -109,17 +106,13 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg if (argi == argc) { // check we encountered the -dirn flag opserr << "WARNING no -dirn flag encountered " - << "- element ZeroLength eleTag? iNode? jNode? " - << "-mat matID1? ... -dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + << "\n"; return TCL_ERROR; } if (numMat == 0) { opserr << "WARNING no materials specified " - << "- element ZeroLength eleTag? iNode? jNode? " - << "-mat \n"; + << "\n"; return TCL_ERROR; } @@ -161,9 +154,7 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg argi = 6 + numMat; if (strcmp(argv[argi], "-dir") != 0) { opserr << "WARNING expecting -dirn flag " << argv[argi] - << "- element ZeroLength eleTag? iNode? jNode? " - << "-mat matID1? ... -dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + << "\n"; delete[] theMats; return TCL_ERROR; @@ -183,17 +174,18 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg argi++; int dirnID; + const int ndf = builder->getNDF(); // read the dirn identifiers for (int j = 0; j < numMat; j++) { - if (Tcl_GetInt(interp, argv[argi], &dirnID) != TCL_OK) { - opserr << "WARNING invalid directiion " << argv[argi] - << "- element ZeroLength eleTag? iNode? jNode? " - << "-mat matID1? ... -dir dirMat1? .. " - << "<-orient x1? x2? x3? y1? y2? y3?>\n"; + if ((Tcl_GetInt(interp, argv[argi], &dirnID) != TCL_OK) || (dirnID < 1) || (dirnID > ndf)) { + opserr << OpenSees::PromptValueError + << "invalid directiion " << argv[argi] + << "\n"; delete[] theMats; return TCL_ERROR; - } else { + } + else { theDirns[j] = dirnID - 1; // the minus g3 to C++ argi++; } @@ -240,13 +232,12 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg y(2) = 0.0; } else if (ndm == 3) { - if (argc < (argi + 4)) { + if (argc < (argi + 3)) { opserr << "WARNING not enough parameters after -orient flag" << OpenSees::SignalMessageEnd; delete[] theMats; return TCL_ERROR; } - argi++; // read the y values for (int j = 0; j < 3; j++) { if (Tcl_GetDouble(interp, argv[argi], &value) != TCL_OK) { @@ -270,7 +261,8 @@ TclCommand_addZeroLength(ClientData clientData, Tcl_Interp *interp, Tcl_Size arg if (argi < argc) if ((Tcl_GetInt(interp, argv[argi], &doRayleighDamping) == TCL_OK)) argi++; - } else if (strcmp(argv[argi], "-dampMats") == 0) { + } + else if (strcmp(argv[argi], "-dampMats") == 0) { doRayleighDamping = 2; argi++; for (int i = 0; i < numMat; i++) { From 6902d2774590c4fa6fcafb742301ea89b56bb029 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:40:16 -0800 Subject: [PATCH 086/161] Update numberer.cpp --- SRC/runtime/commands/analysis/numberer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/SRC/runtime/commands/analysis/numberer.cpp b/SRC/runtime/commands/analysis/numberer.cpp index 9857d8c83f..50efab8801 100644 --- a/SRC/runtime/commands/analysis/numberer.cpp +++ b/SRC/runtime/commands/analysis/numberer.cpp @@ -103,3 +103,13 @@ TclCommand_setNumberer(ClientData clientData, Tcl_Interp* interp, int argc, TCL_ return TCL_OK; } +int +TclCommand_runNumberer(ClientData clientData, Tcl_Interp* interp, int argc, TCL_Char ** const argv) +{ + BasicAnalysisBuilder *builder = (BasicAnalysisBuilder *)clientData; + assert(builder != nullptr); + + builder->domainChanged(); + + return TCL_OK; +} From 91ddb462319ca6a8dadb4d95cfcda757c6363890 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:40:47 -0800 Subject: [PATCH 087/161] Update commands.cpp --- SRC/runtime/commands/domain/commands.cpp | 160 ++++++++++++----------- 1 file changed, 85 insertions(+), 75 deletions(-) diff --git a/SRC/runtime/commands/domain/commands.cpp b/SRC/runtime/commands/domain/commands.cpp index e7ea1ff1a8..598e2efaf2 100644 --- a/SRC/runtime/commands/domain/commands.cpp +++ b/SRC/runtime/commands/domain/commands.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -82,6 +81,85 @@ Tcl_CmdProc TclCommand_record; Tcl_CmdProc TclCommand_setLoadConst; Tcl_CmdProc TclCommand_setCreep; +namespace { +static struct { + const char *name; + int (*func)(ClientData, Tcl_Interp *, Tcl_Size, TCL_Char ** const); +} domainCommands[] = { + {"loadConst", &TclCommand_setLoadConst}, + {"recorder", &TclAddRecorder}, + {"region", &TclCommand_addMeshRegion}, + + {"printGID", &printModelGID}, + + {"setTime", &TclCommand_setTime}, + {"getTime", &TclCommand_getTime}, + {"setCreep", &TclCommand_setCreep}, + + // DAMPING + {"rayleigh", &rayleighDamping}, + + {"getLoadFactor", &getLoadFactor}, + + // + {"basicDeformation", &basicDeformation}, + {"basicForce", &basicForce}, + {"basicStiffness", &basicStiffness}, + + + {"nodeDOFs", &nodeDOFs}, + {"nodeCoord", &nodeCoord}, + {"nodeMass", &nodeMass}, + {"nodeVel", &nodeVel}, + {"nodeDisp", &nodeDisp}, + {"nodeAccel", &nodeAccel}, + {"nodeResponse", &nodeResponse}, + {"nodePressure", &nodePressure}, + {"nodeBounds", &nodeBounds}, + {"findNodeWithID", &findID}, + {"nodeUnbalance", &nodeUnbalance}, + {"nodeEigenvector", &nodeEigenvector}, + {"nodeReaction", &nodeReaction}, + + {"reactions", &calculateNodalReactions}, + + {"setNodeVel", &setNodeVel}, + {"setNodeDisp", &setNodeDisp}, + {"setNodeAccel", &setNodeAccel}, + {"setNodeCoord", &setNodeCoord}, + {"nodeRotation", &nodeRotation}, + {"getNodeTags", &getNodeTags}, + + + + {"getParamTags", &getParamTags}, + {"getParamValue", &getParamValue}, + {"parameter", &TclCommand_parameter}, + {"addToParameter", &TclCommand_parameter}, + {"updateParameter", &TclCommand_parameter}, + {"setParameter", &TclCommand_setParameter}, + + + {"getEleLoadTags", &getEleLoadTags}, + {"getEleLoadData", &getEleLoadData}, + {"getEleLoadClassTags", &getEleLoadClassTags}, + + + {"sectionForce", §ionForce}, + {"sectionTag", §ionTag}, + {"sectionDisplacement", §ionDisplacement}, + {"sectionDeformation", §ionDeformation}, + {"sectionStiffness", §ionStiffness}, + {"sectionFlexibility", §ionFlexibility}, + {"sectionLocation", §ionLocation}, + {"sectionWeight", §ionWeight}, + + {"recorderValue", &OPS_recorderValue}, + {"record", &TclCommand_record}, + + {"InitialStateAnalysis", &InitialStateAnalysis}, +}; +} // TODO: reimplement defaultUnits and setParameter // int defaultUnits(ClientData, Tcl_Interp *, int, TCL_Char ** const argv); @@ -92,6 +170,7 @@ G3_AddTclDomainCommands(Tcl_Interp *interp, Domain* the_domain) ClientData domain = (ClientData)the_domain; + { using namespace OpenSees::DomainCommands; // Domain @@ -118,82 +197,13 @@ G3_AddTclDomainCommands(Tcl_Interp *interp, Domain* the_domain) Tcl_CreateCommand(interp, "setElementRayleighDampingFactors", &addElementRayleigh, domain, nullptr); Tcl_CreateCommand(interp, "setElementRayleighFactors", &addElementRayleigh, domain, nullptr); // Modal - Tcl_CreateCommand(interp, "modalProperties", &modalProperties, domain, nullptr); + Tcl_CreateCommand(interp, "modalProperties", &modalProperties, domain, nullptr); } - Tcl_CreateCommand(interp, "loadConst", &TclCommand_setLoadConst, domain, nullptr); - Tcl_CreateCommand(interp, "recorder", &TclAddRecorder, domain, nullptr); - Tcl_CreateCommand(interp, "region", &TclCommand_addMeshRegion, domain, nullptr); - - Tcl_CreateCommand(interp, "printGID", &printModelGID, domain, nullptr); - - Tcl_CreateCommand(interp, "setTime", &TclCommand_setTime, domain, nullptr); - Tcl_CreateCommand(interp, "getTime", &TclCommand_getTime, domain, nullptr); - Tcl_CreateCommand(interp, "setCreep", &TclCommand_setCreep, nullptr, nullptr); - - // DAMPING - Tcl_CreateCommand(interp, "rayleigh", &rayleighDamping, domain, nullptr); - - Tcl_CreateCommand(interp, "getLoadFactor", &getLoadFactor, domain, nullptr); - - // - Tcl_CreateCommand(interp, "basicDeformation", &basicDeformation, domain, nullptr); - Tcl_CreateCommand(interp, "basicForce", &basicForce, domain, nullptr); - Tcl_CreateCommand(interp, "basicStiffness", &basicStiffness, domain, nullptr); - - - Tcl_CreateCommand(interp, "nodeDOFs", &nodeDOFs, domain, nullptr); - Tcl_CreateCommand(interp, "nodeCoord", &nodeCoord, domain, nullptr); - Tcl_CreateCommand(interp, "nodeMass", &nodeMass, domain, nullptr); - Tcl_CreateCommand(interp, "nodeVel", &nodeVel, domain, nullptr); - Tcl_CreateCommand(interp, "nodeDisp", &nodeDisp, domain, nullptr); - Tcl_CreateCommand(interp, "nodeAccel", &nodeAccel, domain, nullptr); - Tcl_CreateCommand(interp, "nodeResponse", &nodeResponse, domain, nullptr); - Tcl_CreateCommand(interp, "nodePressure", &nodePressure, domain, nullptr); - Tcl_CreateCommand(interp, "nodeBounds", &nodeBounds, domain, nullptr); - Tcl_CreateCommand(interp, "findNodeWithID", &findID, domain, nullptr); - Tcl_CreateCommand(interp, "nodeUnbalance", &nodeUnbalance, domain, nullptr); - Tcl_CreateCommand(interp, "nodeEigenvector", &nodeEigenvector, domain, nullptr); - Tcl_CreateCommand(interp, "nodeReaction", &nodeReaction, domain, nullptr); - - Tcl_CreateCommand(interp, "reactions", &calculateNodalReactions, domain, nullptr); - - Tcl_CreateCommand(interp, "setNodeVel", &setNodeVel, domain, nullptr); - Tcl_CreateCommand(interp, "setNodeDisp", &setNodeDisp, domain, nullptr); - Tcl_CreateCommand(interp, "setNodeAccel", &setNodeAccel, domain, nullptr); - Tcl_CreateCommand(interp, "setNodeCoord", &setNodeCoord, domain, nullptr); - Tcl_CreateCommand(interp, "nodeRotation", &nodeRotation, domain, nullptr); - Tcl_CreateCommand(interp, "getNodeTags", &getNodeTags, domain, nullptr); - - - - Tcl_CreateCommand(interp, "getParamTags", &getParamTags, domain, nullptr); - Tcl_CreateCommand(interp, "getParamValue", &getParamValue, domain, nullptr); - Tcl_CreateCommand(interp, "parameter", &TclCommand_parameter, domain, nullptr); - Tcl_CreateCommand(interp, "addToParameter", &TclCommand_parameter, domain, nullptr); - Tcl_CreateCommand(interp, "updateParameter", &TclCommand_parameter, domain, nullptr); - Tcl_CreateCommand(interp, "setParameter", &TclCommand_setParameter, domain, nullptr); - - - Tcl_CreateCommand(interp, "getEleLoadTags", &getEleLoadTags, domain, nullptr); - Tcl_CreateCommand(interp, "getEleLoadData", &getEleLoadData, domain, nullptr); - Tcl_CreateCommand(interp, "getEleLoadClassTags", &getEleLoadClassTags, domain, nullptr); - - - Tcl_CreateCommand(interp, "sectionForce", §ionForce, domain, nullptr); - Tcl_CreateCommand(interp, "sectionTag", §ionTag, domain, nullptr); - Tcl_CreateCommand(interp, "sectionDisplacement", §ionDisplacement, domain, nullptr); - Tcl_CreateCommand(interp, "sectionDeformation", §ionDeformation, domain, nullptr); - Tcl_CreateCommand(interp, "sectionStiffness", §ionStiffness, domain, nullptr); - Tcl_CreateCommand(interp, "sectionFlexibility", §ionFlexibility, domain, nullptr); - Tcl_CreateCommand(interp, "sectionLocation", §ionLocation, domain, nullptr); - Tcl_CreateCommand(interp, "sectionWeight", §ionWeight, domain, nullptr); - - Tcl_CreateCommand(interp, "recorderValue", &OPS_recorderValue, domain, nullptr); - Tcl_CreateCommand(interp, "record", &TclCommand_record, domain, nullptr); - - Tcl_CreateCommand(interp, "InitialStateAnalysis", &InitialStateAnalysis, nullptr, nullptr); - + for (int i = 0; i < sizeof(domainCommands) / sizeof(domainCommands[0]); ++i) { + Tcl_CreateCommand(interp, domainCommands[i].name, + domainCommands[i].func, domain, nullptr); + } // sensitivity Tcl_CreateCommand(interp, "computeGradients", &computeGradients, (ClientData)domain, (Tcl_CmdDeleteProc *)NULL); From 16741aaeff48a29d265fe893b5c0c8aa6c36941f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:40:55 -0800 Subject: [PATCH 088/161] Update element_load.cpp --- SRC/runtime/commands/domain/loading/element_load.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SRC/runtime/commands/domain/loading/element_load.cpp b/SRC/runtime/commands/domain/loading/element_load.cpp index e5c7f7b7b9..4dce09f089 100644 --- a/SRC/runtime/commands/domain/loading/element_load.cpp +++ b/SRC/runtime/commands/domain/loading/element_load.cpp @@ -828,8 +828,9 @@ TclCommand_addElementalLoad(ClientData clientData, Tcl_Interp *interp, for (int i = 0; i < 18; ++i) { if (Tcl_GetDouble(interp, argv[count], &BufferData) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid data " << argv[count] - << " for -beamThermal 3D\n"; + opserr << OpenSees::PromptValueError + << "invalid data " << argv[count] + << " for -shellThermal 3D\n"; return TCL_ERROR; } indata[i] = BufferData; @@ -865,8 +866,9 @@ TclCommand_addElementalLoad(ClientData clientData, Tcl_Interp *interp, for (int i = 0; i < 10; ++i) { if (Tcl_GetDouble(interp, argv[count], &BufferData) != TCL_OK) { - opserr << OpenSees::PromptValueError << "eleLoad - invalid data " << argv[count] - << " for -beamThermal 3D\n"; + opserr << OpenSees::PromptValueError + << "eleLoad - invalid data " << argv[count] + << " for -shellThermal 3D\n"; return TCL_ERROR; } indata[i] = BufferData; From 6da926613e15805e59719eba062316b9f4e7944b Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:41:04 -0800 Subject: [PATCH 089/161] Update element.cpp --- SRC/runtime/commands/modeling/element.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SRC/runtime/commands/modeling/element.cpp b/SRC/runtime/commands/modeling/element.cpp index e1043d3dc0..a3a1a71a10 100644 --- a/SRC/runtime/commands/modeling/element.cpp +++ b/SRC/runtime/commands/modeling/element.cpp @@ -315,6 +315,7 @@ TclCommand_addElement(ClientData clientData, Tcl_Interp *interp, int argc, TCL_C strcasecmp(argv[1], "ForceFrame") == 0 || strcasecmp(argv[1], "MixedFrame") == 0 || strcasecmp(argv[1], "ExactFrame") == 0 || + strcasecmp(argv[1], "ShearFrame") == 0 || strcasecmp(argv[1], "ForceDeltaFrame") == 0 || strcasecmp(argv[1], "ForceBeamColumn") == 0 || From ae859642996f439f8e6d5421ce61d767343c5e53 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:41:19 -0800 Subject: [PATCH 090/161] Delete Makefile --- SRC/system_of_eqn/eigenSOE/Makefile | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 SRC/system_of_eqn/eigenSOE/Makefile diff --git a/SRC/system_of_eqn/eigenSOE/Makefile b/SRC/system_of_eqn/eigenSOE/Makefile deleted file mode 100644 index bf8821b61d..0000000000 --- a/SRC/system_of_eqn/eigenSOE/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../../../Makefile.def - -OBJS = EigenSOE.o \ - EigenSolver.o \ - ArpackSOE.o \ - ArpackSolver.o \ - SymBandEigenSOE.o \ - SymBandEigenSolver.o \ - FullGenEigenSOE.o \ - FullGenEigenSolver.o - -all: $(OBJS) - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o - -spotless: clean - @$(RM) $(RMFLAGS) - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. From 4f44e35b5b1359d007e20316a81fe160ac13c8ea Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:42:08 -0800 Subject: [PATCH 091/161] Update analysis.cpp --- SRC/runtime/commands/analysis/analysis.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SRC/runtime/commands/analysis/analysis.cpp b/SRC/runtime/commands/analysis/analysis.cpp index dc29cecae8..bfd81680d6 100644 --- a/SRC/runtime/commands/analysis/analysis.cpp +++ b/SRC/runtime/commands/analysis/analysis.cpp @@ -63,7 +63,8 @@ extern "C" int OPS_ResetInputNoBuilder(ClientData clientData, TCL_Char ** const argv, Domain *domain); Tcl_CmdProc TclCommand_clearAnalysis; -Tcl_CmdProc TclCommand_setNumberer; +extern Tcl_CmdProc TclCommand_setNumberer; +extern Tcl_CmdProc TclCommand_runNumberer; namespace OpenSees { Tcl_CmdProc responseSpectrumAnalysis; } @@ -80,6 +81,7 @@ G3_AddTclAnalysisAPI(Tcl_Interp *interp, ModelRegistry& context) Tcl_CreateCommand(interp, "_clearAnalysis", &TclCommand_clearAnalysis, analysis, nullptr); Tcl_CreateCommand(interp, "numberer", TclCommand_setNumberer, analysis, nullptr); + Tcl_CreateCommand(interp, "number", TclCommand_runNumberer, analysis, nullptr); Tcl_CreateCommand(interp, "responseSpectrumAnalysis", &OpenSees::responseSpectrumAnalysis, nullptr, nullptr); From 678464817e86d654a9d5385505eb080b2a67470f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:42:24 -0800 Subject: [PATCH 092/161] Update Bilin02.cpp --- SRC/material/uniaxial/Bilin02.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/SRC/material/uniaxial/Bilin02.cpp b/SRC/material/uniaxial/Bilin02.cpp index b770f4c54e..b60864fb17 100644 --- a/SRC/material/uniaxial/Bilin02.cpp +++ b/SRC/material/uniaxial/Bilin02.cpp @@ -1010,13 +1010,9 @@ Bilin02::setTrialStrain(double strain, double strainRate) double dCap2Neg=(fCapRefNeg+ekhardNeg*dyNeg-fyNeg)/(ekhardNeg-capSlopeOrigNeg*Ke); //cpNeg=min(dCap1Neg,dCap2Neg); if (dCap1Neg Date: Fri, 23 Jan 2026 02:45:57 -0800 Subject: [PATCH 093/161] Create ShearFrame3d.tpp --- SRC/element/Frame/ShearFrame3d.tpp | 928 +++++++++++++++++++++++++++++ 1 file changed, 928 insertions(+) create mode 100644 SRC/element/Frame/ShearFrame3d.tpp diff --git a/SRC/element/Frame/ShearFrame3d.tpp b/SRC/element/Frame/ShearFrame3d.tpp new file mode 100644 index 0000000000..488283f31e --- /dev/null +++ b/SRC/element/Frame/ShearFrame3d.tpp @@ -0,0 +1,928 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, Claudio M. Perez +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// +// +// Please cite the following resources in any derivative works: +// https://doi.org/10.5281/zenodo.10456866 +// https://doi.org/10.1002/nme.7506 +// +//===----------------------------------------------------------------------===// +// +// Torsion warping is due to [4], shear warping is due to [5] +// +// [1] Simo J.C. (1985): A finite strain beam formulation. The three-dimensional +// dynamic problem. Part I. +// Computer Methods in Applied Mechanics and Engineering, 49(1):55–70. +// https://doi.org/10.1016/0045-7825(85)90050-7 +// +// [2] Simo J.C., Vu-Quoc L. (1986): A three-dimensional finite-strain rod model +// Part II: Computational aspects. +// Computer Methods in Applied Mechanics and Engineering, 58(1):79–116. +// https://doi.org/10/b8wd4z +// +// [3] Perez C.M., and Filippou F.C. (2024): +// "On Nonlinear Geometric Transformations of Finite Elements" +// Int. J. Numer. Meth. Engrg. +// https://doi.org/10.1002/nme.7506 +// +// [4] Simo J.C., Vu-Quoc L. (1991): A Geometrically-exact rod model incorporating shear +// and torsion-warping deformation. +// International Journal of Solids and Structures, 27(3):371-393. +// doi: 10.1016/0020-7683(91)90089-x +// +// [5] Perez C.M., Filippou F.C., Mosalam K.M. (2025): Untitled work. +// +//===----------------------------------------------------------------------===// +// +// Claudio M. Perez +// +#include +#include +#include +#include +#include +#include +#include + +#include "for_int.tpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +// + +namespace OpenSees { + +template +ShearFrame3d::ShearFrame3d(int tag, + std::array& nodes, + FrameSection* section[nen - 1], + CrdTransf& transform) + : FiniteElement(tag, 0, nodes, 1), + xn{0}, + jxs(0), + R0(), + transform(&transform), + logarithm(Logarithm::None), + stencil(nullptr), + parameterID(0) +{ + p.zero(); + K.zero(); + + for (int i = 0; i < nip; i++) { + pres[i].point = 0.0; + pres[i].weight = 0.0; + pres[i].material = section[i]->getFrameCopy(); + } +} + + +template +ShearFrame3d::~ShearFrame3d() +{ + for (GaussPoint& point : pres) + if (point.material != nullptr) + delete point.material; + + if (stencil != nullptr) + delete stencil; +} + + +template +int +ShearFrame3d::setNodes() +{ + auto& theNodes = this->FiniteElement::theNodes; + + if (transform->initialize(theNodes[0], theNodes[nen-1]) != 0) { + opserr << " -- Error initializing coordinate transformation\n"; + return -1; + } + const Vector& xi = theNodes[ 0]->getCrds(); + const Vector& xj = theNodes[nen-1]->getCrds(); + double L = (xj-xi).Norm(); + jxs = L; + + + // Node locations in local (scalar) coordinate + for (unsigned i=0; i < nen; i++) + xn[i] = i*L/double(nen-1); + + GaussLegendre<1, nip> gauss; + for (unsigned i=0; i < nip; i++) { + pres[i].point = (gauss.pts[i] + 1.0)*L/2.0; + pres[i].weight = gauss.wts[i]*L/2.0; + lagrange(pres[i].point, xn, pres[i].shape); + } + + // Zero out the state of the Gauss pres + this->revertToStart(); + + return 0; +} + +template +int +ShearFrame3d::revertToStart() +{ + // Revert the transformation to start + if (transform->revertToStart() != 0) + return -2; + + Vector E1(3), E2(3), E3(3); + transform->getLocalAxes(E1, E2, E3); + + for (int i=0; irevertToStart() != 0) + return -1; + } + past = pres; + + // Revert the element state to start + // NOTE: This assumes that there are zero initial stresses? + p.zero(); + K.zero(); + + return 0; +} + + +template +int +ShearFrame3d::revertToLastCommit() +{ + pres = past; + + for (GaussPoint& point : pres) { + FrameSection& section = *point.material; + + if (section.revertToLastCommit() != 0) + return -1; + } + + return 0; +} + +template +int +ShearFrame3d::update() +{ + constexpr static Vector3D D {1, 0, 0}; + auto& theNodes = this->FiniteElement::theNodes; + const bool Linear = true; + + // + // Collect nodal parameters + // + VectorND ddu[nen]; + for (unsigned i=0; i < nen; i++) { + const Vector& ddui = theNodes[i]->getIncrDeltaDisp(); + for (int j=0; j xyz[nen]; + std::array,nen> uwarp{}; + + for (unsigned i=0; i < nen; i++) { + const Vector& xi = theNodes[i]->getCrds(); + const Vector& ui = theNodes[i]->getTrialDisp(); + for (int j=0; j warp{}; + std::array dwarp{}; + + for (int k=0; k e { + gamma[0], gamma[1], gamma[2], + kappa[0], kappa[1], kappa[2], + }; + for (int j=0; j(e) != 0) + return -1; + + const VectorND s = section.getResultant(); + const MatrixND Ks = section.getTangent(State::Pres); + + + // + // A = diag(R, R); + // + MatrixND A{}; + for (int j=0; j<3; j++) { + for (int k=0; k<3; k++) { + A(j,k) = R(j,k); + A(j+3,k+3) = R(j,k); + } + } + for (int j=0; j<2*nwm; j++) + A(6+j,6+j) = 1.0; + + + MatrixND B[nen]; + for (unsigned j=0; j Bj{}; + B_nat(Bj, pres[i].shape, R*D, j); + B[j] = A^Bj; + + // p += B s w + VectorND pj = B[j]^s; + for (int l=0; l Kjk{}; + for (unsigned j=0; j G{}; + // for (unsigned j=0; j(G, A*s, dx, pres[i].shape, j, k); + // K.assemble(G, ndf*j, ndf*k, pres[i].weight); + // } + // } + } // Main Gauss loop + + for (FrameLoad* load : frame_loads) { + for (auto [xp, wp] : load->quadrature()) { + const double w = wp*jxs; + const double xc = xp; + + double shp[2][nen]; + lagrange(xp*jxs, xn, shp); + Versor q; + if (xp == 0.0) + q = theNodes[0]->getTrialRotation(); + else if (xp == 1.0) + q = theNodes[nen-1]->getTrialRotation(); + else { + q = theNodes[0]->getTrialRotation().slerp( + theNodes[nen-1]->getTrialRotation(), xp); + } + Matrix3D R = MatrixFromVersor(q); +#ifndef _MSC_VER + for_int([&](auto i_) constexpr { + constexpr int i = i_.value; + load->addLoadAtPoint(p, xc, w*shp[0][i], jxs, R0, R); + for_int([&](auto j_) constexpr { + constexpr int j = j_.value; + load->addTangAtPoint(K, xc, w*shp[0][i]*shp[0][j], jxs, R0, R); + }); + }); +#endif + } + } + return 0; +} + + +template +const Vector & +ShearFrame3d::getResistingForce() +{ + thread_local Vector wrapper(0); + wrapper.setData(p); + return wrapper; +} + + +template +const Matrix & +ShearFrame3d::getTangentStiff() +{ + thread_local Matrix wrapper(0,0); + wrapper.setData(K); + return wrapper; +} + + +template +const Matrix & +ShearFrame3d::getInitialStiff() +{ + static MatrixND Ki{}; + static Matrix wrapper(Ki); + return wrapper; +} + + +template +const Matrix & +ShearFrame3d::getMass() +{ + // TODO + static MatrixND M{}; + static Matrix wrapper(M); + return wrapper; +} + +template +const Vector & +ShearFrame3d::getResistingForceSensitivity(int grad) +{ + static constexpr Vector3D D {1, 0, 0}; + static VectorND dp; + static Vector wrapper(dp); + dp.zero(); + + auto& theNodes = this->FiniteElement::theNodes; + + // Form displaced node locations xyz + VectorND xyz[nen]; + for (unsigned i=0; i < nen; i++) { + const Vector& xi = theNodes[i]->getCrds(); + const Vector& ui = theNodes[i]->getTrialDisp(); + for (int j=0; j s = section.getResultantGradient(grad, true); + + // + // A = diag(R, R); + // + const Matrix3D& R = pres[i].rotation; + + MatrixND A{}; + for (int j=0; j<3; j++) { + for (int k=0; k<3; k++) { + A(j,k) = R(j,k); + A(j+3,k+3) = R(j,k); + } + } + for (int j=0; j<2*nwm; j++) + A(6+j,6+j) = 1.0; + + MatrixND B[nen]; + for (unsigned j=0; j Bj; + Bj.zero(); + B_nat(Bj, pres[i].shape, R*D, j); + B[j] = A^Bj; + + // p += B s w + VectorND pj = B[j]^s; + for (int l=0; l +int +ShearFrame3d::addLoad(ElementalLoad* theLoad, double loadFactor) +{ + + int type = theLoad->getClassTag(); + + if (type == LOAD_TAG_FrameLoad && loadFactor == 0.0) + frame_loads.erase((FrameLoad*)theLoad); + + else if (type == LOAD_TAG_FrameLoad && loadFactor == 1.0) { + FrameLoad* frame_load = (FrameLoad*)theLoad; + if (!frame_load->conservative()) + frame_loads.insert(frame_load); + } + else + return -1; + + // TODO: compute conservative load on flag == -1? +#if 0 + else { + c_loads[frame_load->getTag()] = VectorND{0.0}; + } +#endif + + return 0; +} + + +template +Response* +ShearFrame3d::setResponse(const char** argv, int argc, OPS_Stream& output) +{ + + Response* theResponse = nullptr; + double L = 0; + if (this->setState(State::Init) == 0) { + auto& theNodes = this->FiniteElement::theNodes; + const Vector& xi = theNodes[ 0]->getCrds(); + const Vector& xj = theNodes[nen-1]->getCrds(); + L = (xi-xj).Norm(); + } + + const ID& node_tags = this->getExternalNodes(); + output.tag("ElementOutput"); + output.attr("eleType", this->getClassType()); + output.attr("eleTag", this->getTag()); + output.attr("node1", node_tags(0)); + output.attr("node2", node_tags(nen-1)); + + // + // compare argv[0] for known response types + // + + // Global forces + if (strcmp(argv[0], "forces") == 0 || + strcmp(argv[0], "force") == 0 || + strcmp(argv[0], "globalForce") == 0 || + strcmp(argv[0], "globalForces") == 0) { + + output.tag("ResponseType", "Px_1"); + output.tag("ResponseType", "Py_1"); + output.tag("ResponseType", "Pz_1"); + output.tag("ResponseType", "Mx_1"); + output.tag("ResponseType", "My_1"); + output.tag("ResponseType", "Mz_1"); + output.tag("ResponseType", "Px_2"); + output.tag("ResponseType", "Py_2"); + output.tag("ResponseType", "Pz_2"); + output.tag("ResponseType", "Mx_2"); + output.tag("ResponseType", "My_2"); + output.tag("ResponseType", "Mz_2"); + + theResponse = new ElementResponse(this, Respond::GlobalForce, Vector(nen*ndf)); + + // Local force + } else if (strcmp(argv[0], "localForce") == 0 || + strcmp(argv[0], "localForces") == 0) { + + output.tag("ResponseType", "N_1"); + output.tag("ResponseType", "Vy_1"); + output.tag("ResponseType", "Vz_1"); + output.tag("ResponseType", "T_1"); + output.tag("ResponseType", "My_1"); + output.tag("ResponseType", "Mz_1"); + output.tag("ResponseType", "N_2"); + output.tag("ResponseType", "Vy_2"); + output.tag("ResponseType", "Vz_2"); + output.tag("ResponseType", "T_2"); + output.tag("ResponseType", "My_2"); + output.tag("ResponseType", "Mz_2"); + + theResponse = new ElementResponse(this, Respond::LocalForce, Vector(nen*ndf)); + + } else if (strcmp(argv[0], "RayleighForces") == 0 || + strcmp(argv[0], "rayleighForces") == 0) { + + theResponse = new ElementResponse(this, 12, Vector(12)); + + } else if (strcmp(argv[0], "sections") == 0) { + if (this->setState(State::Init) != 0) + return nullptr; + + CompositeResponse* theCResponse = new CompositeResponse(); + int numResponse = 0; + const int numSections = pres.size(); + + for (int i = 0; i < numSections; i++) { + output.tag("GaussPointOutput"); + output.attr("number", i + 1); + output.attr("eta", pres[i].point * L); + + Response* theSectionResponse = pres[i].material->setResponse(&argv[1], argc - 1, output); + + if (theSectionResponse != nullptr) + numResponse = theCResponse->addResponse(theSectionResponse); + } + + if (numResponse == 0) // no valid responses found + delete theCResponse; + else + theResponse = theCResponse; + } + + // 10-11: Integration + else if (strcmp(argv[0], "integrationPoints") == 0) + theResponse = new ElementResponse(this, 10, Vector(pres.size())); + + else if (strcmp(argv[0], "integrationWeights") == 0) + theResponse = new ElementResponse(this, 11, Vector(pres.size())); + + // 110-111: sections + else if (strcmp(argv[0], "sectionTags") == 0) + theResponse = new ElementResponse(this, 110, ID(pres.size())); + + else if (strcmp(argv[0], "sectionDisplacements") == 0) { + if (argc > 1 && strcmp(argv[1], "local") == 0) + theResponse = new ElementResponse(this, 1111, Matrix(pres.size(), 3)); + else + theResponse = new ElementResponse(this, 111, Matrix(pres.size(), 3)); + } + + else if (strstr(argv[0], "section") != nullptr) { + + if (argc > 1) { + + int sectionNum = atoi(argv[1]); + + if (sectionNum > 0 && sectionNum <= (int)pres.size() && argc > 2) { + if (this->setState(State::Init) != 0) + return nullptr; + + output.tag("GaussPointOutput"); + output.attr("number", sectionNum); + output.attr("eta", 2.0 * pres[sectionNum - 1].point - 1.0); + + if (strcmp(argv[2], "dsdh") != 0) { + theResponse = pres[sectionNum - 1].material->setResponse(&argv[2], argc - 2, output); + } else { + int order = pres[sectionNum - 1].material->getOrder(); + theResponse = new ElementResponse(this, 76, Vector(order)); + Information& info = theResponse->getInformation(); + info.theInt = sectionNum; + } + + output.endTag(); + } + + else if (sectionNum == 0) { + // argv[1] was not an int, we want all sections, + + CompositeResponse* theCResponse = new CompositeResponse(); + int numResponse = 0; + const int numSections = pres.size(); + + for (int i = 0; i < numSections; i++) { + + output.tag("GaussPointOutput"); + output.attr("number", i + 1); + output.attr("eta", pres[i].point * L); + + Response* theSectionResponse = pres[i].material->setResponse(&argv[1], argc - 1, output); + + if (theSectionResponse != nullptr) { + numResponse = theCResponse->addResponse(theSectionResponse); + } + } + + if (numResponse == 0) // no valid responses found + delete theCResponse; + else + theResponse = theCResponse; + } + } + } + + else if (strcmp(argv[0], "energy") == 0) { + return new ElementResponse(this, 2000, 0.0); + } + + output.endTag(); + + return theResponse; +} + +template +int +ShearFrame3d::getResponse(int responseID, Information &info) +{ + + double L = 0; + if (this->setState(State::Init) == 0) { + auto& theNodes = this->FiniteElement::theNodes; + const Vector& xi = theNodes[ 0]->getCrds(); + const Vector& xj = theNodes[nen-1]->getCrds(); + L = (xi-xj).Norm(); + } + + + // NOTE: This will never be called with Respond::GlobalForce; + // it gets intercepted by Domain::getElementResponse + if (responseID == Respond::GlobalForce) + return info.setVector(this->getResistingForce()); + + else if (responseID == Respond::LocalForce) { + thread_local VectorND q{0.0}; + Vector q_resp(q); + + auto p = this->getResistingForce(); + + for (unsigned i=0; isetState(State::Init) != 0) + return -1; + + Vector locs(pres.size()); + for (int i = 0; i < nip; i++) + locs[i] = pres[i].point * L; + + return info.setVector(locs); + } + + else if (responseID == 11) { + // ensure we have L, xi[] and wt[] + if (this->setState(State::Init) != 0) + return -1; + + Vector weights(pres.size()); + for (unsigned i = 0; i < nip; i++) + weights(i) = pres[i].weight * L; + + return info.setVector(weights); + } + + else if (responseID == 110) { + const int numSections = pres.size(); + ID tags(numSections); + for (int i = 0; i < numSections; i++) + tags(i) = pres[i].material->getTag(); + return info.setID(tags); + } + + else if (responseID == 12) + return info.setVector(this->getRayleighDampingForces()); + + return -1; +} + +template +int +ShearFrame3d::sendSelf(int commitTag, Channel& theChannel) +{ + // TODO + return -1; +} + +template +int +ShearFrame3d::recvSelf(int commitTag, Channel& theChannel, FEM_ObjectBroker& theBroker) +{ + // TODO + return -1; +} + +template +void +ShearFrame3d::Print(OPS_Stream& stream, int flag) +{ + const ID& node_tags = this->getExternalNodes(); + + if (flag == OPS_PRINT_PRINTMODEL_JSON) { + + stream << OPS_PRINT_JSON_ELEM_INDENT << "{"; + stream << "\"name\": " << this->getTag() << ", "; + stream << "\"type\": \"" << this->getClassType() << "\", "; + stream << "\"nodes\": ["; + for (int i = 0; i < (int)nen - 1; i++) + stream << node_tags(i) << ", "; + stream << node_tags(nen - 1) << "]"; + stream << ", "; + + + stream << "\"sections\": ["; + for (decltype(pres.size()) i = 0; i < pres.size() - 1; i++) + stream << pres[i].material->getTag() << ", "; + stream << pres[pres.size() - 1].material->getTag() << "]"; + stream << ", "; + + stream << "\"transform\": " << transform->getTag() ; + stream << "}"; + } +} + +template +int +ShearFrame3d::setParameter(const char** argv, int argc, Parameter& param) +{ + if (argc < 1) + return -1; + + int result = -1; + + + // Section response + if (strstr(argv[0], "sectionX") != nullptr) { + if (argc > 2) { + float sectionLoc = atof(argv[1]); + + const int numSections = pres.size(); + double xi[nip]; + double L = jxs; + stencil->getSectionLocations(numSections, L, xi); + + sectionLoc /= L; + + float minDistance = fabs(xi[0] - sectionLoc); + int sectionNum = 0; + for (int i = 1; i < numSections; i++) { + if (fabs(pres[i].point - sectionLoc) < minDistance) { + minDistance = fabs(pres[i].point - sectionLoc); + sectionNum = i; + } + } + + return pres[sectionNum].material->setParameter(&argv[2], argc - 2, param); + } + } + + // If the parameter belongs to a particular section or lower + if (strstr(argv[0], "section") != nullptr) { + + if (argc < 3) + return -1; + + // Get section number + int sectionNum = atoi(argv[1]); + + if (sectionNum > 0 && sectionNum <= (int)pres.size()) + return pres[sectionNum - 1].material->setParameter(&argv[2], argc - 2, param); + + else + return -1; + } + + // If the parameter belongs to all sections or lower + if (strstr(argv[0], "allSections") != nullptr) { + + if (argc < 2) + return -1; + + for (GaussPoint& point : pres) { + int ok = point.material->setParameter(&argv[1], argc - 1, param); + if (ok != -1) + result = ok; + } + + return result; + } + + if (strstr(argv[0], "integration") != 0) { + + if (argc < 2) + return -1; + + return stencil->setParameter(&argv[1], argc - 1, param); + } + + // Default, send to everything + + for (GaussPoint& point : pres) { + int ok = point.material->setParameter(argv, argc, param); + if (ok != -1) + result = ok; + } + + // int ok = stencil->setParameter(argv, argc, param); + // if (ok != -1) + // result = ok; + + return result; +} + + +template +int +ShearFrame3d::updateParameter(int parameterID, Information& info) +{ + return -1; +} + + +template +int +ShearFrame3d::activateParameter(int passedParameterID) +{ + parameterID = passedParameterID; + return 0; +} + +} // namespace OpenSees From 3b2172ee3ab24e0f3923803facc33064d8a610fd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:46:01 -0800 Subject: [PATCH 094/161] Create ShearFrame3d.h --- SRC/element/Frame/ShearFrame3d.h | 169 +++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 SRC/element/Frame/ShearFrame3d.h diff --git a/SRC/element/Frame/ShearFrame3d.h b/SRC/element/Frame/ShearFrame3d.h new file mode 100644 index 0000000000..9ee7c35f5b --- /dev/null +++ b/SRC/element/Frame/ShearFrame3d.h @@ -0,0 +1,169 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, Claudio M. Perez +// All rights reserved. No warranty, explicit or implicit, is provided. +// +// This source code is licensed under the BSD 2-Clause License. +// See LICENSE file or https://opensource.org/licenses/BSD-2-Clause +// +//===----------------------------------------------------------------------===// +// +// Claudio M. Perez +// +#pragma once +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace OpenSees { + +template +class ShearFrame3d: + public FiniteElement +{ +public: + enum Logarithm { + None, + LogLeft, + LogRight + }; + + ShearFrame3d(int tag, + std::array& nodes, + FrameSection *section[nen-1], + CrdTransf& transf + ); + + ~ShearFrame3d(); + + const char* + getClassType() const final + { + return "ShearFrame3d"; + } + + int setNodes() override; + const Vector &getResistingForce() final; + const Matrix &getTangentStiff() override; + const Matrix &getMass() override; + const Matrix &getInitialStiff() override; + + int update() final; + int addLoad(ElementalLoad* , double scale) final; + + int revertToStart() override; + int revertToLastCommit() override; + int commitState() final { + + if (this->Element::commitState() != 0) + opserr << "ShearFrame3d::commitState () - failed in base class"; + + past = pres; + + for (GaussPoint& point : pres) { + if (point.material->commitState() != 0) + return -1; + } + return 0; + } + + // Element: Parameters + int setParameter(const char **argv, int argc, Parameter &) final; + int updateParameter(int parameterID, Information &) final; + int activateParameter(int parameterID) final; + // Element: Sensitivity + const Vector& getResistingForceSensitivity(int grad) final; + + Response *setResponse(const char **argv, int argc, OPS_Stream &s) final; + virtual int getResponse(int responseID, Information &) final; + + // MovableObject + int sendSelf(int cTag, Channel&) override; + int recvSelf(int cTag, Channel&, FEM_ObjectBroker&) override; + + // TaggedObject + void Print(OPS_Stream& s, int flag) override; + + private: + // + // Constexpr + // + constexpr static int + nsr = 6+2*nwm, // Number of section resultants + ndm = 3, // Dimension of the problem (3D) + nip = nen-1, // Number of integration points + ndf = 6+nwm; // Degrees of freedom per node + + enum Respond: int { + GlobalForce = 1, + BasicPlasticDeformation = 4, + LocalForce = 2, + BasicForce = 7, + BasicStiff =19, + }; + + // Layout of stress resultants + static constexpr FrameStressLayout scheme = { + FrameStress::N, + FrameStress::Vy, + FrameStress::Vz, + FrameStress::T, + FrameStress::My, + FrameStress::Mz, + FrameStress::Bimoment, + // FrameStress::By, + // FrameStress::Bz, + FrameStress::Bishear, + // FrameStress::Qy, + // FrameStress::Qz + }; + + // + // + // + struct GaussPoint { + double point, + weight; + FrameSection* material; + + double shape[2][nen]; + Matrix3D rotation; + Vector3D curvature; + }; + // Node locations in local (scalar) coordinate + double xn[nen]; + double jxs; + + Matrix3D R0; + + std::set frame_loads; + + std::array pres; + std::array past; + CrdTransf* transform; + Logarithm logarithm; + BeamIntegration* stencil; + + // + // + VectorND p; + MatrixND K; + // Parameters + int parameterID; +}; + +} // namespace OpenSees +#include "ShearFrame3d.tpp" From e440d7e9c7b4212d0eccb2dea1ea2d5549534c8f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:46:25 -0800 Subject: [PATCH 095/161] Update PrismFrame3d.cpp --- SRC/element/Frame/PrismFrame3d.cpp | 47 +++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/SRC/element/Frame/PrismFrame3d.cpp b/SRC/element/Frame/PrismFrame3d.cpp index a27880738c..2b9770d914 100644 --- a/SRC/element/Frame/PrismFrame3d.cpp +++ b/SRC/element/Frame/PrismFrame3d.cpp @@ -20,6 +20,7 @@ // // Written: cmp 2024 // +#include #include #include "PrismFrame3d.h" #include @@ -95,7 +96,7 @@ PrismFrame3d::PrismFrame3d(int tag, ke.zero(); kg.zero(); km.zero(); - +#if 0 // 1) Get Area properties section_tag = section.getTag(); section.getIntegral(Field::Unit, State::Init, A); @@ -141,7 +142,24 @@ PrismFrame3d::PrismFrame3d(int tag, Ay = Kc(1,1)/G; Az = Kc(2,2)/G; } +#else + Frame::Prism prism_props(section); + A = *prism_props.A; + Iy = *prism_props.Iy; + Iz = *prism_props.Iz; + Jx = *prism_props.J; + E = *prism_props.E; + G = *prism_props.G; + if (!shear_flag) { + Ay = Az = 0.0; + } + else { + Ay = *prism_props.Ay; + Az = *prism_props.Az; + } +#endif + Iyz = 0.0; // TODO if (!use_mass) { if (section.getIntegral(Field::Density, State::Init, density) == 0) { @@ -445,20 +463,35 @@ PrismFrame3d::getResistingForce() pl[7] = -pl[1]; // Vjy pl[8] = -pl[2]; // Vjz #endif - pl[3] = -q5; // Ti + pl[3] = -q5; // Ti pl[4] = q3; pl[5] = q1; - pl[6] = q[0]; // Nj - pl[9] = q5; // Tj - pl[10] = q4; - pl[11] = q2; + pl[6] = q[0]; // Nj + pl[9] = q5; // Tj + pl[10] = q4; + pl[11] = q2; + // 2. Element loads VectorND<12> pf{0.0}; + // 2.1 Legacy load classes + double p0[5]{}; + if (eleLoads.size() > 0) + this->computeReactions(p0); + pf[0] = p0[0]; pf[1] = p0[1]; pf[7] = p0[2]; pf[2] = p0[3]; pf[8] = p0[4]; + + // 2.2 Frame load classes + for (auto load : frame_loads) { + load->template addLinearSolution(pf, L, + basic_system->t.getInitialRotation(), + basic_system->t.getRotation()); + } + + // 3. Push to global system #if 0 static VectorND<12> pg; static Vector wrapper(pg); @@ -470,7 +503,7 @@ PrismFrame3d::getResistingForce() static Vector wrapper(pl); basic_system->t.push(pl, Operation::Total); if (pf.norm() > 0.0) [[unlikely]] { - basic_system->linear.push(pf, Operation::Total); + basic_system->linear.push(pf, Operation::Rotation); pl += pf; } #endif From fde3047218c1f38c5c935563a1ab3d7676227fd3 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:50:08 -0800 Subject: [PATCH 096/161] Update FrameLoad.h --- SRC/element/Frame/FrameLoad.h | 107 +++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 21 deletions(-) diff --git a/SRC/element/Frame/FrameLoad.h b/SRC/element/Frame/FrameLoad.h index 35faa53376..5f7a648011 100644 --- a/SRC/element/Frame/FrameLoad.h +++ b/SRC/element/Frame/FrameLoad.h @@ -16,6 +16,7 @@ // Claudio M. Perez // #pragma once +#include "Prism.h" #include #include #include @@ -279,14 +280,16 @@ class FrameLoad: public ElementalLoad { Vector3D rx = r[0]; rx[0] = 0.0; - rx = R*(R0*rx); + // rx = R*(R0*rx); + rx = R0*rx; switch (basis) { case Embedding: nm = R^p[0]; // + rx.cross(m[0]); break; case Reference: - nm = R^(R0^p[0]); - M = (R^m[0]) + rx.cross(nm); + nm = R^(R0*p[0]); + // nm = R^p[0]; + M = (R^m[0]) + (R^(rx.cross(p[0]))); break; case Director: nm = p[0]; @@ -311,6 +314,7 @@ class FrameLoad: public ElementalLoad case FrameStress::Vy: s[i] += M[2]*scale + wy*(x - 0.5*L); break; case FrameStress::Vz: s[i] += -M[1]*scale + wz*(x - 0.5*L); break; + case FrameStress::T : s[i] += M[0]*(L-x)*scale; break; case FrameStress::My: s[i] += -wz*0.5*x*(x - L); break; case FrameStress::Mz: s[i] += wy*0.5*x*(x - L); break; default: @@ -366,13 +370,25 @@ class FrameLoad: public ElementalLoad } } + template void addBasicTangent(MatrixND& Ks, VectorND& s) const { - VectorND<3> nm = s.template extract<3>(0), - M = s.template extract<3>(3); + VectorND<3> nm{}, M{}; + for (int i=0; i& q0, double L, + Frame::Release release, + const Matrix3D& R0, const Matrix3D& R) const + { + switch (shape) { + case Heaviside: { + double scale = pattern.getLoadFactor(); + double wx = p[0][0] * scale; // Axial + double wy = p[0][1] * scale; // Transverse + double wz = p[0][2] * scale; // Transverse + + double P = wx*L; // +/- + double Vy = 0.5*wy*L; + double Vz = 0.5*wz*L; + // Fixed end forces in basic system + double Mz = Vy/6.0*L; // wy*L*L/12 + double My = Vz/6.0*L; // wz*L*L/12 + q0[0] -= 0.5*P; + if (!(release.i & Frame::Release::Mz) && + !(release.j & Frame::Release::Mz)) { + q0[1] -= Mz; + q0[2] += Mz; + } + if (release.i & Frame::Release::Mz) + q0[2] += wy/8*L*L; + + if (release.j & Frame::Release::Mz) + q0[1] -= wy/8*L*L; + + if (!(release.i & Frame::Release::My) && + !(release.j & Frame::Release::My)) { + q0[3] += My; + q0[4] -= My; + } + if (release.i & Frame::Release::My) + q0[4] -= wz/8*L*L; + + if (release.j & Frame::Release::My) + q0[3] += wz/8*L*L; + } } + + return 0; } + private: Vector3D getForce(double x, const Matrix3D& R0, From ba59e4ac5ee999f528b2908977d0286685ea5594 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 02:53:48 -0800 Subject: [PATCH 097/161] Update frames.cpp --- .../commands/modeling/element/frames.cpp | 699 +++++++++++------- 1 file changed, 441 insertions(+), 258 deletions(-) diff --git a/SRC/runtime/commands/modeling/element/frames.cpp b/SRC/runtime/commands/modeling/element/frames.cpp index 54f6a315d0..0b02239a4d 100644 --- a/SRC/runtime/commands/modeling/element/frames.cpp +++ b/SRC/runtime/commands/modeling/element/frames.cpp @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,33 @@ struct Options { int geom_flag; }; +enum class FrameClass { + ForceFrame3d, + ForceDeltaFrame3d, + EulerFrame3d, + EulerDeltaFrame3d, + ExactFrame3d, + CubicFrame3d, + // Legacy + DispBeamColumn2d, + DispBeamColumn3d, + DispBeamColumnNL2d, + DispBeamColumn2dThermal, + DispBeamColumn3dThermal, + DispBeamColumnAsym3d, + ElasticForceBeamColumn2d, + ElasticForceBeamColumn3d, + ElasticForceBeamColumnWarping2d, + ForceBeamColumn2d, + ForceBeamColumn3d, + ForceBeamColumnCBDI2d, + ForceBeamColumnCBDI3d, + ForceBeamColumnWarping2d, + ForceBeamColumn2dThermal, + TimoshenkoBeamColumn2d, + Unknown +}; + extern BeamIntegration* GetBeamIntegration(TCL_Char* type, int); extern BeamIntegrationRule* GetHingeStencil(int argc, TCL_Char ** const argv); @@ -168,7 +196,6 @@ CreateFrame(ModelRegistry& builder, const std::array& shear_center, Options& options) { - std::vector sections; // Finalize sections @@ -204,7 +231,7 @@ CreateFrame(ModelRegistry& builder, // // Create the element // - Element *theElement = nullptr; + Element *theElement = nullptr; int iNode = nodev[0], jNode = nodev[1]; @@ -266,6 +293,8 @@ CreateFrame(ModelRegistry& builder, if (CheckTransformation(*builder.getDomain(), nodev[0], nodev[nodev.size()-1], *theTransf) != TCL_OK) return nullptr; + + // Create 3d frame elements if (strstr(name, "Frame") != nullptr) { if (strstr(name, "Exact") == nullptr) { @@ -287,7 +316,7 @@ CreateFrame(ModelRegistry& builder, mass, options.mass_flag); } - if (strcmp(name, "CubicFrame") == 0) { + else if (strcmp(name, "CubicFrame") == 0) { if (options.shear_flag) theElement = new CubicFrame3d(tag, nodes, sections, @@ -310,6 +339,37 @@ CreateFrame(ModelRegistry& builder, use_mass); } + else if (strcmp(name, "ShearFrame") == 0) { + if (!options.shear_flag) { + opserr << OpenSees::PromptValueError + << "ShearFrame3d requires shear" + << OpenSees::SignalMessageEnd; + return nullptr; + } + + int ndf = builder.getNDF(); + if (sections.size() < nodev.size()-1) + for (unsigned i = 0; i < nodev.size()-1; ++i) + sections.push_back(sections[0]); + + unsigned nen = nodev.size(); + static_loop<2,6>([&](auto nn) constexpr { + if (nn.value == nen) { + std::array nodes; + std::copy_n(nodev.begin(), nn.value, nodes.begin()); + static_loop<0,4>([&](auto nwm) constexpr { + if (nwm.value+6 == ndf) + theElement = new ShearFrame3d(tag, nodes, sections.data(), *theTransf); + }); + } + }); + if (theElement == nullptr) { + opserr << OpenSees::PromptValueError + << "invalid number of dofs for ShearFrame; got " << ndf + << OpenSees::SignalMessageEnd; + return nullptr; + } + } else if ((strstr(name, "Force") != 0) || (strcmp(name, "MixedFrame") == 0)) { if (strcmp(name, "ForceDeltaFrame") == 0 || options.geom_flag) { @@ -347,7 +407,8 @@ CreateFrame(ModelRegistry& builder, int ndf = builder.getNDF(); if (sections.size() > MAX_NIP) { opserr << OpenSees::PromptValueError - << "too many sections for ForceFrame3d: " << static_cast(sections.size()) + << "too many sections for element: " + << static_cast(sections.size()) << OpenSees::SignalMessageEnd; return nullptr; } @@ -425,19 +486,19 @@ CreateFrame(ModelRegistry& builder, beamIntegr, *theTransf, mass, options.mass_flag); - else if (strcmp(name, "dispBeamColumnWithSensitivity") == 0) + else if (strcasecmp(name, "dispBeamColumnWithSensitivity") == 0) theElement = new DispBeamColumn3d( tag, iNode, jNode, nIP, secptrs, beamIntegr, *theTransf, mass); - else if (strcmp(name, "dispBeamColumnThermal") == 0) + else if (strcasecmp(name, "dispBeamColumnThermal") == 0) theElement = new DispBeamColumn3dThermal( tag, iNode, jNode, nIP, secptrs, beamIntegr, *theTransf, mass); - else if (strcmp(name, "forceBeamColumnCBDI") == 0) + else if (strcasecmp(name, "forceBeamColumnCBDI") == 0) theElement = new ForceBeamColumnCBDI3d(tag, iNode, jNode, nIP, secptrs, beamIntegr, *theTransf, mass, false, max_iter, tol); - else if (strcmp(name, "dispBeamColumnAsym") == 0) + else if (strcasecmp(name, "dispBeamColumnAsym") == 0) theElement = new DispBeamColumnAsym3d(tag, iNode, jNode, nIP, secptrs, beamIntegr, *theTransf, shear_center[0], shear_center[1], @@ -453,28 +514,29 @@ CreateFrame(ModelRegistry& builder, // 0 1 2 3 4 // element beam 1 $i $j 0 1 2 // -// a) +// Legacy: +// a) Gauss Inline // 0 1 2 3 4 5 6 // 0 1 // element $type $tag $ndi $ndj $trn "Gauss arg1 arg2 ..." // <-mass $mass> <-iter $iter $tol> // -// b) +// b) Gauss Predefined // 0 1 // element(type, tag, ndi, ndj, trn, itag, // iter=(10, 1e-12), mass=0.0) // -// c) "Original/Obsolete" +// c) "Original/Obsolete": Gauss Tabulated, Prismatic // 0 1 2 // element $type $tag $ndi $ndj $nip $sec $trn // <-mass $mass> <-iter $iter $tol> <-integration $ityp> // -// d) +// d) Gauss Tabulated, Non-Prismatic // 0 1 ... (2 + nIP) // element $type $tag $ndi $ndj $nip -sections ... $trn // <-mass $massDens> <-cMass> <-integration $ityp> // -// e) +// or // 0 // element $type $tag $ndi $ndj $trn // -sections {...} @@ -506,7 +568,6 @@ CreateFrame(ModelRegistry& builder, // // "-transform" $Tag // "-vertical" {} -// "-horizontal" {} // // "-sections" $SectionTags // - if cannot split $SectionTags as list, then @@ -551,23 +612,32 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, int argc, TCL_Char **const argv) { assert(clientData != nullptr); - ModelRegistry *builder = (ModelRegistry*)clientData; + ModelRegistry *builder = static_cast(clientData); Domain *domain = builder->getDomain(); assert(domain != nullptr); int status = TCL_OK; -//enum class GaussMethod { -// None, -// Rule, // Quadrature name + section locations; Hinge methods -// Quad, // Quadrature name -//} gauss_method = GaussMethod::None; + enum class FrameSyntax { + None, + A, // _GaussInline, + B, // _GaussLookup, + C, // _GaussPrismRule, + D, // _GaussHingeRule, + X + } syntax = FrameSyntax::None; + + struct { + bool transform = false; + bool integration = false; + bool sections = false; + } received; // collect positional arguments std::vector positions; - // + // // Preliminary checks // int ndm = builder->getNDM(); @@ -596,6 +666,43 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, // // Required positional arguments // + FrameClass beam_type = FrameClass::Unknown; + if (strcasecmp(argv[1], "dispBeamColumn") == 0) { + if (ndm == 2) + beam_type = FrameClass::DispBeamColumn2d; + else + beam_type = FrameClass::DispBeamColumn3d; + } + else if ((strcasecmp(argv[1], "forceBeamColumn") == 0) || + (strcasecmp(argv[1], "nonlinearBeamColumn") == 0)) { + if (ndm == 2) + beam_type = FrameClass::ForceBeamColumn2d; + else + beam_type = FrameClass::ForceBeamColumn3d; + } + else if (strcasecmp(argv[1], "timoshenkoBeamColumn") == 0) { + if (ndm == 2) + beam_type = FrameClass::TimoshenkoBeamColumn2d; + else { + opserr << OpenSees::PromptValueError + << "timoshenkoBeamColumn not available in 3d\n" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + } + else if (strcasecmp(argv[1], "ForceFrame") == 0) { + if (ndm == 2) + beam_type = FrameClass::ForceBeamColumn2d; + else + beam_type = FrameClass::ForceFrame3d; + } + // else { + // opserr << OpenSees::PromptValueError + // << "unknown beam element type " << argv[1] + // << OpenSees::SignalMessageEnd; + // return TCL_ERROR; + // } + int tag; if (Tcl_GetInt(interp, argv[2], &tag) != TCL_OK) { opserr << OpenSees::PromptValueError @@ -605,7 +712,6 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, } int argi = 5; - // bool multi_node = false; std::vector multi_nodes; { int list_argc; @@ -642,20 +748,9 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, int max_iter = 10; double tol = 1.0e-12; double mass = 0.0; - bool use_mass = false; int transfTag; - std::vector section_tags; - const char* integration_type = nullptr; - BeamIntegration *beamIntegr = nullptr; - BeamIntegrationRule *theRule = nullptr; - int itg_tag; std::array shear_center = {0.0, 0.0}; - // If we get a BeamIntegration from a BeamIntegrationRule - // then we dont own it and can't delete it - bool deleteBeamIntegr = true; - bool removeHingeIntegr = false; - // // Defaults // @@ -663,20 +758,23 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, options.mass_flag = 0; options.shear_flag = -1; options.geom_flag = 0; - if (strcasecmp(argv[1], "elasticBeamColumn") == 0) { - options.shear_flag = 0; - } - if (strcasecmp(argv[1], "dispBeamColumn") == 0 || - strcasecmp(argv[1], "nonlinearBeamColumn") == 0) { - options.shear_flag = 0; - } - else if (strcasecmp(argv[1], "timoshenkoBeamColumn") == 0) { - options.shear_flag = 1; + options.use_mass = 0; + switch (beam_type) { + case FrameClass::DispBeamColumn2d: + case FrameClass::DispBeamColumn3d: + case FrameClass::ForceBeamColumn2d: + case FrameClass::ForceBeamColumn3d: + options.shear_flag = 0; + break; + case FrameClass::TimoshenkoBeamColumn2d: + options.shear_flag = 1; + break; + default: + break; } - // - // Parse positions + // Parse keywords // { while (argi < argc) { @@ -684,28 +782,25 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, if (strcmp(argv[argi], "-shear") == 0) { if (argc < argi + 2) { opserr << OpenSees::PromptValueError << "not enough arguments, expected -shear $flag\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetInt(interp, argv[argi + 1], &options.shear_flag) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid shear_flag, expected integer\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } argi += 2; } // Geometry else if (strcmp(argv[argi], "-order") == 0) { + syntax = FrameSyntax::X; if (argc < argi + 2) { opserr << OpenSees::PromptValueError << "not enough arguments, expected -order $flag\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetInt(interp, argv[argi + 1], &options.geom_flag) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid geom_flag, expected integer\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } argi += 2; } @@ -714,18 +809,15 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, else if (strcmp(argv[argi], "-iter") == 0) { if (argc < argi + 3) { opserr << OpenSees::PromptValueError << "not enough -iter args need -iter max_iter? tol?\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetInt(interp, argv[argi + 1], &max_iter) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid max_iter\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetDouble(interp, argv[argi + 2], &tol) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid tol\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } argi += 3; } @@ -733,16 +825,14 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, else if (strcmp(argv[argi], "-mass") == 0) { if (argc < argi + 2) { opserr << OpenSees::PromptValueError << "not enough arguments, expected -mass $mass\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetDouble(interp, argv[argi + 1], &mass) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid mass\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } argi += 2; - use_mass = true; + options.use_mass = 1; // mass type } else if ((strcmp(argv[argi], "-lMass") == 0) || @@ -756,92 +846,22 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, argi++; } - // Quadrature - else if (strcmp(argv[argi], "-integration") == 0) { - if (argc < argi + 2) { - opserr << OpenSees::PromptValueError << "not enough arguments, expected -integration $integration\n"; - status = TCL_ERROR; - goto clean_up; - } - - argi++; - integration_type = argv[argi]; - // beamIntegr = GetBeamIntegration(argv[argi]); - - // if (beamIntegr == nullptr) { - // opserr << OpenSees::PromptValueError << "invalid integration type\n"; - // status = TCL_ERROR; - // goto clean_up; - // } - argi++; - } - - else if (strcmp(argv[argi], "-gauss_points") == 0) { - if (argc < argi + 2) { - opserr << OpenSees::PromptValueError << "not enough arguments, expected -gauss-points $nIP\n"; - status = TCL_ERROR; - goto clean_up; - } - - int nIP; - if (Tcl_GetInt(interp, argv[argi + 1], &nIP) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid nIP\n"; - status = TCL_ERROR; - goto clean_up; - } - argi += 2; - - if (integration_type == nullptr) { - opserr << OpenSees::PromptValueError << "-gauss-points must be preceded by -integration\n"; - status = TCL_ERROR; - goto clean_up; - } - - beamIntegr = GetBeamIntegration((TCL_Char*)integration_type, nIP); - if (beamIntegr == nullptr) { - opserr << OpenSees::PromptValueError << "invalid integration type or nIP\n"; - status = TCL_ERROR; - goto clean_up; - } - deleteBeamIntegr = true; - } - // Transform else if (strcmp(argv[argi], "-transform") == 0) { + syntax = FrameSyntax::X; if (argc < argi + 2) { - opserr << OpenSees::PromptValueError << "not enough arguments, expected -transform $transform\n"; - status = TCL_ERROR; - goto clean_up; + opserr << OpenSees::PromptValueError + << "not enough arguments, expected -transform $transform\n"; + return TCL_ERROR; } argi++; if (Tcl_GetInt(interp, argv[argi], &transfTag) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid transform\n"; - status = TCL_ERROR; - goto clean_up; - } - argi++; - } - - // Section - else if (strcmp(argv[argi], "-section") == 0) { - if (argc < argi + 2) { - opserr << OpenSees::PromptValueError << "not enough arguments, expected -section $section\n"; - status = TCL_ERROR; - goto clean_up; - } - - argi++; - int sec_tag; - if (Tcl_GetInt(interp, argv[argi], &sec_tag) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid sec_tag\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } - - section_tags.push_back(sec_tag); - argi++; + received.transform = true; } else if (strcmp(argv[argi], "-shearCenter") == 0) { @@ -849,39 +869,63 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, opserr << OpenSees::PromptValueError << "not enough arguments, expected -shearCenter $y $z" << OpenSees::SignalMessageEnd; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetDouble(interp, argv[argi + 1], &shear_center[0]) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid shear_center y\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } if (Tcl_GetDouble(interp, argv[argi + 2], &shear_center[1]) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid shear_center z\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } argi += 3; } - //else if (strcmp(argv[argi], "-sections") == 0) { - // split possible lists present in argv - //char *List = Tcl_Merge(inArgc, inArgv); - //if (List == nullptr) { - // opserr << OpenSees::PromptValueError << "problem merging list\n"; - // return TCL_ERROR; - //} - // int secc; - // TCL_Char ** secv; - // if (Tcl_SplitList(interp, argv[positions[2]], &secc, &secv) != TCL_OK) { - // opserr << OpenSees::PromptValueError << "problem splitting list\n"; - // return TCL_ERROR; - // } - //Tcl_Free((char *)List); - - //} + // Quadrature + else if (strcmp(argv[argi], "-integration") == 0) { + // Either syntax c, d, or e. + if (syntax == FrameSyntax::X) { + opserr << OpenSees::PromptValueError + << "-integration cannot be used with Xara options\n"; + return TCL_ERROR; + } + syntax = FrameSyntax::C; + for (int ii=0; ii 1 && strcmp(argv[positions[1]], "-sections") == 0) { - - int nIP; - if (Tcl_GetInt(interp, argv[positions[0]], &nIP) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid nIP\n"; - status = TCL_ERROR; - goto clean_up; - } - // TODO: Make sure 2+nIP < positions.size() - - // Get section tags - for (int i = 0; i < nIP; i++) { - int secTag; - if (Tcl_GetInt(interp, argv[positions[2+i]], &secTag) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid section\n"; - status = TCL_ERROR; - goto clean_up; - } - section_tags.push_back(secTag); - } - - if (Tcl_GetInt(interp, argv[positions[2+nIP]], &transfTag) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid transform\n"; - status = TCL_ERROR; - goto clean_up; + // If we get a BeamIntegration from a BeamIntegrationRule + // then we dont own it and can't delete it + bool deleteBeamIntegr = true; + BeamIntegration *beamIntegr = nullptr; + std::vector section_tags; + if (syntax == FrameSyntax::None) { + // a or b + if (positions.size() == 2 || positions.size() > 3) { + int itg_tag; + if (Tcl_GetInt(interp, argv[positions[1]], &itg_tag) == TCL_OK) + syntax = FrameSyntax::B; + else + syntax = FrameSyntax::A; } + // c + else if (positions.size() == 3) + syntax = FrameSyntax::C; } - // Version e) ? - else if (positions.size() == 1) { - if (section_tags.empty()) { - status = TCL_ERROR; - goto clean_up; - } - } - // Version a or b - else if (positions.size() == 2 || positions.size() > 3) { + if (syntax == FrameSyntax::A || + syntax == FrameSyntax::B) { // Here we create a BeamIntegrationRule (theRule) which is a pair of // section tags and a BeamIntegration. In this case we do not // delete the BeamIntegration because it is owned by theRule. + deleteBeamIntegr = false; + // Geometric transformation if (Tcl_GetInt(interp, argv[positions[0]], &transfTag) != TCL_OK) { @@ -949,19 +972,25 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, status = TCL_ERROR; goto clean_up; } - + received.transform = true; + + int itg_tag; // Version b) - if (Tcl_GetInt(interp, argv[positions[1]], &itg_tag) == TCL_OK) { - deleteBeamIntegr = false; - removeHingeIntegr = false; + if (syntax == FrameSyntax::B) { + if (Tcl_GetInt(interp, argv[positions[1]], &itg_tag) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid integration tag " << argv[positions[1]] + << OpenSees::SignalMessageEnd; + status = TCL_ERROR; + goto clean_up; + } } - // Version a) else { #if !defined(OPS_API) // If we fail to parse an integer tag for the integration, - // then we assume that the integration is specified as a - // BeamIntegration command + // then we assume that the integration is specified as an + // inline BeamIntegration command builder->findFreeTag(itg_tag); std::string integrCommand{argv[positions[1]]}; if (integrCommand.find(" ") == std::string::npos) { @@ -973,34 +1002,37 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, integrCommand.insert(0, "beamIntegration "); if (Tcl_Eval(interp, integrCommand.c_str()) != TCL_OK) { opserr << OpenSees::PromptValueError << "failed to parse integration\n"; - status = TCL_ERROR; - goto clean_up; + return TCL_ERROR; } - - deleteBeamIntegr = false; - removeHingeIntegr = true; #else return TCL_ERROR; #endif } - theRule = builder->getTypedObject(itg_tag); - if (theRule == nullptr) { - status = TCL_ERROR; - goto clean_up; - } + BeamIntegrationRule* theRule = + builder->getTypedObject(itg_tag); + if (theRule == nullptr) + return TCL_ERROR; - beamIntegr = theRule->getBeamIntegration(); + beamIntegr = theRule->getBeamIntegration()->getCopy(); const ID& secTags = theRule->getSectionTags(); + received.integration = true; for (int i=0; i < secTags.Size(); i++) section_tags.push_back(secTags(i)); + received.sections = true; + + if (syntax == FrameSyntax::A) { + builder->removeObject(itg_tag); + delete theRule; + } } // Version c) // - // .. nip section transf - else if (positions.size() == 3) { + // .. $nip $section $transf + else if (syntax == FrameSyntax::C) { + deleteBeamIntegr = true; int nIP; if (Tcl_GetInt(interp, argv[positions[0]], &nIP) != TCL_OK) { @@ -1009,7 +1041,7 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, goto clean_up; } if (nIP <= 0) { - opserr << OpenSees::PromptValueError << "invalid nIP, must be > 0\n"; + opserr << OpenSees::PromptValueError << "invalid nIP, must be positive.\n"; status = TCL_ERROR; goto clean_up; } @@ -1017,65 +1049,219 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, // int secTag; if (Tcl_GetInt(interp, argv[positions[1]], &secTag) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid secTag\n"; + opserr << OpenSees::PromptValueError + << "invalid secTag\n"; status = TCL_ERROR; goto clean_up; } for (int i=0; i < nIP; i++) section_tags.push_back(secTag); + received.sections = true; + + if ((beamIntegr = GetBeamIntegration("Lobatto", nIP)) == nullptr) { + opserr << OpenSees::PromptValueError + << "invalid integration type or size\n"; + status = TCL_ERROR; + goto clean_up; + } + received.integration = true; // Transform if (Tcl_GetInt(interp, argv[positions[2]], &transfTag) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid transform\n"; + opserr << OpenSees::PromptValueError + << "invalid transform" + << OpenSees::SignalMessageEnd; status = TCL_ERROR; goto clean_up; } + received.transform = true; } + // Version d) + else if (syntax == FrameSyntax::D) { + // positional arguments are: + // 0: nIP + // 1: -sections + // 2: secTag1 + // 3: secTag2... + deleteBeamIntegr = true; + + int nIP; + if (Tcl_GetInt(interp, argv[positions[0]], &nIP) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid nIP\n"; + return TCL_ERROR; + } + if (nIP <= 0) { + opserr << OpenSees::PromptValueError + << "invalid nIP, must be positive." + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + // TODO: Make sure 2+nIP < positions.size() - // - // Finalize the quadrature - // - // TODO - if (section_tags.size() == 1 && theRule == nullptr) { - if (strstr(argv[1], "isp") == 0) { - section_tags.resize(8, section_tags[0]); - } else { - section_tags.resize(8, section_tags[0]); + // Get section tags + for (int i = 0; i < nIP; i++) { + int secTag; + if (Tcl_GetInt(interp, argv[positions[2+i]], &secTag) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid section" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + section_tags.push_back(secTag); + } + if (section_tags.size() != static_cast(nIP)) { + opserr << OpenSees::PromptValueError + << "number of sections does not match nIP" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + received.sections = true; + + if (Tcl_GetInt(interp, argv[positions[2+nIP]], &transfTag) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid transform" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + received.transform = true; + + for (int ii=0; ii" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + beamIntegr = GetBeamIntegration(argv[ii+1], nIP); + if (beamIntegr == nullptr) { + opserr << OpenSees::PromptValueError + << "invalid integration type" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + received.integration = true; + break; + } } } + else if (syntax == FrameSyntax::X) { + deleteBeamIntegr = true; + int n = 5; + int section_tag = -1; + const char* gauss_type = "Legendre"; + + for (int ii=0; ii" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + gauss_type = argv[ii + 1]; + } + else if ((strcmp(argv[ii], "-n") == 0) || + (strcmp(argv[ii], "-gauss_points") == 0)) { + if (argc < ii + 2) { + opserr << OpenSees::PromptValueError + << "not enough arguments, expected -n " + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + if (Tcl_GetInt(interp, argv[ii + 1], &n) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid n: " << argv[ii + 1] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + } + else if (strcmp(argv[ii], "-section") == 0) { + if (argc < ii + 2) { + opserr << OpenSees::PromptValueError + << "not enough arguments, expected -section
" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } - if (beamIntegr == nullptr) { -#if defined(OPS_API) - return TCL_ERROR; -#else - if (integration_type == nullptr) { - if (strstr(argv[1], "ispBeam") == 0) { - integration_type = "Lobatto"; + if (Tcl_GetInt(interp, argv[ii + 1], §ion_tag) != TCL_OK) { + opserr << OpenSees::PromptValueError + << "invalid section tag " << argv[ii + 1] + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + } + } + if (section_tag == -1) { + opserr << OpenSees::PromptValueError + << "missing required argument: -section
" + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + for (int ii=0; ii(*builder, argv[1], tag, multi_nodes, transfTag, - section_tags, *beamIntegr, mass, max_iter, tol, - shear_center, options) + section_tags, *beamIntegr, mass, max_iter, tol, + shear_center, options) : CreateFrame<3, CrdTransf, FrameSection>(*builder, argv[1], tag, multi_nodes, transfTag, - section_tags, *beamIntegr, mass, max_iter, tol, - shear_center, options); + section_tags, *beamIntegr, mass, max_iter, tol, + shear_center, options); if (theElement == nullptr) { @@ -1097,18 +1283,15 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, // // Clean up // + if (deleteBeamIntegr && beamIntegr != nullptr) delete beamIntegr; - if (removeHingeIntegr) { - builder->removeObject(itg_tag); - delete theRule; - } - return status; } + // // BeamWithHinges // From f4d6ab7caab2c46cb23880c74085c4c52f630197 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:00:53 -0800 Subject: [PATCH 098/161] Update EuclidFrameTransf.h --- SRC/coordTransformation/Frame/EuclidFrameTransf.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SRC/coordTransformation/Frame/EuclidFrameTransf.h b/SRC/coordTransformation/Frame/EuclidFrameTransf.h index adf7a73f18..f4d6485dcd 100644 --- a/SRC/coordTransformation/Frame/EuclidFrameTransf.h +++ b/SRC/coordTransformation/Frame/EuclidFrameTransf.h @@ -67,7 +67,7 @@ class EuclidFrameTransf: public FrameTransform const std::array *getRigidOffsets() const final {return offsets;} int initialize(std::array& new_nodes) final; - int update() final; + int update() noexcept final; int commit() final; int revertToLastCommit() final; int revertToStart() final; @@ -77,6 +77,10 @@ class EuclidFrameTransf: public FrameTransform Versor getNodeRotation(int tag) /* final */; Vector3D getNodeRotationLogarithm(int tag) final; + Matrix3D getRotation() const noexcept final { + return basis.getRotation(); + } + int push(VectorND&pl, Operation) final; int push(MatrixND& kl, const VectorND& pl, Operation) final; From 3961ae8e05010fe14d567216e5ff1518e8db5e51 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:00:59 -0800 Subject: [PATCH 099/161] Update EuclidFrameTransf.tpp --- SRC/coordTransformation/Frame/EuclidFrameTransf.tpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp b/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp index 746dbb4cd2..6d69d18f24 100644 --- a/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp @@ -145,7 +145,7 @@ template int EuclidFrameTransf::getLocalAxes(Vector3D &e1, Vector3D &e2, Vector3D &e3) const { - Matrix3D R = basis.getRotation(); + const Matrix3D R = basis.getInitialRotation(); for (int i = 0; i < 3; i++) { e1[i] = R(i,0); e2[i] = R(i,1); @@ -174,7 +174,7 @@ EuclidFrameTransf::getDeformedLength() // template int -EuclidFrameTransf::update() +EuclidFrameTransf::update() noexcept { if (basis.update(nodes) < 0) return -1; @@ -423,7 +423,7 @@ EuclidFrameTransf::push(MatrixND&kb, // 2) Isometry // // 2.2) Projection - // Kl = A ^ k * A + // 2.2.1) Kl = A ^ k * A MatrixND& Kl = kb; const MatrixND A = getProjection(); if (op == Operation::Bubnov) @@ -434,7 +434,7 @@ EuclidFrameTransf::push(MatrixND&kb, const VectorND Ap = A^p; - // Kl += Kw * A + // 2.2.2) Kl += Kw * A Kb.zero(); VectorND<12> qwx{}; for (int i=0; i Date: Fri, 23 Jan 2026 13:01:06 -0800 Subject: [PATCH 100/161] Update FrameTransform.h --- SRC/coordTransformation/Frame/FrameTransform.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/SRC/coordTransformation/Frame/FrameTransform.h b/SRC/coordTransformation/Frame/FrameTransform.h index bce392dbb0..5b748caef9 100644 --- a/SRC/coordTransformation/Frame/FrameTransform.h +++ b/SRC/coordTransformation/Frame/FrameTransform.h @@ -81,7 +81,7 @@ class FrameTransform : public TaggedObject virtual VectorND getNodeLocation(int tag); #endif virtual int initialize(std::array& nodes)=0; - virtual int update() =0; + virtual int update() noexcept =0; virtual int commit() =0; virtual int restart() {return 0;} // TODO virtual int recover() {return 0;} // TODO @@ -95,7 +95,6 @@ class FrameTransform : public TaggedObject virtual int push(VectorND&pl, Operation=0) =0; virtual int push(MatrixND& kl, const VectorND& pl, Operation=0) =0; -#if 1 virtual VectorND pushResponse(VectorND&pl) final { VectorND pg{pl}; push(pg, Operation::Total); @@ -108,10 +107,10 @@ class FrameTransform : public TaggedObject push(kg, pl, Operation::Total); return kg; } -#endif + virtual double getInitialLength() =0; virtual double getDeformedLength() =0; - Matrix3D getRotation() const { + Matrix3D getInitialRotation() const { Vector3D x, y, z; getLocalAxes(x, y, z); @@ -124,6 +123,8 @@ class FrameTransform : public TaggedObject return R; } + virtual Matrix3D getRotation() const noexcept =0; + virtual MatrixND<3,nn*ndf> getRotationTangent() { MatrixND<3,nn*ndf> dR{}; return dR; From ba6dce0de39ed7b73620950a3af5c5815a33f1d4 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:17 -0800 Subject: [PATCH 101/161] Update CrisfieldIsometry.h --- .../Frame/Isometry/CrisfieldIsometry.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h b/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h index 56dea7024c..caabcf2078 100644 --- a/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h @@ -23,6 +23,11 @@ // // References: // +// [1] Perez, C.M., and Filippou F.C. (2024) +// "On Nonlinear Geometric Transformations of Finite Elements" +// Int. J. Numer. Meth. Engrg.; +// Available at: https://doi.org/10.1002/nme.7506 +// // [2] Filippou, F.C. (1998) // "FEDEASLab: Finite Elements for Design Evaluation and Analysis of Structures" // @@ -200,8 +205,6 @@ class CrisfieldIsometry : public AlignedIsometry { return dG; } - // MatrixND<3,6> getRotationGradient(int node) final; - MatrixND<3,6> getRotationGradient(int node) final { constexpr static Vector3D e1{1, 0, 0}; @@ -415,8 +418,8 @@ class CrisfieldIsometry : public AlignedIsometry { // Axial // T(:,7) = [-e1' O' e1' O']'; for (int i = 0; i < 3; i++) { - T(jnx,i ) = -e1[i]; - T(jnx,i+6) = e1[i]; + T(jnx,i ) = -e1[i]; + T(jnx,i+6) = e1[i]; } return T; @@ -433,8 +436,8 @@ class CrisfieldIsometry : public AlignedIsometry { // + ks3 + ks3' + ks4 + ks5; // int addTangent(MatrixND<12,12>& kg, - const VectorND<12>& pl, - const VectorND<12>& ul) + const VectorND<12>& pl, + const VectorND<12>& ul) { const Vector3D &e1 = e[0], From a88519878aa0eb80ebd943b420db5e7d6e06373f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:20 -0800 Subject: [PATCH 102/161] Update EuclidIsometry.h --- SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h b/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h index d405bcd8d1..a906777612 100644 --- a/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h @@ -21,6 +21,10 @@ // // Written: Claudio M. Perez // +// [1] Perez, C.M., and Filippou F.C. "On Nonlinear Geometric Transformations +// of Finite Elements" Int. J. Numer. Meth. Engrg. 2024; +// https://doi.org/10.1002/nme.7506 +// #pragma once #include #include From a3e36afc32a13750f11e78b01623097adb2f6e30 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:30 -0800 Subject: [PATCH 103/161] Update LinearIsometry.h --- .../Frame/Isometry/LinearIsometry.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h b/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h index a2646f4c32..af4703152b 100644 --- a/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h @@ -22,14 +22,13 @@ // // References: // +// [1] Perez, C.M., and Filippou F.C. "On Nonlinear Geometric Transformations +// of Finite Elements" Int. J. Numer. Meth. Engrg. 2024; +// https://doi.org/10.1002/nme.7506 +// // [2] Filippou, F.C. (1998) // "FEDEASLab: Finite Elements for Design Evaluation and Analysis of Structures" // -// [3] Nour-Omid, B. and Rankin, C.C. (1991) "Finite rotation analysis and -// consistent linearization using projectors", -// Computer Methods in Applied Mechanics and Engineering, 93(3), pp. 353–384. -// Available at: https://doi.org/10.1016/0045-7825(91)90248-5. -// #pragma once #include #include @@ -37,7 +36,6 @@ #include "EuclidIsometry.h" class Node; -#define TRIAD C2 namespace OpenSees { From 0ca4f4c18a5c03eeb40521600d98832c8d041667 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:37 -0800 Subject: [PATCH 104/161] Update RankinIsometry.h --- .../Frame/Isometry/RankinIsometry.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h b/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h index 59981fa27c..f2e89acf3a 100644 --- a/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h @@ -22,6 +22,10 @@ // // References: // +// [1] Perez, C.M., and Filippou F.C. "On Nonlinear Geometric Transformations +// of Finite Elements" Int. J. Numer. Meth. Engrg. 2024; +// https://doi.org/10.1002/nme.7506 +// // [2] Filippou, F.C. (1998) // "FEDEASLab: Finite Elements for Design Evaluation and Analysis of Structures" // @@ -58,8 +62,7 @@ class RankinIsometry : public AlignedIsometry { Matrix3D R; { - Vector3D e1 = dx; - e1 /= e1.norm(); + const Vector3D e1 = dx/dx.norm(); constexpr static Vector3D D2 {0,1,0}; const Vector3D E2 = this->AlignedIsometry::R[init]*D2; @@ -67,7 +70,7 @@ class RankinIsometry : public AlignedIsometry Vector3D e3 = e1.cross(q); e3 /= e3.norm(); - Vector3D e2 = e3.cross(e1); + const Vector3D e2 = e3.cross(e1); for (int i = 0; i < 3; i++) { R(i,0) = e1[i]; @@ -75,7 +78,7 @@ class RankinIsometry : public AlignedIsometry R(i,2) = e3[i]; } - Vector3D Q = R^q; + const Vector3D Q = R^q; n = Q[0]/Q[1]; } return R; From da88181864215fad5458f9358fad20b46763c00f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:42 -0800 Subject: [PATCH 105/161] Update SphericalIsometry.h --- SRC/coordTransformation/Frame/Isometry/SphericalIsometry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/coordTransformation/Frame/Isometry/SphericalIsometry.h b/SRC/coordTransformation/Frame/Isometry/SphericalIsometry.h index 1a10102e83..cc96dd42e8 100644 --- a/SRC/coordTransformation/Frame/Isometry/SphericalIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/SphericalIsometry.h @@ -93,8 +93,8 @@ SphericalIsometry::update() { Ln = e1.norm(); if (Ln == 0.0) [[unlikely]] { - opserr << "\nSouzaFrameTransf: deformed length is 0.0\n"; - return -2; + opserr << "\nSouzaFrameTransf: deformed length is 0.0\n"; + return -2; } e1 /= Ln; From f40ad692c2aaa66376b8b03e9f96216b1ac4170c Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:45 -0800 Subject: [PATCH 106/161] Update LinearFrameTransf.tpp --- SRC/coordTransformation/Frame/LinearFrameTransf.tpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SRC/coordTransformation/Frame/LinearFrameTransf.tpp b/SRC/coordTransformation/Frame/LinearFrameTransf.tpp index e227fba8d8..89d84c2db8 100644 --- a/SRC/coordTransformation/Frame/LinearFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/LinearFrameTransf.tpp @@ -260,7 +260,7 @@ LinearFrameTransf::getDeformedLength() template int -LinearFrameTransf::update() +LinearFrameTransf::update() noexcept { constexpr Vector3D iv{1, 0, 0}; From edb631699facf574faf53335c51b56958670d7e6 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:50 -0800 Subject: [PATCH 107/161] Update LinearFrameTransf.h --- SRC/coordTransformation/Frame/LinearFrameTransf.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/SRC/coordTransformation/Frame/LinearFrameTransf.h b/SRC/coordTransformation/Frame/LinearFrameTransf.h index 136c137bcf..372e8cca03 100644 --- a/SRC/coordTransformation/Frame/LinearFrameTransf.h +++ b/SRC/coordTransformation/Frame/LinearFrameTransf.h @@ -53,7 +53,7 @@ class LinearFrameTransf: public FrameTransform int getLocalAxes(Vector3D &x, Vector3D &y, Vector3D &z) const override; int initialize(std::array& ) final; - int update() final; + int update() noexcept final; int commit() final; int revertToLastCommit() final; int revertToStart() final; @@ -62,14 +62,15 @@ class LinearFrameTransf: public FrameTransform Vector3D getNodeRotationLogarithm(int tag) final; VectorND getStateVariation() final; + Matrix3D getRotation() const noexcept final { + return this->getInitialRotation(); + } + using Operation = typename FrameTransform::Operation; int push(VectorND&pl, Operation) final; int push(MatrixND& kl, const VectorND& pl, Operation) final; - // // method used to rotate consistent mass matrix - // const Matrix &getGlobalMatrixFromLocal(const Matrix &local); - // Sensitivity // From 086f2e31d103b01c8e5c315a055d05a267997c77 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:54 -0800 Subject: [PATCH 108/161] Update PDeltaFrameTransf3d.h --- SRC/coordTransformation/Frame/PDeltaFrameTransf3d.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.h b/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.h index 522f04b127..bba83cdde3 100644 --- a/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.h +++ b/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.h @@ -51,7 +51,7 @@ class PDeltaFrameTransf: public FrameTransform double getDeformedLength() final; int initialize(std::array&) final; - int update() final; + int update() noexcept final; int commit() final; int revertToLastCommit() final; int revertToStart() final; @@ -61,6 +61,10 @@ class PDeltaFrameTransf: public FrameTransform Vector3D getNodeRotationLogarithm(int tag) final; const std::array *getRigidOffsets() const final { return linear.getRigidOffsets();} + Matrix3D getRotation() const noexcept final { + return this->getInitialRotation(); + } + using Operation = typename FrameTransform::Operation; int push(VectorND&pl, Operation) final; int push(MatrixND& kl, const VectorND& pl, Operation) final; From fb87904c328932dedafe60979ddc91b78e20b389 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:01:57 -0800 Subject: [PATCH 109/161] Update PDeltaFrameTransf3d.tpp --- SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp b/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp index 0b3d9ec9c5..75c6f372d0 100644 --- a/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp +++ b/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp @@ -73,7 +73,7 @@ PDeltaFrameTransf::initialize(std::array& new_nodes) template int -PDeltaFrameTransf::update() +PDeltaFrameTransf::update() noexcept { return linear.update(); } From b4c9bad5eaffbe64737358d7de8613cefcdf50f8 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:02:03 -0800 Subject: [PATCH 110/161] Update SouzaFrameTransf.h --- SRC/coordTransformation/Frame/SouzaFrameTransf.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/SRC/coordTransformation/Frame/SouzaFrameTransf.h b/SRC/coordTransformation/Frame/SouzaFrameTransf.h index cad97523b5..755b196ab2 100644 --- a/SRC/coordTransformation/Frame/SouzaFrameTransf.h +++ b/SRC/coordTransformation/Frame/SouzaFrameTransf.h @@ -28,6 +28,10 @@ // // Adapted from work by: Remo Magalhaes de Souza (rmsouza@ce.berkeley.edu) // +// [1] Perez, C.M., and Filippou F.C.. "On Nonlinear Geometric Transformations +// of Finite Elements" Int. J. Numer. Meth. Engrg. 2024; +// https://doi.org/10.1002/nme.7506 +// // [2] Crisfield, M.A. (1990) "A consistent co-rotational formulation for // non-linear, three-dimensional, beam-elements", Computer Methods in Applied // Mechanics and Engineering, 81(2), pp. 131–150. Available at: @@ -67,7 +71,7 @@ class SouzaFrameTransf: public FrameTransform FrameTransform *getCopy() const final; int initialize(std::array& new_nodes) final; - int update() final; + int update() noexcept final; int commit() final; int revertToLastCommit() final; int revertToStart() final; @@ -81,10 +85,15 @@ class SouzaFrameTransf: public FrameTransform Vector3D getNodePosition(int tag) final; Vector3D getNodeRotationLogarithm(int tag) final; + Matrix3D getRotation() const noexcept final { + return crs.getRotation(); + } + using Operation = typename FrameTransform::Operation; int push(VectorND&pl, Operation) final; int push(MatrixND& kl, const VectorND& pl, Operation) final; + // Sensitivity double getLengthGrad() final; const Vector &getBasicDisplTotalGrad(int grad); // final; From 182a72e4cda1d09dc7122b4cee13d90aaee5d7fb Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:02:06 -0800 Subject: [PATCH 111/161] Update SouzaFrameTransf.tpp --- SRC/coordTransformation/Frame/SouzaFrameTransf.tpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp b/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp index 8a5d9a4f42..9bdb906dec 100644 --- a/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp @@ -27,6 +27,10 @@ // // Adapted from: Remo Magalhaes de Souza (rmsouza@ce.berkeley.edu) // +// [1] Perez, C.M., and Filippou F.C.. "On Nonlinear Geometric Transformations +// of Finite Elements" Int. J. Numer. Meth. Engrg. 2024; +// https://doi.org/10.1002/nme.7506 +// // [2] Crisfield, M.A. (1990) "A consistent co-rotational formulation for // non-linear, three-dimensional, beam-elements", Computer Methods in Applied // Mechanics and Engineering, 81(2), pp. 131–150. Available at: @@ -277,7 +281,7 @@ SouzaFrameTransf::getNodeRotationLogarithm(int tag) // template int -SouzaFrameTransf::update() +SouzaFrameTransf::update() noexcept { // determine global displacement increments from last iteration From 83d515d84ffee4c12806b18f7b419d7f963f2d7b Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:10:11 -0800 Subject: [PATCH 112/161] warning fixes --- SRC/handler/DataFileStreamAdd.cpp | 14 +++++++------- SRC/recorder/NodeRecorderRMS.cpp | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/SRC/handler/DataFileStreamAdd.cpp b/SRC/handler/DataFileStreamAdd.cpp index e77cc80941..c9b313f0de 100644 --- a/SRC/handler/DataFileStreamAdd.cpp +++ b/SRC/handler/DataFileStreamAdd.cpp @@ -333,14 +333,14 @@ DataFileStreamAdd::write(Vector &data) for (int j=0; jgetNode(nodeTag); if (theNode != 0) { - xmlOrder(nodeCount++) = i+1; - for (int j=0; j Date: Fri, 23 Jan 2026 13:10:48 -0800 Subject: [PATCH 113/161] Update HHTHSIncrReduct.cpp --- .../integrator/Hybrid/HHTHSIncrReduct.cpp | 45 ------------------- 1 file changed, 45 deletions(-) diff --git a/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp b/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp index 024a872b1a..70eab8bb31 100755 --- a/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp +++ b/SRC/analysis/integrator/Hybrid/HHTHSIncrReduct.cpp @@ -245,7 +245,6 @@ int HHTHSIncrReduct::formNodTangent(DOF_Group *theDof) int HHTHSIncrReduct::domainChanged() { - AnalysisModel *theModel = this->getAnalysisModel(); LinearSOE *theLinSOE = this->getLinearSOE(); const Vector &x = theLinSOE->getX(); int size = x.Size(); @@ -286,50 +285,6 @@ int HHTHSIncrReduct::domainChanged() Ualphadot = new Vector(size); Ualphadotdot = new Vector(size); scaledDeltaU = new Vector(size); - - // check we obtained the new - if (Ut == 0 || Ut->Size() != size || - Utdot == 0 || Utdot->Size() != size || - Utdotdot == 0 || Utdotdot->Size() != size || - U == 0 || U->Size() != size || - Udot == 0 || Udot->Size() != size || - Udotdot == 0 || Udotdot->Size() != size || - Ualpha == 0 || Ualpha->Size() != size || - Ualphadot == 0 || Ualphadot->Size() != size || - Ualphadotdot == 0 || Ualphadotdot->Size() != size || - scaledDeltaU == 0 || scaledDeltaU->Size() != size) { - - opserr << "HHTHSIncrReduct::domainChanged() - ran out of memory\n"; - - // delete the old - if (Ut != 0) - delete Ut; - if (Utdot != 0) - delete Utdot; - if (Utdotdot != 0) - delete Utdotdot; - if (U != 0) - delete U; - if (Udot != 0) - delete Udot; - if (Udotdot != 0) - delete Udotdot; - if (Ualpha != 0) - delete Ualpha; - if (Ualphadot != 0) - delete Ualphadot; - if (Ualphadotdot != 0) - delete Ualphadotdot; - if (scaledDeltaU != 0) - delete scaledDeltaU; - - Ut = 0; Utdot = 0; Utdotdot = 0; - U = 0; Udot = 0; Udotdot = 0; - Ualpha = 0; Ualphadot = 0; Ualphadotdot = 0; - scaledDeltaU = 0; - - return -1; - } } this->getAnalysisModel()->getState(*U, *Udot, *Udotdot, 0); From ac6dba9bda693d781a200120ef392e995d3f7b23 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 13:13:41 -0800 Subject: [PATCH 114/161] Update ZeroLength.cpp --- SRC/element/Point/ZeroLength.cpp | 175 ++++++++++++++++--------------- 1 file changed, 91 insertions(+), 84 deletions(-) diff --git a/SRC/element/Point/ZeroLength.cpp b/SRC/element/Point/ZeroLength.cpp index 11fbf7ac2e..7227806356 100644 --- a/SRC/element/Point/ZeroLength.cpp +++ b/SRC/element/Point/ZeroLength.cpp @@ -1007,95 +1007,102 @@ ZeroLength::Print(OPS_Stream &s, int flag) Response* ZeroLength::setResponse(const char **argv, int argc, OPS_Stream &output) { - Response *theResponse = nullptr; - - output.tag("ElementOutput"); - output.attr("eleType","ZeroLength"); - output.attr("eleTag",this->getTag()); - output.attr("node1",connectedExternalNodes[0]); - output.attr("node2",connectedExternalNodes[1]); - - char outputData[10]; - - if ((strcmp(argv[0],"force") == 0) || (strcmp(argv[0],"forces") == 0) - || (strcmp(argv[0],"globalForces") == 0) || (strcmp(argv[0],"globalforces") == 0)) { - - char outputData[20]; - int numDOFperNode = numDOF/2; - for (int i=0; igetTag()); + output.attr("node1",connectedExternalNodes[0]); + output.attr("node2",connectedExternalNodes[1]); + + char outputData[256]; + + if ((strcmp(argv[0],"force") == 0) || + (strcmp(argv[0],"forces") == 0) || + (strcmp(argv[0],"globalForces") == 0) || + (strcmp(argv[0],"globalforces") == 0)) { + + char outputData[256]; + int numDOFperNode = numDOF/2; + for (int i=0; i 2) { - int matNum = atoi(argv[1]); - int numMat = numMaterials1d; - if (useRayleighDamping == 2) - numMat *= 2; - if (matNum >= 1 && matNum <= numMat) - theResponse = theMaterial1d[matNum-1]->setResponse(&argv[2], argc-2, output); - } + } + else if ((strcmp(argv[0],"defoANDforce") == 0) || + (strcmp(argv[0],"deformationANDforces") == 0) || + (strcmp(argv[0],"deformationsANDforces") == 0)) { + + int i; + for (i=0; i 2) { + int matNum = atoi(argv[1]); + int numMat = numMaterials1d; + if (useRayleighDamping == 2) + numMat *= 2; + if (matNum >= 1 && matNum <= numMat) + theResponse = theMaterial1d[matNum-1]->setResponse(&argv[2], argc-2, output); } + } + + if ((strcmp(argv[0],"dampingForces") == 0) || (strcmp(argv[0],"rayleighForces") == 0)) { + theResponse = new ElementResponse(this, 15, Vector(numDOF)); + } - output.endTag(); + output.endTag(); - return theResponse; + return theResponse; } int @@ -1118,15 +1125,15 @@ ZeroLength::getResponse(int responseID, Information &eleInformation) if (alphaM != 0.0 || betaK != 0.0 || betaK0 != 0.0 || betaKc != 0.0) *theVector += this->getRayleighDampingForces(); } else if (useRayleighDamping == 2) { - for (int mat=0; matgetStress(); - - // compute residual due to resisting force - for (int i=0; igetStress(); + + // compute residual due to resisting force + for (int i=0; i Date: Fri, 23 Jan 2026 14:44:46 -0800 Subject: [PATCH 115/161] Refactor Node coordinate and inertia handling Replaces dynamic coordinate Vector allocation with a fixed-size array and stack-allocated Vector (xyz), updating all constructors and methods to use the new approach. Adds position and rotation inertia members with methods to update them, and updates getMass to use these values. Removes unused display and rotation methods, modernizes pointer checks, and makes several methods noexcept for safety and clarity. --- SRC/domain/node/Node.cpp | 265 +++++++++++++----------- SRC/domain/node/Node.h | 58 +++--- SRC/runtime/commands/modeling/nodes.cpp | 126 ++++++++--- 3 files changed, 265 insertions(+), 184 deletions(-) diff --git a/SRC/domain/node/Node.cpp b/SRC/domain/node/Node.cpp index 04ffc292b7..40a446f702 100644 --- a/SRC/domain/node/Node.cpp +++ b/SRC/domain/node/Node.cpp @@ -60,14 +60,17 @@ int Node::numMatrices = 0; Node::Node(int theClassTag) :TaggedObject(0),MovableObject(theClassTag), numberDOF(0), theDOF_GroupPtr(0), - Crd(0), commitDisp(0), commitVel(0), commitAccel(0), + coord_data{0,0,0}, xyz(coord_data, 0), + position_inertia{0.0}, rotation_inertia{0.0,0.0,0.0}, + commitDisp(0), commitVel(0), commitAccel(0), trialDisp(0), trialVel(0), trialAccel(0), unbalLoad(0), incrDisp(0), incrDeltaDisp(0), disp(0), vel(0), accel(0), dbTag1(0), rotation(nullptr), dbTag2(0), dbTag3(0), dbTag4(0), R(0), mass(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), - index(-1), reaction(0) + index(-1), + reaction(nullptr) { // for FEM_ObjectBroker, recvSelf() must be invoked on object @@ -85,14 +88,16 @@ Node::Node(int theClassTag) Node::Node(int tag, int theClassTag) :TaggedObject(tag), MovableObject(theClassTag), numberDOF(0), theDOF_GroupPtr(0), - Crd(0), commitDisp(0), commitVel(0), commitAccel(0), + coord_data{0,0,0}, xyz(coord_data, 0), + position_inertia{0.0}, rotation_inertia{0.0,0.0,0.0}, + commitDisp(0), commitVel(0), commitAccel(0), trialDisp(0), trialVel(0), trialAccel(0), unbalLoad(0), incrDisp(0), incrDeltaDisp(0), disp(0), vel(0), accel(0), rotation(nullptr), dbTag1(0), dbTag2(0), dbTag3(0), dbTag4(0), R(0), mass(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), - index(-1), reaction(0)//, displayLocation(0) + index(-1), reaction(nullptr) { // for subclasses - they must implement all the methods with // their own data structures. @@ -105,17 +110,21 @@ Node::Node(int tag, int theClassTag) theNodalThermalActionPtr = 0; } -Node::Node(int tag, int ndof, double Crd1, Vector *dLoc) +Node::Node(int tag, int ndof, double Crd1) :TaggedObject(tag),MovableObject(NOD_TAG_Node), numberDOF(ndof), theDOF_GroupPtr(0), - Crd(0), commitDisp(0), commitVel(0), commitAccel(0), + coord_data{Crd1, 0,0}, xyz(coord_data, 1), + position_inertia{0.0}, rotation_inertia{0.0,0.0,0.0}, + // State + commitDisp(0), commitVel(0), commitAccel(0), trialDisp(0), trialVel(0), trialAccel(0), unbalLoad(0), incrDisp(0), incrDeltaDisp(0), disp(0), vel(0), accel(0), rotation(nullptr), dbTag1(0), dbTag2(0), dbTag3(0), dbTag4(0), R(0), mass(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), - index(-1), reaction(0) + index(-1), + reaction(nullptr) { this->createDisp(); dispSensitivity = 0; @@ -125,23 +134,27 @@ Node::Node(int tag, int ndof, double Crd1, Vector *dLoc) theNodalThermalActionPtr = 0; - Crd = new Vector(1); - (*Crd)(0) = Crd1; + // Crd = new Vector(1); + // xyz(0) = Crd1; } // Node(int tag, int ndof, double Crd1, double yCrd); // constructor for 2d nodes -Node::Node(int tag, int ndof, double Crd1, double Crd2, Vector *dLoc) +Node::Node(int tag, int ndof, double Crd1, double Crd2) :TaggedObject(tag), MovableObject(NOD_TAG_Node), numberDOF(ndof), theDOF_GroupPtr(0), - Crd(0), commitDisp(0), commitVel(0), commitAccel(0), + coord_data{Crd1, Crd2, 0}, xyz(coord_data, 2), + position_inertia{0.0}, rotation_inertia{0.0,0.0,0.0}, + // State + commitDisp(0), commitVel(0), commitAccel(0), trialDisp(0), trialVel(0), trialAccel(0), unbalLoad(0), incrDisp(0), incrDeltaDisp(0), disp(0), vel(0), accel(0), rotation(nullptr), dbTag1(0), dbTag2(0), dbTag3(0), dbTag4(0), R(0), mass(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), + index(-1), reaction(0) { this->createDisp(); @@ -152,27 +165,27 @@ Node::Node(int tag, int ndof, double Crd1, double Crd2, Vector *dLoc) theNodalThermalActionPtr = 0; - Crd = new Vector(2); - (*Crd)(0) = Crd1; - (*Crd)(1) = Crd2; - - index = -1; } // Node(int tag, int ndof, double Crd1, double Crd2, double zCrd); // constructor for 3d nodes - Node::Node(int tag, int ndof, double Crd1, double Crd2, double Crd3, Vector *dLoc) + Node::Node(int tag, int ndof, double Crd1, double Crd2, double Crd3) :TaggedObject(tag), MovableObject(NOD_TAG_Node), numberDOF(ndof), theDOF_GroupPtr(0), - Crd(0), commitDisp(0), commitVel(0), commitAccel(0), + coord_data{Crd1, Crd2, Crd3}, xyz(coord_data, 3), + position_inertia{0.0}, rotation_inertia{0.0,0.0,0.0}, mass(0), + // State + commitDisp(0), commitVel(0), commitAccel(0), trialDisp(0), trialVel(0), trialAccel(0), unbalLoad(0), incrDisp(0), incrDeltaDisp(0), disp(0), vel(0), accel(0), rotation(nullptr), dbTag1(0), dbTag2(0), dbTag3(0), dbTag4(0), - R(0), mass(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), + R(0), + unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), + index(-1), reaction(0) { this->createDisp(); @@ -183,12 +196,6 @@ Node::Node(int tag, int ndof, double Crd1, double Crd2, Vector *dLoc) theNodalThermalActionPtr = 0;//Added by Liming for initializing NodalLoadPointer, [SIF] - Crd = new Vector(3); - (*Crd)(0) = Crd1; - (*Crd)(1) = Crd2; - (*Crd)(2) = Crd3; - - index = -1; } @@ -198,13 +205,15 @@ Node::Node(int tag, int ndof, double Crd1, double Crd2, Vector *dLoc) Node::Node(const Node &otherNode, bool copyMass) :TaggedObject(otherNode.getTag()),MovableObject(otherNode.getClassTag()), numberDOF(otherNode.numberDOF), theDOF_GroupPtr(0), - Crd(0), commitDisp(0), commitVel(0), commitAccel(0), + coord_data{}, xyz(coord_data, otherNode.getCrds().Size()), + position_inertia{}, rotation_inertia{0.0,0.0,0.0}, + commitDisp(0), commitVel(0), commitAccel(0), trialDisp(0), trialVel(0), trialAccel(0), unbalLoad(0), incrDisp(0), incrDeltaDisp(0), disp(0), vel(0), accel(0), rotation(nullptr), dbTag1(0), dbTag2(0), dbTag3(0), dbTag4(0), - R(0), mass(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), + R(0), unbalLoadWithInertia(0), alphaM(0.0), theEigenvectors(0), reaction(0) { this->createDisp(); @@ -215,7 +224,8 @@ Node::Node(const Node &otherNode, bool copyMass) theNodalThermalActionPtr = 0;//Added by Liming for initializing NodalLoadPointer, [SIF] - Crd = new Vector(otherNode.getCrds()); + for (int i=0; icreateDisp(); @@ -243,8 +253,7 @@ Node::Node(const Node &otherNode, bool copyMass) } if (otherNode.mass != 0 && copyMass == true) { - mass = new Matrix(*(otherNode.mass)) ; - // TODO; zero? + mass = new Matrix(*(otherNode.mass)); } if (otherNode.R != 0) { @@ -257,8 +266,6 @@ Node::Node(const Node &otherNode, bool copyMass) Node::~Node() { - if (Crd != nullptr) - delete Crd; if (commitDisp != nullptr) delete commitDisp; @@ -354,14 +361,13 @@ const Vector & Node::getCrds() const { // return the vector of nodal coordinates - return *Crd; + return xyz; } - const Vector & -Node::getDisp() +Node::getDisp() noexcept { // construct memory and Vectors for trial and committed // displacement on first call to this method, getTrialDisp() @@ -407,34 +413,22 @@ Node::getAccel() ** ** *********************************************************************/ -const Vector & -Node::getTrialDisp() -{ -#if 0 - if (trialDisp == nullptr) - this->createDisp(); -#endif - return *trialDisp; -} +// const Vector & +// Node::getTrialDisp() noexcept +// { +// return *trialDisp; +// } const Vector & -Node::getIncrDisp() +Node::getIncrDisp() noexcept { -#if 0 - if (incrDisp == nullptr) - this->createDisp(); -#endif return *incrDisp; } const Vector & -Node::getIncrDeltaDisp() +Node::getIncrDeltaDisp() noexcept { -#if 0 - if (incrDeltaDisp == 0) - this->createDisp(); -#endif - return *incrDeltaDisp; + return *incrDeltaDisp; } Versor @@ -472,7 +466,7 @@ Node::getTrialAccel() int -Node::setTrialDisp(double value, int dof) +Node::setTrialDisp(double value, int dof) noexcept { // check vector arg is of correct size assert(dof >= 0 && dof < numberDOF); @@ -490,7 +484,7 @@ Node::setTrialDisp(double value, int dof) } int -Node::setTrialDisp(const Vector &newTrialDisp) +Node::setTrialDisp(const Vector &newTrialDisp) noexcept { // check vector arg is of correct size assert(newTrialDisp.Size() == numberDOF); @@ -643,7 +637,7 @@ Node::incrTrialAccel(const Vector &incrAccel) void -Node::zeroUnbalancedLoad() +Node::zeroUnbalancedLoad() noexcept { if (unbalLoad != nullptr) unbalLoad->Zero(); @@ -736,7 +730,7 @@ Node::addInertiaLoadSensitivityToUnbalance(const Vector &accelG, double fact, bo const Vector & -Node::getUnbalancedLoad() +Node::getUnbalancedLoad() noexcept { // make sure it was created before we return it if (unbalLoad == nullptr) @@ -773,7 +767,7 @@ Node::getUnbalancedLoadIncInertia() } int -Node::commitState() +Node::commitState() noexcept { // check disp exists, if does set commit = trial, incr = 0.0 if (trialDisp != 0) { @@ -880,14 +874,21 @@ Node::revertToStart() const Matrix & Node::getMass() { - if (index == -1) { + if (index == -1) [[unlikely]] { setGlobalMatrices(); } // make sure it was created before we return it if (mass == 0) { - theMatrices[index]->Zero(); - return *theMatrices[index]; + Matrix& Mass = *theMatrices[index]; + Mass.Zero(); + const int ndm = xyz.Size(); + for (int i=0; i= 3) { + opserr << "Node::addRotationInertia - dof " + << dof << " invalid for node " << this->getTag() << "\n"; + return -1; + } + rotation_inertia[dof-1] += value; + return 0; +} + + int Node::setNumColR(int numCol) @@ -1091,7 +1120,7 @@ const Matrix & Node::getEigenvectors() { // check the eigen vectors have been set - if (theEigenvectors == 0) { + if (theEigenvectors == nullptr) { opserr << "Node::getEigenvectors() - eigenvectors have not been set\n"; // TODO: Handle this! exit(-1); @@ -1123,7 +1152,7 @@ Node::sendSelf(int cTag, Channel &theChannel) data(13) = R->noCols(); } - data(7) = Crd->Size(); + data(7) = xyz.Size(); if (dbTag1 == 0) dbTag1 = theChannel.getDbTag(); @@ -1147,7 +1176,7 @@ Node::sendSelf(int cTag, Channel &theChannel) return res; } - res = theChannel.sendVector(dataTag, cTag, *Crd); + res = theChannel.sendVector(dataTag, cTag, xyz); if (res < 0) { opserr << " Node::sendSelf() - failed to send Vecor data\n"; return res; @@ -1230,10 +1259,9 @@ Node::recvSelf(int cTag, Channel &theChannel, dbTag4 = data(11); // create a Vector to hold coordinates IF one needed - if (Crd == nullptr) - Crd = new Vector(numberCrd); + xyz.setData(coord_data, numberCrd); - if (theChannel.recvVector(dataTag, cTag, *Crd) < 0) { + if (theChannel.recvVector(dataTag, cTag, xyz) < 0) { opserr << "Node::recvSelf() - failed to receive the Coordinate vector\n"; return -2; } @@ -1406,7 +1434,7 @@ Node::Print(OPS_Stream &s, int flag) { if (flag == OPS_PRINT_CURRENTSTATE) { // print out everything s << "\n Node: " << this->getTag() << "\n"; - s << "\tCoordinates : " << *Crd; + s << "\tCoordinates : " << xyz; if (commitDisp != 0) s << "\tDisps: " << *trialDisp; if (commitVel != 0) @@ -1438,10 +1466,10 @@ Node::Print(OPS_Stream &s, int flag) s << "\"name\": " << this->getTag() << ", "; s << "\"ndf\": " << numberDOF << ", "; s << "\"crd\": ["; - int numCrd = Crd->Size(); + int numCrd = xyz.Size(); for (int i = 0; i < numCrd - 1; i++) - s << (*Crd)(i) << ", "; - s << (*Crd)(numCrd - 1) << "]"; + s << xyz(i) << ", "; + s << xyz(numCrd - 1) << "]"; if (mass != 0) { s << ", \"mass\": ["; for (int i = 0; i < numberDOF - 1; i++) @@ -1459,7 +1487,7 @@ Matrix Node::getMassSensitivity() { if (index == -1) - setGlobalMatrices(); + setGlobalMatrices(); if (mass == 0) { theMatrices[index]->Zero(); @@ -1543,11 +1571,13 @@ Node::setParameter(const char **argv, int argc, Parameter ¶m) } else if (strstr(argv[0],"coord") != 0) { int direction = atoi(argv[1]); - if (direction >= 1 && direction <= 3) { - if (Crd != 0) - param.setValue((*Crd)(direction-1)); + if (direction >= 1 && direction <= xyz.Size()) { + param.setValue(xyz(direction-1)); return param.addObject(direction+3, this); } + else { + return -1; + } } else opserr << "WARNING: Could not set parameter in Node. " << endln; @@ -1574,10 +1604,10 @@ Node::updateParameter(int pparameterID, Information &info) else if (pparameterID >= 4 && pparameterID <= 6) { - if ( (*Crd)(pparameterID-4) != info.theDouble) { + if ( xyz(pparameterID-4) != info.theDouble) { // Set the new coordinate value - (*Crd)(pparameterID-4) = info.theDouble; + xyz(pparameterID-4) = info.theDouble; // Need to "setDomain" to make the change take effect. Domain *theDomain = this->getDomain(); @@ -1685,7 +1715,7 @@ Node::getAccSensitivity(int dof, int gradIndex) const Vector & Node::getReaction() { - if (reaction == 0) + if (reaction == nullptr) reaction = new Vector(numberDOF); // TODO; zero this? @@ -1734,8 +1764,8 @@ Node::resetReactionForce(int flag) } else { if (mass != 0 && alphaM != 0) { if (alphaM != 0.0) { - const Vector &theVel = this->getTrialVel(); // in case vel not created - reaction->addMatrixVector(1.0, *mass, theVel, alphaM); + const Vector &theVel = this->getTrialVel(); // in case vel not created + reaction->addMatrixVector(1.0, *mass, theVel, alphaM); } } } @@ -1807,8 +1837,8 @@ Node::getResponse(NodeData responseType) void Node::setCrds(double Crd1) { - if (Crd != 0 && Crd->Size() >= 1) - (*Crd)(0) = Crd1; + if (xyz.Size() >= 1) + xyz(0) = Crd1; // Need to "setDomain" to make the change take effect. Domain *theDomain = this->getDomain(); @@ -1822,9 +1852,9 @@ Node::setCrds(double Crd1) void Node::setCrds(double Crd1, double Crd2) { - if (Crd != 0 && Crd->Size() >= 2) { - (*Crd)(0) = Crd1; - (*Crd)(1) = Crd2; + if (xyz.Size() >= 2) { + xyz(0) = Crd1; + xyz(1) = Crd2; // Need to "setDomain" to make the change take effect. Domain *theDomain = this->getDomain(); @@ -1838,10 +1868,10 @@ Node::setCrds(double Crd1, double Crd2) void Node::setCrds(double Crd1, double Crd2, double Crd3) { - if (Crd != 0 && Crd->Size() >= 3) { - (*Crd)(0) = Crd1; - (*Crd)(1) = Crd2; - (*Crd)(2) = Crd3; + if (xyz.Size() >= 3) { + xyz(0) = Crd1; + xyz(1) = Crd2; + xyz(2) = Crd3; // Need to "setDomain" to make the change take effect. Domain *theDomain = this->getDomain(); @@ -1855,10 +1885,11 @@ Node::setCrds(double Crd1, double Crd2, double Crd3) void Node::setCrds(const Vector &newCrds) { - if (Crd != 0 && Crd->Size() == newCrds.Size()) { - (*Crd) = newCrds; + if (xyz.Size() == newCrds.Size()) { + for (int i=0; igetDomain(); @@ -1870,31 +1901,6 @@ Node::setCrds(const Vector &newCrds) } #if 1 -int -Node::getDisplayRots(Vector& res, double fact, int mode) -{ - int ndm = Crd->Size(); - int resSize = res.Size(); - int nRotDOFs = numberDOF - ndm; - if (resSize < nRotDOFs) - return -1; - - if (mode < 0) { - int eigenMode = -mode; - for (int i = ndm; i < resSize; i++) - res(i) = (*theEigenvectors)(i, eigenMode - 1) * fact; - - } else { - for (int i = ndm; i < resSize; i++) - res(i) = (*commitDisp)(i) * fact; - } - - // zero rest - for (int i = nRotDOFs; i < resSize; i++) - res(i) = 0; - - return 0; -} int Node::getDisplayCrds(Vector &res, double fact, int mode) @@ -1902,11 +1908,6 @@ Node::getDisplayCrds(Vector &res, double fact, int mode) return -1; } -int -Node::setDisplayCrds(const Vector &theCrds) -{ - return -1; -} #endif @@ -1924,6 +1925,20 @@ Node::setNodalThermalActionPtr(NodalThermalAction* theAction) } // Add Pointer to NodalThermalAction id applicable-----end------L.Jiang, {SIF] + +int +Node::resetGlobalMatrices() +{ + if (numMatrices > 0) { + for (int i=0; i #include - // TODO: Remove include of NodeData #include "NodeData.h" +#include class Vector; class Matrix; @@ -50,7 +49,9 @@ class DOF_Group; class NodalThermalAction; //L.Jiang [ SIF ] class Domain; class Element; -namespace OpenSees {struct Versor;} +namespace OpenSees { + struct Versor; +} using OpenSees::Versor; class Node : @@ -65,21 +66,21 @@ class Node : // constructors Node(int classTag); Node(int tag, int classTag); - Node(int tag, int ndof, double Crd1, Vector *displayLoc = 0); - Node(int tag, int ndof, double Crd1, double Crd2, Vector *displayLoc = 0); - Node(int tag, int ndof, double Crd1, double Crd2, double Crd3, Vector *displayLoc = 0); + Node(int tag, int ndof, double Crd1); + Node(int tag, int ndof, double Crd1, double Crd2); + Node(int tag, int ndof, double Crd1, double Crd2, double Crd3); Node(const Node &theCopy, bool copyMass = true); // destructor VIRTUAL ~Node(); // public methods dealing with the DOF at the node - VIRTUAL int getNumberDOF(void) const; + VIRTUAL int getNumberDOF() const; VIRTUAL void setDOF_GroupPtr(DOF_Group *theDOF_Grp); - VIRTUAL DOF_Group *getDOF_GroupPtr(void); + VIRTUAL DOF_Group *getDOF_GroupPtr(); // public methods for obtaining the nodal coordinates - VIRTUAL const Vector &getCrds(void) const; + VIRTUAL const Vector &getCrds() const; VIRTUAL void setCrds(double Crd1); VIRTUAL void setCrds(double Crd1, double Crd2); VIRTUAL void setCrds(double Crd1, double Crd2, double Crd3); @@ -89,7 +90,7 @@ class Node : // State // // public methods dealing with the committed state of the node - virtual int commitState(); + virtual int commitState() noexcept; virtual int revertToLastCommit(); virtual int revertToStart(); @@ -98,10 +99,10 @@ class Node : // // public methods for obtaining committed and trial // response quantities of the node - VIRTUAL const Vector &getDisp(); - VIRTUAL const Vector &getIncrDisp(); - VIRTUAL const Vector &getIncrDeltaDisp(); - VIRTUAL const Vector &getTrialDisp(); + VIRTUAL const Vector &getDisp() noexcept; + VIRTUAL const Vector &getIncrDisp() noexcept; + VIRTUAL const Vector &getIncrDeltaDisp() noexcept; + VIRTUAL const Vector &getTrialDisp() noexcept {return *trialDisp;} VIRTUAL Versor getTrialRotation(); VIRTUAL const Vector &getVel(); @@ -110,8 +111,8 @@ class Node : VIRTUAL const Vector &getTrialAccel(); // public methods for updating the trial response quantities - virtual int setTrialDisp (double value, int dof); - virtual int setTrialDisp (const Vector &); + virtual int setTrialDisp (double value, int dof) noexcept; + virtual int setTrialDisp (const Vector &) noexcept; virtual int incrTrialDisp (const Vector &); VIRTUAL int setTrialVel (const Vector &); VIRTUAL int setTrialAccel (const Vector &); @@ -122,6 +123,8 @@ class Node : VIRTUAL const Matrix &getMass(); VIRTUAL const Matrix &getDamp(); VIRTUAL int setMass(const Matrix &theMass); + VIRTUAL int addPositionInertia(double value); + VIRTUAL int addRotationInertia(double value, unsigned dof); VIRTUAL int setNumColR(int numCol); VIRTUAL int setR(int row, int col, double Value); VIRTUAL const Vector &getRV(const Vector &V); @@ -139,10 +142,10 @@ class Node : // // Load information // - VIRTUAL void zeroUnbalancedLoad(void); + VIRTUAL void zeroUnbalancedLoad() noexcept; VIRTUAL int addUnbalancedLoad(const Vector &load, double fact = 1.0); VIRTUAL int addInertiaLoadToUnbalance(const Vector &accel, double fact = 1.0); - VIRTUAL const Vector &getUnbalancedLoad(); + VIRTUAL const Vector &getUnbalancedLoad() noexcept; VIRTUAL const Vector &getUnbalancedLoadIncInertia(); @@ -157,9 +160,8 @@ class Node : // // Parallel // - VIRTUAL int sendSelf(int commitTag, Channel &theChannel); - VIRTUAL int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); + VIRTUAL int sendSelf(int commitTag, Channel &); + VIRTUAL int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); // // Misc @@ -190,10 +192,11 @@ class Node : // Display // VIRTUAL int getDisplayCrds(Vector &results, double fact, int displayMode=0); - VIRTUAL int getDisplayRots(Vector& results, double fact, int displayMode=0); - VIRTUAL int setDisplayCrds(const Vector &theCrds); #endif + // Reset global matrices + static int resetGlobalMatrices(); + Domain *getDomain() {return theDomain;}; void setDomain(Domain *model) {theDomain = model;}; @@ -218,8 +221,6 @@ class Node : static Matrix **theMatrices; static int numMatrices; - static Matrix **theVectors; - static int numVectors; int index; @@ -235,12 +236,17 @@ class Node : NodalThermalAction *theNodalThermalActionPtr; //Added by Liming Jiang for pointer to nodalThermalAction, [SIF] Vector *Crd; // original nodal coords + Vector xyz; + double coord_data[3]; Matrix *R; // nodal participation matrix Matrix *mass; // pointer to mass matrix - Vector *unbalLoadWithInertia; double alphaM; // rayleigh damping factor + double position_inertia; + double rotation_inertia[3]; + // State + Vector *unbalLoadWithInertia; Matrix *theEigenvectors; diff --git a/SRC/runtime/commands/modeling/nodes.cpp b/SRC/runtime/commands/modeling/nodes.cpp index d81cdd810c..293a09757f 100644 --- a/SRC/runtime/commands/modeling/nodes.cpp +++ b/SRC/runtime/commands/modeling/nodes.cpp @@ -36,6 +36,17 @@ #define G3_NUM_DOF_BUFFER 20 + +int +TclCommand_wipeNodes(ClientData clientData, Tcl_Interp *interp, + Tcl_Size argc, TCL_Char ** const argv) +{ + // TODO: Check that all nodes are deleted from the domain + // assert(clientData != nullptr); + Node::resetGlobalMatrices(); + return TCL_OK; +} + int TclCommand_addNode(ClientData clientData, Tcl_Interp *interp, int argc, TCL_Char ** const argv) @@ -63,7 +74,8 @@ TclCommand_addNode(ClientData clientData, Tcl_Interp *interp, int argc, int nodeId; if (Tcl_GetInt(interp, argv[1], &nodeId) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid nodeTag\n"; - opserr << " Want: node nodeTag? [ndm coordinates?] <-mass [ndf values?]>\n"; + opserr << " Want: node nodeTag? [ndm coordinates?] <-mass [ndf values?]>" + << OpenSees::SignalMessageEnd; return TCL_ERROR; } @@ -163,25 +175,13 @@ TclCommand_addNode(ClientData clientData, Tcl_Interp *interp, int argc, theNode->setMass(mass); } else if (strcmp(argv[currentArg], "-dispLoc") == 0) { - currentArg++; - if (argc < currentArg + ndm) { - opserr << OpenSees::PromptValueError << "incorrect number of nodal display location terms, " - "need ndm\n"; - return TCL_ERROR; - } - Vector displayLoc(ndm); - double theCrd; - for (int i = 0; i < ndm; ++i) { - if (Tcl_GetDouble(interp, argv[currentArg++], &theCrd) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid nodal mass term\n"; - opserr << "node: " << nodeId << ", dof: " << i + 1 << "\n"; - return TCL_ERROR; - } - displayLoc(i) = theCrd; - } - theNode->setDisplayCrds(displayLoc); - - } else if (strcmp(argv[currentArg], "-disp") == 0) { + + opswrn << G3_WARN_PROMPT + << "-dispLoc option is no longer supported\n" + << OpenSees::SignalMessageEnd; + currentArg += 1+ndm; + } + else if (strcmp(argv[currentArg], "-disp") == 0) { currentArg++; if (argc < currentArg + ndf) { opserr << OpenSees::PromptValueError << "incorrect number of nodal disp terms\n"; @@ -263,8 +263,9 @@ TclCommand_addNodalMass(ClientData clientData, Tcl_Interp *interp, int argc, int ndf = argc - 2; // make sure at least one other argument - if (argc < (1 + ndf)) { - opserr << OpenSees::PromptValueError << "insufficient arguments, expected:\n" + if (argc < 2 + 1) { + opserr << OpenSees::PromptValueError + << "insufficient arguments, expected:\n" " mass nodeId <" << ndf << " mass values>\n"; return TCL_ERROR; } @@ -272,29 +273,88 @@ TclCommand_addNodalMass(ClientData clientData, Tcl_Interp *interp, int argc, // get the id of the node int nodeId; if (Tcl_GetInt(interp, argv[1], &nodeId) != TCL_OK) { - opserr << OpenSees::PromptValueError << "invalid nodeId: " << argv[1]; + opserr << OpenSees::PromptValueError + << "invalid nodeId: " << argv[1]; opserr << " - mass nodeId " << ndf << " forces\n"; return TCL_ERROR; } + Node* node = theTclDomain->getNode(nodeId); + if (node == nullptr) { + opserr << OpenSees::PromptValueError << "node " << nodeId << " does not exist in domain\n"; + return TCL_ERROR; + } + + const int ndm = node->getCrds().Size(); // check for mass terms - Matrix mass(ndf,ndf); - for (int i=0; i= argc) { + opserr << OpenSees::PromptValueError + << "missing nodal mass term after -position\n" + << "\n"; + return TCL_ERROR; + } + if (Tcl_GetDouble(interp, argv[argi+1], &position_inertia[0]) != TCL_OK) { opserr << OpenSees::PromptValueError << "invalid nodal mass term\n"; - opserr << "node: " << nodeId << ", dof: " << i+1 << "\n"; + opserr << "node: " << nodeId << "\n"; return TCL_ERROR; } - mass(i,i) = theMass; + for (int j=1; jsetMass(mass, nodeId) != 0) { - opserr << OpenSees::PromptValueError << "failed to set mass at node " << nodeId << "\n"; - return TCL_ERROR; + if (argi < argc) { + if (argc - argi < ndm) { + opserr << OpenSees::PromptValueError + << "insufficient nodal mass terms, need " << ndf << "\n"; + return TCL_ERROR; + } + for (int i=0; iaddPositionInertia(position_inertia[0]); + } + else { + Matrix mass(ndf,ndf); + for (int i=0; isetMass(mass); } - // if get here we have sucessfully created the node and added it to the domain return TCL_OK; } From 02631a2783ce64e37ac025fa20c5ee3592dc0498 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:45:31 -0800 Subject: [PATCH 116/161] Update modal.cpp --- SRC/runtime/commands/analysis/modal/modal.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/SRC/runtime/commands/analysis/modal/modal.cpp b/SRC/runtime/commands/analysis/modal/modal.cpp index 578730b4e8..283e4ce4a2 100644 --- a/SRC/runtime/commands/analysis/modal/modal.cpp +++ b/SRC/runtime/commands/analysis/modal/modal.cpp @@ -6,7 +6,6 @@ #include "DomainModalProperties.h" #include "ResponseSpectrumAnalysis.h" - namespace OpenSees { Tcl_CmdProc responseSpectrumAnalysis; @@ -19,6 +18,9 @@ modalProperties(ClientData clientData, { // modalProperties <-print> <-file $fileName> <-unorm> + assert(clientData != nullptr); + Domain* domain = static_cast(clientData); + // some kudos static bool first_done = false; if (!first_done) { @@ -57,8 +59,7 @@ modalProperties(ClientData clientData, ++loc; } - - Domain* domain = static_cast(clientData); + // create the modal properties, compute them, // and add them to the domain From 7b0ba2e584f2249e68ed092cdf7781d16fa47668 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:45:56 -0800 Subject: [PATCH 117/161] Update ViscousDamper.cpp --- SRC/material/uniaxial/viscous/ViscousDamper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SRC/material/uniaxial/viscous/ViscousDamper.cpp b/SRC/material/uniaxial/viscous/ViscousDamper.cpp index 3460b8b7c3..d265668418 100644 --- a/SRC/material/uniaxial/viscous/ViscousDamper.cpp +++ b/SRC/material/uniaxial/viscous/ViscousDamper.cpp @@ -242,9 +242,8 @@ ViscousDamper::setTrialStrain(double strain, double strainRate) if ((fabs(Tnugr) > 0.) && (Tstress == 0)) { //from positive to negative - if ((strain < Tnugr) && ((strain-Tnugr) > -LGap)) { - fd0 = 0.; + fd0 = 0.; } } From 2fca14b5e5a5c82d982ac1f0763ff697782ad612 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:47:32 -0800 Subject: [PATCH 118/161] Fix local frame loads and mass, explore state determination --- SRC/element/Frame/ForceFrame3d.h | 2 + SRC/element/Frame/ForceFrame3d.tpp | 425 +++++++++++++++++++++++++---- 2 files changed, 373 insertions(+), 54 deletions(-) diff --git a/SRC/element/Frame/ForceFrame3d.h b/SRC/element/Frame/ForceFrame3d.h index 641484e2b0..d1658cf50f 100644 --- a/SRC/element/Frame/ForceFrame3d.h +++ b/SRC/element/Frame/ForceFrame3d.h @@ -186,6 +186,8 @@ class ForceFrame3d: public BasicFrame3d, // // Functions // + int update01(); + int update02(); int getInitialFlexibility(MatrixND &Fe); int getInitialDeformations(Vector &v0); diff --git a/SRC/element/Frame/ForceFrame3d.tpp b/SRC/element/Frame/ForceFrame3d.tpp index a2a31bcc7a..685d6f9a41 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -194,9 +194,13 @@ ForceFrame3d::getIntegral(Field field, State state, doub // Integrate density to compute total mass case Field::Density: { + // use element density if supplied + if (use_density) { + total = density * basic_system->getInitialLength(); + return 0; + } for (GaussPoint& sample : points) { double value = 0.0; - // use element density if supplied if (use_density) total += sample.weight*density; @@ -366,6 +370,7 @@ ForceFrame3d::getMass() ALWAYS_STATIC Matrix Wrapper{M}; // lumped mass matrix double m = 0.5*total_mass; + M.zero(); M(0,0) = m; M(1,1) = m; M(2,2) = m; @@ -624,6 +629,352 @@ public: template int ForceFrame3d::update() +{ + if (!getenv("Force02")) + return this->update01(); + else + return this->update02(); + + return 0; +} + + +template +int +ForceFrame3d::update01() +{ + constexpr static double TOL_SUBDIV = DBL_EPSILON*10; + + + // If we have completed a recvSelf() do a revertToLastCommit() + // to get sr, etc. set correctly + if (state_flag == 2) + this->revertToLastCommit(); + + // + // Localize deformations + // + basic_system->update(); + + double L = basic_system->getInitialLength(); + + + VectorND dv_total{}, dv_trial{}; + VectorND dv{}; + { + const Vector& dvb = basic_system->getBasicIncrDeltaDisp(); + for (int i=0; i<6; i++) { + dv[i] = dvb[i]; + } + } + + // + // + // + if ((state_flag != 0) && + (dv.norm() <= DBL_EPSILON) && + (eleLoads.size()==0) && + (frame_loads.size()==0)) + return 0; + + // Basic DOFs + VectorND Dv{}; + { + const Vector& v = basic_system->getBasicTrialDisp(); + for (int i=0; i<6; i++) + Dv[i] = v[i] - dv[i]; + } + + { + // Warping DOFs + Node** nodes = this->getNodePtrs(); + for (int i=0; igetTrialDisp(); + const Vector& duj = nodes[j]->getIncrDeltaDisp(); + dv[NNW+i*nwm+j] = duj[6+i]; + Dv[NNW+i*nwm+j] = uj[6+i] - duj[6+i]; + } + } + } + + dv_total = dv; + dv_trial = dv_total; + + static constexpr double factor = 10.0; + double dW; // section strain energy (work) norm + double dW0 = 0.0; + + + static VectorND es_trial[NIP]{}; // strain + static VectorND sr_trial[NIP]{}; // stress resultant + static MatrixND Fs_trial[NIP]{}; // flexibility + + // + // Iterate to find compatible forces and deformations + // + // First try first a Newton iteration, if that fails we try an initial + // flexibility iteration on first iteration and then regular Newton, if + // that fails we use the initial flexiblity for all iterations. + // If they both fail we subdivide dV & try to get compatible forces + // and deformations. If they work, and we have subdivided we apply + // the remaining dV. + // + enum class Strategy { + Newton, InitialIterations, InitialThenNewton + }; + static constexpr std::array solve_strategy { + Strategy::Newton, // Strategy::InitialIterations, Strategy::InitialThenNewton + }; + + int subdivision = 1; + bool converged = false; + + const int nip = points.size(); + while ((converged == false) && (subdivision <= max_subdivision)) { + + for (Strategy strategy : solve_strategy ) { + + // Allow extra iterations for initial tangent strategy + const int numIters = (strategy==Strategy::InitialIterations) ? 10*max_iter : max_iter; + + for (int i = 0; i < nip; i++) { + es_trial[i] = points[i].es; + Fs_trial[i] = points[i].Fs; + sr_trial[i] = points[i].sr; + } + + if (state_flag == 2) + continue; + + VectorND q_trial = q_pres; + + q_trial += K_pres*dv; + + for (int j = 0; j < numIters; j++) { + + VectorND vr{}; // element residual deformations + MatrixND F{}; // element flexibility matrix + ForceInterpolation interp; + + // + // Gauss Loop + // + for (int i = 0; i < nip; i++) { + double xL = points[i].point; + double wtL = points[i].weight * L; + + // Retrieve section flexibility, deformations, and forces from last iteration + const MatrixND& Fs = Fs_trial[i]; + const VectorND& sr = sr_trial[i]; + FrameSection& section = *points[i].material; + const MatrixND b = interp.b(xL, L); + + // + // a. Calculate section force by interpolation of q_trial + // + // si = b*q + bp*w; + + // Interpolation of q_trial + // b*q_trial + // + VectorND si = b * q_trial; + + // + // Add the particular solution + // + if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) + this->addLoadAtSection(si, points[i].point * L); + + + // + // b. Compute section deformations es_trial + // + // es += Fs * ( si - sr(e) ); + // + if (state_flag != 0) { + + // Form stress increment ds from last iteration + // ds = si - si_past; + const VectorND ds = si - sr; + + // Add strain correction + // es += Fs * ds; + switch (strategy) { + case Strategy::Newton: + // regular Newton + es_trial[i].addMatrixVector(Fs, ds, 1.0); + break; + + case Strategy::InitialThenNewton: + // Newton with initial tangent if first iteration + // otherwise regular Newton + if (j == 0) { + MatrixND Fs0 = section.template getFlexibility(State::Init); + es_trial[i].addMatrixVector(Fs0, ds, 1.0); + } else + es_trial[i].addMatrixVector(Fs, ds, 1.0); + break; + + case Strategy::InitialIterations: + // Newton with initial tangent + MatrixND Fs0 = section.template getFlexibility(State::Init); + es_trial[i].addMatrixVector(Fs0, ds, 1.0); + break; + } + } + + + // + // c. Set trial section state and get response + // + if (section.setTrialState(es_trial[i]) < 0) { + opserr << "element " << this->getTag() << ", section " << i << ": failed in setTrial\n"; + return -1; + } + + sr_trial[i] = section.getResultant(); + Fs_trial[i] = section.template getFlexibility(); + + // + // d. Integrate element flexibility matrix + // + // F += (B' * Fs * B) * wi * L; + // + F.addMatrixTripleProduct(1.0, b, Fs, b, wtL); + + // + // e. Integrate residual deformations + // + // vr += (B' * (es + des)) * wi * L; + // + { + // calculate section residual deformations + // des = Fs * ds, with ds = si - sr[i]; + const VectorND ds = si - sr; + + // B' * des + vr.addMatrixTransposeVector(1.0, b, Fs*ds+es_trial[i], wtL); + } + } // Gauss loop + + + // dv = Dv + dv_trial - vr + dv = Dv; + dv += dv_trial; + dv -= vr; + + // + // Finalize trial element state + // + // K_trial = inv(F) + // q_trial += K * (Dv + dv_trial - vr) + // + const Cholesky cholF(F); + + VectorND dqe{}; + if (cholF.solve(&dv[0], &dqe[0]) < 0) [[unlikely]] { + // opserr << "ForceFrame3d: Failed to solve for dqe with Cholesky\n"; + if (F.solve(dv, dqe) < 0) + return -1; + } + + dW = dqe.dot(dv); + if (dW0 == 0.0) + dW0 = dW; + + q_trial += dqe; + + // + // Check for convergence of this interval + // + if (std::fabs(dW) < tol) { + + // Set the target displacement + dv_total -= dv_trial; + Dv += dv_trial; + + // Check if we have got to where we wanted + if (dv_total.dot(dv_total) <= TOL_SUBDIV*TOL_SUBDIV) { + converged = true; + + } else { + // We've converged but we have more to do; + // reset variables for start of next subdivision + dv_trial = dv_total; + // NOTE setting subdivide to 1 again maybe too much + subdivision = 1; + } + + // set K_pres, es and q_pres values + // K_pres = K_trial; + + if (cholF.invert(K_pres) < 0) [[unlikely]] { + if (F.invert(K_pres) < 0) + return -1; + } + q_pres = q_trial; + + for (int k = 0; k < nip; k++) { + points[k].es = es_trial[k]; + points[k].Fs = Fs_trial[k]; + points[k].sr = sr_trial[k]; + } + + // break out of j & l loops + goto iterations_completed; + } + else { // if (fabs(dW) < tol) { + + // if we have failed to converge for all of our Newton schemes + // - reduce step size by the factor specified + if (j == (numIters - 1)) {// } && (strategy == Strategy::InitialThenNewton)) { + dv_trial /= factor; + subdivision++; + } + } + } // for (iteration) + } // for (strategy) + +iterations_completed: + ; + + } // while (converged == false) + + + if (converged == false) [[unlikely]] { + opserr << "WARNING - ForceFrame3d failed internal state determination "; + opserr << "for element " + << this->getTag() + << "; dW = " << dW + << ", dW0 = " << dW0 + << "\n"; + return -1; + } + else { + ForceInterpolation interp; + for (int k=0; k B = interp.b(points[k].point, L); + VectorND si = B * q_pres; + // Add the particular solution + if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) + this->addLoadAtSection(si, points[k].point * L); + + MatrixND& Fs = points[k].Fs; + points[k].es = points[k].es + Fs*(si - sr_trial[k]); + points[k].sr = si; + } + } + + state_flag = 1; + + return 0; +} + + +template +int +ForceFrame3d::update02() { constexpr static double TOL_SUBDIV = DBL_EPSILON*10; @@ -859,7 +1210,7 @@ ForceFrame3d::update() VectorND dqe{}; if (cholF.solve(&dv[0], &dqe[0]) < 0) [[unlikely]] { - opserr << "ForceFrame3d: Failed to solve for dqe with Cholesky\n"; + // opserr << "ForceFrame3d: Failed to solve for dqe with Cholesky\n"; if (F.solve(dv, dqe) < 0) return -1; } @@ -880,7 +1231,7 @@ ForceFrame3d::update() Dv += dv_trial; // Check if we have got to where we wanted - if (dv_total.norm() <= TOL_SUBDIV) { + if (dv_total.dot(dv_total) <= TOL_SUBDIV*TOL_SUBDIV) { converged = true; } else { @@ -1014,7 +1365,6 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d { double L = basic_system->getInitialLength(); - double jsx = 1.0 / L; // // Gauss Loop // @@ -1022,9 +1372,10 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d const MatrixND<3,2*NDF>& dR = basic_system->t.getRotationTangent(); MatrixND F{}; + ForceInterpolation interp; + for (int i = 0; i < nip; i++) { double xL = points[i].point; - double xL1 = xL - 1.0; double wtL = points[i].weight * L; // Retrieve section flexibility, deformations, and forces from last iteration @@ -1036,73 +1387,37 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d // F += (B' * Fs * dsp) * wi * L; // { + const MatrixND b = interp.b(xL, L); MatrixND FsB; FsB.zero(); for (auto load : frame_loads) { VectorND sp{}; load->template addBasicSolution(sp, points[i].point*L, L, - Eye3, basic_system->t.getRotation()); + basic_system->t.getInitialRotation(), + basic_system->t.getRotation()); MatrixND Ks{}; load->template addBasicTangent(Ks, sp); FsB += Fs*Ks*dR*wtL; } - for (int jj = 0; jj < nsr; jj++) { - for (int ii = 0; ii < NDF; ii++) { - switch (scheme[jj]) { - case FrameStress::N: - F(jnx, ii) += 1.0 * FsB(jj, ii); // Nj - break; - case FrameStress::Vy: - F(imz, ii) += jsx * FsB(jj, ii); - F(jmz, ii) += jsx * FsB(jj, ii); - break; - case FrameStress::Vz: - F(imy, ii) += jsx * FsB(jj, ii); - F(jmy, ii) += jsx * FsB(jj, ii); - break; - case FrameStress::T: - F(jmx, ii) += 1.0 * FsB(jj, ii); - break; - case FrameStress::My: - F(imy, ii) += xL1 * FsB(jj, ii); - F(jmy, ii) += xL * FsB(jj, ii); - break; - case FrameStress::Mz: - F(imz, ii) += xL1 * FsB(jj, ii); - F(jmz, ii) += xL * FsB(jj, ii); - break; - case FrameStress::Bimoment: - F(iwx, ii) += xL1 * FsB(jj, ii); - F(jwx, ii) += xL * FsB(jj, ii); - break; - case FrameStress::Bishear: - F(iwx, ii) += jsx * FsB(jj, ii); - F(jwx, ii) += jsx * FsB(jj, ii); - break; - } - } - } + F.addMatrixTransposeProduct(1.0, b, FsB, wtL); } } // Gauss loop - - // VectorND pf{}; for (auto load : frame_loads) { load->template addLinearSolution(pf, L, - Eye3, // TODO? + basic_system->t.getInitialRotation(), basic_system->t.getRotation()); } MatrixND<2*NDF,2*NDF> Kf{}; #if BASIC_TRANSFORM == 1 - ForceInterpolation interp; const static MatrixND<2*NDF,NBV> Tb = interp.reshape_matrix(); // FormBasicTransform(); Kf = Tb*F; #else @@ -1135,7 +1450,8 @@ ForceFrame3d::addLoadAtSection(VectorND& sp, double double L = basic_system->getInitialLength(); for (auto load : frame_loads) { load->template addBasicSolution(sp, x, L, - Eye3, basic_system->t.getRotation()); + basic_system->t.getInitialRotation(), + basic_system->t.getRotation()); } for (auto[load, loadFactor] : eleLoads) { @@ -1926,7 +2242,7 @@ int ForceFrame3d::getResponse(int responseID, Information& info) { THREAD_LOCAL Vector vp(6); - THREAD_LOCAL MatrixND fe; + THREAD_LOCAL MatrixND fe{}; if (responseID == Respond::GlobalForce) return info.setVector(this->getResistingForce()); @@ -2290,6 +2606,7 @@ ForceFrame3d::setParameter(const char** argv, int argc, if ((strcmp(argv[0], "rho") == 0) || (strcmp(argv[0], "density") == 0)) { param.setValue(density); + use_density = true; return param.addObject(1, this); } @@ -2379,6 +2696,8 @@ ForceFrame3d::updateParameter(int parameterID, Informati { if (parameterID == 1) { this->density = info.theDouble; + total_mass = density * basic_system->getInitialLength(); + use_density = true; return 0; } else return -1; @@ -2797,24 +3116,22 @@ ForceFrame3d::getResistingForce() #endif // 2. Element loads - + VectorND pf{}; // 2.1 Legacy load classes double p0[5]{}; if (eleLoads.size() > 0) this->computeReactions(p0); - - // 2.2 Frame load classes - VectorND pf; - pf.zero(); pf[0*NDF + 0] = p0[0]; // N pf[0*NDF + 1] = p0[1]; // Vy pf[0*NDF + 2] = p0[3]; // Vz pf[1*NDF + 1] = p0[2]; // Vy pf[1*NDF + 2] = p0[4]; // Vz + + // 2.2 Frame load classes for (auto load : frame_loads) { load->template addLinearSolution(pf, L, - Eye3, // TODO? + basic_system->t.getInitialRotation(), basic_system->t.getRotation()); } From 6236703e293093d636c6838580045c2a5a80b679 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:47:43 -0800 Subject: [PATCH 119/161] Update NodalLoad.h --- SRC/domain/node/NodalLoad.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SRC/domain/node/NodalLoad.h b/SRC/domain/node/NodalLoad.h index 72fbc11009..ab49e21db7 100644 --- a/SRC/domain/node/NodalLoad.h +++ b/SRC/domain/node/NodalLoad.h @@ -46,13 +46,12 @@ class NodalLoad : public Load ~NodalLoad(); virtual void setDomain(Domain *newDomain); - virtual int getNodeTag(void) const; + virtual int getNodeTag() const; virtual void applyLoad(double loadFactor); virtual void applyLoadSensitivity(double loadFactor); - virtual int sendSelf(int commitTag, Channel &theChannel); - virtual int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); + virtual int sendSelf(int commitTag, Channel &); + virtual int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &); virtual void Print(OPS_Stream &s, int flag =0); From 3c7ee15bc328a451c2658cfc597c8b7dbff8a04a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:47:46 -0800 Subject: [PATCH 120/161] Update NodalLoad.cpp --- SRC/domain/node/NodalLoad.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SRC/domain/node/NodalLoad.cpp b/SRC/domain/node/NodalLoad.cpp index 69b8b73257..5fc9fa4437 100644 --- a/SRC/domain/node/NodalLoad.cpp +++ b/SRC/domain/node/NodalLoad.cpp @@ -64,7 +64,7 @@ NodalLoad::~NodalLoad() void NodalLoad::setDomain(Domain *newDomain) { - // first get myNodePtr + // first get myNodePtr if (newDomain == 0) return; @@ -120,10 +120,10 @@ NodalLoad::applyLoadSensitivity(double loadFactor) if (myNodePtr == 0) { Domain *theDomain=this->getDomain(); if ((theDomain == 0) || - (myNodePtr = theDomain->getNode(myNode)) == 0) { - opserr << "WARNING NodalLoad::applyLoadSensitivity() - No associated Node node " ; - opserr << " for NodalLoad " << *this; - return; + (myNodePtr = theDomain->getNode(myNode)) == 0) { + opserr << "WARNING NodalLoad::applyLoadSensitivity() - No associated Node node " ; + opserr << " for NodalLoad " << *this; + return; } } From 7ab7bab36d0eb800adcfc0fc7095f96bc7691236 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:48:34 -0800 Subject: [PATCH 121/161] Refactor AnalysisModel to require Domain reference Changed AnalysisModel constructor to take a Domain reference, ensuring the model is always associated with a domain. Added ApproxDOF helper to pre-size DOF and FE element containers based on the domain, improving initialization efficiency. --- SRC/analysis/model/AnalysisModel.cpp | 19 +++++++++++++++++-- SRC/analysis/model/AnalysisModel.h | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/SRC/analysis/model/AnalysisModel.cpp b/SRC/analysis/model/AnalysisModel.cpp index cb46584f2f..d465891d7b 100644 --- a/SRC/analysis/model/AnalysisModel.cpp +++ b/SRC/analysis/model/AnalysisModel.cpp @@ -56,10 +56,22 @@ #define START_EQN_NUM 0 #define START_VERTEX_NUM 0 +static int +ApproxDOF(Domain& domain) +{ + int nf = 0; + Node *nodePtr; + NodeIter &theNodes = domain.getNodes(); + while ((nodePtr = theNodes()) != nullptr) + nf += nodePtr->getNumberDOF(); + + return nf; +} -AnalysisModel::AnalysisModel() + +AnalysisModel::AnalysisModel(Domain& domain) : MovableObject(AnaMODEL_TAGS_AnalysisModel), - myDomain(nullptr), myHandler(nullptr), + myDomain(&domain), myHandler(nullptr), myDOFGraph(0), myGroupGraph(0) , numFE_Ele(0), numDOF_Grp(0), numEqn(0) , eigenVectors(0), eigenValues(0), dampingForces(0) @@ -69,6 +81,9 @@ AnalysisModel::AnalysisModel() theDOFs = new VectorOfTaggedObjects(); // 256); theFEiter = new FE_EleIter(theFEs); theDOFiter = new DOF_GrpIter(theDOFs); + + theDOFs->setSize(ApproxDOF(domain)); + theFEs->setSize(domain.getNumElements()); } diff --git a/SRC/analysis/model/AnalysisModel.h b/SRC/analysis/model/AnalysisModel.h index 843cf21a3e..86090dcca7 100644 --- a/SRC/analysis/model/AnalysisModel.h +++ b/SRC/analysis/model/AnalysisModel.h @@ -54,7 +54,7 @@ using FE_EleIter = TaggedIterator; class AnalysisModel: public MovableObject { public: - AnalysisModel(); + AnalysisModel(Domain&); ~AnalysisModel(); void setLinks(Domain &, ConstraintHandler &); From 7b7621beb2d675782fd022ff6a61aec36db372c5 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:02:55 -0800 Subject: [PATCH 122/161] Update boucwen.cpp --- SRC/runtime/commands/modeling/material/boucwen.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SRC/runtime/commands/modeling/material/boucwen.cpp b/SRC/runtime/commands/modeling/material/boucwen.cpp index dd04552a5b..32eb06db78 100644 --- a/SRC/runtime/commands/modeling/material/boucwen.cpp +++ b/SRC/runtime/commands/modeling/material/boucwen.cpp @@ -420,9 +420,10 @@ ParseBoucWen(ClientData clientData, Tcl_Interp *interp, case Positions::EndRequired: // This will not be reached break; - + + case Positions::EndAllowed: case Positions::End: - opserr << "Invalid value for option " << argv[i] << "\n"; + opserr << "Invalid positional argument " << argv[i] << "\n"; return TCL_ERROR; } } From 3bde602347a03e1cd8479ccd1415e378f7f3f496 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:22:52 -0800 Subject: [PATCH 123/161] Update boucwen.cpp --- SRC/runtime/commands/modeling/material/boucwen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SRC/runtime/commands/modeling/material/boucwen.cpp b/SRC/runtime/commands/modeling/material/boucwen.cpp index 32eb06db78..a58e2ea211 100644 --- a/SRC/runtime/commands/modeling/material/boucwen.cpp +++ b/SRC/runtime/commands/modeling/material/boucwen.cpp @@ -630,9 +630,10 @@ TclCommand_newBoucWen(ClientData clientData, Tcl_Interp *interp, Mu, N, Beta, Gamma, Tolerance, Iterations, - End, + EndAllowed, Ao, DeltaA, DeltaV, DeltaN, PinchSlope, PinchStart, PinchRate, PinchSize, PinchSlip, PinchLamda, + End }; return ParseBoucWen(clientData, interp, argc, argv); } From 3033bbd8716aaf09088de5717793b55b16bd6e6d Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:27:45 -0800 Subject: [PATCH 124/161] Update BasicAnalysisBuilder.cpp --- SRC/runtime/runtime/BasicAnalysisBuilder.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp index 8bbff621a4..c25253a3ea 100644 --- a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp +++ b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp @@ -75,7 +75,7 @@ BasicAnalysisBuilder::BasicAnalysisBuilder(ModelRegistry& context) theDomain(context.getDomain()), theHandler(nullptr), theNumberer(nullptr), - theAnalysisModel(new AnalysisModel()), + theAnalysisModel(new AnalysisModel(*context.getDomain())), theAlgorithm(nullptr), theSOE(nullptr), theEigenSOE(nullptr), @@ -138,7 +138,7 @@ BasicAnalysisBuilder::wipe() } if (theAnalysisModel != nullptr) { delete theAnalysisModel; - theAnalysisModel = new AnalysisModel(); + theAnalysisModel = new AnalysisModel(*context.getDomain()); } } @@ -231,7 +231,7 @@ BasicAnalysisBuilder::number() { theAnalysisModel->clearAll(); - if (theHandler != nullptr) { + if (theHandler != nullptr && theNumberer != nullptr) { // Create FE_Element and DOF_Group objects // and add to the AnalysisModel. @@ -336,7 +336,8 @@ BasicAnalysisBuilder::analyze(int num_steps, double size_steps, int flag) } default: - opserr << OpenSees::PromptValueError << "No Analysis type has been specified \n"; + opserr << OpenSees::PromptValueError + << "No Analysis type has been specified \n"; return -1; } @@ -986,7 +987,7 @@ BasicAnalysisBuilder::eigen(int numMode, elePtr->zeroTangent(); elePtr->addMtoTang(1.0); if (theEigenSOE->addM(elePtr->getTangent(0), elePtr->getID()) < 0) { - opserr << "WARNING BasicAnalysisBuilder::eigen -"; + opserr << G3_WARN_PROMPT << "eigen -"; opserr << " failed in addA for ID " << elePtr->getID() << "\n"; result = -2; } From e21f911dc500e463b5717f3e7482d8b84a319c51 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:28:01 -0800 Subject: [PATCH 125/161] Update BasicAnalysisBuilder.h --- SRC/runtime/runtime/BasicAnalysisBuilder.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/SRC/runtime/runtime/BasicAnalysisBuilder.h b/SRC/runtime/runtime/BasicAnalysisBuilder.h index 4962fb06cb..fc9bc4cc8d 100644 --- a/SRC/runtime/runtime/BasicAnalysisBuilder.h +++ b/SRC/runtime/runtime/BasicAnalysisBuilder.h @@ -48,7 +48,11 @@ class EigenSOE; class StaticIntegrator; class TransientIntegrator; class ConvergenceTest; +namespace OpenSees { +class LoadCase; +} +#include class BasicAnalysisBuilder { @@ -92,8 +96,12 @@ class BasicAnalysisBuilder Domain* getDomain(); + AnalysisModel& getAnalysisModel() { + return *theAnalysisModel; + } int initialize(); + int domainChanged(); int setStaticAnalysis(); int setTransientAnalysis(); @@ -103,7 +111,6 @@ class BasicAnalysisBuilder int getNumEigen() {return numEigen;} int formUnbalance(); - int domainChanged(); // Performing analysis int analyze(int num_steps, double size_steps, int flag=Increment|Iterate|Commit); @@ -121,7 +128,9 @@ class BasicAnalysisBuilder int setGradientType(int flag); void wipe(); - + int setLoadCase(std::string& name); + int newLoadCase(std::string& name); + enum CurrentAnalysis CurrentAnalysisFlag = EMPTY_ANALYSIS; private: From c13be37d6d48f0f4ddb52def86e39020196f823d Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:29:32 -0800 Subject: [PATCH 126/161] Remove PartitionedModelBuilder references from FEM_ObjectBroker Eliminated the getPtrNewPartitionedModelBuilder method and related class forward declaration from FEM_ObjectBroker. This simplifies the interface and implementation, likely because PartitionedModelBuilder is no longer needed or supported. --- SRC/actor/objectBroker/FEM_ObjectBroker.cpp | 8 -------- SRC/actor/objectBroker/FEM_ObjectBroker.h | 7 +------ 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/SRC/actor/objectBroker/FEM_ObjectBroker.cpp b/SRC/actor/objectBroker/FEM_ObjectBroker.cpp index c7c16d429b..c75e3b5b97 100644 --- a/SRC/actor/objectBroker/FEM_ObjectBroker.cpp +++ b/SRC/actor/objectBroker/FEM_ObjectBroker.cpp @@ -56,14 +56,6 @@ FEM_ObjectBroker::getNewActor(int classTag, Channel *theChannel) } -PartitionedModelBuilder * -FEM_ObjectBroker::getPtrNewPartitionedModelBuilder(Subdomain &theSubdomain, - int classTag) -{ - return 0; -} - - GraphNumberer * FEM_ObjectBroker::getPtrNewGraphNumberer(int classTag) { diff --git a/SRC/actor/objectBroker/FEM_ObjectBroker.h b/SRC/actor/objectBroker/FEM_ObjectBroker.h index d8a3147ea5..b6f9c97b55 100644 --- a/SRC/actor/objectBroker/FEM_ObjectBroker.h +++ b/SRC/actor/objectBroker/FEM_ObjectBroker.h @@ -65,7 +65,6 @@ class LinearSOE; class EigenSOE; class DomainSolver; class DomainDecompositionAnalysis; -class PartitionedModelBuilder; class CrdTransf; class Damping; @@ -101,11 +100,7 @@ class FEM_ObjectBroker FEM_ObjectBroker(); virtual ~FEM_ObjectBroker(); - virtual Actor*getNewActor(int classTag, Channel *theChannel); - - virtual PartitionedModelBuilder * - getPtrNewPartitionedModelBuilder(Subdomain &theSub, - int classTag); + virtual Actor*getNewActor(int classTag, Channel *); virtual GraphNumberer *getPtrNewGraphNumberer(int classTag); From 3e6be7b4995c54507bd9fba7a2982fab71b5e40b Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sat, 24 Jan 2026 04:21:39 -0800 Subject: [PATCH 127/161] Update J2ThreeDimensional.h --- SRC/material/plastic/J2ThreeDimensional.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/SRC/material/plastic/J2ThreeDimensional.h b/SRC/material/plastic/J2ThreeDimensional.h index 6436a0ba61..11186896d0 100644 --- a/SRC/material/plastic/J2ThreeDimensional.h +++ b/SRC/material/plastic/J2ThreeDimensional.h @@ -83,14 +83,10 @@ class J2ThreeDimensional : public J2Plasticity { ~J2ThreeDimensional(); const char* - getClassType() const - { - return "J2ThreeDimensional"; - } + getClassType() const {return "J2ThreeDimensional";} NDMaterial* getCopy(); - //send back type of material const char* getType() const; int getOrder() const; @@ -98,10 +94,8 @@ class J2ThreeDimensional : public J2Plasticity { //get the strain and integrate plasticity equations int setTrialStrain(const Vector& strain_from_element); - //unused trial strain functions - int setTrialStrain(const Vector& v, const Vector& r); + // unused trial strain functions int setTrialStrainIncr(const Vector& v); - int setTrialStrainIncr(const Vector& v, const Vector& r); const Vector& getStrain(); From 220999a04d7ee573e3b28c334c9c2cc38ce16d6e Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 25 Jan 2026 01:22:53 -0800 Subject: [PATCH 128/161] Refactor ForceFrame3d for clarity and efficiency Refactored ForceFrame3d to improve code clarity, efficiency, and maintainability. Key changes include consolidating and simplifying the calculation of flexibility matrices, using references to avoid unnecessary copies, introducing consistent use of ForceInterpolation, and adjusting subdivision and convergence logic. Also updated transform and push operations to use the Transform enum directly, and removed redundant or commented code blocks. --- SRC/element/Frame/ForceFrame3d.h | 4 +- SRC/element/Frame/ForceFrame3d.tpp | 250 +++++++++++------------------ 2 files changed, 95 insertions(+), 159 deletions(-) diff --git a/SRC/element/Frame/ForceFrame3d.h b/SRC/element/Frame/ForceFrame3d.h index d1658cf50f..ffd601bd0c 100644 --- a/SRC/element/Frame/ForceFrame3d.h +++ b/SRC/element/Frame/ForceFrame3d.h @@ -58,8 +58,8 @@ class ForceFrame3d: public BasicFrame3d, NDF = 6+nwm, ndm = 3, // dimension of the problem (3D) NEN = 2, // number of element nodes - NBV = 6+nwm*2, // number of element DOFs in the basic system - max_subdivision= 10; + NBV = 6+nwm*2; // number of element DOFs in the basic system + public: const char * diff --git a/SRC/element/Frame/ForceFrame3d.tpp b/SRC/element/Frame/ForceFrame3d.tpp index 685d6f9a41..5449f86dda 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -434,8 +434,9 @@ ForceFrame3d::getInitialStiff() // calculate element stiffness matrix ALWAYS_STATIC MatrixND K_init; - if (Cholesky(F_init).invert(K_init) < 0) - opserr << "ForceFrame3d: Failed to invert flexibility"; + if (Cholesky(F_init).invert(K_init) < 0) { + opserr << "ForceFrame3d: Failed to invert flexibility\n"; + } Matrix wrapper(K_init); Ki = new Matrix(basic_system->getInitialGlobalStiffMatrix(wrapper)); @@ -495,10 +496,9 @@ public: return Tb; } - MatrixND + const MatrixND & b(double xL, double L) { - MatrixND B{}; for (int i = 0; i < nsr; i++) { switch (scheme[i]) { case FrameStress::N: @@ -622,6 +622,8 @@ public: } } } +private: + MatrixND B; }; } @@ -658,31 +660,21 @@ ForceFrame3d::update01() double L = basic_system->getInitialLength(); - - VectorND dv_total{}, dv_trial{}; - VectorND dv{}; + VectorND dv_total{}; { const Vector& dvb = basic_system->getBasicIncrDeltaDisp(); for (int i=0; i<6; i++) { - dv[i] = dvb[i]; + dv_total[i] = dvb[i]; } } - // - // - // - if ((state_flag != 0) && - (dv.norm() <= DBL_EPSILON) && - (eleLoads.size()==0) && - (frame_loads.size()==0)) - return 0; // Basic DOFs - VectorND Dv{}; + VectorND v0{}; { const Vector& v = basic_system->getBasicTrialDisp(); for (int i=0; i<6; i++) - Dv[i] = v[i] - dv[i]; + v0[i] = v[i] - dv_total[i]; } { @@ -692,16 +684,29 @@ ForceFrame3d::update01() for (int j=0; j<2; j++) { const Vector& uj = nodes[j]->getTrialDisp(); const Vector& duj = nodes[j]->getIncrDeltaDisp(); - dv[NNW+i*nwm+j] = duj[6+i]; - Dv[NNW+i*nwm+j] = uj[6+i] - duj[6+i]; + dv_total[NNW+i*nwm+j] = duj[6+i]; + v0[NNW+i*nwm+j] = uj[6+i] - duj[6+i]; + // dv_total[NNW+2*nwm+j] = duj[6+i]; + // Dv[NNW+2*nwm+j] = uj[6+i] - duj[6+i]; } } } - dv_total = dv; - dv_trial = dv_total; + // + // + // + if ((state_flag != 0) && + (dv_total.norm() <= DBL_EPSILON) && + (eleLoads.size()==0) && + (frame_loads.size()==0)) + return 0; - static constexpr double factor = 10.0; + + // VectorND dv = dv_total; + VectorND dv_trial = dv_total; + + static constexpr int max_subdivision= 5; + static constexpr double factor = 5.0; double dW; // section strain energy (work) norm double dW0 = 0.0; @@ -723,15 +728,17 @@ ForceFrame3d::update01() enum class Strategy { Newton, InitialIterations, InitialThenNewton }; - static constexpr std::array solve_strategy { - Strategy::Newton, // Strategy::InitialIterations, Strategy::InitialThenNewton + static constexpr std::array solve_strategy { + Strategy::Newton, Strategy::InitialThenNewton, Strategy::InitialIterations, }; - int subdivision = 1; + int subdivision = 0; bool converged = false; + ForceInterpolation interp{}; + const int nip = points.size(); - while ((converged == false) && (subdivision <= max_subdivision)) { + while ((converged == false) && (subdivision < max_subdivision)) { for (Strategy strategy : solve_strategy ) { @@ -747,15 +754,14 @@ ForceFrame3d::update01() if (state_flag == 2) continue; - VectorND q_trial = q_pres; + VectorND q_trial = q_pres; - q_trial += K_pres*dv; + q_trial += K_pres*dv_trial; for (int j = 0; j < numIters; j++) { VectorND vr{}; // element residual deformations MatrixND F{}; // element flexibility matrix - ForceInterpolation interp; // // Gauss Loop @@ -768,7 +774,7 @@ ForceFrame3d::update01() const MatrixND& Fs = Fs_trial[i]; const VectorND& sr = sr_trial[i]; FrameSection& section = *points[i].material; - const MatrixND b = interp.b(xL, L); + const MatrixND& b = interp.b(xL, L); // // a. Calculate section force by interpolation of q_trial @@ -860,7 +866,7 @@ ForceFrame3d::update01() // dv = Dv + dv_trial - vr - dv = Dv; + VectorND dv = v0; dv += dv_trial; dv -= vr; @@ -892,7 +898,7 @@ ForceFrame3d::update01() // Set the target displacement dv_total -= dv_trial; - Dv += dv_trial; + v0 += dv_trial; // Check if we have got to where we wanted if (dv_total.dot(dv_total) <= TOL_SUBDIV*TOL_SUBDIV) { @@ -903,7 +909,7 @@ ForceFrame3d::update01() // reset variables for start of next subdivision dv_trial = dv_total; // NOTE setting subdivide to 1 again maybe too much - subdivision = 1; + subdivision = 0; } // set K_pres, es and q_pres values @@ -920,6 +926,19 @@ ForceFrame3d::update01() points[k].Fs = Fs_trial[k]; points[k].sr = sr_trial[k]; } + // for (int k=0; k& B = interp.b(points[k].point, L); + // VectorND si = B * q_pres; + // // Add the particular solution + // if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) + // this->addLoadAtSection(si, points[k].point * L); + + // points[k].Fs = Fs_trial[k]; + // MatrixND& Fs = points[k].Fs; + // points[k].es = es_trial[k] + Fs*(si - sr_trial[k]); + // points[k].sr = si; + // // points[k].material->setTrialState(points[k].es); + // } // break out of j & l loops goto iterations_completed; @@ -928,7 +947,7 @@ ForceFrame3d::update01() // if we have failed to converge for all of our Newton schemes // - reduce step size by the factor specified - if (j == (numIters - 1)) {// } && (strategy == Strategy::InitialThenNewton)) { + if (j == (numIters - 1) && (strategy == solve_strategy.back())) { dv_trial /= factor; subdivision++; } @@ -943,27 +962,35 @@ iterations_completed: if (converged == false) [[unlikely]] { - opserr << "WARNING - ForceFrame3d failed internal state determination "; + opserr << "WARNING - ForceFrame3d failed state determination "; opserr << "for element " << this->getTag() << "; dW = " << dW - << ", dW0 = " << dW0 + << ", tol = " << tol + << ", sub = " << subdivision << "\n"; return -1; } else { - ForceInterpolation interp; - for (int k=0; k B = interp.b(points[k].point, L); - VectorND si = B * q_pres; - // Add the particular solution - if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) - this->addLoadAtSection(si, points[k].point * L); - - MatrixND& Fs = points[k].Fs; - points[k].es = points[k].es + Fs*(si - sr_trial[k]); - points[k].sr = si; + if (subdivision > 1) { + opserr << "ForceFrame3d::update - element " + << this->getTag() + << " required " << subdivision + << " subdivisions to converge\n"; } + + // ForceInterpolation interp{}; + // for (int k=0; k& B = interp.b(points[k].point, L); + // VectorND si = B * q_pres; + // // Add the particular solution + // if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) + // this->addLoadAtSection(si, points[k].point * L); + + // MatrixND& Fs = points[k].Fs; + // points[k].es = points[k].es + Fs*(si - sr_trial[k]); + // points[k].sr = si; + // } } state_flag = 1; @@ -1034,6 +1061,7 @@ ForceFrame3d::update02() dv_total = dv; dv_trial = dv_total; + static constexpr int max_subdivision= 5; static constexpr double factor = 10.0; double dW; // section strain energy (work) norm double dW0 = 0.0; @@ -1063,6 +1091,7 @@ ForceFrame3d::update02() int subdivision = 1; bool converged = false; + ForceInterpolation interp{}; const int nip = points.size(); while ((converged == false) && (subdivision <= max_subdivision)) { @@ -1088,7 +1117,6 @@ ForceFrame3d::update02() VectorND vr{}; // element residual deformations MatrixND F{}; // element flexibility matrix - ForceInterpolation interp; // // Gauss Loop @@ -1101,7 +1129,7 @@ ForceFrame3d::update02() const MatrixND& Fs = Fs_trial[i]; const VectorND& sr = sr_trial[i]; FrameSection& section = *points[i].material; - const MatrixND b = interp.b(xL, L); + const MatrixND& b = interp.b(xL, L); // // a. Calculate section force by interpolation of q_trial @@ -1309,8 +1337,8 @@ ForceFrame3d::getTangentStiff() #if BASIC_TRANSFORM == 1 - ForceInterpolation interp; - const static MatrixND<2*NDF,NBV> Tb = interp.reshape_matrix(); //FormBasicTransform(); + ForceInterpolation interp{}; + const MatrixND<2*NDF,NBV> Tb = interp.reshape_matrix(); //FormBasicTransform(); kl = Tb*kb * Tb.transpose(); pl = Tb * q_pres; #else @@ -1352,8 +1380,7 @@ ForceFrame3d::getTangentStiff() } #endif - using Operation = typename FrameTransform<2,NDF>::Operation; - basic_system->t.push(kl, pl, Operation::Total); + basic_system->t.push(kl, pl); this->addLoadTangent(kl, 1.0); return Wrapper; } @@ -1372,7 +1399,7 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d const MatrixND<3,2*NDF>& dR = basic_system->t.getRotationTangent(); MatrixND F{}; - ForceInterpolation interp; + ForceInterpolation interp{}; for (int i = 0; i < nip; i++) { double xL = points[i].point; @@ -1387,7 +1414,7 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d // F += (B' * Fs * dsp) * wi * L; // { - const MatrixND b = interp.b(xL, L); + const MatrixND& b = interp.b(xL, L); MatrixND FsB; FsB.zero(); for (auto load : frame_loads) { @@ -1436,8 +1463,7 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d } #endif // - using Operation = typename FrameTransform<2,NDF>::Operation; - basic_system->t.push(Kf, pf, Operation::Bubnov); + basic_system->t.push(Kf, pf, Transform::Bubnov); K += Kf; } @@ -1778,6 +1804,7 @@ ForceFrame3d::getInitialFlexibility(MatrixND& f double jsx = 1.0 / L; const int numSections = points.size(); + ForceInterpolation interp{}; for (int i = 0; i < numSections; i++) { double xL = points[i].point; @@ -1786,91 +1813,8 @@ ForceFrame3d::getInitialFlexibility(MatrixND& f const MatrixND fSec = points[i].material->template getFlexibility(State::Init); - static MatrixND FB; - FB.zero(); - for (int ii = 0; ii < nsr; ii++) { - switch (scheme[ii]) { - case FrameStress::N: - for (int jj = 0; jj < nsr; jj++) - FB(jj, 0) += fSec(jj, ii) * wtL; - break; - case FrameStress::Mz: - for (int jj = 0; jj < nsr; jj++) { - double tmp = fSec(jj, ii) * wtL; - FB(jj, 1) += xL1 * tmp; - FB(jj, 2) += xL * tmp; - } - break; - case FrameStress::Vy: - for (int jj = 0; jj < nsr; jj++) { - double tmp = jsx * fSec(jj, ii) * wtL; - FB(jj, 1) += tmp; - FB(jj, 2) += tmp; - } - break; - case FrameStress::My: - for (int jj = 0; jj < nsr; jj++) { - double tmp = fSec(jj, ii) * wtL; - FB(jj, 3) += xL1 * tmp; - FB(jj, 4) += xL * tmp; - } - break; - case FrameStress::Vz: - for (int jj = 0; jj < nsr; jj++) { - double tmp = jsx * fSec(jj, ii) * wtL; - FB(jj, 3) += tmp; - FB(jj, 4) += tmp; - } - break; - case FrameStress::T: - for (int jj = 0; jj < nsr; jj++) - FB(jj, 5) += fSec(jj, ii) * wtL; - break; - default: break; - } - } - // - for (int ii = 0; ii < nsr; ii++) { - switch (scheme[ii]) { - case FrameStress::N: - for (int jj = 0; jj < NBV; jj++) - fe(0, jj) += FB(ii, jj); - break; - case FrameStress::Mz: - for (int jj = 0; jj < NBV; jj++) { - double tmp = FB(ii, jj); - fe(1, jj) += xL1 * tmp; - fe(2, jj) += xL * tmp; - } - break; - case FrameStress::Vy: - for (int jj = 0; jj < NBV; jj++) { - double tmp = jsx * FB(ii, jj); - fe(1, jj) += tmp; - fe(2, jj) += tmp; - } - break; - case FrameStress::My: - for (int jj = 0; jj < NBV; jj++) { - double tmp = FB(ii, jj); - fe(3, jj) += xL1 * tmp; - fe(4, jj) += xL * tmp; - } - break; - case FrameStress::Vz: - for (int jj = 0; jj < NBV; jj++) { - double tmp = jsx * FB(ii, jj); - fe(3, jj) += tmp; - fe(4, jj) += tmp; - } - break; - case FrameStress::T: - for (int jj = 0; jj < NBV; jj++) - fe(5, jj) += FB(ii, jj); - break; - default: break; - } - } + const MatrixND& b = interp.b(xL, L); + fe += b.transpose() * fSec * b * wtL; } return 0; } @@ -3099,8 +3043,8 @@ ForceFrame3d::getResistingForce() static VectorND pl{}; #if BASIC_TRANSFORM == 1 - ForceInterpolation interp; - const static MatrixND<2*NDF,NBV> Tb = interp.reshape_matrix(); + ForceInterpolation interp{}; + const MatrixND<2*NDF,NBV> Tb = interp.reshape_matrix(); pl = Tb * q_pres; #else pl.zero(); @@ -3138,25 +3082,17 @@ ForceFrame3d::getResistingForce() // 3. Push to global system #if 0 - thread_local VectorND pg; - thread_local Vector wrapper(pg); - - pg = basic_system->t.pushResponse(pl); - pg += basic_system->linear.pushResponse(pf); -#elif 0 - using Operation = typename FrameTransform<2,NDF>::Operation; thread_local Vector wrapper(pl); - basic_system->t.push(pl, Operation::Total); + basic_system->t.push(pl, Transform::Total); if (pf.norm() > 0) [[unlikely]] { - basic_system->linear.push(pf, Operation::Total); + basic_system->linear.push(pf, Transform::Total); pl += pf; } #else - using Operation = typename FrameTransform<2,NDF>::Operation; thread_local Vector wrapper(pl); - basic_system->t.push(pl, Operation::Total); + basic_system->t.push(pl, Transform::Total); if (pf.norm() > 0) [[unlikely]] { - basic_system->t.push(pf, Operation::Rotation); + basic_system->t.push(pf, Transform::Total&~(Transform::Adjoint|Transform::Logarithm));//Transform::Rotation);//|Transform::Tangent); pl += pf; } #endif From efce819353e4b5d4931a6ca58e4d381da594d657 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:12:04 -0800 Subject: [PATCH 129/161] Update J2Plasticity.h --- SRC/material/plastic/J2Plasticity.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/SRC/material/plastic/J2Plasticity.h b/SRC/material/plastic/J2Plasticity.h index 3d94cef371..cb6d75b77a 100644 --- a/SRC/material/plastic/J2Plasticity.h +++ b/SRC/material/plastic/J2Plasticity.h @@ -52,6 +52,7 @@ #include #include #include +#include "hardening/FlowStress.h" namespace OpenSees { class J2Plasticity : public NDMaterial { @@ -74,20 +75,20 @@ class J2Plasticity : public NDMaterial { virtual ~J2Plasticity(); - virtual NDMaterial* getCopy(const char* type); + NDMaterial* getCopy(const char* type) override; + NDMaterial* getCopy() override; + const char* getType() const override; + int getOrder() const override; // Material State - virtual int commitState(); - virtual int revertToLastCommit(); - virtual int revertToStart(); - virtual int setTrialStrain(const Vector &v) { + int commitState() override; + int revertToLastCommit() override; + int revertToStart() override; + int setTrialStrain(const Vector &v) override { assert(false); return -1; } - virtual NDMaterial* getCopy(); - virtual const char* getType() const; - virtual int getOrder() const; double getRho() @@ -95,8 +96,8 @@ class J2Plasticity : public NDMaterial { return rho; } - virtual int setParameter(const char** argv, int argc, Parameter& param); - virtual int updateParameter(int parameterID, Information& info); + int setParameter(const char** argv, int argc, Parameter&) override; + int updateParameter(int parameterID, Information&) override; virtual int activateParameter(int paramID); // MovableObject From 54cba98597b913368a6e60eedc82f9c385807bd3 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:16:50 -0800 Subject: [PATCH 130/161] Create FlowStress.h --- SRC/material/plastic/hardening/FlowStress.h | 70 +++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 SRC/material/plastic/hardening/FlowStress.h diff --git a/SRC/material/plastic/hardening/FlowStress.h b/SRC/material/plastic/hardening/FlowStress.h new file mode 100644 index 0000000000..8683fabf45 --- /dev/null +++ b/SRC/material/plastic/hardening/FlowStress.h @@ -0,0 +1,70 @@ +#pragma once +#include +#include + +// template +// class MisesFlow { +// public: +// MisesFlow(double G, Resistance Y, Backstress X) +// : G(G), Y(Y), X(X) {} + +// std::tuple +// operator()(const VectorND<9>& s, const VectorND<9>& n, double lam) const { +// const auto [y, dy] = Y(lam); +// const auto [x, dx] = X(lam); +// return {f, df}; +// } +// private: +// double G; // shear modulus +// Resistance Y; // flow stress +// Backstress X; // kinematic hardening +// }; + +namespace Resistance { + +class Linear { +public: + Linear(double H) : H(H) {} + std::tuple operator()(double kappa) const { + return {H*kappa, H}; + } +private: + double R(double kappa) const { return H*kappa; } + double dR(double kappa) const { return H; } +private: + double H; // hardening modulus +}; + +class Voce { +public: + Voce(double b, double Q) : b(b), Q(Q) {} + std::tuple operator()(double kappa) const { + return {R(kappa), dR(kappa)}; + } +private: + double R(double kappa) const { return Q*(1.0 - std::exp(-b*kappa)); } + double dR(double kappa) const { return Q*b*std::exp(-b*kappa); } + +private: + double b; // hardening rate + double Q; // saturation stress +}; + + + +class Mroz { +public: + Mroz(double b, double Q, double n) : b(b), Q(Q), n(n) {} + std::tuple operator()(double kappa) const { + return {R(kappa), dR(kappa)}; + } +private: + double R(double kappa) const { return Q*(1.0 - std::exp(-b*std::pow(kappa, n))); } + double dR(double kappa) const { return Q*b*n*std::pow(kappa, n-1)*std::exp(-b*std::pow(kappa, n)); } +private: + double b; // hardening rate + double Q; // saturation stress + double n; // initial hardening exponent +}; + +} // namespace Flow \ No newline at end of file From 1a0d43dd178162a417b1d913a7e4a01739f9bc4d Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 26 Jan 2026 22:35:16 -0800 Subject: [PATCH 131/161] Update J2ThreeDimensional.cpp --- SRC/material/plastic/J2ThreeDimensional.cpp | 22 ++++++++------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/SRC/material/plastic/J2ThreeDimensional.cpp b/SRC/material/plastic/J2ThreeDimensional.cpp index ada6e94e1a..773347e9a8 100644 --- a/SRC/material/plastic/J2ThreeDimensional.cpp +++ b/SRC/material/plastic/J2ThreeDimensional.cpp @@ -81,16 +81,21 @@ J2ThreeDimensional::J2ThreeDimensional(int tag, double rho) : J2Plasticity(tag, ND_TAG_J2ThreeDimensional, K, G, yield0, yield_infty, d, H, viscosity, rho) { + } J2ThreeDimensional ::J2ThreeDimensional(int tag, double K, double G) : J2Plasticity(tag, ND_TAG_J2ThreeDimensional, K, G) { + } -J2ThreeDimensional::~J2ThreeDimensional() {} +J2ThreeDimensional::~J2ThreeDimensional() +{ + +} NDMaterial* @@ -104,14 +109,14 @@ J2ThreeDimensional::getCopy() const char* -J2ThreeDimensional ::getType() const +J2ThreeDimensional::getType() const { return "ThreeDimensional"; } int -J2ThreeDimensional ::getOrder() const +J2ThreeDimensional::getOrder() const { return 6; } @@ -141,11 +146,6 @@ J2ThreeDimensional ::setTrialStrain(const Vector& strain_from_element) //unused trial strain functions -int -J2ThreeDimensional::setTrialStrain(const Vector& v, const Vector& r) -{ - return this->setTrialStrain(v); -} int J2ThreeDimensional::setTrialStrainIncr(const Vector& v) @@ -161,12 +161,6 @@ J2ThreeDimensional::setTrialStrainIncr(const Vector& v) return this->setTrialStrain(newStrain); } -int -J2ThreeDimensional::setTrialStrainIncr(const Vector& v, const Vector& r) -{ - return this->setTrialStrainIncr(v); -} - const Vector& J2ThreeDimensional::getStrain() From c7219e430f92f1dd0a500d3419b87c96c8e54206 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:15:34 -0800 Subject: [PATCH 132/161] Update J2Plasticity.cpp --- SRC/material/plastic/J2Plasticity.cpp | 57 ++++++++++++--------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/SRC/material/plastic/J2Plasticity.cpp b/SRC/material/plastic/J2Plasticity.cpp index c915f4c447..6d55cd5ee2 100644 --- a/SRC/material/plastic/J2Plasticity.cpp +++ b/SRC/material/plastic/J2Plasticity.cpp @@ -52,7 +52,7 @@ #include #include #include // IbunI, IIdev - +#include "hardening/FlowStress.h" extern double ops_Dt; @@ -236,6 +236,7 @@ J2Plasticity::plastic_integrator() { double dt = ops_Dt; const double tolerance = 1.0e-10 * sigma_0; + const double G = shear; static Matrix dev_stress(3, 3); // deviatoric stress @@ -243,7 +244,6 @@ J2Plasticity::plastic_integrator() double NbunN; // normal bun normal double inv_norm_tau = 0.0; - double tang = 0.0; constexpr static int max_iterations = 25; @@ -259,10 +259,10 @@ J2Plasticity::plastic_integrator() // compute the trial deviatoric stresses - // dev_stress = (2.0*shear) * ( dev_strain - epsilon_p_n ) ; + // dev_stress = (2.0*G) * ( dev_strain - epsilon_p_n ) ; dev_stress = dev_strain; dev_stress -= epsilon_p_n; - dev_stress *= 2.0 * shear; + dev_stress *= 2.0*G; double norm_tau = 0.0; // norm of deviatoric stress @@ -284,58 +284,53 @@ J2Plasticity::plastic_integrator() double phi = norm_tau - root23 * q(xi_n); - double c1 = 0.0; - double c2 = 0.0; - double c3 = 0.0; - double theta_inv = 0.0; - double gamma = 0.0; + double Dlam = 0.0; if (phi > 0.0) { // plastic // solve for gamma - double resid = 1.0; + double g = 1.0; int iteration_counter = 0; - while (fabs(resid) > tolerance) { + while (std::fabs(g) > tolerance) { - resid = norm_tau - (2.0 * shear) * gamma - root23 * q(xi_n + root23 * gamma); + g = norm_tau - (2.0*G)*Dlam - root23*q(xi_n + root23*Dlam); if (eta > 0.0 && dt > 0.0) - resid -= (eta / dt) * gamma; + g -= (eta / dt) * Dlam; - tang = -(2.0 * shear) - 2. / 3. * qprime(xi_n + root23 * gamma); + double Dg = -(2.0*G) - (2./3.)*qprime(xi_n + root23*Dlam); if (eta > 0.0 && dt > 0.0) - tang -= (eta / dt); + Dg -= (eta / dt); - gamma -= (resid / tang); + Dlam -= (g / Dg); iteration_counter++; if (iteration_counter > max_iterations) { opserr << "More than " << max_iterations; opserr << " iterations in J2-plasticity. " - << "residual is " << fabs(resid) << " > " << tolerance << "\n"; + << "residual is " << std::fabs(g) << " > " << tolerance << "\n"; return -1; } } - gamma *= 1.0 - 1e-08; + Dlam *= 1.0 - 1e-08; // update plastic internal variables - epsilon_p_nplus1 = epsilon_p_n + gamma * normal; - - xi_nplus1 = xi_n + root23 * gamma; + epsilon_p_nplus1 = epsilon_p_n + Dlam*normal; + xi_nplus1 = xi_n + root23*Dlam; // recompute deviatoric stresses - dev_stress = (2.0 * shear) * (dev_strain - epsilon_p_nplus1); + dev_stress = (2.0*G) * (dev_strain - epsilon_p_nplus1); // compute the terms for plastic part of tangent - double theta = (2.0 * shear) + 2./3. * qprime(xi_nplus1); + double theta = (2.0*G) + (2./3.)*qprime(xi_nplus1); if (eta > 0.0 && dt > 0.0) theta += (eta / dt); @@ -353,7 +348,7 @@ J2Plasticity::plastic_integrator() epsilon_p_nplus1 = epsilon_p_n; xi_nplus1 = xi_n; - gamma = 0.0; + Dlam = 0.0; theta_inv = 0.0; } // end if phi > 0 @@ -367,17 +362,17 @@ J2Plasticity::plastic_integrator() // compute the tangent - c1 = -4.0 * shear * shear; - c2 = c1 * theta_inv; - c3 = c1 * gamma * inv_norm_tau; + double c1 = -4.0 * shear * shear; + double c2 = c1 * theta_inv; + double c3 = c1 * Dlam * inv_norm_tau; for (int ii = 0; ii < 6; ii++) { for (int jj = 0; jj < 6; jj++) { int i, j, k, l; - index_map(ii, i, j); - index_map(jj, k, l); + this->index_map(ii, i, j); + this->index_map(jj, k, l); NbunN = normal(i, j) * normal(k, l); @@ -431,7 +426,7 @@ J2Plasticity::doInitialTangent() double J2Plasticity::q(double xi) { - return Hard*xi + sigma_infty + (sigma_0 - sigma_infty) * exp(-delta * xi); + return Hard*xi + sigma_infty + (sigma_0 - sigma_infty) * std::exp(-delta * xi); } @@ -439,7 +434,7 @@ J2Plasticity::q(double xi) double J2Plasticity::qprime(double xi) { - return (sigma_0 - sigma_infty) * (-delta) * exp(-delta * xi) + Hard; + return (sigma_0 - sigma_infty) * (-delta)*std::exp(-delta * xi) + Hard; } From ff89903156377cb2acfd0ff23439169c62634fdb Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:37:28 -0800 Subject: [PATCH 133/161] Refactor frame transformation operations to use bitmask enums Replaces the Operation enum class with a bitmask-based Transform::Action enum for frame transformation operations, enabling more flexible and composable operation flags. Updates all relevant method signatures and logic to use integer-based flags, and refactors push/pull logic in frame transformation classes accordingly. Also includes minor type and const-correctness improvements, and unifies rotation Jacobian interfaces for isometry classes. --- .../Frame/BasicFrameTransf.h | 1 - .../Frame/BasicFrameTransf.tpp | 6 +- .../Frame/EuclidFrameTransf.h | 10 +- .../Frame/EuclidFrameTransf.tpp | 141 +++++++++------- .../Frame/FrameTransform.h | 78 +++++++-- .../Frame/Isometry/BattiniIsometry.h | 41 ++++- .../Frame/Isometry/CrisfieldIsometry.h | 6 +- .../Frame/Isometry/EuclidIsometry.h | 16 +- .../Frame/Isometry/LinearIsometry.h | 127 +++++++++++++-- .../Frame/Isometry/RankinIsometry.h | 67 ++++---- .../Frame/LinearFrameTransf.h | 5 +- .../Frame/LinearFrameTransf.tpp | 51 +++--- .../Frame/PDeltaFrameTransf3d.h | 5 +- .../Frame/PDeltaFrameTransf3d.tpp | 64 +++++--- .../Frame/SouzaFrameTransf.h | 5 +- .../Frame/SouzaFrameTransf.tpp | 17 +- SRC/element/Frame/ForceFrame3d.h | 2 + SRC/element/Frame/ForceFrame3d.tpp | 152 +++++++++++------- SRC/element/Frame/MixedFrame3d.cpp | 6 - SRC/element/Frame/PrismFrame3d.cpp | 6 +- SRC/element/Frame/PrismFrame3d02.cpp | 4 +- 21 files changed, 531 insertions(+), 279 deletions(-) diff --git a/SRC/coordTransformation/Frame/BasicFrameTransf.h b/SRC/coordTransformation/Frame/BasicFrameTransf.h index c706aad48c..1f2005c2e9 100644 --- a/SRC/coordTransformation/Frame/BasicFrameTransf.h +++ b/SRC/coordTransformation/Frame/BasicFrameTransf.h @@ -97,7 +97,6 @@ class BasicFrameTransf3d: public CrdTransf LinearFrameTransf<2,ndf> linear; private: - using Operation = typename FrameTransform<2,ndf>::Operation; constexpr static int NBV = 6; constexpr static int NDF = ndf; enum : int { diff --git a/SRC/coordTransformation/Frame/BasicFrameTransf.tpp b/SRC/coordTransformation/Frame/BasicFrameTransf.tpp index 8ce818b43d..6553554ed9 100644 --- a/SRC/coordTransformation/Frame/BasicFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/BasicFrameTransf.tpp @@ -203,7 +203,7 @@ BasicFrameTransf3d::getGlobalResistingForce(const Vector &q_pres, const Vec } // - t.push(pl, Operation::Total); + t.push(pl, Transform::Total); #if 0 if (p0.Norm() > 0.0) [[unlikely]] { @@ -215,7 +215,7 @@ BasicFrameTransf3d::getGlobalResistingForce(const Vector &q_pres, const Vec pf[0*NDF + 2] = p0[3]; pf[1*NDF + 1] = p0[2]; pf[1*NDF + 2] = p0[4]; - linear.push(pf, Operation::Total); + linear.push(pf, Transform::Total); pl += pf; } #endif @@ -323,7 +323,7 @@ BasicFrameTransf3d::getGlobalStiffMatrix(const Matrix &kb, const Vector &q_ kl(0*NDF+3, i) = kl(i, 0*NDF+3) = i==0? kl(NDF+3, NDF+0): (i==3? kl(NDF+3, NDF+3) : -kl( NDF+3, i)); }); #endif - t.push(kl, pl, Operation::Total); + t.push(kl, pl, Transform::Total); return Wrapper; } diff --git a/SRC/coordTransformation/Frame/EuclidFrameTransf.h b/SRC/coordTransformation/Frame/EuclidFrameTransf.h index f4d6485dcd..3fd6b038a2 100644 --- a/SRC/coordTransformation/Frame/EuclidFrameTransf.h +++ b/SRC/coordTransformation/Frame/EuclidFrameTransf.h @@ -54,7 +54,6 @@ class EuclidFrameTransf: public FrameTransform ~EuclidFrameTransf(); - using Operation = typename FrameTransform::Operation; const char *getClassType() const {return "EuclidFrameTransf";} @@ -81,22 +80,23 @@ class EuclidFrameTransf: public FrameTransform return basis.getRotation(); } - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; - + int push(VectorND&pl, int op) final; + int push(MatrixND& kl, const VectorND& pl, int op) final; + MatrixND<3,ndf*nn> getRotationTangent() final { MatrixND<3,ndf*nn> dR{}; for (int i=0; i& dp, VectorND& pl) final; // TaggedObject void Print(OPS_Stream &s, int flag) final; diff --git a/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp b/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp index 6d69d18f24..9c9e6b5b68 100644 --- a/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/EuclidFrameTransf.tpp @@ -218,7 +218,7 @@ EuclidFrameTransf::getNodePosition(int node) Vector3D u = this->pullPosition<&Node::getTrialDisp>(node); u -= basis.getPosition(); const Vector& Xn = nodes[node]->getCrds(); - Vector3D X3 {Xn[0], Xn[1], Xn[2]}; + const Vector3D X3 {Xn[0], Xn[1], Xn[2]}; u += basis.getRotationDelta()^X3; return u; } @@ -245,7 +245,7 @@ EuclidFrameTransf::getStateVariation() } } - const Matrix3D R = basis.getRotation(); + const Matrix3D& R = basis.getRotation(); // -) Global Offsets // Do ui -= ri x wi @@ -313,21 +313,22 @@ EuclidFrameTransf::getStateVariation() template // VectorND int -EuclidFrameTransf::push(VectorND&p, Operation op) +EuclidFrameTransf::push(VectorND&p, int op) { VectorND& pa = p; - if (op != Operation::Rotation) { - - // 3) Element Parameters - if (1) { // !(offset_flags & LogIter)) { - for (int i=0; i::push(VectorND&p, Operation op) pa.template assemble<6>(i*ndf, basis.getRotationGradient(i)^m, -1.0); } - if (op == Operation::Isometry) - return 0; + // if (op == Transform::Isometry) + // return 0; // 2.2) Rotation - // pa = this->FrameTransform::pushConstant(pa); - Matrix3D R = basis.getRotation(); - for (int i=0; i int EuclidFrameTransf::push(MatrixND&kb, const VectorND& pb, - Operation op) + int op) { VectorND p = pb; + for (int i=0; i Kb = kb; // 1) Element parameters - if (op != Operation::Rotation) {// && (op != Operation::Bubnov)) {//!(offset_flags & LogIter)) { + if (op & Transform::Logarithm) { + // if (op != Transform::Rotation) {// && (op != Transform::Bubnov)) {//!(offset_flags & LogIter)) { for (int i=0; i::push(MatrixND&kb, } } } + // // 2) Isometry // // 2.2) Projection // 2.2.1) Kl = A ^ k * A - MatrixND& Kl = kb; - const MatrixND A = getProjection(); - if (op == Operation::Bubnov) - Kl = A^kb; - else - Kl.addMatrixTripleProduct(0, A, Kb, 1); + // if ((op & Transform::Adjoint) || (op & Transform::Tangent)) + { + MatrixND& Kl = kb; + const MatrixND A = getProjection(); + if (op == Transform::Bubnov) + Kl = A^kb; + else + Kl.addMatrixTripleProduct(0, A, Kb, 1); - const VectorND Ap = A^p; + const VectorND Ap = A^p; - // 2.2.2) Kl += Kw * A - Kb.zero(); - VectorND<12> qwx{}; - for (int i=0; i qwx{}; + for (int i=0; i Kw = basis.getRotationJacobian(qwx); - Kb.assemble(Kw.template extract<0, 6, 0, 6>(), 0, 0, 1.0); - Kb.assemble(Kw.template extract<0, 6, 6,12>(), 0, ndf, 1.0); - Kb.assemble(Kw.template extract<6,12, 0, 6>(), ndf, 0, 1.0); - Kb.assemble(Kw.template extract<6,12, 6,12>(), ndf, ndf, 1.0); - Kl.addMatrixProduct(Kb, A, 1.0); + if (op != Transform::Bubnov) [[likely]] { + MatrixND Kb{}; + Kb.zero(); + if constexpr (ndf == 6) { + Kl.addMatrixProduct(basis.getRotationJacobian(qwx), A, 1.0); + } + else { + const MatrixND<6*nn,6*nn> Kw = basis.getRotationJacobian(qwx); + Kb.assemble(Kw.template extract<0, 6, 0, 6>(), 0, 0, 1.0); + Kb.assemble(Kw.template extract<0, 6, 6,12>(), 0, ndf, 1.0); + Kb.assemble(Kw.template extract<6,12, 0, 6>(), ndf, 0, 1.0); + Kb.assemble(Kw.template extract<6,12, 6,12>(), ndf, ndf, 1.0); + Kl.addMatrixProduct(Kb, A, 1.0); + } + } } - } - // - // Kl += -W'*Pn'*A - Pnm * W - // - Kb.zero(); - for (int j=0; j Gj = basis.getRotationGradient(j); - for (int i=0; i Kb{}; + Kb.zero(); + for (int j=0; j Gj = basis.getRotationGradient(j); + for (int i=0; i::pushRotation(Kl, basis.getRotation()); + FrameTransform::pushRotation(kb, basis.getRotation()); return 0; } diff --git a/SRC/coordTransformation/Frame/FrameTransform.h b/SRC/coordTransformation/Frame/FrameTransform.h index 5b748caef9..47f57f92f3 100644 --- a/SRC/coordTransformation/Frame/FrameTransform.h +++ b/SRC/coordTransformation/Frame/FrameTransform.h @@ -48,23 +48,32 @@ enum { namespace OpenSees { +namespace Transform { +enum Action : int { + None = 0, + + Logarithm = 1u << 0, + // LocalOffset = 1u << 1, + Isometry = 1u << 2, + Rotation = 1u << 3, + Offset = 1u << 4, + Bubnov = 1u << 6, + Adjoint = 1u << 7, + Tangent = 1u << 8, + Total = (1u<<0) + | (1u<<1) + | (1u<<2) | (1u<<3) | (1u<<4) | (1u<<5) + | (1u<<6)| (1u<<7) + | (1u<<8) +}; +} + template class FrameTransform : public TaggedObject { public: explicit FrameTransform(int tag) : TaggedObject(tag) {} - enum class Operation { - Total = 0, - Logarithm = 1<<0, - LocalOffset = 1<<1, - Isometry = 1<<2, - Rotation, - GlobalOffset, - Exponential, - Bubnov - }; - virtual FrameTransform *getCopy() const =0; @@ -92,19 +101,21 @@ class FrameTransform : public TaggedObject //virtual VectorND getStateLogarithm() =0; // virtual VectorND getStateVariation() =0; // pull - virtual int push(VectorND&pl, Operation=0) =0; - virtual int push(MatrixND& kl, const VectorND& pl, Operation=0) =0; + virtual int push(VectorND&pl, int=Transform::Total) =0; + virtual int push(MatrixND& kl, + const VectorND& pl, + int=Transform::Total) =0; virtual VectorND pushResponse(VectorND&pl) final { VectorND pg{pl}; - push(pg, Operation::Total); + push(pg, Transform::Total); return pg; } virtual MatrixND pushResponse(MatrixND& kl, const VectorND& pl) final { MatrixND kg{kl}; - push(kg, pl, Operation::Total); + push(kg, pl, Transform::Total); return kg; } @@ -201,6 +212,43 @@ class FrameTransform : public TaggedObject MatrixND pushConstant(const MatrixND& kl); }; + +// namespace { +// constexpr std::uint32_t to_u(Transform op) noexcept { +// return static_cast(op); +// } + +// constexpr Transform op_from_u(std::uint32_t v) noexcept { +// return static_cast(v); +// } +// } + +// constexpr Transform operator|(Transform a, Transform b) noexcept { +// return op_from_u(to_u(a) | to_u(b)); +// } +// constexpr Transform operator&(Transform a, Transform b) noexcept { +// return op_from_u(to_u(a) & to_u(b)); +// } +// constexpr Transform operator^(Transform a, Transform b) noexcept { +// return op_from_u(to_u(a) ^ to_u(b)); +// } + +// constexpr Transform& operator|=(Transform& a, Transform b) noexcept { +// a = a | b; return a; +// } +// constexpr Transform& operator&=(Transform& a, Transform b) noexcept { +// a = a & b; return a; +// } +// constexpr Transform& operator^=(Transform& a, Transform b) noexcept { +// a = a ^ b; return a; +// } + +// // IMPORTANT: mask ~ so we don't turn on undefined bits. +// constexpr Transform operator~(Transform a) noexcept { +// constexpr std::uint32_t mask = to_u(Transform::Total); +// return op_from_u(mask & ~to_u(a)); +// } + } #include "FrameTransform.tpp" diff --git a/SRC/coordTransformation/Frame/Isometry/BattiniIsometry.h b/SRC/coordTransformation/Frame/Isometry/BattiniIsometry.h index c8e0cd66c3..6d3ed9d25f 100644 --- a/SRC/coordTransformation/Frame/Isometry/BattiniIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/BattiniIsometry.h @@ -77,7 +77,7 @@ class BattiniIsometry : public AlignedIsometry Vector3D e3 = e1.cross(q); e3 /= e3.norm(); - Vector3D e2 = e3.cross(e1); + const Vector3D e2 = e3.cross(e1); for (int i = 0; i < 3; i++) { R(i,0) = e1[i]; @@ -85,7 +85,7 @@ class BattiniIsometry : public AlignedIsometry R(i,2) = e3[i]; } - Vector3D Q = R^q; + const Vector3D Q = R^q; n = Q[0]/Q[1]; Vector3D QI = R^(RI*E2); @@ -120,10 +120,45 @@ class BattiniIsometry : public AlignedIsometry Gb(0,3) = n22/2.0; Gb(0,4) = -n12/2.0; } - + return Gb; } + + MatrixND + getRotationJacobian(const VectorND&pwx) final + { + if constexpr (nn != 2) { + return MatrixND {}; + } + else { + // TODO: Copied from RankinIsometry.h, need to adapt to Battini + MatrixND<3,12> NWL{}; + const double Ln = this->getLength(); + + constexpr static Matrix3D ex = Hat(Vector3D {1,0,0}); + + for (int i=0; i Gamma{}; + Gamma.template insert<0,0>(ex, 1.0); + Gamma(3,0) = -1.0; + Gamma.template insert<6,0>(ex, -1.0); + + MatrixND<12,3> Psi{}; + Psi.template insert<3,0>(Eye3, 1.0); + Psi.template insert<6,0>(ex, -Ln); + Psi.template insert<9,0>(Eye3, 1.0); + + const Matrix3D B = Gamma^Psi; + Matrix3D A; + B.invert(A); + return Gamma*A.transpose()*NWL; + } + } + private: Vector3D q {0,1,0}; double n = 0, diff --git a/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h b/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h index caabcf2078..9a21c79ac2 100644 --- a/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/CrisfieldIsometry.h @@ -198,9 +198,9 @@ class CrisfieldIsometry : public AlignedIsometry { return E; } - MatrixND<12,12> - getRotationJacobian(const VectorND<12>&pl) final { - MatrixND<12,12> dG{}; + MatrixND + getRotationJacobian(const VectorND&pl) final { + MatrixND dG{}; // TODO return dG; } diff --git a/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h b/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h index a906777612..fba459497f 100644 --- a/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h @@ -52,13 +52,13 @@ class Isometry virtual double getLength() const =0; - virtual Matrix3D getRotation() const =0; - virtual Vector3D getPosition() =0; + virtual const Matrix3D& getRotation() const =0; + virtual Vector3D getPosition() =0; virtual Vector3D getPositionVariation(int ndf, double* du) =0; virtual Vector3D getRotationVariation(int ndf, double* du) =0; - virtual MatrixND<12,12> getRotationJacobian(const VectorND<12>&pl) { - return MatrixND<12,12> {}; + virtual MatrixND<6*nn,6*nn> getRotationJacobian(const VectorND<6*nn>&pl) { + return MatrixND<6*nn,6*nn> {}; } virtual Matrix3D getRotationDelta() =0; virtual MatrixND<3,6> getRotationGradient(int node) =0; @@ -127,8 +127,8 @@ class AlignedIsometry : public Isometry virtual int update(std::array& nodes) final { - Matrix3D RI = MatrixFromVersor(nodes[0]->getTrialRotation()); - Matrix3D RJ = MatrixFromVersor(nodes[nn-1]->getTrialRotation()); + const Matrix3D RI = MatrixFromVersor(nodes[0]->getTrialRotation()); + const Matrix3D RJ = MatrixFromVersor(nodes[nn-1]->getTrialRotation()); Vector3D dx = dX; // @@ -153,7 +153,7 @@ class AlignedIsometry : public Isometry int - update(const Matrix3D& RI, const Matrix3D& RJ, const Vector3D& dx, std::array& nodes) final + update(const Matrix3D& RI, const Matrix3D& RJ, const Vector3D& dx, std::array& nodes) override { // Calculate the deformed length Ln = dx.norm(); @@ -200,7 +200,7 @@ class AlignedIsometry : public Isometry return Ln; } - Matrix3D + const Matrix3D& getRotation() const final { return R[pres]; } diff --git a/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h b/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h index af4703152b..98a2e71057 100644 --- a/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/LinearIsometry.h @@ -40,40 +40,143 @@ class Node; namespace OpenSees { template -class LinearIsometry : public AlignedIsometry +class LinearIsometry : public Isometry { public: LinearIsometry(const Vector3D& vecxz) - : AlignedIsometry(vecxz) + : vz(vecxz), c{}, R{}, dX{}, Xc{}, offsets{nullptr} { } - Matrix3D - update_basis(const Matrix3D&, const Matrix3D&, const Vector3D&) final + void + setOffsets(std::array* offsets) { + this->offsets = offsets; + } + + + virtual int + initialize(std::array& nodes) final + { + for (int i=0; igetTrialRotation(); + + const Vector &XI = nodes[ 0]->getCrds(); + const Vector &XJ = nodes[nn-1]->getCrds(); + + for (int i=0; i<3; i++) + dX[i] = XJ[i] - XI[i]; + + L = dX.norm(); + Vector3D e1 = dX/L; + + // + Vector3D e2 = vz.cross(e1); + + const double ynorm = e2.norm(); + + if (ynorm == 0.0) + return -1; + + e2 /= ynorm; + + Vector3D e3 = e1.cross(e2); + + e2 = e3.cross(e1); + + for (int i = 0; i < 3; i++) { + R[init](i,0) = e1[i]; + R[init](i,1) = e2[i]; + R[init](i,2) = e3[i]; + } + + const Vector& XC = nodes[ic]->getCrds(); + Xc = Vector3D {XC[0], XC[1], XC[2]}; + // Cbar + c[init] = R[init]^Xc; + + return 0; + } + + virtual + int update(std::array& nodes) final { + + return 0; + } + + int + update(const Matrix3D& RI, const Matrix3D& RJ, const Vector3D& dx, std::array& nodes) final { - return this->AlignedIsometry::R[init]; + return 0; } + MatrixND<3,6> getRotationGradient(int node) final { MatrixND<3,6> Gb{}; constexpr Matrix3D ix = Hat(Vector3D {1, 0, 0}); - const double Ln = this->getLength(); - if (node == 0) { - Gb.template insert<0,0>( ix, -1.0/Ln); + Gb.template insert<0,0>( ix, -1.0/L); Gb(0,3) = 0.5; } else if (node == nn-1) { - Gb.template insert<0,0>( ix, 1.0/Ln); - Gb(0,3) = 0.5; + Gb.template insert<0,0>( ix, 1.0/L); + Gb(0,3) = 0.5; } return Gb; } -private: - using AlignedIsometry::init; + + + virtual Vector3D + getRotationVariation(int ndf, double* du) final { + // psi_r = omega + return Vector3D {}; + } + + double + getLength() const override { + return L; + } + + const Matrix3D& + getRotation() const final { + return R[init]; + } + + Matrix3D + getInitialRotation() const { + return R[init]; + } + + virtual Matrix3D + getRotationDelta() final { + return Matrix3D{}; + } + + Vector3D + getLocation() { + return c[init]; + } + + Vector3D + getPosition() override { + // Return Delta c + return c[init] - (R[init]^Xc) ; + } + + Vector3D + getPositionVariation(int ndf, double* du) override { + return Vector3D {}; + } + +protected: + constexpr static int ic = 0; // std::floor(0.5*(nn+1)); + enum {pres, init}; double L; + Vector3D vz, dX, Xc; + Matrix3D R[2]; + Vector3D c[2]; + std::array* offsets = nullptr; // offsets }; } // namespace OpenSees \ No newline at end of file diff --git a/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h b/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h index f2e89acf3a..491310e4bd 100644 --- a/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h +++ b/SRC/coordTransformation/Frame/Isometry/RankinIsometry.h @@ -85,37 +85,44 @@ class RankinIsometry : public AlignedIsometry } - MatrixND<12,12> - getRotationJacobian(const VectorND<12>&pwx) final + MatrixND<6*nn,6*nn> + getRotationJacobian(const VectorND<6*nn>&pwx) final { - MatrixND<3,12> NWL{}; - const double Ln = this->getLength(); - - constexpr static Matrix3D ex = Hat(Vector3D {1,0,0}); - - for (int i=0; i= 202000L - static constinit MatrixND<12,3> Gamma = MakeGamma(); - static constinit MatrixND<12,3> Psi0 = MakePsi(); - MatrixND<12,3> Psi = Psi0; - Psi.template insert<6,0>(ex, -Ln); -#else - MatrixND<12,3> Gamma{}; - Gamma.template insert<0,0>(ex, 1.0); - Gamma(3,0) = -1.0; - Gamma.template insert<6,0>(ex, -1.0); - - MatrixND<12,3> Psi{}; - Psi.template insert<3,0>(Eye3, 1.0); - Psi.template insert<6,0>(ex, -Ln); - Psi.template insert<9,0>(Eye3, 1.0); -#endif - const Matrix3D B = Gamma^Psi; - Matrix3D A; - B.invert(A); - return Gamma*A.transpose()*NWL; + if constexpr (nn != 2) { + // TODO: Implement for nn != 2 + return MatrixND<6*nn,6*nn> {}; + } + else { + + MatrixND<3,12> NWL{}; + const double Ln = this->getLength(); + + constexpr static Matrix3D ex = Hat(Vector3D {1,0,0}); + + for (int i=0; i= 202000L + static constinit MatrixND<12,3> Gamma = MakeGamma(); + static constinit MatrixND<12,3> Psi0 = MakePsi(); + MatrixND<12,3> Psi = Psi0; + Psi.template insert<6,0>(ex, -Ln); + #else + MatrixND<12,3> Gamma{}; + Gamma.template insert<0,0>(ex, 1.0); + Gamma(3,0) = -1.0; + Gamma.template insert<6,0>(ex, -1.0); + + MatrixND<12,3> Psi{}; + Psi.template insert<3,0>(Eye3, 1.0); + Psi.template insert<6,0>(ex, -Ln); + Psi.template insert<9,0>(Eye3, 1.0); + #endif + const Matrix3D B = Gamma^Psi; + Matrix3D A; + B.invert(A); + return Gamma*A.transpose()*NWL; + } } MatrixND<3,6> diff --git a/SRC/coordTransformation/Frame/LinearFrameTransf.h b/SRC/coordTransformation/Frame/LinearFrameTransf.h index 372e8cca03..acf0527bf0 100644 --- a/SRC/coordTransformation/Frame/LinearFrameTransf.h +++ b/SRC/coordTransformation/Frame/LinearFrameTransf.h @@ -66,10 +66,9 @@ class LinearFrameTransf: public FrameTransform return this->getInitialRotation(); } - using Operation = typename FrameTransform::Operation; - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; + int push(VectorND&pl, int) final; + int push(MatrixND& kl, const VectorND& pl, int) final; // Sensitivity diff --git a/SRC/coordTransformation/Frame/LinearFrameTransf.tpp b/SRC/coordTransformation/Frame/LinearFrameTransf.tpp index 89d84c2db8..0d1a324f4d 100644 --- a/SRC/coordTransformation/Frame/LinearFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/LinearFrameTransf.tpp @@ -346,7 +346,6 @@ LinearFrameTransf::pull(VectorND& ul, ul.assemble(i*ndf+3, ixDu, -1.0/L); } - // return ul; return 0; } @@ -392,12 +391,12 @@ LinearFrameTransf::getNodeRotationLogarithm(int node) // template int -LinearFrameTransf::push(VectorND&p, Operation op) +LinearFrameTransf::push(VectorND&p, int op) { - VectorND pa = p; // NOTE + VectorND& pa = p; // NOTE constexpr Vector3D iv{1, 0, 0}; - if (op != Operation::Rotation) { + if (op & Transform::Adjoint) { // 1.1) Sum of moments: m = sum_i mi + sum_i (xi x ni) Vector3D m{}; for (int i=0; i::push(VectorND&p, Operation op) } const Vector3D ixm = iv.cross(m); - // 1.2) Adjust force part + // 1.2) Adjust shear/torsion for (int i=0; iFrameTransform::pushConstant(pa); + if (op & Transform::Rotation) + p = this->FrameTransform::pushConstant(pa); return 0; } + template int LinearFrameTransf::push(MatrixND&kb, const VectorND&, - Operation op) + int op) { static constexpr Vector3D axis{1, 0, 0}; + static constexpr Matrix3D I {1,0,0, + 0,1,0, + 0,0,1}; static constexpr Matrix3D ix = Hat(Vector3D{1, 0, 0}); static constexpr Matrix3D ioi = axis.bun(Vector3D{1, 0, 0}); + const Matrix3D R = (op & Transform::Rotation) ? this->R : I; const Matrix3D RT = R.transpose(); - const Matrix3D ixRT = ix*RT; + const Matrix3D ixRT = (op & Transform::Adjoint) ? ix*RT : Matrix3D{0.0}; MatrixND A{}; - if constexpr (ndf > 6) - A.addDiagonal(1.0); + A.addDiagonal(1.0); { MatrixND<3,ndf> Gb{}; @@ -456,24 +457,25 @@ LinearFrameTransf::push(MatrixND&kb, // TODO(nn>2): Interpolate coordinate if constexpr (b == 0) - Gb.template insert<0,0>(ixRT, -1/L); + Gb.template insert<0,0>(ixRT, -1.0/L); else if constexpr (b == nn-1) - Gb.template insert<0,0>(ixRT, 1/L); + Gb.template insert<0,0>(ixRT, 1.0/L); // TODO(nn>2): Interpolate coordinate A.assemble(ix*Gb, a*ndf , b*ndf, double(a)/double(nn-1)*L); A.assemble( Gb, a*ndf+3, b*ndf, -1.0); }); }); + + // MatrixND kl = kb; + // kb.addMatrixTripleProduct(0, A, kl, 1); + const MatrixND KA = kb*A; + kb.addMatrixTransposeProduct(0.0, A, KA, 1.0); } - // MatrixND kl = kb; - // kb.addMatrixTripleProduct(0, A, kl, 1); - const MatrixND KA = kb*A; - kb.addMatrixTransposeProduct(0.0, A, KA, 1.0); - if (offsets != nullptr) [[unlikely]] { + if (op & Transform::Offset && offsets != nullptr) [[unlikely]] this->pushOffsets(kb, *offsets); - } + return 0; } @@ -553,7 +555,7 @@ LinearFrameTransf::pushGrad(VectorND& dp, double doneOverL = -dL/(L*L); constexpr Vector3D iv{1, 0, 0}; - +#if 1 // 1.1) Sum of moments: m = sum_i mi + sum_i (xi x ni) Vector3D m{}; for (int i=0; i::pushGrad(VectorND& dp, // 1.2) Adjust force part for (int i=0; i::pushGrad(VectorND& dp, dp.assemble(base+3, R*Vector3D{dp[base+3], dp[base+4], dp[base+5]}, 1.0); } - this->push(pl, Operation::Isometry); + this->push(pl, Transform::Isometry); Matrix3D dR = FrameOrientationGradient(xi, xj, vz, di, dj, dv); for (int i=0; i return this->getInitialRotation(); } - using Operation = typename FrameTransform::Operation; - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; + int push(VectorND&pl, int) final; + int push(MatrixND& kl, const VectorND& pl, int) final; FrameTransform *getCopy() const final; diff --git a/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp b/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp index 75c6f372d0..e5900b0944 100644 --- a/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp +++ b/SRC/coordTransformation/Frame/PDeltaFrameTransf3d.tpp @@ -101,47 +101,62 @@ PDeltaFrameTransf::getDeformedLength() template -// VectorND int -PDeltaFrameTransf::push(VectorND&pl, Operation op) +PDeltaFrameTransf::push(VectorND&pl, int op) { - // - // Include leaning column effects (P-Delta) - // // Axial force const double N = pl[1*ndf+0]; + // + // 1) let linear.push do redistribution (isometry only) + // + if (op & Transform::Adjoint) { + + // Include leaning column effects (P-Delta) + + const Vector3D Du = linear.getDelta()/linear.getInitialLength(); - const Vector3D Du = linear.getDelta()/linear.getInitialLength(); + pl[0*ndf+1] -= Du[1] * N; + pl[1*ndf+1] += Du[1] * N; - pl[0*ndf+1] -= Du[1] * N; - pl[1*ndf+1] += Du[1] * N; + pl[0*ndf+2] -= Du[2] * N; + pl[1*ndf+2] += Du[2] * N; + linear.push(pl, Transform::Adjoint); + } - pl[0*ndf+2] -= Du[2] * N; - pl[1*ndf+2] += Du[2] * N; + linear.push(pl, op&~Transform::Adjoint); - return linear.push(pl, op); + return 0; } template // MatrixND int -PDeltaFrameTransf::push(MatrixND& kl, const VectorND &pl, Operation op) +PDeltaFrameTransf::push(MatrixND& kl, + const VectorND &pl, int op) { - // Include geometric stiffness effects in local system; - // - // Kl += [ ] double NoverL = pl[6] / linear.getInitialLength(); - kl(1, 1) += NoverL; - kl(2, 2) += NoverL; - kl(7, 7) += NoverL; - kl(8, 8) += NoverL; - kl(1, 7) -= NoverL; - kl(7, 1) -= NoverL; - kl(2, 8) -= NoverL; - kl(8, 2) -= NoverL; - return linear.push(kl, pl, op); + // + if (op & Transform::Adjoint) { + linear.push(kl, pl, Transform::Adjoint); + + // + // Include geometric stiffness effects in local system; + // + // Kl += [ ] + kl(1, 1) += NoverL; + kl(2, 2) += NoverL; + kl(7, 7) += NoverL; + kl(8, 8) += NoverL; + + kl(1, 7) -= NoverL; + kl(7, 1) -= NoverL; + kl(2, 8) -= NoverL; + kl(8, 2) -= NoverL; + } + + return linear.push(kl, pl, op&~Transform::Adjoint); } @@ -187,6 +202,7 @@ PDeltaFrameTransf::getLengthGrad() return linear.getLengthGrad(); } + template void PDeltaFrameTransf::Print(OPS_Stream &s, int flag) diff --git a/SRC/coordTransformation/Frame/SouzaFrameTransf.h b/SRC/coordTransformation/Frame/SouzaFrameTransf.h index 755b196ab2..f653b1b3c3 100644 --- a/SRC/coordTransformation/Frame/SouzaFrameTransf.h +++ b/SRC/coordTransformation/Frame/SouzaFrameTransf.h @@ -89,9 +89,8 @@ class SouzaFrameTransf: public FrameTransform return crs.getRotation(); } - using Operation = typename FrameTransform::Operation; - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; + int push(VectorND&pl, int) final; + int push(MatrixND& kl, const VectorND& pl, int) final; // Sensitivity diff --git a/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp b/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp index 9bdb906dec..e7f2dfde2a 100644 --- a/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp +++ b/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp @@ -107,8 +107,7 @@ SouzaFrameTransf::getCopy() const SouzaFrameTransf *theCopy = new SouzaFrameTransf(this->getTag(), vz, offsets); - theCopy->nodes[0] = nodes[0]; - theCopy->nodes[1] = nodes[1]; + theCopy->nodes = nodes; theCopy->xAxis = xAxis; theCopy->L = L; theCopy->Ln = Ln; @@ -157,7 +156,7 @@ SouzaFrameTransf::revertToLastCommit() { // determine global displacement increments from last iteration const Vector &dispI = nodes[0]->getTrialDisp(); - const Vector &dispJ = nodes[1]->getTrialDisp(); + const Vector &dispJ = nodes[nn-1]->getTrialDisp(); for (int k = 0; k < 3; k++) { alphaI(k) = dispI(k+3); @@ -194,7 +193,7 @@ SouzaFrameTransf::initialize(std::array& new_nodes) // Add initial displacements at nodes if (initialDispChecked == false) { const Vector &nodeIDisp = nodes[0]->getDisp(); - const Vector &nodeJDisp = nodes[1]->getDisp(); + const Vector &nodeJDisp = nodes[nn-1]->getDisp(); for (int i = 0; i<6; i++) if (nodeIDisp[i] != 0.0) { nodeIInitialDisp = new double [6]; @@ -367,7 +366,7 @@ SouzaFrameTransf::update() noexcept template int -SouzaFrameTransf::push(VectorND&pl, Operation) +SouzaFrameTransf::push(VectorND&pl, int) { // return T^pl; VectorND pg{}; @@ -395,9 +394,9 @@ template int SouzaFrameTransf::push(MatrixND& kl, const VectorND& pl, - Operation op) + int op) { - MatrixND<12,12> KT = kl*T; + MatrixND<6*nn,6*nn> KT = kl*T; kl.addMatrixTransposeProduct(0.0, T, KT, 1.0); // Add geometric part @@ -463,8 +462,8 @@ template double SouzaFrameTransf::getLengthGrad() { - const int di = nodes[0]->getCrdsSensitivity(); - const int dj = nodes[1]->getCrdsSensitivity(); + const int di = nodes[ 0]->getCrdsSensitivity(); + const int dj = nodes[nn-1]->getCrdsSensitivity(); Vector3D dxi{0.0}; Vector3D dxj{0.0}; diff --git a/SRC/element/Frame/ForceFrame3d.h b/SRC/element/Frame/ForceFrame3d.h index ffd601bd0c..9e6832b2b9 100644 --- a/SRC/element/Frame/ForceFrame3d.h +++ b/SRC/element/Frame/ForceFrame3d.h @@ -181,6 +181,8 @@ class ForceFrame3d: public BasicFrame3d, LocalForce = 2, BasicForce = 7, BasicStiff =19, + ResultantGradient=76, + ResultantStiffness=1001 }; // diff --git a/SRC/element/Frame/ForceFrame3d.tpp b/SRC/element/Frame/ForceFrame3d.tpp index 5449f86dda..ad86624ecc 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -704,9 +705,10 @@ ForceFrame3d::update01() // VectorND dv = dv_total; VectorND dv_trial = dv_total; + const VectorND Dv = dv_total; - static constexpr int max_subdivision= 5; - static constexpr double factor = 5.0; + static constexpr int max_subdivision= 10; + static constexpr double factor = 10.0; double dW; // section strain energy (work) norm double dW0 = 0.0; @@ -741,10 +743,27 @@ ForceFrame3d::update01() while ((converged == false) && (subdivision < max_subdivision)) { for (Strategy strategy : solve_strategy ) { + if (strategy != Strategy::Newton) { + opserr << " Element " << this->getTag() + << ": Attempting strategy "; + switch (strategy) { + case Strategy::Newton: + opserr << "Newton"; + break; + case Strategy::InitialIterations: + opserr << "Initial Tangent Iterations"; + break; + case Strategy::InitialThenNewton: + opserr << "Initial Tangent then Newton"; + break; + } + opserr << "\n"; + } // Allow extra iterations for initial tangent strategy const int numIters = (strategy==Strategy::InitialIterations) ? 10*max_iter : max_iter; + for (int i = 0; i < nip; i++) { es_trial[i] = points[i].es; Fs_trial[i] = points[i].Fs; @@ -762,6 +781,7 @@ ForceFrame3d::update01() VectorND vr{}; // element residual deformations MatrixND F{}; // element flexibility matrix + double DWi = 0.0; // // Gauss Loop @@ -772,9 +792,9 @@ ForceFrame3d::update01() // Retrieve section flexibility, deformations, and forces from last iteration const MatrixND& Fs = Fs_trial[i]; - const VectorND& sr = sr_trial[i]; - FrameSection& section = *points[i].material; + const VectorND& s0 = sr_trial[i]; const MatrixND& b = interp.b(xL, L); + FrameSection& section = *points[i].material; // // a. Calculate section force by interpolation of q_trial @@ -802,7 +822,7 @@ ForceFrame3d::update01() // Form stress increment ds from last iteration // ds = si - si_past; - const VectorND ds = si - sr; + const VectorND ds = si - s0; // Add strain correction // es += Fs * ds; @@ -835,7 +855,7 @@ ForceFrame3d::update01() // c. Set trial section state and get response // if (section.setTrialState(es_trial[i]) < 0) { - opserr << "element " << this->getTag() << ", section " << i << ": failed in setTrial\n"; + opserr << " Element " << this->getTag() << ", section " << i << ": failed in setTrial\n"; return -1; } @@ -857,11 +877,14 @@ ForceFrame3d::update01() { // calculate section residual deformations // des = Fs * ds, with ds = si - sr[i]; - const VectorND ds = si - sr; + const VectorND ds = si - s0; // B' * des vr.addMatrixTransposeVector(1.0, b, Fs*ds+es_trial[i], wtL); + + DWi += ds.dot(Fs*ds)*wtL; } + } // Gauss loop @@ -880,12 +903,12 @@ ForceFrame3d::update01() VectorND dqe{}; if (cholF.solve(&dv[0], &dqe[0]) < 0) [[unlikely]] { - // opserr << "ForceFrame3d: Failed to solve for dqe with Cholesky\n"; + opserr << "ForceFrame3d: Failed to solve for dqe with Cholesky\n"; if (F.solve(dv, dqe) < 0) return -1; } - dW = dqe.dot(dv); + dW = dqe.dot(dv)+DWi; if (dW0 == 0.0) dW0 = dW; @@ -900,16 +923,24 @@ ForceFrame3d::update01() dv_total -= dv_trial; v0 += dv_trial; + if (subdivision > 0) + opserr << " " << LOG_SUCCESS << "Subdivision " << subdivision + << " converged with dW = " << dW + << ", tol = " << tol << "\n"; + // Check if we have got to where we wanted if (dv_total.dot(dv_total) <= TOL_SUBDIV*TOL_SUBDIV) { converged = true; - - } else { + } + else { // We've converged but we have more to do; // reset variables for start of next subdivision - dv_trial = dv_total; + + // keep the working step size as long as we dont surpass dv_total + if (dv_trial.dot(dv_trial) > dv_total.dot(dv_total)) + dv_trial = dv_total; // NOTE setting subdivide to 1 again maybe too much - subdivision = 0; + // subdivision = 0; } // set K_pres, es and q_pres values @@ -926,19 +957,6 @@ ForceFrame3d::update01() points[k].Fs = Fs_trial[k]; points[k].sr = sr_trial[k]; } - // for (int k=0; k& B = interp.b(points[k].point, L); - // VectorND si = B * q_pres; - // // Add the particular solution - // if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) - // this->addLoadAtSection(si, points[k].point * L); - - // points[k].Fs = Fs_trial[k]; - // MatrixND& Fs = points[k].Fs; - // points[k].es = es_trial[k] + Fs*(si - sr_trial[k]); - // points[k].sr = si; - // // points[k].material->setTrialState(points[k].es); - // } // break out of j & l loops goto iterations_completed; @@ -950,6 +968,11 @@ ForceFrame3d::update01() if (j == (numIters - 1) && (strategy == solve_strategy.back())) { dv_trial /= factor; subdivision++; + opserr << " Element " << this->getTag() + << ": Attempting substep " << subdivision + << " with " + << " dW = " << dW + << ", tol = " << tol << "\n"; } } } // for (iteration) @@ -962,17 +985,17 @@ iterations_completed: if (converged == false) [[unlikely]] { - opserr << "WARNING - ForceFrame3d failed state determination "; - opserr << "for element " + opserr << " Element " << this->getTag() - << "; dW = " << dW + << ": failed to converge with " + << " dW = " << dW << ", tol = " << tol - << ", sub = " << subdivision + << ", % dv = " << 100.0*dv_trial.norm()/Dv.norm() << "\n"; return -1; } else { - if (subdivision > 1) { + if (subdivision > 0) { opserr << "ForceFrame3d::update - element " << this->getTag() << " required " << subdivision @@ -980,17 +1003,17 @@ iterations_completed: } // ForceInterpolation interp{}; - // for (int k=0; k& B = interp.b(points[k].point, L); - // VectorND si = B * q_pres; - // // Add the particular solution - // if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) - // this->addLoadAtSection(si, points[k].point * L); - - // MatrixND& Fs = points[k].Fs; - // points[k].es = points[k].es + Fs*(si - sr_trial[k]); - // points[k].sr = si; - // } + for (int k=0; k& B = interp.b(points[k].point, L); + VectorND si = B * q_pres; + // Add the particular solution + if ((frame_loads.size() != 0) || (eleLoads.size() != 0)) + this->addLoadAtSection(si, points[k].point * L); + + MatrixND& Fs = points[k].Fs; + points[k].es = points[k].es + Fs*(si - sr_trial[k]); + points[k].sr = si; + } } state_flag = 1; @@ -1115,6 +1138,7 @@ ForceFrame3d::update02() for (int j = 0; j < numIters; j++) { + double DWi = 0.0; // VectorND vr{}; // element residual deformations MatrixND F{}; // element flexibility matrix @@ -1127,7 +1151,7 @@ ForceFrame3d::update02() // Retrieve section flexibility, deformations, and forces from last iteration const MatrixND& Fs = Fs_trial[i]; - const VectorND& sr = sr_trial[i]; + const VectorND& s0 = sr_trial[i]; FrameSection& section = *points[i].material; const MatrixND& b = interp.b(xL, L); @@ -1157,7 +1181,7 @@ ForceFrame3d::update02() // Form stress increment ds from last iteration // ds = si - si_past; - const VectorND ds = si - sr; + const VectorND ds = si - s0; // Add strain correction // es += Fs * ds; @@ -1212,7 +1236,7 @@ ForceFrame3d::update02() { // calculate section residual deformations // des = Fs * ds, with ds = si - sr[i]; - const VectorND ds = si - sr; + const VectorND ds = si - s0; VectorND des = Fs*ds; des += es_trial[i]; @@ -1380,7 +1404,7 @@ ForceFrame3d::getTangentStiff() } #endif - basic_system->t.push(kl, pl); + basic_system->t.push(kl, pl, Transform::Total);//&~Transform::Logarithm); this->addLoadTangent(kl, 1.0); return Wrapper; } @@ -2125,14 +2149,22 @@ ForceFrame3d::setResponse(const char** argv, int argc, O output.attr("number", sectionNum); output.attr("eta", 2.0 * points[sectionNum - 1].point - 1.0); - if (strcmp(argv[2], "dsdh") != 0) { - theResponse = points[sectionNum - 1].material->setResponse(&argv[2], argc - 2, output); - } else { + if (argc > 2 && strcmp(argv[2], "tangent") == 0) { + // stiffness + theResponse = new ElementResponse(this, Respond::ResultantStiffness, Matrix(nsr, nsr)); + Information& info = theResponse->getInformation(); + info.theInt = sectionNum; + } + else if (argc > 2 && strcmp(argv[2], "dsdh") == 0) { + // dsdh int order = points[sectionNum - 1].material->getOrder(); - theResponse = new ElementResponse(this, 76, Vector(order)); + theResponse = new ElementResponse(this, Respond::ResultantGradient, Vector(order)); Information& info = theResponse->getInformation(); info.theInt = sectionNum; } + else { + theResponse = points[sectionNum - 1].material->setResponse(&argv[2], argc - 2, output); + } output.endTag(); } @@ -2247,6 +2279,13 @@ ForceFrame3d::getResponse(int responseID, Information& i else if (responseID == 19) return info.setMatrix(K_pres); + // Ks + else if (responseID == Respond::ResultantStiffness) { + int i = info.theInt; + MatrixND K = points[i-1].material->template getTangent(State::Pres); + return info.setMatrix(K); + } + // Plastic rotation else if (responseID == 4) { this->getInitialFlexibility(fe); @@ -2296,12 +2335,6 @@ ForceFrame3d::getResponse(int responseID, Information& i return info.setID(tags); } - else if (responseID == 111 || responseID == 1111) { - } - - else if (responseID == 112) { - } - else if (responseID == 12) return info.setVector(this->getRayleighDampingForces()); @@ -2443,12 +2476,11 @@ ForceFrame3d::getResponseSensitivity(int responseID, int } // dsdh - else if (responseID == 76) { + else if (responseID == Respond::ResultantGradient) { int sectionNum = info.theInt; - VectorND dsdh; - dsdh.zero(); + VectorND dsdh{}; if (eleLoads.size() > 0) this->getStressGrad(dsdh, sectionNum - 1, gradNumber); @@ -3090,7 +3122,7 @@ ForceFrame3d::getResistingForce() } #else thread_local Vector wrapper(pl); - basic_system->t.push(pl, Transform::Total); + basic_system->t.push(pl, Transform::Total);//&~(Transform::Logarithm)); if (pf.norm() > 0) [[unlikely]] { basic_system->t.push(pf, Transform::Total&~(Transform::Adjoint|Transform::Logarithm));//Transform::Rotation);//|Transform::Tangent); pl += pf; diff --git a/SRC/element/Frame/MixedFrame3d.cpp b/SRC/element/Frame/MixedFrame3d.cpp index 4da15d5a73..9514756c5c 100644 --- a/SRC/element/Frame/MixedFrame3d.cpp +++ b/SRC/element/Frame/MixedFrame3d.cpp @@ -67,12 +67,6 @@ #include #include -#include -#include -#include -#include -#include -#include Matrix MixedFrame3d::theMatrix(NEGD, NEGD); Vector MixedFrame3d::theVector(NEGD); diff --git a/SRC/element/Frame/PrismFrame3d.cpp b/SRC/element/Frame/PrismFrame3d.cpp index 2b9770d914..1212f4c6c3 100644 --- a/SRC/element/Frame/PrismFrame3d.cpp +++ b/SRC/element/Frame/PrismFrame3d.cpp @@ -499,11 +499,11 @@ PrismFrame3d::getResistingForce() pg = basic_system->t.pushResponse(pl); pg += basic_system->linear.pushResponse(pf); #else - using Operation = typename FrameTransform<2,6>::Operation; + static Vector wrapper(pl); - basic_system->t.push(pl, Operation::Total); + basic_system->t.push(pl, Transform::Total); if (pf.norm() > 0.0) [[unlikely]] { - basic_system->linear.push(pf, Operation::Rotation); + basic_system->linear.push(pf, Transform::Rotation); pl += pf; } #endif diff --git a/SRC/element/Frame/PrismFrame3d02.cpp b/SRC/element/Frame/PrismFrame3d02.cpp index e79d912ab0..b81a19eb76 100644 --- a/SRC/element/Frame/PrismFrame3d02.cpp +++ b/SRC/element/Frame/PrismFrame3d02.cpp @@ -209,9 +209,7 @@ PrismFrame3d02::getTangentStiff() kb = this->getBasicTangent(State::Pres, 0); - using Operation = typename FrameTransform<2,6>::Operation; - - basic_system->t.push(kb, q, Operation::Total); + basic_system->t.push(kb, q, Transform::Total); return wrapper; } From 12dec3492769def123ca67d88f9ad3ee24a2d493 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:37:38 -0800 Subject: [PATCH 134/161] Update ExactFrame3d.tpp --- SRC/element/Frame/ExactFrame3d.tpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/element/Frame/ExactFrame3d.tpp b/SRC/element/Frame/ExactFrame3d.tpp index 198af5fce4..e2b4f0bb8a 100644 --- a/SRC/element/Frame/ExactFrame3d.tpp +++ b/SRC/element/Frame/ExactFrame3d.tpp @@ -640,7 +640,7 @@ ExactFrame3d::setResponse(const char** argv, int argc, OPS_Stream& outp for (int i = 0; i < numSections; i++) { output.tag("GaussPointOutput"); output.attr("number", i + 1); - output.attr("eta", pres[i].point * L); + output.attr("eta", pres[i].point); Response* theSectionResponse = pres[i].material->setResponse(&argv[1], argc - 1, output); @@ -784,7 +784,7 @@ ExactFrame3d::getResponse(int responseID, Information &info) Vector locs(pres.size()); for (int i = 0; i < nip; i++) - locs[i] = pres[i].point * L; + locs[i] = pres[i].point; return info.setVector(locs); } From cfea94fb5a7a3bf04ba04d153d75d0582a57779f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:39:07 -0800 Subject: [PATCH 135/161] Update ForceFrame3d.tpp --- SRC/element/Frame/ForceFrame3d.tpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SRC/element/Frame/ForceFrame3d.tpp b/SRC/element/Frame/ForceFrame3d.tpp index ad86624ecc..85ca0e1c9f 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -1832,7 +1832,6 @@ ForceFrame3d::getInitialFlexibility(MatrixND& f for (int i = 0; i < numSections; i++) { double xL = points[i].point; - double xL1 = xL - 1.0; double wtL = points[i].weight * L; const MatrixND fSec = points[i].material->template getFlexibility(State::Init); From ad45a492463f07cae70f9cdb434e48a25509f553 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:39:21 -0800 Subject: [PATCH 136/161] Update ForceFrame3d.tpp --- SRC/element/Frame/ForceFrame3d.tpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SRC/element/Frame/ForceFrame3d.tpp b/SRC/element/Frame/ForceFrame3d.tpp index 85ca0e1c9f..a33d58ea5f 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -1825,7 +1825,6 @@ ForceFrame3d::getInitialFlexibility(MatrixND& f fe.zero(); double L = basic_system->getInitialLength(); - double jsx = 1.0 / L; const int numSections = points.size(); ForceInterpolation interp{}; From 73826b405d220236f0e64d62d484bddd83170938 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:40:06 -0800 Subject: [PATCH 137/161] Update ForceFrame3d.tpp --- SRC/element/Frame/ForceFrame3d.tpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SRC/element/Frame/ForceFrame3d.tpp b/SRC/element/Frame/ForceFrame3d.tpp index a33d58ea5f..6569c5c92d 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -1138,7 +1138,6 @@ ForceFrame3d::update02() for (int j = 0; j < numIters; j++) { - double DWi = 0.0; // VectorND vr{}; // element residual deformations MatrixND F{}; // element flexibility matrix From 2593cc7eda3fbff2d56cc474001b5fe767aa9d17 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:41:35 -0800 Subject: [PATCH 138/161] Update AnalysisModel.h --- SRC/analysis/model/AnalysisModel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SRC/analysis/model/AnalysisModel.h b/SRC/analysis/model/AnalysisModel.h index 86090dcca7..862743b050 100644 --- a/SRC/analysis/model/AnalysisModel.h +++ b/SRC/analysis/model/AnalysisModel.h @@ -65,7 +65,7 @@ class AnalysisModel: public MovableObject void clearDOFGraph(); // called by Numberer and Analysis void clearDOFGroupGraph(); int getNumDOF_Groups() const; - DOF_Group *getDOF_GroupPtr(int tag); + DOF_Group *getDOF_GroupPtr(int tag); FE_EleIter &getFEs(); DOF_GrpIter &getDOFs(); void setNumEqn(int); From f0027410d690278a017c0f778bfff861c10d2f27 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:42:24 -0800 Subject: [PATCH 139/161] Update ExponReducing.cpp --- SRC/material/Yield/plasticHardeningMaterial/ExponReducing.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/SRC/material/Yield/plasticHardeningMaterial/ExponReducing.cpp b/SRC/material/Yield/plasticHardeningMaterial/ExponReducing.cpp index ce3a924809..bd19ef460f 100644 --- a/SRC/material/Yield/plasticHardeningMaterial/ExponReducing.cpp +++ b/SRC/material/Yield/plasticHardeningMaterial/ExponReducing.cpp @@ -48,8 +48,6 @@ double ExponReducing::getTrialPlasticStiffness() if(K < (Kp0*resFactor)) K = Kp0*resFactor; - -// opserr << "K = " << K << ", sFactor = " << sFactor << endln; if(K <0.0) { From e467bf10be2610ba8c15b97cf529c0cbde752841 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:10:31 -0800 Subject: [PATCH 140/161] Update TclPackageClassBroker.cpp --- SRC/runtime/runtime/TclPackageClassBroker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/runtime/runtime/TclPackageClassBroker.cpp b/SRC/runtime/runtime/TclPackageClassBroker.cpp index cca3795956..3758503daa 100644 --- a/SRC/runtime/runtime/TclPackageClassBroker.cpp +++ b/SRC/runtime/runtime/TclPackageClassBroker.cpp @@ -458,7 +458,7 @@ using namespace OpenSees::Hash::literals; #include "DomainDecompositionAnalysis.h" // load patterns -#include "LoadPattern.h" +#include "StaticPattern.h" #include "UniformExcitation.h" #include "MultiSupportPattern.h" #include "GroundMotion.h" @@ -1405,7 +1405,7 @@ TclPackageClassBroker::getNewLoadPattern(int classTag) { switch (classTag) { case PATTERN_TAG_LoadPattern: - return new LoadPattern(); + return new StaticPattern(); case PATTERN_TAG_UniformExcitation: return new UniformExcitation(); From 0930141f6d166feb3bc69cad4dd011c7e70272c7 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:11:02 -0800 Subject: [PATCH 141/161] formatting --- .../diagonal/DistributedDiagonalSOE.cpp | 73 ++++++++----------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/SRC/system_of_eqn/linearSOE/diagonal/DistributedDiagonalSOE.cpp b/SRC/system_of_eqn/linearSOE/diagonal/DistributedDiagonalSOE.cpp index d96d7c59db..8a3df28e7f 100644 --- a/SRC/system_of_eqn/linearSOE/diagonal/DistributedDiagonalSOE.cpp +++ b/SRC/system_of_eqn/linearSOE/diagonal/DistributedDiagonalSOE.cpp @@ -49,7 +49,8 @@ DistributedDiagonalSOE::DistributedDiagonalSOE(DistributedDiagonalSolver &the_So size(0), A(0), B(0), X(0), vectX(0), vectB(0), isAfactored(false), processID(0), numProcesses(0), numChannels(0), theChannels(0), localCol(0), - myDOFs(0,32), myDOFsShared(0,16), numShared(0), dataShared(0), vectShared(0), theModel(0) + myDOFs(0,32), myDOFsShared(0,16), numShared(0), dataShared(0), vectShared(0) + , theModel(0) { the_Solver.setLinearSOE(*this); } @@ -59,7 +60,8 @@ DistributedDiagonalSOE::DistributedDiagonalSOE() size(0), A(0), B(0), X(0), vectX(0), vectB(0), isAfactored(false), processID(0), numProcesses(0), numChannels(0), theChannels(0), localCol(0), - myDOFs(0,32), myDOFsShared(0,16), numShared(0), dataShared(0), vectShared(0), theModel(0) + myDOFs(0,32), myDOFsShared(0,16), numShared(0), dataShared(0), vectShared(0) + , theModel(0) { } @@ -195,21 +197,21 @@ DistributedDiagonalSOE::setSize(Graph &theGraph) // need to send to all others for (int k=0; ksendID(0, 0, otherSize); - if (numOther != 0) { - theChannel->sendID(0, 0, otherDOFS); - } - } + Channel *theChannel = theChannels[k]; + if (k != j) { + theChannel->sendID(0, 0, otherSize); + if (numOther != 0) { + theChannel->sendID(0, 0, otherDOFS); + } + } } // need to merge with mine for (int l=0; lrecvID(0, 0, otherSize); int numOther = otherSize(0); if (numOther != 0) { - otherDOFS.resize(numOther); - theChannel->recvID(0, 0, otherDOFS); + otherDOFS.resize(numOther); + theChannel->recvID(0, 0, otherDOFS); } // need to merge with mine for (int k=0; kgetFEs(); FE_Element *elePtr; while ((elePtr = theEle()) != nullptr) - elePtr->setID(); + elePtr->setID(); // invoke setSize() on the Solver @@ -309,8 +311,6 @@ DistributedDiagonalSOE::setSize(Graph &theGraph) int solverOK = the_Solver->setSize(); if (solverOK < 0) { - // opserr << "WARNING DistributedDiagonalSOE::setSize :"; - // opserr << " solver failed setSize()\n"; return solverOK; } @@ -322,35 +322,26 @@ DistributedDiagonalSOE::addA(const Matrix &m, const ID &id, double fact) { // check for a quick return if (fact == 0.0) return 0; - -#ifdef _G3DEBUG - // check that m and id are of similar size - int idSize = id.Size(); - if (idSize != m.noRows() && idSize != m.noCols()) { - opserr << "FullGenLinSOE::addA() - Matrix and ID not of similar sizes\n"; - return -1; - } -#endif if (fact == 1.0) { // do not need to multiply if fact == 1.0 for (int i=0; i= 0) { - A[pos] += m(i,i); + A[pos] += m(i,i); } } } else if (fact == -1.0) { // do not need to multiply if fact == -1.0 for (int i=0; i= 0) { - A[pos] -= m(i,i); + A[pos] -= m(i,i); } } } else { for (int i=0; i= 0) { - A[pos] += m(i,i) * fact; + A[pos] += m(i,i) * fact; } } } @@ -380,19 +371,19 @@ DistributedDiagonalSOE::addB(const Vector &v, const ID &id, double fact) for (int i=0; i= 0) - B[pos] += v(i); + B[pos] += v(i); } } else if (fact == -1.0) { // do not need to multiply if fact == -1.0 for (int i=0; i= 0) - B[pos] -= v(i); + B[pos] -= v(i); } } else { for (int i=0; i= 0) - B[pos] += v(i) * fact; + B[pos] += v(i) * fact; } } return 0; @@ -425,7 +416,7 @@ DistributedDiagonalSOE::setB(const Vector &v, double fact) } void -DistributedDiagonalSOE::zeroA(void) +DistributedDiagonalSOE::zeroA() { double *Aptr = A; for (int i=0; i Date: Tue, 27 Jan 2026 18:11:33 -0800 Subject: [PATCH 142/161] Update NodeND.h --- SRC/domain/node/NodeND.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/SRC/domain/node/NodeND.h b/SRC/domain/node/NodeND.h index 439a9f0d40..00203554c0 100644 --- a/SRC/domain/node/NodeND.h +++ b/SRC/domain/node/NodeND.h @@ -4,13 +4,13 @@ template class NodeND: public Node { - public: +public: NodeND(int tag, double crd) : Node(tag, ndf) {static_assert(ndm == 1); createDisp();} NodeND(int tag, double crd1, double crd2) : Node(tag, ndf) {static_assert(ndm == 2); createDisp();} NodeND(int tag, double crd1, double crd2, double crd3): Node(tag, ndf) {static_assert(ndm == 3); createDisp();} - virtual int setTrialDisp (double value, int dof) final { + int setTrialDisp (double value, int dof) noexcept final { assert(dof >= 0 && dof < ndf); double tDisp = value; displ[dof+2*ndf] = tDisp - displ[dof+ndf]; @@ -19,7 +19,7 @@ class NodeND: public Node { return 0; } - virtual int setTrialDisp (const Vector & newTrialDisp) final { + int setTrialDisp (const Vector & newTrialDisp) noexcept final { assert(newTrialDisp.Size() == ndf); for (int i=0; i Date: Tue, 27 Jan 2026 18:12:03 -0800 Subject: [PATCH 143/161] Update ctest.cpp --- SRC/runtime/commands/analysis/ctest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/runtime/commands/analysis/ctest.cpp b/SRC/runtime/commands/analysis/ctest.cpp index 277cbf3d87..3fb6911790 100644 --- a/SRC/runtime/commands/analysis/ctest.cpp +++ b/SRC/runtime/commands/analysis/ctest.cpp @@ -302,9 +302,9 @@ getCTestNorms(ClientData clientData, Tcl_Interp *interp, int size = data.Size(); Tcl_Obj *result = Tcl_NewListObj(size, NULL); - for (int i = 0; i < size; ++i) { + for (int i = 0; i < size; ++i) Tcl_ListObjAppendElement(interp, result, Tcl_NewDoubleObj(data(i))); - } + Tcl_SetObjResult(interp, result); return TCL_OK; From ef77710fdee87c5949365c9f4fa5c4f7a38673f7 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:12:51 -0800 Subject: [PATCH 144/161] Update algorithm.cpp --- SRC/runtime/commands/analysis/algorithm.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SRC/runtime/commands/analysis/algorithm.cpp b/SRC/runtime/commands/analysis/algorithm.cpp index 79d54f6d1d..3ea45b8809 100644 --- a/SRC/runtime/commands/analysis/algorithm.cpp +++ b/SRC/runtime/commands/analysis/algorithm.cpp @@ -92,6 +92,7 @@ std::unordered_map Algorithms { {"KrylovNewton", TclCommand_newAcceleratedNewton}, {"PeriodicNewton", TclCommand_newAcceleratedNewton}, {"RaphsonNewton", TclCommand_newAcceleratedNewton}, + {"AcceleratedNewton", TclCommand_newAcceleratedNewton}, }; } @@ -680,7 +681,8 @@ TclCommand_newAcceleratedNewton(ClientData clientData, Tcl_Interp *interp, Tcl_S } Accelerator *accel = nullptr; - if (strcmp(argv[1], "MillerNewton") == 0) { + if ((type == AcceleratorType::Miller) || + (strcmp(argv[1], "MillerNewton") == 0)) { accel = new MillerAccelerator(maxDim, 0.01, correction_tangent); } From 7c381a9f3e9b9aacb22daff974dfcf2f6587d5ce Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:13:10 -0800 Subject: [PATCH 145/161] Update linalg.hh --- SRC/runtime/commands/utilities/linalg.hh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SRC/runtime/commands/utilities/linalg.hh b/SRC/runtime/commands/utilities/linalg.hh index 413ebc8d95..92a91aab38 100644 --- a/SRC/runtime/commands/utilities/linalg.hh +++ b/SRC/runtime/commands/utilities/linalg.hh @@ -19,7 +19,11 @@ namespace export verify proc verify {cmd {value ""} {reference ""} {tolerance 1e-12} {about ""}} { if {$cmd == "error"} { - set check [expr abs(($value - $reference)/$reference)] + if {$reference == 0} { + set check [expr abs($value)] + } else { + set check [expr abs(($value - $reference)/$reference)] + } if {$check > $tolerance} { puts " \033\[31mFAIL\033\[0m: | $value - $reference | = $check > $tolerance" error "$about" From 3d3995f5753d3575843e779eb61f416483378985 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:59:30 -0800 Subject: [PATCH 146/161] Update TclPackageClassBroker.cpp --- SRC/runtime/runtime/TclPackageClassBroker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SRC/runtime/runtime/TclPackageClassBroker.cpp b/SRC/runtime/runtime/TclPackageClassBroker.cpp index 3758503daa..a179745a6d 100644 --- a/SRC/runtime/runtime/TclPackageClassBroker.cpp +++ b/SRC/runtime/runtime/TclPackageClassBroker.cpp @@ -1404,8 +1404,8 @@ LoadPattern * TclPackageClassBroker::getNewLoadPattern(int classTag) { switch (classTag) { - case PATTERN_TAG_LoadPattern: - return new StaticPattern(); + // case PATTERN_TAG_LoadPattern: + // return new StaticPattern(); case PATTERN_TAG_UniformExcitation: return new UniformExcitation(); From e918603bba5c8ec08ac63b41f924a9cd9c5e3905 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Tue, 27 Jan 2026 19:03:13 -0800 Subject: [PATCH 147/161] Update FrameTraceSection3d.cpp --- SRC/material/Frame/FrameTraceSection3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SRC/material/Frame/FrameTraceSection3d.cpp b/SRC/material/Frame/FrameTraceSection3d.cpp index f553aab4e9..14ebbe270b 100644 --- a/SRC/material/Frame/FrameTraceSection3d.cpp +++ b/SRC/material/Frame/FrameTraceSection3d.cpp @@ -48,7 +48,7 @@ ID FrameTraceSection3d::code(nsr); FrameTraceSection3d::FrameTraceSection3d(int tag, int num): FrameSection(tag, SEC_TAG_FrameTraceSection3d), - s(), e(), + s{}, e{}, e_wrap(e), s_wrap(s), shear_align{}, shift_twist{}, From 58f2a5b0aed89b4ef084f87cf3830976c8842fcd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:16:19 -0800 Subject: [PATCH 148/161] Update FrameTraceSection3d.cpp --- SRC/material/Frame/FrameTraceSection3d.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/SRC/material/Frame/FrameTraceSection3d.cpp b/SRC/material/Frame/FrameTraceSection3d.cpp index 14ebbe270b..68ee8e486d 100644 --- a/SRC/material/Frame/FrameTraceSection3d.cpp +++ b/SRC/material/Frame/FrameTraceSection3d.cpp @@ -454,27 +454,18 @@ FrameTraceSection3d::stateDetermination(Tangent& K, VectorND* s_trial, cons const Matrix3D Ciow = C*iow; const Matrix3D Ciodw = C*iodw; { - // K.nn.addMatrix(C, 1.0); - // K.nm.addMatrix(Crx, 1.0); K.sw.assemble(Ciow, 0, 0, 1.0); K.sv.assemble(Ciodw, 0, 0, 1.0); } { - // K.mn.addSpinMatrixProduct(r, C, 1.0); - // K.mm.addSpinMatrixProduct(r, Crx, 1.0); K.sw.assemble(Hat(r)*Ciow, 3, 0, 1.0); K.sv.assemble(Hat(r)*Ciodw, 3, 0, 1.0); } { - // K.wn.addTranspose(Ciow, 1.0); - // K.wm.addMatrixTransposeProduct(1.0, iow, Crx, 1.0); K.ww.addMatrixTransposeProduct(1.0, iow, Ciow, 1.0); K.wv.addMatrixTransposeProduct(1.0, iow, Ciodw, 1.0); } { - // K.vn.addTranspose(Ciodw, 1.0); - // K.vm.addMatrixTransposeProduct(1.0, iodw, Crx, 1.0); - // K.vw.addMatrixTransposeProduct(1.0, iodw, Ciow, 1.0); K.vv.addMatrixTransposeProduct(1.0, iodw, Ciodw, 1.0); } } From f22edb416ffc081c5a2c214639b3f337e305a9fd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sat, 31 Jan 2026 23:04:04 -0800 Subject: [PATCH 149/161] Refactor ArpackSolver memory management and API Replace raw pointer management for eigenvalues and eigenvectors with an EigenData struct. Update method signatures to use final and add overloads for getEigenvector. Refactor workspace allocation and NCV calculation, improve error handling, and remove unused code. --- SRC/system_of_eqn/eigenSOE/ArpackSolver.cpp | 428 +++++++++++++------- SRC/system_of_eqn/eigenSOE/ArpackSolver.h | 54 ++- 2 files changed, 327 insertions(+), 155 deletions(-) diff --git a/SRC/system_of_eqn/eigenSOE/ArpackSolver.cpp b/SRC/system_of_eqn/eigenSOE/ArpackSolver.cpp index 45be55a9a2..7d24d308f0 100644 --- a/SRC/system_of_eqn/eigenSOE/ArpackSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/ArpackSolver.cpp @@ -15,7 +15,7 @@ ** Frank McKenna (fmckenna@ce.berkeley.edu) ** ** Gregory L. Fenves (fenves@ce.berkeley.edu) ** ** Filip C. Filippou (filippou@ce.berkeley.edu) ** -** ** +** ** ** ****************************************************************** */ // // This is the solver that works on the ArpackSOE. It uses the LinearSOE @@ -31,11 +31,102 @@ // // It is based on previous work of Jun Peng(Stanford) // +// From SciPy (Symmetric): +// +// # The following modes are supported: +// # mode = 1: +// # Solve the standard eigenvalue problem: +// # A*x = lambda*x : +// # A - symmetric +// # Arguments should be +// # matvec = left multiplication by A +// # M_matvec = None [not used] +// # Minv_matvec = None [not used] +// # +// # mode = 2: +// # Solve the general eigenvalue problem: +// # A*x = lambda*M*x +// # A - symmetric +// # M - symmetric positive definite +// # Arguments should be +// # matvec = left multiplication by A +// # M_matvec = left multiplication by M +// # Minv_matvec = left multiplication by M^-1 +// # +// # mode = 3: +// # Solve the general eigenvalue problem in shift-invert mode: +// # A*x = lambda*M*x +// # A - symmetric +// # M - symmetric positive semi-definite +// # Arguments should be +// # matvec = None [not used] +// # M_matvec = left multiplication by M +// # or None, if M is the identity +// # Minv_matvec = left multiplication by [A-sigma*M]^-1 +// # +// # mode = 4: +// # Solve the general eigenvalue problem in Buckling mode: +// # A*x = lambda*AG*x +// # A - symmetric positive semi-definite +// # AG - symmetric indefinite +// # Arguments should be +// # matvec = left multiplication by A +// # M_matvec = None [not used] +// # Minv_matvec = left multiplication by [A-sigma*AG]^-1 +// # +// # mode = 5: +// # Solve the general eigenvalue problem in Cayley-transformed mode: +// # A*x = lambda*M*x +// # A - symmetric +// # M - symmetric positive semi-definite +// # Arguments should be +// # matvec = left multiplication by A +// # M_matvec = left multiplication by M +// # or None, if M is the identity +// # Minv_matvec = left multiplication by [A-sigma*M]^-1 +// +// For unsymmetric: +// # The following modes are supported: +// # mode = 1: +// # Solve the standard eigenvalue problem: +// # A*x = lambda*x +// # A - square matrix +// # Arguments should be +// # matvec = left multiplication by A +// # M_matvec = None [not used] +// # Minv_matvec = None [not used] +// # +// # mode = 2: +// # Solve the generalized eigenvalue problem: +// # A*x = lambda*M*x +// # A - square matrix +// # M - symmetric, positive semi-definite +// # Arguments should be +// # matvec = left multiplication by A +// # M_matvec = left multiplication by M +// # Minv_matvec = left multiplication by M^-1 +// # +// # mode = 3,4: +// # Solve the general eigenvalue problem in shift-invert mode: +// # A*x = lambda*M*x +// # A - square matrix +// # M - symmetric, positive semi-definite +// # Arguments should be +// # matvec = None [not used] +// # M_matvec = left multiplication by M +// # or None, if M is the identity +// # Minv_matvec = left multiplication by [A-sigma*M]^-1 +// # if A is real and mode==3, use the real part of Minv_matvec +// # if A is real and mode==4, use the imag part of Minv_matvec +// # if A is complex and mode==3, +// # use real and imag parts of Minv_matvec +// // Written: fmk // Created: 05.09 // #include #include +#include #include #include #include // memcpy @@ -55,34 +146,6 @@ namespace { -struct ArpackWorkspace { - ArpackWorkspace(int n, int ncv, int symm=0) : - ldv(n), - ncv(ncv), - lworkl(symm? (ncv*(ncv+8)) : (3*ncv*(ncv+6))), - workl(new double[lworkl]{}), - workd(new double[3*n]{}), - resid(new double[n]{}), - select(new int[ncv]{}), - v(new double[n * ncv]{}) - {} - - ~ArpackWorkspace() { - delete [] workl; - delete [] workd; - delete [] resid; - delete [] select; - } - - int ldv; - int ncv; - int lworkl; - double* v; - double* workl; - double* workd; - double* resid; - int* select; -}; typedef struct { int code; const char *msg; } ErrorEntry; @@ -175,13 +238,105 @@ LookupArpackError(const ErrorEntry *table, size_t count, int code) { if (table[i].code == code) return table[i].msg; return "Unknown error code."; } -} + +struct ArpackWorkspace { + ArpackWorkspace(int n, int nev, int symm) : + size(n), + ldv(n), + nev(nev), + ncv(getNCV(n, nev, symm)), + lworkl(symm==ArpackWorkspace::Symmetric ? 1*( ncv*ncv + 8*ncv) + : 1*(3*ncv*ncv + 6*ncv)), + v(new double[n * ncv]{}), + workl(new double[lworkl+1]{}), + workd(new double[3*n]{}), + resid(new double[n]{}), + select(new int[ncv]{}) + { + assert(n >=0); + assert(ncv <= n); + if (symm == ArpackWorkspace::NonSymmetric) { + assert(ncv > nev + 2); + } + else { + assert(ncv > nev); + } + } + + ~ArpackWorkspace() { + delete [] v; + delete [] workl; + delete [] workd; + delete [] resid; + delete [] select; + } + + ArpackWorkspace(const ArpackWorkspace&) = delete; + ArpackWorkspace& operator=(const ArpackWorkspace&) = delete; + ArpackWorkspace(ArpackWorkspace&&) = delete; + ArpackWorkspace& operator=(ArpackWorkspace&&) = delete; + + enum { Symmetric = 1, NonSymmetric = 2 }; + int getNCV(int n, int nev, int driver) + { + // compute the number of Arnoldi vectors to use + // n is the system size, nev is the number of eigenvectors. + // dsaupd: NCV must be greater than NEV and less than or equal to N. + + // For dnaupd: NCV must satisfy the two inequalities + //. 2 <= NCV-NEV and NCV <= N. + // The only formal requrement is that NCV > NEV + 2. + // However, it is recommended that NCV .ge. 2*NEV+1. See Chapter 8 of: + // + // 2. R.B. Lehoucq, "Analysis and Implementation of an Implicitly + // Restarted Arnoldi Iteration", Rice University Technical Report + // TR95-13, Department of Computational and Applied Mathematics. + // + // Scipy uses min(max(2 * n + 1, 20), n) + #if 1 + int result; + if (2*nev > nev+8) { + result = nev+8; + } else { + result = 2*nev; + } + + if (result >= n) { + result = n; + } + + return result; + #elif 1 + return std::min(std::max(2*nev + 1, 20), n); + #else + // ensure headroom and a sensible floor + int ncv = std::max({2*nev + 8, nev + 20, 20}); + ncv = std::min(ncv, n); + // ARPACK requires ncv > nev+1; enforce with a small bump if saturated + if (ncv <= nev + 1 && n > nev + 1) + ncv = std::min(n, nev + 2); + return ncv; + #endif + } + + int size; // ldv + int ldv; + int nev; + int ncv; + int lworkl; + double* v; + double* workl; + double* workd; + double* resid; + int* select; +}; + +} // namespace ArpackSolver::ArpackSolver() :EigenSolver(EigenSOLVER_TAGS_ArpackSolver), - theSOE(0), numModesMax(0), numMode(0), size(0), - eigenvalues(0), eigenvectors(0) + theSOE(nullptr), numMode(0), size(0), iparam{0}, ipntr{0}, shift(0.0) { } @@ -189,10 +344,7 @@ ArpackSolver::ArpackSolver() ArpackSolver::~ArpackSolver() { - if (eigenvalues != nullptr) - delete [] eigenvalues; - if (eigenvectors != nullptr) - delete [] eigenvectors; + solution.clear(); } @@ -200,11 +352,13 @@ int ArpackSolver::solve(int numModes, bool generalized, bool findSmallest) { if (generalized == false) { - opserr << "ArpackSolver::solve - at moment only solves generalized problem\n"; + return solveI(numModes, generalized, findSmallest); + // opserr << "ArpackSolver::solve - at moment only solves generalized problem\n"; return -1; } theSOE = theArpackSOE->theSOE; + numMode = 0; if (theSOE == nullptr) { opserr << "ArpackSolver::setSize() - no LinearSOE set\n"; @@ -215,18 +369,23 @@ ArpackSolver::solve(int numModes, bool generalized, bool findSmallest) // // this is done each time method is called!! .. this needs to be cleaned up - int n = size; - int nev = numModes; - int ncv = getNCV(n, nev); + int n = theArpackSOE->getNumEqn(); // size; + const int nev = numModes; + if (n < nev || nev < 1) { + opserr << "ArpackSolver::solve - no. of modes requested is invalid\n"; + return -1; + } + solution.reserve(n, numModes); int ido = 0; double tol = std::numeric_limits::epsilon(); int info = 0; int maxitr = 1000; - int mode = 3; - bool rvec = true; - iparam[0] = 1; + int mode = 3; // + iparam[0] = 1; // exact shifts + iparam[1] = 0; // not used by ARPACK iparam[2] = maxitr; + iparam[3] = 1; // NB; must be 1. iparam[6] = mode; int processID = theArpackSOE->processID; @@ -246,11 +405,12 @@ char which[3]; ? arpack::which::largest_magnitude : arpack::which::smallest_magnitude; - arpack::bmat bmat = arpack::bmat::generalized; - arpack::howmny howmy = arpack::howmny::ritz_vectors; + arpack::bmat bmat = arpack::bmat::generalized; // 'G' + arpack::howmny howmy = arpack::howmny::ritz_vectors; // 'A' #endif - ArpackWorkspace w(n, ncv); + ArpackWorkspace w(n, nev, ArpackWorkspace::Symmetric); + int ncv = w.ncv; if (false) { std::vector ones(n, 1.0), mdiag(n); @@ -286,10 +446,9 @@ char which[3]; } // - // I Compute Eigenvalues + // I Arnoldi Iteration // - while (true) { - + while (true) { arpack::saupd(ido, bmat, n, which, nev, tol, w.resid, ncv, w.v, w.ldv, iparam, ipntr, w.workd, w.workl, w.lworkl, info); @@ -363,15 +522,15 @@ char which[3]; // // // - - if (info < 0) { + // iparam[4]: number of converged eigenvalues + if (info < 0 || iparam[4] == 0) { opserr << "Arpack returned with flag " << info << "\n "; opserr << LookupArpackError(DsaupdErrors, sizeof(DsaupdErrors) / sizeof(ErrorEntry), info); opserr << OpenSees::SignalMessageEnd; if (info == -9999) { return this->solveI(numModes, generalized, findSmallest); } - + return info; } // @@ -383,26 +542,22 @@ char which[3]; } else if (info == 3) { opserr << "ArpackSolver::No Shifts could be applied during implicit,"; - opserr << "Arnoldi update, try increasing NCV." << endln; + opserr << "Arnoldi update, try increasing NCV." << "\n"; } double sigma = shift; if (iparam[4] > 0) { - rvec = true; - n = size; - if (numModes > numModesMax) { - if (eigenvalues != nullptr) delete [] eigenvalues; - if (eigenvectors != nullptr) delete [] eigenvectors; - - eigenvalues = new double[nev]{}; - eigenvectors = new double[n * nev]{}; - - numModesMax = numModes; - } + this->numMode = numModes; + bool rvec = true; + solution.reserve(n, nev); + assert(w.ldv >= 1); + if (rvec) + assert(w.ldv >= n); arpack::seupd(rvec, howmy, w.select, - eigenvalues, eigenvectors, + solution.eigenvalues, // D + solution.eigenvectors, // Z w.ldv, sigma, bmat, n, which, nev, tol, w.resid, ncv, w.v, w.ldv, @@ -418,8 +573,6 @@ char which[3]; } } } - - numMode = numModes; return 0; } @@ -429,29 +582,40 @@ char which[3]; int ArpackSolver::solveI(int numModes, bool generalized, bool findSmallest) { - // Solve - int n = size; + // Asymmetric solver + + // Solve + theSOE = theArpackSOE->theSOE; + numMode = 0; + int n = theArpackSOE->getNumEqn(); // size; + + if (n < numModes || numModes < 1) { + opserr << "ArpackSolver::solve - no. of modes requested is invalid\n"; + return -1; + } + assert (theSOE != nullptr); + + solution.reserve(n, numModes); int ido = 0; double tol = std::numeric_limits::epsilon(); int info = 0; int maxitr = 1000; int mode = 1; - bool rvec = true; double sigma = shift; int nev = numModes; - int ncv = getNCV(n, nev); - ArpackWorkspace work(n, ncv); + ArpackWorkspace work(n, nev, ArpackWorkspace::NonSymmetric); + int ncv = work.ncv; arpack::bmat bmat = arpack::bmat::identity; arpack::which which = arpack::which::largest_magnitude; iparam[0] = 1; // exact shifts iparam[2] = maxitr; - iparam[6] = mode; // mode 1 (std. problem, user OP) + iparam[6] = mode; // mode 1 (std. problem) - // + // // I Arnoldi Iteration // while (true) { @@ -462,8 +626,8 @@ ArpackSolver::solveI(int numModes, bool generalized, bool findSmallest) work.workd, work.workl, work.lworkl, info); - // assert(ipntr[0] >= 1 && ipntr[0] <= 3*n); - // assert(ipntr[1] >= 1 && ipntr[1] <= 3*n); + assert(ipntr[0] >= 1 && ipntr[0] <= 3*n); + assert(ipntr[1] >= 1 && ipntr[1] <= 3*n); if (ido == -1 || ido == 1) { // x is at workd[ipntr[0]-1] @@ -472,15 +636,21 @@ ArpackSolver::solveI(int numModes, bool generalized, bool findSmallest) double* y = &work.workd[ipntr[1]-1]; // y = M * x - theArpackSOE->opM(n, x, y); + if (generalized == true) + theArpackSOE->opM(n, x, y); + else + // theArpackSOE->opM(n, x, y); + this->myCopy(n, x, y); // solve (K - σ M) z = y, store solution (z) into y - theVector.setData(y, n); - theSOE->setB(theVector); - theSOE->solve(); // factor Aσ and solve - const Vector& X = theSOE->getX(); - for (int i=0; isetB(theVector); + theSOE->solve(); // factor Aσ and solve + const Vector& X = theSOE->getX(); + for (int i=0; i 0) { - rvec = true; - n = size; + else { + bool rvec = true; arpack::howmny howmny = arpack::howmny::ritz_vectors; double* di = new double[nev]{}; double* workev = new double[3*ncv]{}; - double* z = new double[n*ncv]{}; - if (numModes > numModesMax) { - if (eigenvalues != nullptr) delete [] eigenvalues; - if (eigenvectors != nullptr) delete [] eigenvectors; - - eigenvalues = new double[nev]{}; - eigenvectors = new double[n * nev]{}; - - numModesMax = numModes; - } + double* z = new double[n*(nev+1)]{}; arpack::neupd(rvec, howmny, work.select, - eigenvalues, di, z, + solution.eigenvalues, di, z, work.ldv, sigma, 0.0, workev, bmat, n, which, nev, tol, @@ -524,39 +685,34 @@ ArpackSolver::solveI(int numModes, bool generalized, bool findSmallest) work.workd, work.workl, work.lworkl, info); if (info == 0) { + numMode = iparam[4]; for (int i=0; i nev+8) { - result = nev+8; - } else { - result = 2*nev+1; - } - - if (result >= n) { - result = n; - } - - return result; - - // ensure headroom and a sensible floor - int ncv = std::max({2*nev + 8, nev + 20, 20}); - ncv = std::min(ncv, n); - // ARPACK requires ncv > nev+1; enforce with a small bump if saturated - if (ncv <= nev + 1 && n > nev + 1) - ncv = std::min(n, nev + 2); - return ncv; -} - void @@ -612,16 +741,24 @@ ArpackSolver::setEigenSOE(ArpackSOE &theArpSOE) const Vector & ArpackSolver::getEigenvector(int mode) +{ + this->getEigenvector(mode, theVector); + + return theVector; +} + +int +ArpackSolver::getEigenvector(int mode, Vector &eigenvector) { if (mode <= 0 || mode > numMode) { - theVector.Zero(); + return -1; } int index = (mode - 1) * size; - theVector.setData(&eigenvectors[index], size); + eigenvector.setData(&solution.eigenvectors[index], size); - return theVector;; + return 0; } @@ -633,8 +770,8 @@ ArpackSolver::getEigenvalue(int mode) return -1; } - if (eigenvalues != nullptr) - return eigenvalues[mode-1]; + if (mode <= numMode) + return solution.eigenvalues[mode-1]; else { opserr << "ArpackSOE::getEigenvalue() - eigenvalues not yet determined"; return -2; @@ -645,20 +782,19 @@ ArpackSolver::getEigenvalue(int mode) int ArpackSolver::setSize() { - size = theArpackSOE->Msize; + size = theArpackSOE->getNumEqn(); // Msize; return 0; } int -ArpackSolver::sendSelf(int commitTag, Channel &theChannel) +ArpackSolver::sendSelf(int commitTag, Channel &) { return 0; } int -ArpackSolver::recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker) +ArpackSolver::recvSelf(int commitTag, Channel &, FEM_ObjectBroker &) { return 0; } diff --git a/SRC/system_of_eqn/eigenSOE/ArpackSolver.h b/SRC/system_of_eqn/eigenSOE/ArpackSolver.h index b44520ea4f..18e63aa2ad 100644 --- a/SRC/system_of_eqn/eigenSOE/ArpackSolver.h +++ b/SRC/system_of_eqn/eigenSOE/ArpackSolver.h @@ -55,23 +55,59 @@ class ArpackSolver : public EigenSolver int setSize(); int setEigenSOE(ArpackSOE &theSOE); - const Vector &getEigenvector(int mode); - double getEigenvalue(int mode); + const Vector &getEigenvector(int mode) final; + int getEigenvector(int mode, Vector &theVector) final; + double getEigenvalue(int mode) final; - int sendSelf(int commitTag, Channel &theChannel); - int recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker); + int sendSelf(int commitTag, Channel &); + int recvSelf(int commitTag, Channel &, FEM_ObjectBroker &theBroker); protected: private: LinearSOE *theSOE; ArpackSOE *theArpackSOE; - int numModesMax; - int numMode; int size; - double *eigenvalues; - double *eigenvectors; + int numMode; + struct EigenData { + int ndf = 0; + int numModesMax = 0; + double *eigenvalues = nullptr; + double *eigenvectors = nullptr; + + void clear() { + if (eigenvalues != nullptr) + delete [] eigenvalues; + if (eigenvectors != nullptr) + delete [] eigenvectors; + eigenvalues = nullptr; + eigenvectors = nullptr; + numModesMax = 0; + ndf = 0; + } + void zero() { + if (eigenvalues != nullptr && numModesMax > 0) + std::memset(eigenvalues, 0, numModesMax * sizeof(double)); + if (eigenvectors != nullptr && ndf > 0 && numModesMax > 0) + std::memset(eigenvectors, 0, ndf * numModesMax * sizeof(double)); + } + + void reserve(int n, int nev) { + if (numModesMax < nev) { + if (eigenvalues != nullptr) + delete [] eigenvalues; + eigenvalues = new double[nev]{}; + numModesMax = nev; + } + if (this->ndf != n || numModesMax < nev) { + if (eigenvectors != nullptr) + delete [] eigenvectors; + + eigenvectors = new double[n * nev]{}; + this->ndf = n; + } + } + } solution; Vector theVector; double shift; From 8986724dda2876448803161ed3d6d3337d292f8f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sat, 31 Jan 2026 23:05:04 -0800 Subject: [PATCH 150/161] Update EigenSolver.h --- SRC/system_of_eqn/eigenSOE/EigenSolver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SRC/system_of_eqn/eigenSOE/EigenSolver.h b/SRC/system_of_eqn/eigenSOE/EigenSolver.h index ffba6c5a44..802ffb94d7 100644 --- a/SRC/system_of_eqn/eigenSOE/EigenSolver.h +++ b/SRC/system_of_eqn/eigenSOE/EigenSolver.h @@ -26,7 +26,8 @@ class EigenSolver : public MovableObject EigenSolver(int classTag); virtual ~EigenSolver(); - virtual int solve(int numModes, bool generalized, bool findSmallest = true) =0; + virtual int solve(int numModes, bool generalized, bool findSmallest = true) =0; + virtual int getEigenvector(int mode, Vector &theVector) =0; virtual const Vector &getEigenvector(int mode) = 0; virtual double getEigenvalue(int mode) = 0; From 856428609b875505e7de02bf9880a60baf9c667a Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sat, 31 Jan 2026 23:06:31 -0800 Subject: [PATCH 151/161] Update ArpackSolver.h --- SRC/system_of_eqn/eigenSOE/ArpackSolver.h | 1 + 1 file changed, 1 insertion(+) diff --git a/SRC/system_of_eqn/eigenSOE/ArpackSolver.h b/SRC/system_of_eqn/eigenSOE/ArpackSolver.h index 18e63aa2ad..2a5a4b5353 100644 --- a/SRC/system_of_eqn/eigenSOE/ArpackSolver.h +++ b/SRC/system_of_eqn/eigenSOE/ArpackSolver.h @@ -42,6 +42,7 @@ #include #include +#include // memcpy, memset class LinearSOE; From 85b7d7407f9deadd77b61e5eceee941bd37ec899 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sat, 31 Jan 2026 23:09:02 -0800 Subject: [PATCH 152/161] implement new getEigenvector --- .../eigenSOE/FullGenEigenSolver.cpp | 206 +++++++++++++++--- .../eigenSOE/FullGenEigenSolver.h | 2 + .../eigenSOE/SymBandEigenSolver.cpp | 31 +++ .../eigenSOE/SymBandEigenSolver.h | 1 + .../eigenSOE/SymmGeneralizedEigenSolver.cpp | 21 +- .../eigenSOE/SymmGeneralizedEigenSolver.h | 1 + 6 files changed, 229 insertions(+), 33 deletions(-) diff --git a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp index e7035094b4..ff1f75953f 100644 --- a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp @@ -27,12 +27,11 @@ #include #include +#include #include #include #include -#include #include -#include #include @@ -44,6 +43,8 @@ extern "C" int DGGEV(char *JOBVL, char *JOBVR, int *N, double *A, int *LDA, int *LDVR, double *WORK, int *LWORK, int *INFO); #else +#define DGGEV dggev_ +#define DGEEV dgeev_ extern "C" int dggev_(char *JOBVL, char *JOBVR, int *N, double *A, int *LDA, double *B, int *LDB, double *ALPHAR, double *ALPHAI, @@ -52,6 +53,11 @@ extern "C" int dggev_(char *JOBVL, char *JOBVR, int *N, double *A, int *LDA, #endif +extern "C" int DGEEV(char *JOBVL, char *JOBVR, int *N, double *A, + int *LDA, double *WR, double *WI, double *VL, + int *LDVL, double *VR, int *LDVR, double *WORK, + int *LWORK, int *INFO); + FullGenEigenSolver::FullGenEigenSolver() : EigenSolver(EigenSOLVER_TAGS_FullGenEigenSolver), @@ -75,9 +81,11 @@ FullGenEigenSolver::~FullGenEigenSolver() } -int FullGenEigenSolver::solve(int nEigen, bool generalized, bool findSmallest) +int +FullGenEigenSolver::solve(int nEigen, bool generalized, bool findSmallest) { if (generalized == false) { + return this->solveI(nEigen, findSmallest); opserr << "FullGenEigenSolver::solve() - only solves generalized problem\n"; return -1; } @@ -201,7 +209,7 @@ int FullGenEigenSolver::solve(int nEigen, bool generalized, bool findSmallest) } - // sort eigenvalues in ascending order and return sorting ID + // sort eigenvalues in ascending order and return sorting ID this->sort(n, eigenvalue, sortingID); for (int i=0; isize; + numEigen = nEigen > n ? n : nEigen; + + // K matrix (standard problem: K v = lambda v) + double *Kptr = theSOE->A; + int ldK = n; + + // allocate eigenvalue storage + if (eigenvalue != nullptr) delete [] eigenvalue; + eigenvalue = new double[n]; // will hold real parts only + + // scratch for LAPACK eigenvalues (real & imag parts) + double *wr = new double[n]; + double *wi = new double[n]; + + // (re)allocate right eigenvectors buffer (column-major, n x n) + if (eigenvector != nullptr) delete [] eigenvector; + eigenvector = new double[n * n]; + int ldvr = n; + + // dummy left eigenvectors + double vl_dummy; // not referenced since jobvl = 'N' + int ldvl = 1; + + // sorting index + if (sortingID != nullptr) delete [] sortingID; + sortingID = new int[n]; + + // workspace query + int info = 0; + int lwork = -1; + double wkopt; + +#ifdef _WIN32 + DGEEV((char*)"N", (char*)"V", &n, Kptr, &ldK, wr, wi, + &vl_dummy, &ldvl, eigenvector, &ldvr, &wkopt, &lwork, &info); +#else + dgeev_((char*)"N", (char*)"V", &n, Kptr, &ldK, wr, wi, + &vl_dummy, &ldvl, eigenvector, &ldvr, &wkopt, &lwork, &info); +#endif + if (info != 0) { + opserr << "FullGenEigenSolver::solveI() - DGEEV workspace query failed, info=" << info << endln; + delete [] wr; delete [] wi; + return info < 0 ? info : -info; + } + + lwork = (int)wkopt; + double *work = new double[lwork]; + + // DGEEV call (overwrites Kptr with Schur-like data) + DGEEV((char*)"N", (char*)"V", &n, Kptr, &ldK, wr, wi, + &vl_dummy, &ldvl, eigenvector, &ldvr, work, &lwork, &info); + + if (info < 0) { + opserr << "FullGenEigenSolver::solveI() - invalid argument number " + << -info << " passed to LAPACK dgeev routine\n"; + delete [] wr; delete [] wi; delete [] work; + return info; + } + if (info > 0) { + opserr << "FullGenEigenSolver::solveI() - the LAPACK dgeev routine " + << "failed to converge, info=" << info << endln; + delete [] wr; delete [] wi; delete [] work; + return -info; + } -int FullGenEigenSolver::setSize() + // mark factored (not strictly meaningful for standard eigensolve, but kept for consistency) + theSOE->factored = true; + + // Transfer eigenvalues, flag complex ones + for (int i = 0; i < n; ++i) { + if (wi[i] == 0.0) { + eigenvalue[i] = wr[i]; + } else { + // Complex pair (columns i and i+1 contain conjugate pair in LAPACK’s real storage) + eigenvalue[i] = DBL_MAX; + opserr << "FullGenEigenSolver::solveI() - eigenvalue " << (i+1) + << " is complex with magnitude " << std::hypot(wr[i], wi[i]) << endln; + // Optionally also mark pair partner if this is the first of the pair + if (i+1 < n && wi[i+1] == -wi[i]) { + eigenvalue[i+1] = DBL_MAX; + ++i; // skip partner column since we've handled it + } + } + } + + for (int i = 0; i < n; ++i) + sortingID[i] = i; + + // Sort ascending by default + this->sort(n, eigenvalue, sortingID); + + // Flip to descending if largest requested + if (!findSmallest) { + // reverse eigenvalue[] and sortingID[] in-place + for (int i = 0, j = n-1; i < j; ++i, --j) { + std::swap(eigenvalue[i], eigenvalue[j]); + std::swap(sortingID[i], sortingID[j]); + } + } + + // Warn about undetermined (complex) among the requested numEigen + for (int i = 0; i < numEigen; ++i) { + if (eigenvalue[i] == DBL_MAX) { + opserr << "FullGenEigenSolver::solveI() - eigenvalue " + << (i+1) << " is complex/undetermined for standard (real) solve\n"; + } + } + + // Clean up + delete [] wr; + delete [] wi; + delete [] work; + + return 0; +} + +int +FullGenEigenSolver::setSize() { int size = theSOE->size; @@ -249,7 +388,8 @@ int FullGenEigenSolver::setSize() } -int FullGenEigenSolver::setEigenSOE(FullGenEigenSOE &thesoe) +int +FullGenEigenSolver::setEigenSOE(FullGenEigenSOE &thesoe) { theSOE = &thesoe; @@ -257,13 +397,22 @@ int FullGenEigenSolver::setEigenSOE(FullGenEigenSOE &thesoe) } -const Vector& FullGenEigenSolver::getEigenvector(int mode) +const Vector& +FullGenEigenSolver::getEigenvector(int mode) +{ + this->getEigenvector(mode, *eigenV); + + return *eigenV; +} + +int +FullGenEigenSolver::getEigenvector(int mode, Vector &theVector) { if (mode <= 0 || mode > numEigen) { opserr << "FullGenEigenSolver::getEigenVector() - mode " << mode << " is out of range (1 - " << numEigen << ")\n"; - eigenV->Zero(); - return *eigenV; + theVector.Zero(); + return -1; } int size = theSOE->size; @@ -271,36 +420,37 @@ const Vector& FullGenEigenSolver::getEigenvector(int mode) if (eigenvector != 0) { for (int i=0; iZero(); + theVector.Zero(); + return -2; } - return *eigenV; + return 0; } double FullGenEigenSolver::getEigenvalue(int mode) { - if (mode <= 0 || mode > numEigen) { - opserr << "FullGenEigenSolver::getEigenvalue() - mode " - << mode << " is out of range (1 - " << numEigen << ")\n"; - return 0.0; - } - - if (eigenvalue != 0) { - return eigenvalue[mode-1]; - } - else { - opserr << "FullGenEigenSolver::getEigenvalue() - " - << "eigenvalues not yet computed\n"; - return 0.0; - } + if (mode <= 0 || mode > numEigen) { + opserr << "FullGenEigenSolver::getEigenvalue() - mode " + << mode << " is out of range (1 - " << numEigen << ")\n"; + return 0.0; + } + + if (eigenvalue != 0) { + return eigenvalue[mode-1]; + } + else { + opserr << "FullGenEigenSolver::getEigenvalue() - " + << "eigenvalues not yet computed\n"; + return 0.0; + } } diff --git a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.h b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.h index ca2134d84a..fb8cc33676 100644 --- a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.h +++ b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.h @@ -44,6 +44,7 @@ class FullGenEigenSolver : public EigenSolver virtual int setEigenSOE(FullGenEigenSOE &); const Vector &getEigenvector(int mode) override; + int getEigenvector(int mode, Vector &theVector) override; double getEigenvalue(int mode) override; int sendSelf(int commitTag, Channel &); @@ -51,6 +52,7 @@ class FullGenEigenSolver : public EigenSolver private: void sort(int length, double *x, int *id); + int solveI(int nEigen, bool findSmallest); FullGenEigenSOE *theSOE; int numEigen; diff --git a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp index dc72d6c692..b9ce1c91b2 100644 --- a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp @@ -289,6 +289,37 @@ SymBandEigenSolver::getEigenvector(int mode) return *eigenV; } + +int +SymBandEigenSolver::getEigenvector(int mode, Vector& eigenV) +{ + if (mode < 1 || mode > numModes) { + opserr << "SymBandEigenSolver::getEigenVector() -- mode " << mode << " is out of range (1 - " + << numModes << ")\n"; + + eigenV.Zero(); + return -1; + } + + int size = theSOE->size; + + int index = (mode - 1) * size; + + if (eigenvector != 0) { + for (int i = 0; i < size; i++) { + eigenV(i) = eigenvector[index++]; + } + } + else { + opserr << "SymBandEigenSolver::getEigenVector() -- eigenvectors not yet computed\n"; + eigenV.Zero(); + return -2; + } + + return 0; +} + + double SymBandEigenSolver::getEigenvalue(int mode) { diff --git a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.h b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.h index f21e0234a1..1aafd6e128 100644 --- a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.h +++ b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.h @@ -46,6 +46,7 @@ class SymBandEigenSolver : public EigenSolver virtual int setEigenSOE(SymBandEigenSOE &theSOE); virtual const Vector &getEigenvector(int mode); + int getEigenvector(int mode, Vector &theVector) final; virtual double getEigenvalue(int mode); int sendSelf(int commitTag, Channel &theChannel); diff --git a/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp index 5d5ffffc05..ac67e902f3 100644 --- a/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.cpp @@ -328,12 +328,22 @@ SymmGeneralizedEigenSolver::setEigenSOE(SymmGeneralizedEigenSOE &thesoe) const Vector& SymmGeneralizedEigenSolver::getEigenvector(int mode) +{ + this->getEigenvector(mode, *eigenV); + + return *eigenV; + +} + + +int +SymmGeneralizedEigenSolver::getEigenvector(int mode, Vector &theVector) { if (mode <= 0 || mode > numEigen) { - opserr << "SymmGeneralizedEigenSolver::getEigenVector() - mode " + opserr << "SymmGeneralizedEigenSolver::getEigenvector() - mode " << mode << " is out of range (1 - " << numEigen << ")\n"; - eigenV->Zero(); - return *eigenV; + theVector.Zero(); + return -1; } int size = theSOE->size; @@ -341,16 +351,17 @@ SymmGeneralizedEigenSolver::getEigenvector(int mode) if (eigenvector != nullptr) { for (int i=0; iZero(); + return -2; } - return *eigenV; + return 0; } diff --git a/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.h b/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.h index ec474ddc6a..7e9489c015 100644 --- a/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.h +++ b/SRC/system_of_eqn/eigenSOE/SymmGeneralizedEigenSolver.h @@ -36,6 +36,7 @@ class SymmGeneralizedEigenSolver : public EigenSolver virtual int setEigenSOE(SymmGeneralizedEigenSOE &theSOE); virtual const Vector &getEigenvector(int mode); + int getEigenvector(int mode, Vector &theVector) final; virtual double getEigenvalue(int mode); int sendSelf(int commitTag, Channel &theChannel); From 3ea250316febb066ccf912bc4ea3886e718f24ec Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 14:54:49 -0800 Subject: [PATCH 153/161] Refactor ElementFE to use Element reference instead of pointer Replaces the Element pointer 'myEle' with a reference throughout ElementFE, removing null checks and updating all member accesses. --- SRC/analysis/fe_ele/ElementFE.cpp | 178 +++++++++++------------------- SRC/analysis/fe_ele/ElementFE.h | 4 +- 2 files changed, 65 insertions(+), 117 deletions(-) diff --git a/SRC/analysis/fe_ele/ElementFE.cpp b/SRC/analysis/fe_ele/ElementFE.cpp index f2df7edb83..275638d520 100644 --- a/SRC/analysis/fe_ele/ElementFE.cpp +++ b/SRC/analysis/fe_ele/ElementFE.cpp @@ -46,10 +46,11 @@ int ElementFE::numFEs(0); // number of objects ElementFE::ElementFE(int tag, Element *ele) : FE_Element(tag, (ele->getExternalNodes()).Size(), ele->getNumDOF()) , myID(ele->getNumDOF()), - numDOF(ele->getNumDOF()), myEle(ele), + numDOF(ele->getNumDOF()), myEle(*ele), theResidual(nullptr), theTangent(nullptr), theIntegrator(nullptr) { assert(numDOF > 0); + assert(myEle.isSubdomain() == false); // get elements domain & check it is valid Domain *theDomain = ele->getDomain(); @@ -109,23 +110,23 @@ ElementFE::~ElementFE() // delete tangent and residual if created specially if (numDOF > MAX_NUM_DOF) { - if (theTangent != nullptr) - delete theTangent; - if (theResidual != nullptr) - delete theResidual; + if (theTangent != nullptr) + delete theTangent; + if (theResidual != nullptr) + delete theResidual; } // if this is the last ElementFE, clean up the // storage for the matrix and vector objects if (numFEs == 0) { - for (int i=0; iformEleTangent(this); @@ -183,7 +182,6 @@ ElementFE::getTangent(Integrator *theNewIntegrator) void ElementFE::zeroTangent() { - assert(myEle != nullptr); theTangent->Zero(); } @@ -191,43 +189,37 @@ ElementFE::zeroTangent() void ElementFE::addKtToTang(double fact) { - assert (myEle != nullptr); - // check for a quick return if (fact == 0.0) - return; + return; else - theTangent->addMatrix(myEle->getTangentStiff(),fact); + theTangent->addMatrix(myEle.getTangentStiff(),fact); } void ElementFE::addCtoTang(double fact) { - assert (myEle != nullptr); - // check for a quick return if (fact == 0.0) return; else - theTangent->addMatrix(myEle->getDamp(),fact); + theTangent->addMatrix(myEle.getDamp(),fact); } void ElementFE::addMtoTang(double fact) { - if (myEle != nullptr) { - - // check for a quick return - if (fact == 0.0) - return; - else - theTangent->addMatrix(myEle->getMass(),fact); - } + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle.getMass(),fact); } + void ElementFE::addKiToTang(double fact) { @@ -235,36 +227,28 @@ ElementFE::addKiToTang(double fact) if (fact == 0.0) return; - else // if (myEle->isSubdomain() == false) - theTangent->addMatrix(myEle->getInitialStiff(), fact); + else + theTangent->addMatrix(myEle.getInitialStiff(), fact); } void ElementFE::addKpToTang(double fact, int numP) { - if (myEle != nullptr) { - // check for a quick return - if (fact == 0.0) - return; - - else if (myEle->isSubdomain() == false) { - const Matrix *thePrevMat = myEle->getPreviousK(numP); - if (thePrevMat != nullptr) - theTangent->addMatrix(*thePrevMat, fact); + // check for a quick return + if (fact == 0.0) + return; - } - } + const Matrix *thePrevMat = myEle.getPreviousK(numP); + if (thePrevMat != nullptr) + theTangent->addMatrix(*thePrevMat, fact); } + int ElementFE::storePreviousK(int numP) { - int res = 0; - if (myEle != nullptr) - res = myEle->storePreviousK(numP); - - return res; + return myEle.storePreviousK(numP); } // @@ -278,8 +262,6 @@ ElementFE::getResidual(Integrator *theNewIntegrator) if (theIntegrator == nullptr) return *theResidual; - assert(myEle != nullptr); - theNewIntegrator->formEleResidual(this); return *theResidual; } @@ -287,8 +269,6 @@ ElementFE::getResidual(Integrator *theNewIntegrator) void ElementFE::zeroResidual() { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); theResidual->Zero(); } @@ -297,15 +277,13 @@ ElementFE::zeroResidual() void ElementFE::addRtoResidual(double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); // check for a quick return if (fact == 0.0) return; else { - const Vector &eleResisting = myEle->getResistingForce(); + const Vector &eleResisting = myEle.getResistingForce(); theResidual->addVector(1.0, eleResisting, -fact); } } @@ -314,14 +292,12 @@ ElementFE::addRtoResidual(double fact) void ElementFE::addRIncInertiaToResidual(double fact) { - assert(myEle != nullptr); - // check for a quick return if (fact == 0.0) return; else { - const Vector &eleResisting = myEle->getResistingForceIncInertia(); + const Vector &eleResisting = myEle.getResistingForceIncInertia(); theResidual->addVector(1.0, eleResisting, -fact); } } @@ -330,7 +306,6 @@ ElementFE::addRIncInertiaToResidual(double fact) const Vector & ElementFE::getTangForce(const Vector &disp, double fact) { - assert(myEle != nullptr); // zero out the force vector theResidual->Zero(); @@ -362,7 +337,6 @@ ElementFE::getTangForce(const Vector &disp, double fact) const Vector & ElementFE::getK_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); // zero out the force vector theResidual->Zero(); @@ -382,7 +356,7 @@ ElementFE::getK_Force(const Vector &disp, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); + theResidual->addMatrixVector(1.0, myEle.getTangentStiff(), tmp, fact); return *theResidual; } @@ -391,7 +365,6 @@ ElementFE::getK_Force(const Vector &disp, double fact) const Vector & ElementFE::getKi_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); // zero out the force vector theResidual->Zero(); @@ -411,7 +384,7 @@ ElementFE::getKi_Force(const Vector &disp, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(myEle->getInitialStiff(), tmp, fact); + theResidual->addMatrixVector(myEle.getInitialStiff(), tmp, fact); return *theResidual; } @@ -419,7 +392,6 @@ ElementFE::getKi_Force(const Vector &disp, double fact) const Vector & ElementFE::getM_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); // zero out the force vector theResidual->Zero(); @@ -439,7 +411,7 @@ ElementFE::getM_Force(const Vector &disp, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(myEle->getMass(), tmp, fact); + theResidual->addMatrixVector(myEle.getMass(), tmp, fact); return *theResidual; } @@ -447,14 +419,12 @@ ElementFE::getM_Force(const Vector &disp, double fact) const Vector & ElementFE::getC_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - // zero out the force vector theResidual->Zero(); // check for a quick return if (fact == 0.0) - return *theResidual; + return *theResidual; // get the components we need out of the vector // and place in a temporary vector @@ -467,7 +437,7 @@ ElementFE::getC_Force(const Vector &disp, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); + theResidual->addMatrixVector(myEle.getDamp(), tmp, fact); return *theResidual; } @@ -483,7 +453,6 @@ ElementFE::getLastIntegrator() const Vector & ElementFE::getLastResponse() { - assert(myEle != nullptr); if (theIntegrator != nullptr) { if (theIntegrator->getLastResponse(*theResidual,myID) < 0) { @@ -504,9 +473,6 @@ ElementFE::getLastResponse() void ElementFE::addM_Force(const Vector &accel, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - // check for a quick return if (fact == 0.0) return; @@ -522,14 +488,12 @@ ElementFE::addM_Force(const Vector &accel, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(1.0, myEle->getMass(), tmp, fact); + theResidual->addMatrixVector(1.0, myEle.getMass(), tmp, fact); } void ElementFE::addD_Force(const Vector &accel, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); // check for a quick return if (fact == 0.0) @@ -546,14 +510,12 @@ ElementFE::addD_Force(const Vector &accel, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); + theResidual->addMatrixVector(myEle.getDamp(), tmp, fact); } void ElementFE::addK_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); // check for a quick return if (fact == 0.0) @@ -570,7 +532,7 @@ ElementFE::addK_Force(const Vector &disp, double fact) tmp(i) = 0.0; } - theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); + theResidual->addMatrixVector(1.0, myEle.getTangentStiff(), tmp, fact); } @@ -578,27 +540,23 @@ ElementFE::addK_Force(const Vector &disp, double fact) void ElementFE::addLocalM_Force(const Vector &accel, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); // check for a quick return if (fact == 0.0) return; - theResidual->addMatrixVector(myEle->getMass(), accel, fact); + theResidual->addMatrixVector(myEle.getMass(), accel, fact); } void ElementFE::addLocalD_Force(const Vector &accel, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); // check for a quick return if (fact == 0.0) return; - if (theResidual->addMatrixVector(myEle->getDamp(), accel, fact) < 0){ + if (theResidual->addMatrixVector(myEle.getDamp(), accel, fact) < 0){ opserr << "WARNING ElementFE::addLocalD_Force() - "; opserr << "- addMatrixVector returned error\n"; } @@ -608,7 +566,7 @@ ElementFE::addLocalD_Force(const Vector &accel, double fact) Element * ElementFE::getElement() { - return myEle; + return &myEle; } @@ -616,7 +574,7 @@ ElementFE::getElement() void ElementFE::addResistingForceSensitivity(int gradNumber, double fact) { - theResidual->addVector(1.0, myEle->getResistingForceSensitivity(gradNumber), -fact); + theResidual->addVector(1.0, myEle.getResistingForceSensitivity(gradNumber), -fact); } void @@ -633,35 +591,29 @@ ElementFE::addM_ForceSensitivity(int gradNumber, const Vector &vect, double fact tmp(i) = 0.0; } } - theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber),tmp,fact); + theResidual->addMatrixVector(myEle.getMassSensitivity(gradNumber),tmp,fact); } void ElementFE::addD_ForceSensitivity(int gradNumber, const Vector &vect, double fact) { - assert(myEle != nullptr); // check for a quick return if (fact == 0.0) return; - if (myEle->isSubdomain() == false) { - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = vect(loc); - else - tmp(i) = 0.0; - } - theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), tmp, fact); - } - else { - opserr << "WARNING ElementFE::addD_ForceSensitivity() - "; - opserr << "- this should not be called on a Subdomain!\n"; + // get the components we need out of the vector + // and place in a temporary vector + Vector tmp(numDOF); + for (int i=0; i= 0) + tmp(i) = vect(loc); + else + tmp(i) = 0.0; } + theResidual->addMatrixVector(myEle.getDampSensitivity(gradNumber), tmp, fact); + } void @@ -670,7 +622,7 @@ ElementFE::addLocalD_ForceSensitivity(int gradNumber, const Vector &accel, doubl // check for a quick return if (fact == 0.0) return; - theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), accel, fact); + theResidual->addMatrixVector(myEle.getDampSensitivity(gradNumber), accel, fact); } @@ -678,14 +630,12 @@ ElementFE::addLocalD_ForceSensitivity(int gradNumber, const Vector &accel, doubl void ElementFE::addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); // check for a quick return if (fact == 0.0) return; - if (theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber), accel, fact) < 0) { + if (theResidual->addMatrixVector(myEle.getMassSensitivity(gradNumber), accel, fact) < 0) { opserr << "WARNING ElementFE::addLocalD_ForceSensitivity() - "; opserr << "- addMatrixVector returned error\n"; } @@ -698,7 +648,7 @@ ElementFE::addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, doubl int ElementFE::commitSensitivity(int gradNum, int numGrads) { - myEle->commitSensitivity(gradNum, numGrads); + myEle.commitSensitivity(gradNum, numGrads); return 0; } @@ -708,7 +658,5 @@ ElementFE::commitSensitivity(int gradNum, int numGrads) int ElementFE::updateElement() { - if (myEle != nullptr) - return myEle->update(); - return 0; + return myEle.update(); } diff --git a/SRC/analysis/fe_ele/ElementFE.h b/SRC/analysis/fe_ele/ElementFE.h index cd784c2ba6..911d541a61 100644 --- a/SRC/analysis/fe_ele/ElementFE.h +++ b/SRC/analysis/fe_ele/ElementFE.h @@ -77,7 +77,7 @@ class ElementFE: public FE_Element virtual const Vector &getLastResponse(); Element *getElement() override; - virtual void Print(OPS_Stream&, int flag) {return;}; + virtual void Print(OPS_Stream&, int flag) {return;} virtual void addResistingForceSensitivity(int gradNumber, double fact = 1.0); virtual void addM_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); @@ -96,7 +96,7 @@ class ElementFE: public FE_Element private: // private variables - a copy for each object of the class int numDOF; - Element *myEle; + Element &myEle; Vector *theResidual; Matrix *theTangent; Integrator *theIntegrator; // need for Subdomain From 3775e751eb4d62bbb671d566bbb10ea7607eebbd Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 14:58:58 -0800 Subject: [PATCH 154/161] Refactor FE_Element to use abstract base and remove static storage. Refactor handlers accordingly. Removed static matrix/vector storage and related logic from FE_Element, making it an abstract base class with pure virtual methods for tangent, residual, and ID access. Removed direct element management, shifting responsibility to derived classes. --- SRC/analysis/dof_grp/DOF_Group.cpp | 248 +++--- .../dof_grp/TransformationDOF_Group.cpp | 332 ++++---- SRC/analysis/fe_ele/CMakeLists.txt | 2 + SRC/analysis/fe_ele/FE_Element.cpp | 607 +------------- SRC/analysis/fe_ele/FE_Element.h | 52 +- .../fe_ele/lagrange/LagrangeMP_FE.cpp | 67 +- SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.h | 17 +- .../fe_ele/lagrange/LagrangeSP_FE.cpp | 139 ++-- SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.h | 14 +- SRC/analysis/fe_ele/penalty/PenaltyMP_FE.cpp | 126 ++- SRC/analysis/fe_ele/penalty/PenaltyMP_FE.h | 17 +- SRC/analysis/fe_ele/penalty/PenaltySP_FE.cpp | 141 ++-- SRC/analysis/fe_ele/penalty/PenaltySP_FE.h | 24 +- .../transformation/TransformationFE.cpp | 740 +++++++++--------- .../fe_ele/transformation/TransformationFE.h | 27 +- .../handler/AutoConstraintHandler.cpp | 6 +- .../handler/LagrangeConstraintHandler.cpp | 6 +- .../handler/PenaltyConstraintHandler.cpp | 6 +- SRC/analysis/handler/PlainHandler.cpp | 6 +- .../TransformationConstraintHandler.cpp | 13 +- 20 files changed, 962 insertions(+), 1628 deletions(-) diff --git a/SRC/analysis/dof_grp/DOF_Group.cpp b/SRC/analysis/dof_grp/DOF_Group.cpp index bc00fa07fa..4ea55d0a52 100644 --- a/SRC/analysis/dof_grp/DOF_Group.cpp +++ b/SRC/analysis/dof_grp/DOF_Group.cpp @@ -43,68 +43,58 @@ Vector **DOF_Group::theVectors; // array of pointers to class widde vectors int DOF_Group::numDOFs(0); // number of objects -// DOF_Group(Node *); -// construictor that take the corresponding model node. - DOF_Group::DOF_Group(int tag, Node *node) -:TaggedObject(tag), - unbalance(0), tangent(0), myNode(node), - myID(node->getNumberDOF()), - numDOF(node->getNumberDOF()) -{ - // get number of DOF & verify valid - int numDOF = node->getNumberDOF(); - if (numDOF <= 0) { - opserr << "DOF_Group::DOF_Group(Node *) "; - opserr << " node must have at least 1 dof " << *node; - exit(-1); - } - - // check the ID created is of appropriate size - if (myID.Size() != numDOF) { - opserr << "DOF_Group::DOF_Group(Node *) "; - opserr << " ran out of memory creating ID for node " << *node; - exit(-1); - } +: TaggedObject(tag), + unbalance(0), tangent(0), myNode(node), + myID(node->getNumberDOF()), + numDOF(node->getNumberDOF()) +{ + // get number of DOF & verify valid + int numDOF = node->getNumberDOF(); + if (numDOF <= 0) { + opserr << "DOF_Group::DOF_Group(Node *) "; + opserr << " node must have at least 1 dof " << *node; + exit(-1); + } + + // initially set all the IDs to be -2 + for (int i=0; i 0); - // initially set all the IDs to be -2 - for (int i=0; iZero(); } @@ -373,25 +357,25 @@ DOF_Group::getTangForce(const Vector &Udotdot, double fact) const Vector & DOF_Group::getM_Force(const Vector &Udotdot, double fact) { - if (myNode == 0) { - opserr << "DOF_Group::getM_Force() - no Node associated"; - opserr << " subclass should not call this method \n"; - return *unbalance; - } - - Vector accel(numDOF); - // get accel for the unconstrained dof - for (int i=0; i= 0) - accel(i) = Udotdot(loc); - else accel(i) = 0.0; - } - - unbalance->Zero(); - unbalance->addMatrixVector(myNode->getMass(), accel, fact); - + if (myNode == 0) { + opserr << "DOF_Group::getM_Force() - no Node associated"; + opserr << " subclass should not call this method \n"; return *unbalance; + } + + Vector accel(numDOF); + // get accel for the unconstrained dof + for (int i=0; i= 0) + accel(i) = Udotdot(loc); + else accel(i) = 0.0; + } + + unbalance->Zero(); + unbalance->addMatrixVector(myNode->getMass(), accel, fact); + + return *unbalance; } @@ -418,24 +402,24 @@ DOF_Group::getC_Force(const Vector &Udotdot, double fact) const Vector & DOF_Group::getCommittedDisp() { - assert(myNode != nullptr); - return myNode->getDisp(); + assert(myNode != nullptr); + return myNode->getDisp(); } const Vector & DOF_Group::getCommittedVel() { - assert(myNode != nullptr); - return myNode->getVel(); + assert(myNode != nullptr); + return myNode->getVel(); } const Vector & DOF_Group::getCommittedAccel() { - assert(myNode != nullptr); - return myNode->getAccel(); + assert(myNode != nullptr); + return myNode->getAccel(); } // void setNodeDisp(const Vector &u); @@ -633,7 +617,7 @@ DOF_Group::getEigenvectors() Matrix * -DOF_Group::getT(void) +DOF_Group::getT() { return 0; } @@ -668,15 +652,16 @@ DOF_Group::getVelSensitivity(int gradNumber) return result; } - + + const Vector & DOF_Group::getAccSensitivity(int gradNumber) { - Vector &result = *unbalance; - for (int i=0; igetAccSensitivity(i+1,gradNumber); + Vector &result = *unbalance; + for (int i=0; igetAccSensitivity(i+1,gradNumber); - return result; + return result; } @@ -697,6 +682,7 @@ DOF_Group::saveDispSensitivity(const Vector &v, int gradNum, int numGrads) return myNode->saveDispSensitivity(dudh, gradNum, numGrads); } + int DOF_Group::saveVelSensitivity(const Vector &v, int gradNum, int numGrads) { @@ -796,7 +782,7 @@ DOF_Group::addD_ForceSensitivity(const Vector &Udot, double fact) // AddingSensitivity:END ////////////////////////////////////////// void -DOF_Group::resetNodePtr(void) +DOF_Group::resetNodePtr() { myNode = 0; } diff --git a/SRC/analysis/dof_grp/TransformationDOF_Group.cpp b/SRC/analysis/dof_grp/TransformationDOF_Group.cpp index 0a3608a205..8b7bd71ab8 100644 --- a/SRC/analysis/dof_grp/TransformationDOF_Group.cpp +++ b/SRC/analysis/dof_grp/TransformationDOF_Group.cpp @@ -54,124 +54,124 @@ TransformationDOF_Group::TransformationDOF_Group(int tag, Node *node, :DOF_Group(tag,node), theMP(mp),Trans(0),modTangent(0),modUnbalance(0),modID(0),theSPs(0) { - // determine the number of DOF - int numNodalDOF = node->getNumberDOF(); - const ID &retainedDOF = mp->getRetainedDOFs(); - const ID &constrainedDOF = mp->getConstrainedDOFs(); - int numNodalDOFConstrained = constrainedDOF.Size(); - numConstrainedNodeRetainedDOF = numNodalDOF - numNodalDOFConstrained; - needRetainedData = -1; + // determine the number of DOF + int numNodalDOF = node->getNumberDOF(); + const ID &retainedDOF = mp->getRetainedDOFs(); + const ID &constrainedDOF = mp->getConstrainedDOFs(); + int numNodalDOFConstrained = constrainedDOF.Size(); + numConstrainedNodeRetainedDOF = numNodalDOF - numNodalDOFConstrained; + needRetainedData = -1; - int numRetainedNodeDOF = retainedDOF.Size(); + int numRetainedNodeDOF = retainedDOF.Size(); - modNumDOF = numConstrainedNodeRetainedDOF + numRetainedNodeDOF; + modNumDOF = numConstrainedNodeRetainedDOF + numRetainedNodeDOF; + + // create space for the SP_Constraint array + theSPs = new SP_Constraint *[numNodalDOF]; + for (int ii=0; iigetDomain(); + int nodeTag = node->getTag(); + SP_ConstraintIter &theSPIter = theDomain->getSPs(); + SP_Constraint *sp; + while ((sp = theSPIter()) != 0) { +if (sp->getNodeTag() == nodeTag) { + int dof = sp->getDOF_Number(); + int loc = 0; + for (int i=0; iSize() == 0 || + Trans == 0 || Trans->noRows() == 0) { + + opserr << "FATAL TransformationDOF_Group::TransformationDOF_Group() -"; + opserr << " ran out of memory for size: " << modNumDOF << endln; + exit(-1); + } - /*********************** - // set the SP_Constraint corresponding to the dof in modID - Domain *theDomain=node->getDomain(); - int nodeTag = node->getTag(); - SP_ConstraintIter &theSPIter = theDomain->getSPs(); - SP_Constraint *sp; - while ((sp = theSPIter()) != 0) { - if (sp->getNodeTag() == nodeTag) { - int dof = sp->getDOF_Number(); - int loc = 0; - for (int i=0; iSize() == 0 || - Trans == 0 || Trans->noRows() == 0) { - - opserr << "FATAL TransformationDOF_Group::TransformationDOF_Group() -"; - opserr << " ran out of memory for size: " << modNumDOF << endln; - exit(-1); + for (int i=0; iSize() != modNumDOF || - modTangent == 0 || modTangent->noCols() != modNumDOF) { - opserr << "TransformationDOF_Group::TransformationDOF_Group(Node *) "; - opserr << " ran out of memory for vector/Matrix of size :"; - opserr << modNumDOF << endln; - exit(-1); + modTangent == 0 || modTangent->noCols() != modNumDOF) { + opserr << "TransformationDOF_Group::TransformationDOF_Group(Node *) "; + opserr << " ran out of memory for vector/Matrix of size :"; + opserr << modNumDOF << endln; + exit(-1); } - } else { - modUnbalance = modVectors[modNumDOF]; - modTangent = modMatrices[modNumDOF]; - } } else { - // create matrices and vectors for each object instance - modUnbalance = new Vector(modNumDOF); - modTangent = new Matrix(modNumDOF, modNumDOF); - if (modUnbalance == 0 || modTangent ==0 || - modTangent ==0 || modTangent->noRows() ==0) { - - opserr << "TransformationDOF_Group::TransformationDOF_Group(Node *) "; - opserr << " ran out of memory for vector/Matrix of size :"; - opserr << modNumDOF << endln; - exit(-1); - } + modUnbalance = modVectors[modNumDOF]; + modTangent = modMatrices[modNumDOF]; + } + } else { + // create matrices and vectors for each object instance + modUnbalance = new Vector(modNumDOF); + modTangent = new Matrix(modNumDOF, modNumDOF); + if (modUnbalance == 0 || modTangent ==0 || + modTangent ==0 || modTangent->noRows() ==0) { + + opserr << "TransformationDOF_Group::TransformationDOF_Group(Node *) "; + opserr << " ran out of memory for vector/Matrix of size :"; + opserr << modNumDOF << endln; + exit(-1); } + } #ifdef TRANSF_INCREMENTAL_MP modTotalDisp.resize(modNumDOF); modTotalDisp = getTrialDisp(); #endif // TRANSF_INCREMENTAL_MP - - numTransDOFs++; - theHandler = theTHandler; + + numTransDOFs++; + theHandler = theTHandler; } void @@ -216,15 +216,15 @@ TransformationDOF_Group::TransformationDOF_Group(int tag, if (numTransDOFs == 0) { modMatrices = new Matrix *[MAX_NUM_DOF+1]; modVectors = new Vector *[MAX_NUM_DOF+1]; - - if (modMatrices == 0 || modVectors == 0) { - opserr << "TransformationDOF_Group::TransformationDOF_Group(Node *) "; - opserr << " ran out of memory"; - } - for (int i=0; iDOF_Group::getNumFreeDOF(); + if (modID != 0) { + int numFreeDOF = modNumDOF; + for (int i=0; iDOF_Group::getNumFreeDOF(); } int -TransformationDOF_Group::getNumConstrainedDOF(void) const +TransformationDOF_Group::getNumConstrainedDOF() const { if (modID != 0) { int numConstr = 0; @@ -366,7 +366,7 @@ TransformationDOF_Group::getUnbalance(Integrator *theIntegrator) const Vector & -TransformationDOF_Group::getCommittedDisp(void) +TransformationDOF_Group::getCommittedDisp() { const Vector &responseC = myNode->getDisp(); @@ -400,7 +400,7 @@ TransformationDOF_Group::getCommittedDisp(void) } const Vector & -TransformationDOF_Group::getCommittedVel(void) +TransformationDOF_Group::getCommittedVel() { const Vector &responseC = myNode->getVel(); @@ -589,7 +589,7 @@ TransformationDOF_Group::setNodeVel(const Vector &u) for (int i=numConstrainedNodeRetainedDOF, j=0; igetID(); - - int retainedNode = theMP->getNodeRetained(); - Domain *theDomain = myNode->getDomain(); - Node *retainedNodePtr = theDomain->getNode(retainedNode); - const Vector &responseR = retainedNodePtr->getTrialDisp(); - const ID &retainedDOF = theMP->getRetainedDOFs(); - - modUnbalance->Zero(); - for (int i=numConstrainedNodeRetainedDOF, j=0; igetT(); - if (T != 0) { - - // *unbalance = (*T) * (*modUnbalance); - unbalance->addMatrixVector(0.0, *T, *modUnbalance, 1.0); - - const ID &constrainedDOF = theMP->getConstrainedDOFs(); - for (int i=0; isetTrialDisp((*unbalance)(cDOF), cDOF); - } - } + const ID &theID = this->getID(); + + int retainedNode = theMP->getNodeRetained(); + Domain *theDomain = myNode->getDomain(); + Node *retainedNodePtr = theDomain->getNode(retainedNode); + const Vector &responseR = retainedNodePtr->getTrialDisp(); + const ID &retainedDOF = theMP->getRetainedDOFs(); + + modUnbalance->Zero(); + for (int i=numConstrainedNodeRetainedDOF, j=0; igetT(); + if (T != 0) { + + // *unbalance = (*T) * (*modUnbalance); + unbalance->addMatrixVector(0.0, *T, *modUnbalance, 1.0); + + const ID &constrainedDOF = theMP->getConstrainedDOFs(); + for (int i=0; isetTrialDisp((*unbalance)(cDOF), cDOF); + } + } } } } @@ -1094,24 +1092,24 @@ TransformationDOF_Group::enforceSPs(int doMP) void TransformationDOF_Group::addM_Force(const Vector &Udotdot, double fact) { - // call base class method and return if no MP_Constraint - if (theMP == 0 || modID == 0) { - this->DOF_Group::addM_Force(Udotdot, fact); - return; - } - - for (int i=0; i= 0) - (*modUnbalance)(i) = Udotdot(loc); - else // DO THE SP STUFF - (*modUnbalance)(i) = 0.0; - } + // call base class method and return if no MP_Constraint + if (theMP == 0 || modID == 0) { + this->DOF_Group::addM_Force(Udotdot, fact); + return; + } + + for (int i=0; i= 0) + (*modUnbalance)(i) = Udotdot(loc); + else // DO THE SP STUFF + (*modUnbalance)(i) = 0.0; + } - Vector unmod(Trans->noRows()); - //unmod = (*Trans) * (*modUnbalance); - unmod.addMatrixVector(0.0, *Trans, *modUnbalance, 1.0); - this->addLocalM_Force(unmod, fact); + Vector unmod(Trans->noRows()); + //unmod = (*Trans) * (*modUnbalance); + unmod.addMatrixVector(0.0, *Trans, *modUnbalance, 1.0); + this->addLocalM_Force(unmod, fact); } diff --git a/SRC/analysis/fe_ele/CMakeLists.txt b/SRC/analysis/fe_ele/CMakeLists.txt index a520f0e158..f1e71a2382 100644 --- a/SRC/analysis/fe_ele/CMakeLists.txt +++ b/SRC/analysis/fe_ele/CMakeLists.txt @@ -7,6 +7,8 @@ target_sources(OPS_Analysis PRIVATE FE_Element.cpp + ElementFE.cpp + SubdomainFE.cpp PUBLIC FE_Element.h ) diff --git a/SRC/analysis/fe_ele/FE_Element.cpp b/SRC/analysis/fe_ele/FE_Element.cpp index 718948188c..2b4fb80f7a 100644 --- a/SRC/analysis/fe_ele/FE_Element.cpp +++ b/SRC/analysis/fe_ele/FE_Element.cpp @@ -41,110 +41,12 @@ #define MAX_NUM_DOF 64 -// static variables initialisation -Matrix **FE_Element::theMatrices; // pointers to class wide matrices -Vector **FE_Element::theVectors; // pointers to class widde vectors -int FE_Element::numFEs(0); // number of objects - - -// constructor that take the corresponding model element. -FE_Element::FE_Element(int tag, Element *ele) - : TaggedObject(tag) - , myDOF_Groups((ele->getExternalNodes()).Size()) - , myID(ele->getNumDOF()), - numDOF(ele->getNumDOF()), theModel(0), myEle(ele), - theResidual(nullptr), theTangent(nullptr), theIntegrator(nullptr) -{ - assert(numDOF > 0); - - // get elements domain & check it is valid - Domain *theDomain = ele->getDomain(); - assert(theDomain != nullptr); - - // keep a pointer to all DOF_Groups - int numGroups = ele->getNumExternalNodes(); - const ID &nodes = ele->getExternalNodes(); - - for (int i=0; igetNode(nodes(i)); - assert(nodePtr != nullptr); - - DOF_Group *dofGrpPtr = nodePtr->getDOF_GroupPtr(); - assert(dofGrpPtr != nullptr); - myDOF_Groups(i) = dofGrpPtr->getTag(); - } - - // if this is the first FE_Element we now - // create the arrays used to store pointers to class wide - // matrix and vector objects used to return tangent and residual - if (numFEs == 0) { - theMatrices = new Matrix *[MAX_NUM_DOF+1]; - theVectors = new Vector *[MAX_NUM_DOF+1]; - - for (int i=0; iisSubdomain() == false) { - - // if Elements are not subdomains, set up pointers to - // objects to return tangent Matrix and residual Vector. - if (numDOF <= MAX_NUM_DOF) { - // use class wide objects - if (theVectors[numDOF] == nullptr) { - theVectors[numDOF] = new Vector(numDOF); - theMatrices[numDOF] = new Matrix(numDOF,numDOF); - theResidual = theVectors[numDOF]; - theTangent = theMatrices[numDOF]; - - } else { - theResidual = theVectors[numDOF]; - theTangent = theMatrices[numDOF]; - } - - } else { - // create matrices and vectors for each object instance - theResidual = new Vector(numDOF); - theTangent = new Matrix(numDOF, numDOF); - } - - } else { - // as subdomains have own matrix for tangent and residual don't need - // to set matrix and vector pointers to these objects - theResidual = new Vector(numDOF); - // invoke setFE_ElementPtr() method on Subdomain - Subdomain *theSub = (Subdomain *)ele; - theSub->setFE_ElementPtr(this); - } - - // increment number of FE_Elements by 1 - numFEs++; -} - - FE_Element::FE_Element(int tag, int numDOF_Group, int ndof) :TaggedObject(tag), - myDOF_Groups(numDOF_Group), myID(ndof), numDOF(ndof), theModel(nullptr), - myEle(nullptr), theResidual(nullptr), theTangent(nullptr), theIntegrator(nullptr) + myDOF_Groups(numDOF_Group), numDOF(ndof), theModel(nullptr), + theResidual(nullptr), theTangent(nullptr), theIntegrator(nullptr) { // this is for a subtype, the subtype must set the myDOF_Groups ID array - numFEs++; - - // if this is the first FE_Element we now - // create the arrays used to store pointers to class wide - // matrix and vector objects used to return tangent and residual - if (numFEs == 0) { - theMatrices = new Matrix *[MAX_NUM_DOF+1]; - theVectors = new Vector *[MAX_NUM_DOF+1]; - - for (int i=0; i MAX_NUM_DOF) { - if (theTangent != nullptr) - delete theTangent; - if (theResidual != nullptr) - delete theResidual; - } - - // if this is the last FE_Element, clean up the - // storage for the matrix and vector objects - if (numFEs == 0) { - for (int i=0; igetDOF_GroupPtr(tag); - assert(dofPtr != nullptr); - - const ID &theDOFid = dofPtr->getID(); - - for (int j=0; jisSubdomain() == false) { - if (theNewIntegrator != nullptr) - theNewIntegrator->formEleTangent(this); - - return *theTangent; - - } else { - Subdomain *theSub = (Subdomain *)myEle; - theSub->computeTang(); - return theSub->getTang(); + if (this->setID(*theModel) == 0) { + return 0; } + return -1; } void FE_Element::zeroTangent() { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - theTangent->Zero(); } void FE_Element::addKtToTang(double fact) { - assert (myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - else - theTangent->addMatrix(myEle->getTangentStiff(),fact); } void FE_Element::addCtoTang(double fact) { - assert (myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - else - theTangent->addMatrix(myEle->getDamp(),fact); } void FE_Element::addMtoTang(double fact) { - if (myEle != nullptr) { - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - else - theTangent->addMatrix(myEle->getMass(),fact); - } } void FE_Element::addKiToTang(double fact) { - if (myEle != nullptr) { - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - else // if (myEle->isSubdomain() == false) - theTangent->addMatrix(myEle->getInitialStiff(), fact); - } } void FE_Element::addKpToTang(double fact, int numP) { - if (myEle != nullptr) { - // check for a quick return - if (fact == 0.0) - return; - - else if (myEle->isSubdomain() == false) { - const Matrix *thePrevMat = myEle->getPreviousK(numP); - if (thePrevMat != nullptr) - theTangent->addMatrix(*thePrevMat, fact); - - } else { - opserr << "WARNING FE_Element::addKpToTang() - "; - opserr << "- this should not be called on a Subdomain!\n"; - } - } } int FE_Element::storePreviousK(int numP) { - int res = 0; - if (myEle != nullptr) - res = myEle->storePreviousK(numP); - - return res; } // // RESIDUAL // -const Vector & -FE_Element::getResidual(Integrator *theNewIntegrator) -{ - theIntegrator = theNewIntegrator; - - if (theIntegrator == nullptr) - return *theResidual; - - assert(myEle != nullptr); - - if (myEle->isSubdomain() == false) { - theNewIntegrator->formEleResidual(this); - return *theResidual; - - } else { - Subdomain *theSub = (Subdomain *)myEle; - theSub->computeResidual(); - return theSub->getResistingForce(); - } -} void FE_Element::zeroResidual() { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - theResidual->Zero(); } void FE_Element::addRtoResidual(double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - else { - const Vector &eleResisting = myEle->getResistingForce(); - theResidual->addVector(1.0, eleResisting, -fact); - } } void FE_Element::addRIncInertiaToResidual(double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - else { - const Vector &eleResisting = myEle->getResistingForceIncInertia(); - theResidual->addVector(1.0, eleResisting, -fact); - } } const Vector & FE_Element::getTangForce(const Vector &disp, double fact) { - assert(myEle != nullptr); - - // zero out the force vector - theResidual->Zero(); - - // check for a quick return - if (fact == 0.0) - return *theResidual; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = disp(myID(i)); - else - tmp(i) = 0.0; - } - - if (myEle->isSubdomain() == false) { - // form the tangent again and then add the force - theIntegrator->formEleTangent(this); - theResidual->addMatrixVector(*theTangent,tmp,fact); - - } else { - theResidual->addMatrixVector(((Subdomain *)myEle)->getTang(),tmp,fact); - } return *theResidual; } @@ -453,28 +165,6 @@ FE_Element::getTangForce(const Vector &disp, double fact) const Vector & FE_Element::getK_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - - // zero out the force vector - theResidual->Zero(); - - // check for a quick return - if (fact == 0.0) - return *theResidual; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = disp(myID(i)); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); - return *theResidual; } @@ -482,84 +172,18 @@ FE_Element::getK_Force(const Vector &disp, double fact) const Vector & FE_Element::getKi_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - - // zero out the force vector - theResidual->Zero(); - - // check for a quick return - if (fact == 0.0) - return *theResidual; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = disp(myID(i)); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(myEle->getInitialStiff(), tmp, fact); - return *theResidual; } const Vector & FE_Element::getM_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - - // zero out the force vector - theResidual->Zero(); - - // check for a quick return - if (fact == 0.0) - return *theResidual; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = disp(myID(i)); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(myEle->getMass(), tmp, fact); - return *theResidual; } const Vector & FE_Element::getC_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - - // zero out the force vector - theResidual->Zero(); - - // check for a quick return - if (fact == 0.0) - return *theResidual; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = disp(myID(i)); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); - return *theResidual; } @@ -574,254 +198,45 @@ FE_Element::getLastIntegrator() const Vector & FE_Element::getLastResponse() { - assert(myEle != nullptr); - - if (theIntegrator != nullptr) { - if (theIntegrator->getLastResponse(*theResidual,myID) < 0) { - opserr << "WARNING FE_Element::getLastResponse()"; - opserr << " - the Integrator had problems with getLastResponse()\n"; - } - } - else { - theResidual->Zero(); - opserr << "WARNING FE_Element::getLastResponse()"; - opserr << " No Integrator yet passed\n"; - } - - Vector &result = *theResidual; - return result; + return *theResidual; } -void -FE_Element::addM_Force(const Vector &accel, double fact) -{ - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = accel(loc); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(1.0, myEle->getMass(), tmp, fact); -} void FE_Element::addD_Force(const Vector &accel, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = accel(loc); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(myEle->getDamp(), tmp, fact); } void FE_Element::addK_Force(const Vector &disp, double fact) { - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = disp(loc); - else - tmp(i) = 0.0; - } - - theResidual->addMatrixVector(1.0, myEle->getTangentStiff(), tmp, fact); -} - - - -void -FE_Element::addLocalM_Force(const Vector &accel, double fact) -{ - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - theResidual->addMatrixVector(myEle->getMass(), accel, fact); -} - -void -FE_Element::addLocalD_Force(const Vector &accel, double fact) -{ - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - if (theResidual->addMatrixVector(myEle->getDamp(), accel, fact) < 0){ - opserr << "WARNING FE_Element::addLocalD_Force() - "; - opserr << "- addMatrixVector returned error\n"; - } } -Element * -FE_Element::getElement() -{ - return myEle; -} - // AddingSensitivity:BEGIN ///////////////////////////////// void FE_Element::addResistingForceSensitivity(int gradNumber, double fact) { - theResidual->addVector(1.0, myEle->getResistingForceSensitivity(gradNumber), -fact); + // theResidual->addVector(1.0, myEle->getResistingForceSensitivity(gradNumber), -fact); } void FE_Element::addM_ForceSensitivity(int gradNumber, const Vector &vect, double fact) { - // Get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) { - tmp(i) = vect(loc); - } else { - tmp(i) = 0.0; - } - } - if (theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber),tmp,fact) < 0) { - opserr << "WARNING FE_Element::addM_ForceSensitivity() - "; - opserr << "- addMatrixVector returned error\n"; - } } void FE_Element::addD_ForceSensitivity(int gradNumber, const Vector &vect, double fact) { - assert(myEle != nullptr); - - // check for a quick return - if (fact == 0.0) - return; - - if (myEle->isSubdomain() == false) { - // get the components we need out of the vector - // and place in a temporary vector - Vector tmp(numDOF); - for (int i=0; i= 0) - tmp(i) = vect(loc); - else - tmp(i) = 0.0; - } - if (theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), tmp, fact) < 0){ - opserr << "WARNING FE_Element::addD_ForceSensitivity() - "; - opserr << "- addMatrixVector returned error\n"; - } - } - else { - opserr << "WARNING FE_Element::addD_ForceSensitivity() - "; - opserr << "- this should not be called on a Subdomain!\n"; - } -} - -void -FE_Element::addLocalD_ForceSensitivity(int gradNumber, const Vector &accel, double fact) -{ - if (myEle != nullptr) { - // check for a quick return - if (fact == 0.0) - return; - if (myEle->isSubdomain() == false) { - if (theResidual->addMatrixVector(myEle->getDampSensitivity(gradNumber), - accel, fact) < 0){ - - opserr << "WARNING FE_Element::addLocalD_ForceSensitivity() - "; - opserr << "- addMatrixVector returned error\n"; - } - } - else { - opserr << "WARNING FE_Element::addLocalD_ForceSensitivity() - "; - opserr << "- this should not be called on a Subdomain!\n"; - } - } - else { - opserr << "WARNING FE_Element::addLocalD_ForceSensitivity() - no Element *given "; - opserr << "- subclasses must provide implementation\n"; - } } -void -FE_Element::addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, double fact) -{ - assert(myEle != nullptr); - assert(myEle->isSubdomain() == false); - - // check for a quick return - if (fact == 0.0) - return; - - if (theResidual->addMatrixVector(myEle->getMassSensitivity(gradNumber), accel, fact) < 0) { - opserr << "WARNING FE_Element::addLocalD_ForceSensitivity() - "; - opserr << "- addMatrixVector returned error\n"; - } -} - - - - - int FE_Element::commitSensitivity(int gradNum, int numGrads) { - myEle->commitSensitivity(gradNum, numGrads); return 0; } // AddingSensitivity:END //////////////////////////////////// - -int -FE_Element::updateElement() -{ - if (myEle != nullptr) - return myEle->update(); - return 0; -} diff --git a/SRC/analysis/fe_ele/FE_Element.h b/SRC/analysis/fe_ele/FE_Element.h index 84b9d47538..38d38e598f 100644 --- a/SRC/analysis/fe_ele/FE_Element.h +++ b/SRC/analysis/fe_ele/FE_Element.h @@ -41,26 +41,28 @@ class AnalysisModel; class FE_Element: public TaggedObject { public: - FE_Element(int tag, Element *theElement); FE_Element(int tag, int numDOF_Group, int ndof); virtual ~FE_Element(); + static constexpr int MaxNumDOFs = 100; // + // public methods for setting/obtaining mapping information - virtual const ID &getDOFtags() const; - virtual const ID &getID() const; void setAnalysisModel(AnalysisModel &); - virtual int setID(); + int setID(); + virtual int setID(AnalysisModel &) =0; + virtual const ID &getDOFtags() const final; + virtual const ID &getID() const = 0; // methods to form and obtain the tangent and residual - virtual const Matrix &getTangent(Integrator *); - virtual const Vector &getResidual(Integrator *); + virtual const Matrix &getTangent(Integrator *)=0; + virtual const Vector &getResidual(Integrator *)=0; // methods called by integrator to build tangent - void zeroTangent() ; - void addKtToTang(double fact = 1.0) ; - void addKiToTang(double fact = 1.0) ; - void addCtoTang (double fact = 1.0) ; - void addMtoTang (double fact = 1.0) ; + virtual void zeroTangent() ; + virtual void addKtToTang(double fact = 1.0) ; + virtual void addKiToTang(double fact = 1.0) ; + virtual void addCtoTang (double fact = 1.0) ; + virtual void addMtoTang (double fact = 1.0) ; virtual void addKpToTang(double fact = 1.0, int numP = 0); virtual int storePreviousK(int numP); @@ -75,17 +77,15 @@ class FE_Element: public TaggedObject virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); - virtual void addM_Force(const Vector &accel, double fact = 1.0); + virtual void addM_Force(const Vector &accel, double fact = 1.0){} virtual void addD_Force(const Vector &vel, double fact = 1.0); virtual void addK_Force(const Vector &disp, double fact = 1.0); - virtual int updateElement(); - virtual Integrator *getLastIntegrator(); virtual const Vector &getLastResponse(); - Element *getElement(); + virtual Element *getElement() {return nullptr;} - virtual void Print(OPS_Stream&, int flag) {return;}; + virtual void Print(OPS_Stream&, int flag) {return;} virtual void addResistingForceSensitivity(int gradNumber, double fact = 1.0); virtual void addM_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); @@ -93,31 +93,15 @@ class FE_Element: public TaggedObject virtual int commitSensitivity (int gradNum, int numGrads); protected: - void addLocalM_Force(const Vector &accel, double fact = 1.0); - void addLocalD_Force(const Vector &vel, double fact = 1.0); - void addLocalM_ForceSensitivity(int gradNumber, const Vector &accel, double fact = 1.0); - void addLocalD_ForceSensitivity(int gradNumber, const Vector &vel, double fact = 1.0); - - // protected variables - a copy for each object of the class ID myDOF_Groups; - ID myID; - private: - // private variables - a copy for each object of the class int numDOF; AnalysisModel *theModel; - Element *myEle; Vector *theResidual; Matrix *theTangent; Integrator *theIntegrator; // need for Subdomain - - // - // static variables - // - static Matrix **theMatrices; // array of pointers to class wide matrices - static Vector **theVectors; // array of pointers to class widde vectors - static int numFEs; // number of objects - + static double static_matrix_data[MaxNumDOFs*MaxNumDOFs]; + static double static_vector_data[MaxNumDOFs]; }; #endif diff --git a/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.cpp b/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.cpp index 2465681fba..e86f4431d0 100644 --- a/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.cpp +++ b/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.cpp @@ -52,6 +52,9 @@ LagrangeMP_FE::LagrangeMP_FE(int tag, Domain &theDomain, MP_Constraint &TheMP, : FE_Element(tag, 3, TheMP.getConstrainedDOFs().Size() + TheMP.getRetainedDOFs().Size() + TheMP.getRetainedDOFs().Size()), // *see note 1 + myID( TheMP.getConstrainedDOFs().Size() + + TheMP.getRetainedDOFs().Size() + + TheMP.getRetainedDOFs().Size()), // *see note 1 alpha(Alpha), theMP(&TheMP), theConstrainedNode(0), theRetainedNode(0), theDofGroup(&theGroup), tang(0), resid(0) @@ -123,7 +126,7 @@ LagrangeMP_FE::~LagrangeMP_FE() // void setID(int index, int value); // Method to set the correMPonding index of the ID to value. int -LagrangeMP_FE::setID(void) +LagrangeMP_FE::setID(AnalysisModel& theModel) { int result = 0; @@ -131,15 +134,15 @@ LagrangeMP_FE::setID(void) // as constrained DOFs, this is obtained from the DOF_Group // associated with the constrained node if (theConstrainedNode == 0) { - opserr << "WARNING LagrangeMP_FE::setID(void)"; - opserr << "- no asscoiated Constrained Node\n"; - return -1; + opserr << "WARNING LagrangeMP_FE::setID()"; + opserr << "- no asscoiated Constrained Node\n"; + return -1; } DOF_Group *theConstrainedNodesDOFs = theConstrainedNode->getDOF_GroupPtr(); if (theConstrainedNodesDOFs == 0) { - opserr << "WARNING LagrangeMP_FE::setID(void)"; - opserr << " - no DOF_Group with Constrained Node\n"; - return -2; + opserr << "WARNING LagrangeMP_FE::setID(void)"; + opserr << " - no DOF_Group with Constrained Node\n"; + return -2; } const ID &constrainedDOFs = theMP->getConstrainedDOFs(); @@ -147,38 +150,38 @@ LagrangeMP_FE::setID(void) int size1 = constrainedDOFs.Size(); for (int i=0; i= theConstrainedNode->getNumberDOF()) { - - opserr << "WARNING LagrangeMP_FE::setID(void) - unknown DOF "; - opserr << constrained << " at Node\n"; - myID(i) = -1; // modify so nothing will be added to equations - result = -3; - } - else { - if (constrained >= theConstrainedNodesID.Size()) { - opserr << "WARNING LagrangeMP_FE::setID(void) - "; - opserr << " Nodes DOF_Group too small\n"; - myID(i) = -1; // modify so nothing will be added to equations - result = -4; - } - else - myID(i) = theConstrainedNodesID(constrained); - } + int constrained = constrainedDOFs(i); + if (constrained < 0 || + constrained >= theConstrainedNode->getNumberDOF()) { + + opserr << "WARNING LagrangeMP_FE::setID(void) - unknown DOF "; + opserr << constrained << " at Node\n"; + myID(i) = -1; // modify so nothing will be added to equations + result = -3; + } + else { + if (constrained >= theConstrainedNodesID.Size()) { + opserr << "WARNING LagrangeMP_FE::setID(void) - "; + opserr << " Nodes DOF_Group too small\n"; + myID(i) = -1; // modify so nothing will be added to equations + result = -4; + } + else + myID(i) = theConstrainedNodesID(constrained); + } } // now determine the IDs for the retained dof's if (theRetainedNode == 0) { - opserr << "WARNING LagrangeMP_FE::setID(void)"; - opserr << "- no asscoiated Retained Node\n"; - return -1; + opserr << "WARNING LagrangeMP_FE::setID(void)"; + opserr << "- no asscoiated Retained Node\n"; + return -1; } DOF_Group *theRetainedNodesDOFs = theRetainedNode->getDOF_GroupPtr(); if (theRetainedNodesDOFs == 0) { - opserr << "WARNING LagrangeMP_FE::setID(void)"; - opserr << " - no DOF_Group with Retained Node\n"; - return -2; + opserr << "WARNING LagrangeMP_FE::setID(void)"; + opserr << " - no DOF_Group with Retained Node\n"; + return -2; } const ID &RetainedDOFs = theMP->getRetainedDOFs(); diff --git a/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.h b/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.h index 2d934035ba..bcf5022218 100644 --- a/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.h +++ b/SRC/analysis/fe_ele/lagrange/LagrangeMP_FE.h @@ -55,24 +55,25 @@ class LagrangeMP_FE: public FE_Element virtual ~LagrangeMP_FE(); // public methods - virtual int setID() final; - virtual const Matrix &getTangent(Integrator *theIntegrator); - virtual const Vector &getResidual(Integrator *theIntegrator) final; -// virtual const Vector &getResidual(StaticIntegrator &theIntegrator) final { -// return this->getResidual(static_cast(&theIntegrator)); -// }; + int setID(AnalysisModel&) final; + const ID &getID() const final {return myID;}; + const Matrix &getTangent(Integrator *) final; + const Vector &getResidual(Integrator *) final; virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); virtual const Vector &getK_Force(const Vector &x, double fact = 1.0); virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); - virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + + void zeroTangent() final {tang? tang->Zero() : void();}; protected: private: + ID myID; double alpha; - void determineTangent(void); + void determineTangent(); MP_Constraint *theMP; Node *theConstrainedNode; diff --git a/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.cpp b/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.cpp index 50e4bacab7..2b9d1e8469 100644 --- a/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.cpp +++ b/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.cpp @@ -50,44 +50,39 @@ LagrangeSP_FE::LagrangeSP_FE(int tag, Domain &theDomain, SP_Constraint &TheSP, DOF_Group &theGroup, double Alpha) :FE_Element(tag, 2,2), + myID(2), alpha(Alpha), tang(0), resid(0), theSP(&TheSP), theDofGroup(&theGroup) { - // create a Matrix and a Vector for the tangent and residual - tang = new Matrix(2,2); - resid = new Vector(2); - if ((tang == 0) || (tang->noCols() == 0) || (resid == 0) || - (resid->Size() == 0)) { - opserr << "WARNING LagrangeSP_FE::LagrangeSP_FE()"; - opserr << "- ran out of memory\n"; - exit(-1); - } - - // zero the Matrix and Vector - resid->Zero(); - tang->Zero(); - - theNode = theDomain.getNode(theSP->getNodeTag()); - if (theNode == 0) { - opserr << "WARNING LagrangeSP_FE::LagrangeSP_FE()"; - opserr << "- no asscoiated Node\n"; - exit(-1); - } - - // set the tangent - (*tang)(0,1) = alpha; - (*tang)(1,0) = alpha; - - // set the myDOF_Groups tags indicating the attached id's of the - // DOF_Group objects - DOF_Group *theNodesDOFs = theNode->getDOF_GroupPtr(); - if (theNodesDOFs == 0) { - opserr << "WARNING LagrangeSP_FE::LagrangeSP_FE()"; - opserr << " - no DOF_Group with Constrained Node\n"; - exit(-1); - } - - myDOF_Groups(0) = theNodesDOFs->getTag(); - myDOF_Groups(1) = theDofGroup->getTag(); + // create a Matrix and a Vector for the tangent and residual + tang = new Matrix(2,2); + resid = new Vector(2); + + // zero the Matrix and Vector + resid->Zero(); + tang->Zero(); + + theNode = theDomain.getNode(theSP->getNodeTag()); + if (theNode == 0) { + opserr << "WARNING LagrangeSP_FE::LagrangeSP_FE()"; + opserr << "- no asscoiated Node\n"; + exit(-1); + } + + // set the tangent + (*tang)(0,1) = alpha; + (*tang)(1,0) = alpha; + + // set the myDOF_Groups tags indicating the attached id's of the + // DOF_Group objects + DOF_Group *theNodesDOFs = theNode->getDOF_GroupPtr(); + if (theNodesDOFs == 0) { + opserr << "WARNING LagrangeSP_FE::LagrangeSP_FE()"; + opserr << " - no DOF_Group with Constrained Node\n"; + exit(-1); + } + + myDOF_Groups(0) = theNodesDOFs->getTag(); + myDOF_Groups(1) = theDofGroup->getTag(); } LagrangeSP_FE::~LagrangeSP_FE() @@ -101,33 +96,33 @@ LagrangeSP_FE::~LagrangeSP_FE() // void setID(int index, int value); // Method to set the correSPonding index of the ID to value. int -LagrangeSP_FE::setID(void) +LagrangeSP_FE::setID(AnalysisModel& theModel) { - int result = 0; - - // first determine the IDs in myID for those DOFs marked - // as constrained DOFs, this is obtained from the DOF_Group - // associated with the constrained node - DOF_Group *theNodesDOFs = theNode->getDOF_GroupPtr(); - if (theNodesDOFs == 0) { - opserr << "WARNING LagrangeSP_FE::setID(void)"; - opserr << " - no DOF_Group with Constrained Node\n"; - return -1; - } - - int restrainedDOF = theSP->getDOF_Number(); - const ID &theNodesID = theNodesDOFs->getID(); - - if (restrainedDOF < 0 || restrainedDOF >= theNodesID.Size()) { - opserr << "WARNING LagrangeSP_FE::setID(void)"; - opserr << " - restrained DOF invalid\n"; - return -2; - } - - myID(0) = theNodesID(restrainedDOF); - myID(1) = (theDofGroup->getID())(0); - - return result; + int result = 0; + + // first determine the IDs in myID for those DOFs marked + // as constrained DOFs, this is obtained from the DOF_Group + // associated with the constrained node + DOF_Group *theNodesDOFs = theNode->getDOF_GroupPtr(); + if (theNodesDOFs == 0) { + opserr << "WARNING LagrangeSP_FE::setID()"; + opserr << " - no DOF_Group with Constrained Node\n"; + return -1; + } + + int restrainedDOF = theSP->getDOF_Number(); + const ID &theNodesID = theNodesDOFs->getID(); + + if (restrainedDOF < 0 || restrainedDOF >= theNodesID.Size()) { + opserr << "WARNING LagrangeSP_FE::setID()"; + opserr << " - restrained DOF invalid\n"; + return -2; + } + + myID(0) = theNodesID(restrainedDOF); + myID(1) = (theDofGroup->getID())(0); + + return result; } const Matrix & @@ -179,16 +174,16 @@ LagrangeSP_FE::getResidual(Integrator *theNewIntegrator) const Vector & LagrangeSP_FE::getTangForce(const Vector &disp, double fact) { - double constraint = theSP->getValue(); - int constrainedID = myID(1); - if (constrainedID < 0 || constrainedID >= disp.Size()) { - opserr << "WARNING LagrangeSP_FE::getTangForce() - "; - opserr << " constrained DOF " << constrainedID << " outside disp\n"; - (*resid)(1) = constraint*alpha; - return *resid; - } - (*resid)(1) = disp(constrainedID); - return *resid; + double constraint = theSP->getValue(); + int constrainedID = myID(1); + if (constrainedID < 0 || constrainedID >= disp.Size()) { + opserr << "WARNING LagrangeSP_FE::getTangForce() - "; + opserr << " constrained DOF " << constrainedID << " outside disp\n"; + (*resid)(1) = constraint*alpha; + return *resid; + } + (*resid)(1) = disp(constrainedID); + return *resid; } const Vector & diff --git a/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.h b/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.h index e269471093..c31a0a3049 100644 --- a/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.h +++ b/SRC/analysis/fe_ele/lagrange/LagrangeSP_FE.h @@ -57,21 +57,21 @@ class LagrangeSP_FE: public FE_Element virtual ~LagrangeSP_FE(); // public methods - virtual int setID(); - virtual const Matrix &getTangent(Integrator *theIntegrator); - virtual const Vector &getResidual(Integrator *theIntegrator) final; -// virtual const Vector &getResidual(StaticIntegrator &theIntegrator) final { -// return this->getResidual(static_cast(&theIntegrator)); -// }; + int setID(AnalysisModel& ) final; + const ID &getID() const final {return myID;}; + virtual const Matrix &getTangent(Integrator *); + virtual const Vector &getResidual(Integrator *) final; virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); virtual const Vector &getK_Force(const Vector &x, double fact = 1.0); virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); - virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + void zeroTangent() final {tang? tang->Zero() : void();} protected: private: + ID myID; double alpha; Matrix *tang; Vector *resid; diff --git a/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.cpp b/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.cpp index 4a84ba19c6..6fcd1b4881 100644 --- a/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.cpp +++ b/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.cpp @@ -51,7 +51,9 @@ PenaltyMP_FE::PenaltyMP_FE(int tag, Domain &theDomain, MP_Constraint &TheMP, double Alpha) :FE_Element(tag, 2,(TheMP.getConstrainedDOFs()).Size()+ - (TheMP.getRetainedDOFs()).Size()), + (TheMP.getRetainedDOFs()).Size()), + myID( (TheMP.getConstrainedDOFs()).Size()+ + (TheMP.getRetainedDOFs()).Size()), theMP(&TheMP), theConstrainedNode(0) , theRetainedNode(0), tang(0), resid(0), C(0), alpha(Alpha) { @@ -112,7 +114,7 @@ PenaltyMP_FE::~PenaltyMP_FE() // void setID(int index, int value); // Method to set the correMPonding index of the ID to value. int -PenaltyMP_FE::setID() +PenaltyMP_FE::setID(AnalysisModel &) { int result = 0; @@ -121,10 +123,10 @@ PenaltyMP_FE::setID() // associated with the constrained node DOF_Group *theConstrainedNodesDOFs = theConstrainedNode->getDOF_GroupPtr(); if (theConstrainedNodesDOFs == 0) { - opserr << "WARNING PenaltyMP_FE::setID(void)"; - opserr << " - no DOF_Group with Constrained Node\n"; - return -2; - } + opserr << "WARNING PenaltyMP_FE::setID(void)"; + opserr << " - no DOF_Group with Constrained Node\n"; + return -2; + } const ID &constrainedDOFs = theMP->getConstrainedDOFs(); const ID &theConstrainedNodesID = theConstrainedNodesDOFs->getID(); @@ -201,41 +203,41 @@ PenaltyMP_FE::getTangent(Integrator *theNewIntegrator) const Vector & PenaltyMP_FE::getResidual(Integrator *theNewIntegrator) { - // zero residual, CD = 0 + // zero residual, CD = 0 - // get the solution vector [Uc Ur] - static Vector UU; - const ID& id1 = theMP->getConstrainedDOFs(); - const ID& id2 = theMP->getRetainedDOFs(); - int size = id1.Size() + id2.Size(); - UU.resize(size); - const Vector& Uc = theConstrainedNode->getTrialDisp(); - const Vector& Ur = theRetainedNode->getTrialDisp(); - const Vector& Uc0 = theMP->getConstrainedDOFsInitialDisplacement(); - const Vector& Ur0 = theMP->getRetainedDOFsInitialDisplacement(); - for (int i = 0; i < id1.Size(); ++i) { - int cdof = id1(i); - if (cdof < 0 || cdof >= Uc.Size()) { - opserr << "PenaltyMP_FE::getResidual FATAL Error: Constrained DOF " << cdof << " out of bounds [0-" << Uc.Size() << "]\n"; - exit(-1); - } - UU(i) = Uc(cdof) - Uc0(i); - } - for (int i = 0; i < id2.Size(); ++i) { - int rdof = id2(i); - if (rdof < 0 || rdof >= Ur.Size()) { - opserr << "PenaltyMP_FE::getResidual FATAL Error: Retained DOF " << rdof << " out of bounds [0-" << Ur.Size() << "]\n"; - exit(-1); - } - UU(i+id1.Size()) = Ur(rdof) - Ur0(i); - } + // get the solution vector [Uc Ur] + static Vector UU; + const ID& id1 = theMP->getConstrainedDOFs(); + const ID& id2 = theMP->getRetainedDOFs(); + int size = id1.Size() + id2.Size(); + UU.resize(size); + const Vector& Uc = theConstrainedNode->getTrialDisp(); + const Vector& Ur = theRetainedNode->getTrialDisp(); + const Vector& Uc0 = theMP->getConstrainedDOFsInitialDisplacement(); + const Vector& Ur0 = theMP->getRetainedDOFsInitialDisplacement(); + for (int i = 0; i < id1.Size(); ++i) { + int cdof = id1(i); + if (cdof < 0 || cdof >= Uc.Size()) { + opserr << "PenaltyMP_FE::getResidual FATAL Error: Constrained DOF " << cdof << " out of bounds [0-" << Uc.Size() << "]\n"; + exit(-1); + } + UU(i) = Uc(cdof) - Uc0(i); + } + for (int i = 0; i < id2.Size(); ++i) { + int rdof = id2(i); + if (rdof < 0 || rdof >= Ur.Size()) { + opserr << "PenaltyMP_FE::getResidual FATAL Error: Retained DOF " << rdof << " out of bounds [0-" << Ur.Size() << "]\n"; + exit(-1); + } + UU(i+id1.Size()) = Ur(rdof) - Ur0(i); + } - // compute residual - const Matrix& KK = getTangent(theNewIntegrator); - resid->addMatrixVector(0.0, KK, UU, -1.0); + // compute residual + const Matrix& KK = getTangent(theNewIntegrator); + resid->addMatrixVector(0.0, KK, UU, -1.0); - // done - return *resid; + // done + return *resid; } @@ -276,42 +278,26 @@ PenaltyMP_FE::getM_Force(const Vector &disp, double fact) } void -PenaltyMP_FE::determineTangent(void) +PenaltyMP_FE::determineTangent() { - // first determine [C] = [-I [Ccr]] - C->Zero(); - const Matrix &constraint = theMP->getConstraint(); - int noRows = constraint.noRows(); - int noCols = constraint.noCols(); - - for (int j=0; jZero(); + const Matrix &constraint = theMP->getConstraint(); + int noRows = constraint.noRows(); + int noCols = constraint.noCols(); - for (int i=0; inoRows(); - int cols = C->noCols(); - Matrix CT(cols,rows); - const Matrix &Cref = *C; - // Fill in the transpose of C - for (int k = 0; k < cols; k++) - for (int l = 0; l < rows; l++) - CT(k,l) = Cref(l,k); - // Compute alpha*(C^*C) - tang->addMatrixProduct(0.0, CT, Cref, alpha); - */ - // workaround no longer required - const Matrix &Cref = *C; - tang->addMatrixTransposeProduct(0.0, Cref, Cref, alpha); + // now form the tangent: [K] = alpha * [C]^t[C] + // *(tang) = (*C)^(*C); + // *(tang) *= alpha; + const Matrix &Cref = *C; + tang->addMatrixTransposeProduct(0.0, Cref, Cref, alpha); } diff --git a/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.h b/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.h index b3861849ea..532cf297d7 100644 --- a/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.h +++ b/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.h @@ -18,11 +18,6 @@ ** ** ** ****************************************************************** */ -// $Revision: 1.4 $ -// $Date: 2006-02-08 20:20:00 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/fe_ele/penalty/PenaltyMP_FE.h,v $ - - #ifndef PenaltyMP_FE_h #define PenaltyMP_FE_h @@ -51,11 +46,12 @@ class Node; class PenaltyMP_FE: public FE_Element { public: - PenaltyMP_FE(int tag, Domain &theDomain, MP_Constraint &theMP, double alpha); + PenaltyMP_FE(int tag, Domain &, MP_Constraint &, double alpha); virtual ~PenaltyMP_FE(); // public methods - virtual int setID(void); + int setID(AnalysisModel &) final; + const ID &getID() const final {return myID;} virtual const Matrix &getTangent(Integrator *theIntegrator); virtual const Vector &getResidual(Integrator *theIntegrator); virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); @@ -64,11 +60,13 @@ class PenaltyMP_FE: public FE_Element virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + void zeroTangent() final {tang? tang->Zero() : void();}; protected: private: - void determineTangent(void); + void determineTangent(); + ID myID; MP_Constraint *theMP; Node *theConstrainedNode; @@ -78,8 +76,7 @@ class PenaltyMP_FE: public FE_Element Vector *resid; Matrix *C; // to hold the C matrix double alpha; - - + }; #endif diff --git a/SRC/analysis/fe_ele/penalty/PenaltySP_FE.cpp b/SRC/analysis/fe_ele/penalty/PenaltySP_FE.cpp index cf020df1b5..0a1d88fd7b 100644 --- a/SRC/analysis/fe_ele/penalty/PenaltySP_FE.cpp +++ b/SRC/analysis/fe_ele/penalty/PenaltySP_FE.cpp @@ -17,12 +17,7 @@ ** Filip C. Filippou (filippou@ce.berkeley.edu) ** ** ** ** ****************************************************************** */ - -// $Revision: 1.8 $ -// $Date: 2009-10-13 21:13:01 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/fe_ele/penalty/PenaltySP_FE.cpp,v $ - - +// // File: ~/analysis/fe_ele/penalty/PenaltySP_FE.C // // Written: fmk @@ -54,22 +49,22 @@ Matrix PenaltySP_FE::tang(1,1); Vector PenaltySP_FE::resid(1); PenaltySP_FE::PenaltySP_FE(int tag, Domain &theDomain, - SP_Constraint &TheSP, double Alpha) + SP_Constraint &TheSP, double Alpha) :FE_Element(tag, 1,1), alpha(Alpha), theSP(&TheSP), theNode(0) { - // get a pointer to the Node - theNode = theDomain.getNode(theSP->getNodeTag()); - if (theNode == 0) { - opserr << "FATAL PenaltySP_FE::PenaltySP_FE() - no Node: "; - opserr << theSP->getNodeTag() << "in domain\n"; - exit(-1); - } - - // set the DOF_Group tags - DOF_Group *dofGrpPtr = theNode->getDOF_GroupPtr(); - if (dofGrpPtr != 0) - myDOF_Groups(0) = dofGrpPtr->getTag(); + // get a pointer to the Node + theNode = theDomain.getNode(theSP->getNodeTag()); + if (theNode == 0) { + opserr << "FATAL PenaltySP_FE::PenaltySP_FE() - no Node: "; + opserr << theSP->getNodeTag() << "in domain\n"; + exit(-1); + } + + // set the DOF_Group tags + DOF_Group *dofGrpPtr = theNode->getDOF_GroupPtr(); + if (dofGrpPtr != 0) + myDOF_Groups(0) = dofGrpPtr->getTag(); } @@ -79,34 +74,34 @@ PenaltySP_FE::~PenaltySP_FE() } // void setID(int index, int value); -// Method to set the corresponding index of the ID to value. +// Method to set the corresponding index of the ID to value. int -PenaltySP_FE::setID(void) +PenaltySP_FE::setID(AnalysisModel &) { - DOF_Group *theNodesDOFs = theNode->getDOF_GroupPtr(); - if (theNodesDOFs == 0) { - opserr << "WARNING PenaltySP_FE::setID(void) - no DOF_Group with Node\n"; - return -2; - } - myDOF_Groups(0) = theNodesDOFs->getTag(); - - int restrainedDOF = theSP->getDOF_Number(); - if (restrainedDOF < 0 || restrainedDOF >= theNode->getNumberDOF()) { - opserr << "WARNING PenaltySP_FE::setID(void) - unknown DOF "; - opserr << restrainedDOF << " at Node\n"; - return -3; - } - const ID &theNodesID = theNodesDOFs->getID(); - if (restrainedDOF >= theNodesID.Size()) { - opserr << "WARNING PenaltySP_FE::setID(void) - "; - opserr << " Nodes DOF_Group too small\n"; - return -4; - } - - myID(0) = theNodesID(restrainedDOF); - - return 0; + DOF_Group *theNodesDOFs = theNode->getDOF_GroupPtr(); + if (theNodesDOFs == 0) { + opserr << "WARNING PenaltySP_FE::setID(void) - no DOF_Group with Node\n"; + return -2; + } + myDOF_Groups(0) = theNodesDOFs->getTag(); + + int restrainedDOF = theSP->getDOF_Number(); + if (restrainedDOF < 0 || restrainedDOF >= theNode->getNumberDOF()) { + opserr << "WARNING PenaltySP_FE::setID(void) - unknown DOF "; + opserr << restrainedDOF << " at Node\n"; + return -3; + } + const ID &theNodesID = theNodesDOFs->getID(); + if (restrainedDOF >= theNodesID.Size()) { + opserr << "WARNING PenaltySP_FE::setID(void) - "; + opserr << " Nodes DOF_Group too small\n"; + return -4; + } + + myID(0) = theNodesID(restrainedDOF); + + return 0; } @@ -121,41 +116,41 @@ PenaltySP_FE::getTangent(Integrator *theNewIntegrator) const Vector & PenaltySP_FE::getResidual(Integrator *theNewIntegrator) { - double constraint = theSP->getValue(); - double initialValue = theSP->getInitialValue(); - int constrainedDOF = theSP->getDOF_Number(); - const Vector &nodeDisp = theNode->getTrialDisp(); - - if (constrainedDOF < 0 || constrainedDOF >= nodeDisp.Size()) { - opserr << "WARNING PenaltySP_FE::getTangForce() - "; - opserr << " constrained DOF " << constrainedDOF << " outside disp\n"; - resid(0) = 0; - } - - // (*resid)(0) = alpha * (constraint - nodeDisp(constrainedDOF)); - // is replace with the following to remove possible problems with - // subtracting very small numbers - - resid(0) = alpha * (constraint - (nodeDisp(constrainedDOF) - initialValue)); - - return resid; + double constraint = theSP->getValue(); + double initialValue = theSP->getInitialValue(); + int constrainedDOF = theSP->getDOF_Number(); + const Vector &nodeDisp = theNode->getTrialDisp(); + + if (constrainedDOF < 0 || constrainedDOF >= nodeDisp.Size()) { + opserr << "WARNING PenaltySP_FE::getTangForce() - "; + opserr << " constrained DOF " << constrainedDOF << " outside disp\n"; + resid(0) = 0; + } + + // (*resid)(0) = alpha * (constraint - nodeDisp(constrainedDOF)); + // is replace with the following to remove possible problems with + // subtracting very small numbers + + resid(0) = alpha * (constraint - (nodeDisp(constrainedDOF) - initialValue)); + + return resid; } const Vector & PenaltySP_FE::getTangForce(const Vector &disp, double fact) { - // double constraint = theSP->getValue(); - int constrainedID = myID(0); - if (constrainedID < 0 || constrainedID >= disp.Size()) { - opserr << "WARNING PenaltySP_FE::getTangForce() - "; - opserr << " constrained DOF " << constrainedID << " outside disp\n"; - resid(0) = 0.0; - return resid; - } - resid(0) = alpha * disp(constrainedID); - - return resid; + // double constraint = theSP->getValue(); + int constrainedID = myID(0); + if (constrainedID < 0 || constrainedID >= disp.Size()) { + opserr << "WARNING PenaltySP_FE::getTangForce() - "; + opserr << " constrained DOF " << constrainedID << " outside disp\n"; + resid(0) = 0.0; + return resid; + } + resid(0) = alpha * disp(constrainedID); + + return resid; } const Vector & diff --git a/SRC/analysis/fe_ele/penalty/PenaltySP_FE.h b/SRC/analysis/fe_ele/penalty/PenaltySP_FE.h index 51a22fd38b..b059891c94 100644 --- a/SRC/analysis/fe_ele/penalty/PenaltySP_FE.h +++ b/SRC/analysis/fe_ele/penalty/PenaltySP_FE.h @@ -17,24 +17,19 @@ ** Filip C. Filippou (filippou@ce.berkeley.edu) ** ** ** ** ****************************************************************** */ - -// $Revision: 1.5 $ -// $Date: 2008-11-19 23:38:29 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/fe_ele/penalty/PenaltySP_FE.h,v $ - - #ifndef PenaltySP_FE_h #define PenaltySP_FE_h - -// Written: fmk -// Created: 11/96 -// Revision: A // // Description: This file contains the class definition for PenaltySP_FE. // PenaltySP_FE is a subclass of FE_Element which handles SP_Constraints // using the penalty method. // // What: "@(#) PenaltySP_FE.h, revA" +// +// Written: fmk +// Created: 11/96 +// Revision: A +// #include #include @@ -51,11 +46,12 @@ class Node; class PenaltySP_FE: public FE_Element { public: - PenaltySP_FE(int tag, Domain &theDomain, SP_Constraint &theSP, double alpha=1.0e8); + PenaltySP_FE(int tag, Domain &, SP_Constraint &, double alpha=1.0e8); virtual ~PenaltySP_FE(); // public methods - virtual int setID(void); + int setID(AnalysisModel& ) final; + const ID &getID() const final {return myID;} virtual const Matrix &getTangent(Integrator *theIntegrator); virtual const Vector &getResidual(Integrator *theIntegrator); virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); @@ -63,11 +59,13 @@ class PenaltySP_FE: public FE_Element virtual const Vector &getK_Force(const Vector &x, double fact = 1.0); virtual const Vector &getKi_Force(const Vector &x, double fact = 1.0); virtual const Vector &getC_Force(const Vector &x, double fact = 1.0); - virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + virtual const Vector &getM_Force(const Vector &x, double fact = 1.0); + void zeroTangent() final {tang.Zero();} protected: private: + ID myID; double alpha; SP_Constraint *theSP; Node *theNode; diff --git a/SRC/analysis/fe_ele/transformation/TransformationFE.cpp b/SRC/analysis/fe_ele/transformation/TransformationFE.cpp index 75ad16f8d7..98f13f05f8 100644 --- a/SRC/analysis/fe_ele/transformation/TransformationFE.cpp +++ b/SRC/analysis/fe_ele/transformation/TransformationFE.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -47,84 +48,75 @@ Matrix **TransformationFE::theTransformations; int TransformationFE::numTransFE(0); int TransformationFE::transCounter(0); int TransformationFE::sizeTransformations(0); -double *TransformationFE::dataBuffer = 0; +double *TransformationFE::dataBuffer = 0; double *TransformationFE::localKbuffer = 0; -int *TransformationFE::dofData = 0; ; +int *TransformationFE::dofData = 0; int TransformationFE::sizeBuffer(0); + // TransformationFE(Element *, Integrator *theIntegrator); -// construictor that take the corresponding model element. +// construictor that take the corresponding model element. TransformationFE::TransformationFE(int tag, Element *ele) -:FE_Element(tag, ele), theDOFs(0), numSPs(0), theSPs(0), modID(0), +: ElementFE(tag, ele), + theDOFs(0), numSPs(0), theSPs(0), modID(0), modTangent(0), modResidual(0), numGroups(0), numTransformedDOF(0) { - // set number of original dof at ele - numOriginalDOF = ele->getNumDOF(); - - // create the array of pointers to DOF_Groups - const ID &nodes = ele->getExternalNodes(); - Domain *theDomain = ele->getDomain(); - int numNodes = nodes.Size(); - theDOFs = new DOF_Group *[numNodes]; - - numGroups = numNodes; - - // now fill the array of DOF_Group pointers - for (int i=0; igetNode(nodes(i)); - if (theNode == 0) { - opserr << "FATAL TransformationFE::TransformationFE() - no Node with tag: "; - opserr << nodes(i) << " in the domain\n";; - exit(-1); - } - DOF_Group *theDofGroup = theNode->getDOF_GroupPtr(); - if (theDofGroup == 0) { - opserr << "FATAL TransformationFE::TransformationFE() - no DOF_Group : "; - opserr << " associated with node: " << nodes(i) << " in the domain\n";; - exit(-1); - } - theDOFs[i] = theDofGroup; + // set number of original dof at ele + numOriginalDOF = ele->getNumDOF(); + + // create the array of pointers to DOF_Groups + const ID &nodes = ele->getExternalNodes(); + Domain *theDomain = ele->getDomain(); + int numNodes = nodes.Size(); + theDOFs = new DOF_Group *[numNodes]; + + numGroups = numNodes; + + // now fill the array of DOF_Group pointers + for (int i=0; igetNode(nodes(i)); + if (theNode == 0) { + opserr << "FATAL TransformationFE::TransformationFE() - no Node with tag: "; + opserr << nodes(i) << " in the domain\n";; + exit(-1); + } + DOF_Group *theDofGroup = theNode->getDOF_GroupPtr(); + if (theDofGroup == 0) { + opserr << "FATAL TransformationFE::TransformationFE() - no DOF_Group : "; + opserr << " associated with node: " << nodes(i) << " in the domain\n";; + exit(-1); } + theDOFs[i] = theDofGroup; + } - // see if theTransformation array is big enough - // if not delete the old and create a new one - if (numNodes > sizeTransformations) { - if (theTransformations != 0) - delete [] theTransformations; - - theTransformations = new Matrix *[numNodes]; - if (theTransformations == 0) { - opserr << "FATAL TransformationFE::TransformationFE() - out of memory "; - opserr << "for array of pointers for Transformation matrices of size "; - opserr << numNodes; - exit(-1); - } - sizeTransformations = numNodes; - } - - // if this is the first element of this type create the arrays for - // modified tangent and residual matrices - if (numTransFE == 0) { - modMatrices = new Matrix *[MAX_NUM_DOF+1]; - modVectors = new Vector *[MAX_NUM_DOF+1]; - dataBuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF]; - localKbuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF]; - dofData = new int[MAX_NUM_DOF]; - sizeBuffer = MAX_NUM_DOF*MAX_NUM_DOF; - - if (modMatrices == 0 || modVectors == 0 || dataBuffer == 0 || - localKbuffer == 0 || dofData == 0) { - opserr << "TransformationFE::TransformationFE(Element *) "; - opserr << " ran out of memory"; - } - for (int i=0; i sizeTransformations) { + if (theTransformations != 0) + delete [] theTransformations; + + theTransformations = new Matrix *[numNodes]; + sizeTransformations = numNodes; + } + + // if this is the first element of this type create the arrays for + // modified tangent and residual matrices + if (numTransFE == 0) { + modMatrices = new Matrix *[MAX_NUM_DOF+1]; + modVectors = new Vector *[MAX_NUM_DOF+1]; + dataBuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF]; + localKbuffer = new double[MAX_NUM_DOF*MAX_NUM_DOF]; + dofData = new int[MAX_NUM_DOF]; + sizeBuffer = MAX_NUM_DOF*MAX_NUM_DOF; + + for (int i=0; iFE_Element::getDOFtags(); -} - const ID & -TransformationFE::getID(void) const +TransformationFE::getID() const { // make sure that it exists if (modID == 0) { @@ -198,7 +184,7 @@ TransformationFE::getID(void) const int -TransformationFE::setID() +TransformationFE::setID(AnalysisModel&) { // determine number of DOF numTransformedDOF = 0; @@ -229,7 +215,7 @@ TransformationFE::setID() opserr << "WARNING TransformationFE::setID() - numDOF and"; opserr << " number of dof at the DOF_Groups\n"; return -3; - } + } } // set the pointers to the modified tangent matrix and residual vector @@ -240,13 +226,6 @@ TransformationFE::setID() modMatrices[numTransformedDOF] = new Matrix(numTransformedDOF,numTransformedDOF); modResidual = modVectors[numTransformedDOF]; modTangent = modMatrices[numTransformedDOF]; - if (modResidual == 0 || modResidual->Size() != numTransformedDOF || - modTangent == 0 || modTangent->noCols() != numTransformedDOF) { - opserr << "TransformationFE::setID() "; - opserr << " ran out of memory for vector/Matrix of size :"; - opserr << numTransformedDOF << endln; - exit(-1); - } } else { modResidual = modVectors[numTransformedDOF]; modTangent = modMatrices[numTransformedDOF]; @@ -255,14 +234,6 @@ TransformationFE::setID() // create matrices and vectors for each object instance modResidual = new Vector(numTransformedDOF); modTangent = new Matrix(numTransformedDOF, numTransformedDOF); - if (modResidual == 0 || modResidual->Size() ==0 || - modTangent ==0 || modTangent->noRows() ==0) { - - opserr << "TransformationFE::setID() "; - opserr << " ran out of memory for vector/Matrix of size :"; - opserr << numTransformedDOF << endln; - exit(-1); - } } return 0; @@ -271,99 +242,99 @@ TransformationFE::setID() const Matrix & TransformationFE::getTangent(Integrator *theNewIntegrator) { - const Matrix &theTangent = this->FE_Element::getTangent(theNewIntegrator); + const Matrix &theTangent = this->ElementFE::getTangent(theNewIntegrator); - static ID numDOFs(dofData, 1); - numDOFs.setData(dofData, numGroups); - - // DO THE SP STUFF TO THE TANGENT - - // get the transformation matrix from each dof group & number of local dof - // for original node. - int numNode = numGroups; - for (int a = 0; agetT(); - theTransformations[a] = theT; - if (theT != 0) - numDOFs[a] = theT->noRows(); // T^ - else - numDOFs[a] = theDOFs[a]->getNumDOF(); - } + static ID numDOFs(dofData, 1); + numDOFs.setData(dofData, numGroups); + + // DO THE SP STUFF TO THE TANGENT + + // get the transformation matrix from each dof group & number of local dof + // for original node. + int numNode = numGroups; + for (int a = 0; agetT(); + theTransformations[a] = theT; + if (theT != 0) + numDOFs[a] = theT->noRows(); // T^ + else + numDOFs[a] = theDOFs[a]->getNumDOF(); + } + + // perform Tt K T -- as T is block diagonal do T(i)^T K(i,j) T(j) + // where blocks are of size equal to num ele dof at a node + + int startRow = 0; + int noRowsTransformed = 0; + int noRowsOriginal = 0; + + static Matrix localK; + + // foreach block row, for each block col do + for (int i=0; inoCols(); - noColsTransformed = Tj->noCols(); - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - //localTtKT = (*Ti) ^ localK * (*Tj); - localTtKT.addMatrixTripleProduct(0.0, *Ti, localK, *Tj, 1.0); - } else if (Ti == 0 && Tj != 0) { - noRowsTransformed = numDOFi; - noColsTransformed = Tj->noCols(); - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - // localTtKT = localK * (*Tj); - localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); - } else if (Ti != 0 && Tj == 0) { - noRowsTransformed = Ti->noCols(); - noColsTransformed = numDOFj; - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - //localTtKT = (*Ti) ^ localK; - localTtKT.addMatrixTransposeProduct(0.0, *Ti, localK, 1.0); - } else { - noRowsTransformed = numDOFi; - noColsTransformed = numDOFj; - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - localTtKT = localK; - } - // now copy into modTangent the T(i)^t K(i,j) T(j) product - for (int c=0; cnoCols(); + noColsTransformed = Tj->noCols(); + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + //localTtKT = (*Ti) ^ localK * (*Tj); + localTtKT.addMatrixTripleProduct(0.0, *Ti, localK, *Tj, 1.0); + } else if (Ti == 0 && Tj != 0) { + noRowsTransformed = numDOFi; + noColsTransformed = Tj->noCols(); + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + // localTtKT = localK * (*Tj); + localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); + } else if (Ti != 0 && Tj == 0) { + noRowsTransformed = Ti->noCols(); + noColsTransformed = numDOFj; + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + //localTtKT = (*Ti) ^ localK; + localTtKT.addMatrixTransposeProduct(0.0, *Ti, localK, 1.0); + } else { + noRowsTransformed = numDOFi; + noColsTransformed = numDOFj; + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + localTtKT = localK; + } + // now copy into modTangent the T(i)^t K(i,j) T(j) product + for (int c=0; cFE_Element::getResidual(theNewIntegrator); - // DO THE SP STUFF TO THE TANGENT - - // perform Tt R -- as T is block diagonal do T(i)^T R(i) - // where blocks are of size equal to num ele dof at a node - - int startRowTransformed = 0; - int startRowOriginal = 0; - int numNode = numGroups; - - // foreach block row, for each block col do - for (int i=0; igetT(); - if (Ti != 0) { - noRows = Ti->noCols(); // T^ - noCols = Ti->noRows(); - - /* - Vector orig(noCols); - Vector mod(noRows); - for (int k=startRowOriginal; kgetNumDOF(); - noRows = noCols; - for (int j=0; jElementFE::getResidual(theNewIntegrator); + // DO THE SP STUFF TO THE TANGENT + + // perform Tt R -- as T is block diagonal do T(i)^T R(i) + // where blocks are of size equal to num ele dof at a node + + int startRowTransformed = 0; + int startRowOriginal = 0; + int numNode = numGroups; + + // foreach block row, for each block col do + for (int i=0; igetT(); + if (Ti != 0) { + noRows = Ti->noCols(); // T^ + noCols = Ti->noRows(); + + /* + Vector orig(noCols); + Vector mod(noRows); + for (int k=startRowOriginal; kgetNumDOF(); + noRows = noCols; + for (int j=0; jZero(); - return *modResidual; + opserr << "TransformationFE::getTangForce() - not yet implemented\n"; + modResidual->Zero(); + return *modResidual; } const Vector & TransformationFE::getK_Force(const Vector &accel, double fact) { - this->FE_Element::zeroTangent(); - this->FE_Element::addKtToTang(); - const Matrix &theTangent = this->FE_Element::getTangent(0); + this->ElementFE::zeroTangent(); + this->ElementFE::addKtToTang(); + const Matrix &theTangent = this->ElementFE::getTangent(0); static ID numDOFs(dofData, 1); numDOFs.setData(dofData, numGroups); @@ -469,18 +441,18 @@ TransformationFE::getK_Force(const Vector &accel, double fact) for (int i=0; inoCols(); // CHECK SIZE OF BUFFER localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - // localTtKT = localK * (*Tj); + // localTtKT = localK * (*Tj); localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); } else if (Ti != 0 && Tj == 0) { noRowsTransformed = Ti->noCols(); @@ -550,9 +522,9 @@ TransformationFE::getK_Force(const Vector &accel, double fact) const Vector & TransformationFE::getKi_Force(const Vector &accel, double fact) { - this->FE_Element::zeroTangent(); - this->FE_Element::addKiToTang(); - const Matrix &theTangent = this->FE_Element::getTangent(0); + this->ElementFE::zeroTangent(); + this->ElementFE::addKiToTang(); + const Matrix &theTangent = this->ElementFE::getTangent(0); static ID numDOFs(dofData, 1); numDOFs.setData(dofData, numGroups); @@ -584,18 +556,18 @@ TransformationFE::getKi_Force(const Vector &accel, double fact) for (int i=0; inoCols(); // CHECK SIZE OF BUFFER localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - // localTtKT = localK * (*Tj); + // localTtKT = localK * (*Tj); localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); } else if (Ti != 0 && Tj == 0) { noRowsTransformed = Ti->noCols(); @@ -664,9 +636,9 @@ TransformationFE::getKi_Force(const Vector &accel, double fact) const Vector & TransformationFE::getM_Force(const Vector &accel, double fact) { - this->FE_Element::zeroTangent(); - this->FE_Element::addMtoTang(); - const Matrix &theTangent = this->FE_Element::getTangent(0); + this->ElementFE::zeroTangent(); + this->ElementFE::addMtoTang(); + const Matrix &theTangent = this->ElementFE::getTangent(0); static ID numDOFs(dofData, 1); numDOFs.setData(dofData, numGroups); @@ -698,18 +670,18 @@ TransformationFE::getM_Force(const Vector &accel, double fact) for (int i=0; inoCols(); - noColsTransformed = Tj->noCols(); - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - //localTtKT = (*Ti) ^ localK * (*Tj); - localTtKT.addMatrixTripleProduct(0.0, *Ti, localK, *Tj, 1.0); + noRowsTransformed = Ti->noCols(); + noColsTransformed = Tj->noCols(); + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + //localTtKT = (*Ti) ^ localK * (*Tj); + localTtKT.addMatrixTripleProduct(0.0, *Ti, localK, *Tj, 1.0); } else if (Ti == 0 && Tj != 0) { - noRowsTransformed = numDOFi; - noColsTransformed = Tj->noCols(); - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - // localTtKT = localK * (*Tj); - localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); + noRowsTransformed = numDOFi; + noColsTransformed = Tj->noCols(); + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + // localTtKT = localK * (*Tj); + localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); } else if (Ti != 0 && Tj == 0) { - noRowsTransformed = Ti->noCols(); - noColsTransformed = numDOFj; - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - //localTtKT = (*Ti) ^ localK; - localTtKT.addMatrixTransposeProduct(0.0, *Ti, localK, 1.0); + noRowsTransformed = Ti->noCols(); + noColsTransformed = numDOFj; + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + //localTtKT = (*Ti) ^ localK; + localTtKT.addMatrixTransposeProduct(0.0, *Ti, localK, 1.0); } else { - noRowsTransformed = numDOFi; - noColsTransformed = numDOFj; - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - localTtKT = localK; + noRowsTransformed = numDOFi; + noColsTransformed = numDOFj; + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + localTtKT = localK; } // now copy into modTangent the T(i)^t K(i,j) T(j) product for (int c=0; cFE_Element::zeroTangent(); - this->FE_Element::addCtoTang(); - const Matrix &theTangent = this->FE_Element::getTangent(0); + this->ElementFE::zeroTangent(); + this->ElementFE::addCtoTang(); + const Matrix &theTangent = this->ElementFE::getTangent(0); static ID numDOFs(dofData, 1); numDOFs.setData(dofData, numGroups); @@ -812,58 +784,58 @@ TransformationFE::getC_Force(const Vector &accel, double fact) for (int i=0; inoCols(); - noColsTransformed = Tj->noCols(); - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - //localTtKT = (*Ti) ^ localK * (*Tj); - localTtKT.addMatrixTripleProduct(0.0, *Ti, localK, *Tj, 1.0); + noRowsTransformed = Ti->noCols(); + noColsTransformed = Tj->noCols(); + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + //localTtKT = (*Ti) ^ localK * (*Tj); + localTtKT.addMatrixTripleProduct(0.0, *Ti, localK, *Tj, 1.0); } else if (Ti == 0 && Tj != 0) { - noRowsTransformed = numDOFi; - noColsTransformed = Tj->noCols(); - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - // localTtKT = localK * (*Tj); - localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); + noRowsTransformed = numDOFi; + noColsTransformed = Tj->noCols(); + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + // localTtKT = localK * (*Tj); + localTtKT.addMatrixProduct(0.0, localK, *Tj, 1.0); } else if (Ti != 0 && Tj == 0) { - noRowsTransformed = Ti->noCols(); - noColsTransformed = numDOFj; - // CHECK SIZE OF BUFFER - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - //localTtKT = (*Ti) ^ localK; - localTtKT.addMatrixTransposeProduct(0.0, *Ti, localK, 1.0); + noRowsTransformed = Ti->noCols(); + noColsTransformed = numDOFj; + // CHECK SIZE OF BUFFER + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + //localTtKT = (*Ti) ^ localK; + localTtKT.addMatrixTransposeProduct(0.0, *Ti, localK, 1.0); } else { - noRowsTransformed = numDOFi; - noColsTransformed = numDOFj; - localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); - localTtKT = localK; + noRowsTransformed = numDOFi; + noColsTransformed = numDOFj; + localTtKT.setData(dataBuffer, noRowsTransformed, noColsTransformed); + localTtKT = localK; } // now copy into modTangent the T(i)^t K(i,j) T(j) product for (int c=0; c= 0) - (*modResidual)(i) = disp(loc); - else - (*modResidual)(i) = 0.0; - } - transformResponse(*modResidual, response); - this->addLocalD_Force(response, fact); -} + static Vector response; + response.setData(dataBuffer, numOriginalDOF); + + for (int i=0; i= 0) + (*modResidual)(i) = disp(loc); + else + (*modResidual)(i) = 0.0; + } + transformResponse(*modResidual, response); + this->addLocalD_Force(response, fact); +} void TransformationFE::addM_Force(const Vector &disp, double fact) { - if (fact == 0.0) - return; + if (fact == 0.0) + return; - static Vector response; - response.setData(dataBuffer, numOriginalDOF); - - for (int i=0; i= 0) - (*modResidual)(i) = disp(loc); - else - (*modResidual)(i) = 0.0; - } - transformResponse(*modResidual, response); - this->addLocalM_Force(response, fact); -} + static Vector response; + response.setData(dataBuffer, numOriginalDOF); + + for (int i=0; i= 0) + (*modResidual)(i) = disp(loc); + else + (*modResidual)(i) = 0.0; + } + transformResponse(*modResidual, response); + this->addLocalM_Force(response, fact); +} // CHANGE THE ID SENT const Vector & -TransformationFE::getLastResponse(void) +TransformationFE::getLastResponse() { - Integrator *theLastIntegrator = this->getLastIntegrator(); - if (theLastIntegrator != 0) { - if (theLastIntegrator->getLastResponse(*modResidual,*modID) < 0) { - opserr << "WARNING TransformationFE::getLastResponse(void)"; - opserr << " - the Integrator had problems with getLastResponse()\n"; - } - } - else { - modResidual->Zero(); - opserr << "WARNING TransformationFE::getLastResponse()"; - opserr << " No Integrator yet passed\n"; + Integrator *theLastIntegrator = this->getLastIntegrator(); + if (theLastIntegrator != 0) { + if (theLastIntegrator->getLastResponse(*modResidual,*modID) < 0) { + opserr << "WARNING TransformationFE::getLastResponse(void)"; + opserr << " - the Integrator had problems with getLastResponse()\n"; } - - Vector &result = *modResidual; - return result; + } + else { + modResidual->Zero(); + opserr << "WARNING TransformationFE::getLastResponse()"; + opserr << " No Integrator yet passed\n"; + } + + Vector &result = *modResidual; + return result; } int -TransformationFE::transformResponse(const Vector &modResp, - Vector &unmodResp) +TransformationFE::transformResponse(const Vector &modResp, Vector &unmodResp) { - // perform T R -- as T is block diagonal do T(i) R(i) - // where blocks are of size equal to num ele dof at a node + // perform T R -- as T is block diagonal do T(i) R(i) + // where blocks are of size equal to num ele dof at a node - int startRowOriginal = 0; - int startRowTransformed = 0; - int numNode = numGroups; - int noRows = 0; - int noCols = 0; + int startRowOriginal = 0; + int startRowTransformed = 0; + int numNode = numGroups; + int noRows = 0; + int noCols = 0; - for (int i=0; igetT(); - if (Ti != 0) { - noRows = Ti->noRows(); - noCols = Ti->noCols(); - for (int j=0; jgetNumDOF(); - noRows = noCols; - for (int j=0; jgetT(); + if (Ti != 0) { + noRows = Ti->noRows(); + noCols = Ti->noCols(); + for (int j=0; jgetNumDOF(); + noRows = noCols; + for (int j=0; j= 0) @@ -1011,7 +981,7 @@ TransformationFE::addD_ForceSensitivity(int gradNumber, const Vector &disp, dou } transformResponse(*modResidual, response); this->addLocalD_ForceSensitivity(gradNumber, response, fact); -} +} void TransformationFE::addM_ForceSensitivity(int gradNumber, const Vector &disp, double fact) @@ -1021,7 +991,7 @@ TransformationFE::addM_ForceSensitivity(int gradNumber, const Vector &disp, dou static Vector response; response.setData(dataBuffer, numOriginalDOF); - + for (int i=0; i= 0) @@ -1031,6 +1001,6 @@ TransformationFE::addM_ForceSensitivity(int gradNumber, const Vector &disp, dou } transformResponse(*modResidual, response); this->addLocalM_ForceSensitivity(gradNumber, response, fact); -} +} // AddingSensitivity:END //////////////////////////////////// diff --git a/SRC/analysis/fe_ele/transformation/TransformationFE.h b/SRC/analysis/fe_ele/transformation/TransformationFE.h index b5a3db47f7..5d88b4455d 100644 --- a/SRC/analysis/fe_ele/transformation/TransformationFE.h +++ b/SRC/analysis/fe_ele/transformation/TransformationFE.h @@ -18,11 +18,6 @@ ** ** ** ****************************************************************** */ -// $Revision: 1.9 $ -// $Date: 2006-02-08 20:20:00 $ -// $Source: /usr/local/cvs/OpenSees/SRC/analysis/fe_ele/transformation/TransformationFE.h,v $ - - #ifndef TransformationFE_h #define TransformationFE_h @@ -36,26 +31,24 @@ // // What: "@(#) TransformationFE.h, revA" -#include +#include class SP_Constraint; class DOF_Group; class TransformationConstraintHandler; -class TransformationFE: public FE_Element +class TransformationFE: public ElementFE { public: - TransformationFE(int tag, Element *theElement); + TransformationFE(int tag, Element *); ~TransformationFE(); // public methods for setting/obtaining mapping information - virtual const ID &getDOFtags(void) const; - virtual const ID &getID(void) const; - void setAnalysisModel(AnalysisModel &theModel); - virtual int setID(void); + virtual const ID &getID() const final; + int setID(AnalysisModel&) final; // methods to form and obtain the tangent and residual - virtual const Matrix &getTangent(Integrator *theIntegrator); - virtual const Vector &getResidual(Integrator *theIntegrator); + virtual const Matrix &getTangent(Integrator *); + virtual const Vector &getResidual(Integrator *); // methods for ele-by-ele strategies virtual const Vector &getTangForce(const Vector &x, double fact = 1.0); @@ -66,9 +59,7 @@ class TransformationFE: public FE_Element virtual void addD_Force(const Vector &vel, double fact = 1.0); virtual void addM_Force(const Vector &accel, double fact = 1.0); - const Vector &getLastResponse(void); - int addSP(SP_Constraint &theSP); - + const Vector &getLastResponse(); // AddingSensitivity:BEGIN //////////////////////////////////// virtual void addM_ForceSensitivity (int gradNumber, const Vector &vect, double fact = 1.0); @@ -91,7 +82,7 @@ class TransformationFE: public FE_Element int numTransformedDOF; int numOriginalDOF; - // static variables - single copy for all objects of the class + // static variables - single copy for all objects of the class static Matrix **modMatrices; // array of pointers to class wide matrices static Vector **modVectors; // array of pointers to class widde vectors static Matrix **theTransformations; // for holding pointers to the T matrices diff --git a/SRC/analysis/handler/AutoConstraintHandler.cpp b/SRC/analysis/handler/AutoConstraintHandler.cpp index b06a4b59ff..a7e1b2a98d 100644 --- a/SRC/analysis/handler/AutoConstraintHandler.cpp +++ b/SRC/analysis/handler/AutoConstraintHandler.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -291,14 +293,14 @@ AutoConstraintHandler::handle(const ID* nodesLast) if (elePtr->isSubdomain() == true) { Subdomain* theSub = (Subdomain*)elePtr; if (theSub->doesIndependentAnalysis() == false) { - fePtr = new FE_Element(numFeEle++, elePtr); + fePtr = new SubdomainFE(numFeEle++, theSub); theModel->addFE_Element(fePtr); theSub->setFE_ElementPtr(fePtr); } } else { // just a regular element .. create an FE_Element for it & add to AnalysisModel - fePtr = new FE_Element(numFeEle++, elePtr); + fePtr = new ElementFE(numFeEle++, elePtr); theModel->addFE_Element(fePtr); } } diff --git a/SRC/analysis/handler/LagrangeConstraintHandler.cpp b/SRC/analysis/handler/LagrangeConstraintHandler.cpp index beea8ae33a..f56315ae67 100644 --- a/SRC/analysis/handler/LagrangeConstraintHandler.cpp +++ b/SRC/analysis/handler/LagrangeConstraintHandler.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -117,14 +119,14 @@ LagrangeConstraintHandler::handle(const ID *nodesLast) if (elePtr->isSubdomain() == true) { Subdomain *theSub = (Subdomain *)elePtr; if (theSub->doesIndependentAnalysis() == false) { - FE_Element *fePtr = new FE_Element(numFeEle++, elePtr); + FE_Element *fePtr = new SubdomainFE(numFeEle++, theSub); theModel->addFE_Element(fePtr); theSub->setFE_ElementPtr(fePtr); } } else { // just a regular element - theModel->addFE_Element(new FE_Element(numFeEle++, elePtr)); + theModel->addFE_Element(new ElementFE(numFeEle++, elePtr)); } } diff --git a/SRC/analysis/handler/PenaltyConstraintHandler.cpp b/SRC/analysis/handler/PenaltyConstraintHandler.cpp index 01ffcd54b7..5dafae12d0 100644 --- a/SRC/analysis/handler/PenaltyConstraintHandler.cpp +++ b/SRC/analysis/handler/PenaltyConstraintHandler.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -136,13 +138,13 @@ PenaltyConstraintHandler::handle(const ID *nodesLast) if (elePtr->isSubdomain() == true) { Subdomain *theSub = (Subdomain *)elePtr; if (theSub->doesIndependentAnalysis() == false) { - fePtr = new FE_Element(numFeEle++, elePtr); + fePtr = new SubdomainFE(numFeEle++, theSub); theModel->addFE_Element(fePtr); theSub->setFE_ElementPtr(fePtr); } } else { // just a regular element - fePtr = new FE_Element(numFeEle++, elePtr); + fePtr = new ElementFE(numFeEle++, elePtr); theModel->addFE_Element(fePtr); } } diff --git a/SRC/analysis/handler/PlainHandler.cpp b/SRC/analysis/handler/PlainHandler.cpp index 2dd3b7196b..a360866c78 100644 --- a/SRC/analysis/handler/PlainHandler.cpp +++ b/SRC/analysis/handler/PlainHandler.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -217,14 +219,14 @@ PlainHandler::handle(const ID *nodesLast) Subdomain *theSub = (Subdomain *)elePtr; if (theSub->doesIndependentAnalysis() == false) { - FE_Element *fePtr = new FE_Element(numFe++, elePtr); + FE_Element *fePtr = new SubdomainFE(numFe++, theSub); theModel->addFE_Element(fePtr); theSub->setFE_ElementPtr(fePtr); } } else { // just a regular element .. create an FE_Element for it & add to AnalysisModel - theModel->addFE_Element(new FE_Element(numFe++, elePtr)); + theModel->addFE_Element(new ElementFE(numFe++, elePtr)); } } diff --git a/SRC/analysis/handler/TransformationConstraintHandler.cpp b/SRC/analysis/handler/TransformationConstraintHandler.cpp index 989ee20877..09103e4abf 100644 --- a/SRC/analysis/handler/TransformationConstraintHandler.cpp +++ b/SRC/analysis/handler/TransformationConstraintHandler.cpp @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -141,7 +143,7 @@ TransformationConstraintHandler::handle(const ID *nodesLast) numConstrainedNodes = 0; numDOF = 0; while ((nodPtr = theNod()) != 0) { - DOF_Group *dofPtr = 0; + DOF_Group *dofPtr = nullptr; int nodeTag = nodPtr->getTag(); int numNodalDOF = nodPtr->getNumberDOF(); @@ -272,7 +274,7 @@ TransformationConstraintHandler::handle(const ID *nodesLast) if (theSub->doesIndependentAnalysis() == false) { if (transformedEle.getLocation(tag) < 0) { - fePtr = new FE_Element(numFeEle, elePtr); + fePtr = new SubdomainFE(numFeEle, theSub); } else { fePtr = new TransformationFE(numFeEle, elePtr); theFEs[numFE++] = fePtr; @@ -286,7 +288,7 @@ TransformationConstraintHandler::handle(const ID *nodesLast) } else { if (transformedEle.getLocation(tag) < 0) { - fePtr = new FE_Element(numFeEle, elePtr); + fePtr = new ElementFE(numFeEle, elePtr); } else { fePtr = new TransformationFE(numFeEle, elePtr); @@ -390,7 +392,10 @@ TransformationConstraintHandler::enforceSPs() for (int j=0; jupdateElement(); + Element* ele = theEle->getElement(); + if (ele != nullptr) { + ele->update(); + } } return 0; From d1b12d2580a88d1ea856a3609a8983bd47639e68 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:15:18 -0800 Subject: [PATCH 155/161] Update FullGenEigenSolver.cpp --- .../eigenSOE/FullGenEigenSolver.cpp | 154 +++++++++--------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp index ff1f75953f..0befd40d2a 100644 --- a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp +++ b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -134,13 +134,13 @@ FullGenEigenSolver::solve(int nEigen, bool generalized, bool findSmallest) double *beta = new double [n]; if (eigenvalue != nullptr) - delete [] eigenvalue; + delete [] eigenvalue; eigenvalue = new double [n]; // allocate memory for sorting index array if (sortingID != 0) - delete [] sortingID; + delete [] sortingID; sortingID = new int [n]; // dummy left eigenvectors @@ -176,47 +176,46 @@ FullGenEigenSolver::solve(int nEigen, bool generalized, bool findSmallest) #endif if (info < 0) { - opserr << "FullGenEigenSolver::solve() - invalid argument number " - << -info << " passed to LAPACK dggev routine\n"; - return info; + opserr << "FullGenEigenSolver::solve() - invalid argument number " + << -info << " passed to LAPACK dggev routine\n"; + return info; } if (info > 0) { - opserr << "FullGenEigenSolver::solve() - the LAPACK dggev routine " - << "returned error code " << info << endln; - return -info; + opserr << "The LAPACK dggev routine " + << "returned error code " << info << "\n"; + return -info; } theSOE->factored = true; for (int i=0; isort(n, eigenvalue, sortingID); for (int i=0; isize; + int size = theSOE->size; + + if (eigenV == 0 || eigenV->Size() != size) { + if (eigenV != 0) + delete eigenV; + eigenV = new Vector(size); if (eigenV == 0 || eigenV->Size() != size) { - if (eigenV != 0) - delete eigenV; - - eigenV = new Vector(size); - if (eigenV == 0 || eigenV->Size() != size) { - opserr << "FullGenEigenSolver::setSize() "; - opserr << " - ran out of memory for eigenVector of size "; - opserr << theSOE->size << endln; - return -2; - } + opserr << "FullGenEigenSolver::setSize() "; + opserr << " - ran out of memory for eigenVector of size "; + opserr << theSOE->size << endln; + return -2; } + } - return 0; + return 0; } int FullGenEigenSolver::setEigenSOE(FullGenEigenSOE &thesoe) { - theSOE = &thesoe; + theSOE = &thesoe; - return 0; + return 0; } const Vector& FullGenEigenSolver::getEigenvector(int mode) { - this->getEigenvector(mode, *eigenV); + this->getEigenvector(mode, *eigenV); - return *eigenV; + return *eigenV; } int FullGenEigenSolver::getEigenvector(int mode, Vector &theVector) { - if (mode <= 0 || mode > numEigen) { - opserr << "FullGenEigenSolver::getEigenVector() - mode " - << mode << " is out of range (1 - " << numEigen << ")\n"; - theVector.Zero(); - return -1; - } + if (mode <= 0 || mode > numEigen) { + opserr << "FullGenEigenSolver::getEigenVector() - mode " + << mode << " is out of range (1 - " << numEigen << ")\n"; + theVector.Zero(); + return -1; + } - int size = theSOE->size; - int index = size*sortingID[mode-1]; + int size = theSOE->size; + int index = size*sortingID[mode-1]; - if (eigenvector != 0) { - for (int i=0; i numEigen) { - opserr << "FullGenEigenSolver::getEigenvalue() - mode " - << mode << " is out of range (1 - " << numEigen << ")\n"; - return 0.0; + opserr << "FullGenEigenSolver::getEigenvalue() - mode " + << mode << " is out of range (1 - " << numEigen << ")\n"; + return 0.0; } if (eigenvalue != 0) { @@ -448,7 +447,7 @@ FullGenEigenSolver::getEigenvalue(int mode) } else { opserr << "FullGenEigenSolver::getEigenvalue() - " - << "eigenvalues not yet computed\n"; + << "eigenvalues not yet computed\n"; return 0.0; } } @@ -457,14 +456,15 @@ FullGenEigenSolver::getEigenvalue(int mode) int FullGenEigenSolver::sendSelf(int commitTag, Channel &theChannel) { - return 0; + return 0; } -int FullGenEigenSolver::recvSelf(int commitTag, Channel &theChannel, - FEM_ObjectBroker &theBroker) +int +FullGenEigenSolver::recvSelf(int commitTag, Channel &theChannel, + FEM_ObjectBroker &theBroker) { - return 0; + return 0; } @@ -483,12 +483,12 @@ FullGenEigenSolver::sort(int length, double *x, int *id) d = (d+1)/2; for (i=0; i<(length-d); i++) { if (x[i+d] < x[i]) { - // swap items at positions i+d and d - xTmp = x[i+d]; idTmp = id[i+d]; - x[i+d] = x[i]; id[i+d] = id[i]; - x[i] = xTmp; id[i] = idTmp; - // indicate that a swap has occurred - flag = 1; + // swap items at positions i+d and d + xTmp = x[i+d]; idTmp = id[i+d]; + x[i+d] = x[i]; id[i+d] = id[i]; + x[i] = xTmp; id[i] = idTmp; + // indicate that a swap has occurred + flag = 1; } } } From 1a9c3963b169f08b3c989a94e6c9fc842479c338 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:15:30 -0800 Subject: [PATCH 156/161] formatting --- SRC/system_of_eqn/eigenSOE/EigenSOE.cpp | 43 ++++++++++++++----------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/SRC/system_of_eqn/eigenSOE/EigenSOE.cpp b/SRC/system_of_eqn/eigenSOE/EigenSOE.cpp index 6af8c368b0..34a5f7e0cd 100644 --- a/SRC/system_of_eqn/eigenSOE/EigenSOE.cpp +++ b/SRC/system_of_eqn/eigenSOE/EigenSOE.cpp @@ -1,3 +1,4 @@ + // $Revision: 1.5 $ // $Date: 2009-05-14 22:45:57 $ // $Source: /usr/local/cvs/OpenSees/SRC/system_of_eqn/eigenSOE/EigenSOE.cpp,v $ @@ -18,15 +19,24 @@ #include #include +// for formSystem +#include +#include +#include +#include +#include + EigenSOE::EigenSOE(EigenSolver &theEigenSolver, int classTag) - :MovableObject(classTag), theSolver(&theEigenSolver) + : MovableObject(classTag) + , theSolver(&theEigenSolver) { } EigenSOE::EigenSOE(int classTag) - :MovableObject(classTag), theSolver(0) + : MovableObject(classTag) + , theSolver(nullptr) { } @@ -34,40 +44,42 @@ EigenSOE::EigenSOE(int classTag) EigenSOE::~EigenSOE() { - if (theSolver != 0) + if (theSolver != nullptr) delete theSolver; } int EigenSOE::solve(int numModes, bool generalized, bool findSmallest) { - if (theSolver == 0) + if (theSolver == nullptr) return -1; else - return (theSolver->solve(numModes, generalized, findSmallest)); + return theSolver->solve(numModes, generalized, findSmallest); } int EigenSOE::setSolver(EigenSolver &newSolver) { - theSolver = &newSolver; - return 0; + theSolver = &newSolver; + return 0; } EigenSolver * EigenSOE::getSolver() { - return theSolver; + return theSolver; } const Vector & -EigenSOE::getEigenvector(int mode) { - return theSolver->getEigenvector(mode); +EigenSOE::getEigenvector(int mode) +{ + return theSolver->getEigenvector(mode); } double -EigenSOE::getEigenvalue(int mode) { - return theSolver->getEigenvalue(mode); +EigenSOE::getEigenvalue(int mode) +{ + return theSolver->getEigenvalue(mode); } @@ -78,13 +90,6 @@ EigenSOE::setLinks(AnalysisModel &) } -#include -#include -#include -#include -#include -#include -#include int EigenSOE::formSystem(AnalysisModel &model, bool generalized) { From 5da9aaa142487dc883345921e8ce640b8b50e91f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:17:24 -0800 Subject: [PATCH 157/161] Update LinearSOE.h --- SRC/system_of_eqn/linearSOE/LinearSOE.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/SRC/system_of_eqn/linearSOE/LinearSOE.h b/SRC/system_of_eqn/linearSOE/LinearSOE.h index 6cdf6179c6..e51e5387cc 100644 --- a/SRC/system_of_eqn/linearSOE/LinearSOE.h +++ b/SRC/system_of_eqn/linearSOE/LinearSOE.h @@ -69,11 +69,13 @@ class LinearSOE : public MovableObject virtual int formAp(const Vector &p, Vector &Ap); - virtual const Vector &getX(void) = 0; - virtual const Vector &getB(void) = 0; - virtual const Matrix *getA(void) {return 0;}; - double getDeterminant(void); - virtual double normRHS(void) = 0; + virtual const Vector &getX() = 0; + virtual const Vector &getB() = 0; + virtual const Matrix *getA() {return nullptr;} + virtual int getA(int row, int col, double &value) const {return -2;} + + double getDeterminant(); + virtual double normRHS() = 0; virtual void setX(int loc, double value) =0; virtual void setX(const Vector &X) =0; From fcdb9a97b20f9339a90bd3f75668bb3f9d571367 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:27:56 -0800 Subject: [PATCH 158/161] Update FE_Element.cpp --- SRC/analysis/fe_ele/FE_Element.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SRC/analysis/fe_ele/FE_Element.cpp b/SRC/analysis/fe_ele/FE_Element.cpp index 2b4fb80f7a..5a5e04c747 100644 --- a/SRC/analysis/fe_ele/FE_Element.cpp +++ b/SRC/analysis/fe_ele/FE_Element.cpp @@ -130,6 +130,7 @@ FE_Element::addKpToTang(double fact, int numP) int FE_Element::storePreviousK(int numP) { + return -1; } // From e998c03ad63bb6a4cf540ba241203548172de500 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:28:16 -0800 Subject: [PATCH 159/161] Update FrameTransformBuilder.hpp --- .../modeling/transform/FrameTransformBuilder.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp index 5e6a29856b..40524d2a3c 100644 --- a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp +++ b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp @@ -62,14 +62,18 @@ class FrameTransformBuilder : public TaggedObject { } int tag = this->getTag(); - if (strstr(name, "Linear") != nullptr) - return new LinearFrameTransf (tag, vz, offset_array, offset_flags); + if (strstr(name, "Linear") != nullptr) { + if (!getenv("Linear02")) + return new LinearFrameTransf (tag, vz, offset_array, offset_flags); + else + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); + } else if (strstr(name, "LinearIsometric") != nullptr) return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); else if (strcmp(name, "Corotational") == 0) { - if constexpr (ndf == 6) + if constexpr (ndf == 6 && nn==2) return new SouzaFrameTransf (tag, vz, offset_array, offset_flags); else return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); From d95105d710ac823030246f23cbdc05da29e44788 Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:40:23 -0800 Subject: [PATCH 160/161] Update SubdomainFE.cpp --- SRC/analysis/fe_ele/SubdomainFE.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/SRC/analysis/fe_ele/SubdomainFE.cpp b/SRC/analysis/fe_ele/SubdomainFE.cpp index 1c15657e0f..1ce3cfe000 100644 --- a/SRC/analysis/fe_ele/SubdomainFE.cpp +++ b/SRC/analysis/fe_ele/SubdomainFE.cpp @@ -164,7 +164,6 @@ SubdomainFE::setID(AnalysisModel &theModel) const Matrix & SubdomainFE::getTangent(Integrator *theNewIntegrator) { -#ifdef OLD_FE theIntegrator = theNewIntegrator; { @@ -172,7 +171,6 @@ SubdomainFE::getTangent(Integrator *theNewIntegrator) theSub->computeTang(); return theSub->getTang(); } -#endif } void @@ -287,11 +285,7 @@ SubdomainFE::getResidual(Integrator *theNewIntegrator) assert(myEle != nullptr); - if (myEle->isSubdomain() == false) { - theNewIntegrator->formEleResidual(this); - return *theResidual; - - } else { + { Subdomain *theSub = (Subdomain *)myEle; theSub->computeResidual(); return theSub->getResistingForce(); From 7e8a61942993ef90f3a9d4f083a1bcdd84ba834f Mon Sep 17 00:00:00 2001 From: Claudio Perez <50180406+claudioperez@users.noreply.github.com> Date: Sun, 1 Feb 2026 15:40:26 -0800 Subject: [PATCH 161/161] Update FE_Element.cpp --- SRC/analysis/fe_ele/FE_Element.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/SRC/analysis/fe_ele/FE_Element.cpp b/SRC/analysis/fe_ele/FE_Element.cpp index 5a5e04c747..028f658ec6 100644 --- a/SRC/analysis/fe_ele/FE_Element.cpp +++ b/SRC/analysis/fe_ele/FE_Element.cpp @@ -78,8 +78,6 @@ FE_Element::setAnalysisModel(AnalysisModel &theAnalysisModel) theModel = &theAnalysisModel; } -// void setID(int index, int value); -// Method to set the corresponding index of the ID to value. int FE_Element::setID()