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/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 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); 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/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/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. 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/ElementFE.cpp b/SRC/analysis/fe_ele/ElementFE.cpp new file mode 100644 index 0000000000..275638d520 --- /dev/null +++ b/SRC/analysis/fe_ele/ElementFE.cpp @@ -0,0 +1,662 @@ +//===----------------------------------------------------------------------===// +// +// 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); + assert(myEle.isSubdomain() == false); + + // 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() +{ + theTangent->Zero(); +} + + +void +ElementFE::addKtToTang(double fact) +{ + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle.getTangentStiff(),fact); +} + + +void +ElementFE::addCtoTang(double fact) +{ + // check for a quick return + if (fact == 0.0) + return; + else + theTangent->addMatrix(myEle.getDamp(),fact); +} + + +void +ElementFE::addMtoTang(double fact) +{ + // 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 + theTangent->addMatrix(myEle.getInitialStiff(), fact); +} + + +void +ElementFE::addKpToTang(double fact, int numP) +{ + // 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) +{ + return myEle.storePreviousK(numP); +} + +// +// RESIDUAL +// +const Vector & +ElementFE::getResidual(Integrator *theNewIntegrator) +{ + theIntegrator = theNewIntegrator; + + if (theIntegrator == nullptr) + return *theResidual; + + theNewIntegrator->formEleResidual(this); + return *theResidual; +} + +void +ElementFE::zeroResidual() +{ + + theResidual->Zero(); +} + + +void +ElementFE::addRtoResidual(double fact) +{ + + // 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) +{ + // 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) +{ + + // 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) +{ + + // 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) +{ + + // 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) +{ + + // 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) +{ + // 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() +{ + + 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) +{ + // 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) +{ + + // 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) +{ + + // 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) +{ + + // 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) +{ + + // 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) +{ + + // 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) = vect(loc); + else + tmp(i) = 0.0; + } + theResidual->addMatrixVector(myEle.getDampSensitivity(gradNumber), tmp, fact); + +} + +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) +{ + + // 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() +{ + return myEle.update(); +} diff --git a/SRC/analysis/fe_ele/ElementFE.h b/SRC/analysis/fe_ele/ElementFE.h new file mode 100644 index 0000000000..911d541a61 --- /dev/null +++ b/SRC/analysis/fe_ele/ElementFE.h @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// 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: cmp +// Created: Jan 2026 +// 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 *); + ~ElementFE() override; + + // public methods for setting/obtaining mapping information + 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 + void zeroTangent() override; + 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 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 + diff --git a/SRC/analysis/fe_ele/FE_Element.cpp b/SRC/analysis/fe_ele/FE_Element.cpp index 718948188c..028f658ec6 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; + return -1; } // // 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 +164,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 +171,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 +197,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/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. diff --git a/SRC/analysis/fe_ele/SubdomainFE.cpp b/SRC/analysis/fe_ele/SubdomainFE.cpp new file mode 100644 index 0000000000..1ce3cfe000 --- /dev/null +++ b/SRC/analysis/fe_ele/SubdomainFE.cpp @@ -0,0 +1,702 @@ +//===----------------------------------------------------------------------===// +// +// 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(); + } +} + +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); + + { + 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; +} 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 + 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/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. 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. 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/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. 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 d3f8714576..a7e1b2a98d 100644 --- a/SRC/analysis/handler/AutoConstraintHandler.cpp +++ b/SRC/analysis/handler/AutoConstraintHandler.cpp @@ -35,9 +35,9 @@ #include #include #include -#include +#include +#include #include -#include #include #include #include @@ -293,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/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/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/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. 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 e0cc9be26d..09103e4abf 100644 --- a/SRC/analysis/handler/TransformationConstraintHandler.cpp +++ b/SRC/analysis/handler/TransformationConstraintHandler.cpp @@ -35,9 +35,9 @@ #include #include #include -#include +#include +#include #include -#include #include #include #include @@ -143,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(); @@ -274,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; @@ -288,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); @@ -392,7 +392,10 @@ TransformationConstraintHandler::enforceSPs() for (int j=0; jupdateElement(); + Element* ele = theEle->getElement(); + if (ele != nullptr) { + ele->update(); + } } return 0; 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/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/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/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/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/GeneralizedNewmark.cpp b/SRC/analysis/integrator/Dynamic/GeneralizedNewmark.cpp index 2888ec8825..1a46f1fcf5 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 @@ -30,7 +28,6 @@ // for sensitivity #include #include -#include #include #include 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 901656d580..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 @@ -42,7 +40,6 @@ #include #include // for sensitivity #include -#include #include #include //Abbas 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..5a0497fdf0 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 @@ -42,11 +40,10 @@ #include #include #include -#include #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..f54f617e87 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 @@ -48,9 +47,7 @@ #include #include #include -#include #include -#include #include #include "sparseGEN/PFEMLinSOE.h" 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/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/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/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/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..70eab8bb31 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 @@ -246,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(); @@ -287,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); 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/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 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 df5a3343fe..1c5879175c 100644 --- a/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp +++ b/SRC/analysis/integrator/Static/HarmonicSteadyState.cpp @@ -34,12 +34,9 @@ #include #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..f55f2463a3 100644 --- a/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp +++ b/SRC/analysis/integrator/Static/MinUnbalDispNorm.cpp @@ -31,13 +31,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -106,9 +104,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 @@ -503,13 +501,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 +526,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; } 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/AnalysisModel.cpp b/SRC/analysis/model/AnalysisModel.cpp index a341296df8..d465891d7b 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 @@ -50,28 +47,43 @@ #include #include #include -#include #include #include #include +#include #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) , 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); + + theDOFs->setSize(ApproxDOF(domain)); + theFEs->setSize(domain.getNumElements()); } @@ -123,7 +135,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 +351,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 +380,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 +520,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 +624,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 +846,7 @@ AnalysisModel::setNumEigenvectors(int numEigenvectors) Node *theNode; NodeIter &theNodes = myDomain->getNodes(); while ((theNode = theNodes()) != 0) - theNode->setNumEigenvectors(numEigenvectors); + theNode->setNumEigenvectors(numEigenvectors); } void @@ -895,7 +907,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()); @@ -1008,6 +1020,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..862743b050 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,11 +46,15 @@ class FEM_ObjectBroker; class ConstraintHandler; class Integrator; class LinearSOE; +class OPS_Stream; + +using DOF_GrpIter = TaggedIterator; +using FE_EleIter = TaggedIterator; class AnalysisModel: public MovableObject { public: - AnalysisModel(); + AnalysisModel(Domain&); ~AnalysisModel(); void setLinks(Domain &, ConstraintHandler &); @@ -61,8 +65,8 @@ class AnalysisModel: public MovableObject void clearDOFGraph(); // called by Numberer and Analysis void clearDOFGroupGraph(); int getNumDOF_Groups() const; - DOF_Group *getDOF_GroupPtr(int tag); - FE_EleIter &getFEs(); + DOF_Group *getDOF_GroupPtr(int tag); + 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..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 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/DOF_GrpIter.h b/SRC/analysis/model/DOF_GrpIter.h index a2aa571031..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; - -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 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/FE_EleIter.h b/SRC/analysis/model/FE_EleIter.h index 3c942078a2..4235d89be4 100644 --- a/SRC/analysis/model/FE_EleIter.h +++ b/SRC/analysis/model/FE_EleIter.h @@ -43,21 +43,5 @@ class TaggedObjectStorage; class FE_Element; -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 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/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/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 - - - - - 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/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 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 adf7a73f18..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";} @@ -67,7 +66,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,22 +76,27 @@ class EuclidFrameTransf: public FrameTransform Versor getNodeRotation(int tag) /* final */; Vector3D getNodeRotationLogarithm(int tag) final; - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; - + Matrix3D getRotation() const noexcept final { + return basis.getRotation(); + } + + 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 746dbb4cd2..9c9e6b5b68 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; @@ -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 - // 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); + // 2.2.1) Kl = A ^ k * A + // 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; - // 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 bce392dbb0..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; @@ -81,7 +90,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 @@ -92,26 +101,27 @@ 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; -#if 1 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; } -#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 +134,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; @@ -200,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 56dea7024c..9a21c79ac2 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" // @@ -193,15 +198,13 @@ 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; } - // 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], diff --git a/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h b/SRC/coordTransformation/Frame/Isometry/EuclidIsometry.h index d405bcd8d1..fba459497f 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 @@ -48,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; @@ -123,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; // @@ -149,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(); @@ -196,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 a2646f4c32..98a2e71057 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,45 +36,147 @@ #include "EuclidIsometry.h" class Node; -#define TRIAD C2 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 { - return this->AlignedIsometry::R[init]; + 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 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 96bfcdfed3..491310e4bd 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,46 +78,77 @@ 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; } - 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(); + 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; + } + } - constexpr static Matrix3D ex = Hat(Vector3D {1,0,0}); + MatrixND<3,6> + getRotationGradient(int node) final { + MatrixND<3,6> Gb{}; - 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); + const double Ln = this->getLength(); - 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 - Matrix3D B = Gamma^Psi; - Matrix3D A; - B.invert(A); - return Gamma*A.transpose()*NWL; + 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 +179,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; 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; diff --git a/SRC/coordTransformation/Frame/LinearFrameTransf.h b/SRC/coordTransformation/Frame/LinearFrameTransf.h index 136c137bcf..acf0527bf0 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,14 @@ class LinearFrameTransf: public FrameTransform Vector3D getNodeRotationLogarithm(int tag) final; VectorND getStateVariation() final; - using Operation = typename FrameTransform::Operation; + Matrix3D getRotation() const noexcept final { + return this->getInitialRotation(); + } - 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); - + 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 e227fba8d8..0d1a324f4d 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}; @@ -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 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,9 +61,12 @@ class PDeltaFrameTransf: public FrameTransform Vector3D getNodeRotationLogarithm(int tag) final; const std::array *getRigidOffsets() const final { return linear.getRigidOffsets();} - using Operation = typename FrameTransform::Operation; - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; + Matrix3D getRotation() const noexcept final { + return this->getInitialRotation(); + } + + 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 0b3d9ec9c5..e5900b0944 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(); } @@ -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 cad97523b5..f653b1b3c3 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,9 +85,13 @@ class SouzaFrameTransf: public FrameTransform Vector3D getNodePosition(int tag) final; Vector3D getNodeRotationLogarithm(int tag) final; - using Operation = typename FrameTransform::Operation; - int push(VectorND&pl, Operation) final; - int push(MatrixND& kl, const VectorND& pl, Operation) final; + Matrix3D getRotation() const noexcept final { + return crs.getRotation(); + } + + int push(VectorND&pl, int) final; + int push(MatrixND& kl, const VectorND& pl, int) final; + // Sensitivity double getLengthGrad() final; diff --git a/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp b/SRC/coordTransformation/Frame/SouzaFrameTransf.tpp index 8a5d9a4f42..e7f2dfde2a 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: @@ -103,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; @@ -153,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); @@ -190,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]; @@ -277,7 +280,7 @@ SouzaFrameTransf::getNodeRotationLogarithm(int tag) // template int -SouzaFrameTransf::update() +SouzaFrameTransf::update() noexcept { // determine global displacement increments from last iteration @@ -363,7 +366,7 @@ SouzaFrameTransf::update() template int -SouzaFrameTransf::push(VectorND&pl, Operation) +SouzaFrameTransf::push(VectorND&pl, int) { // return T^pl; VectorND pg{}; @@ -391,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 @@ -459,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/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()); 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); 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/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 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/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/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; } } 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); 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/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 #include #include -#include #include #include 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 ) 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; i +#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(); +} + diff --git a/SRC/domain/pattern/LoadCase.h b/SRC/domain/pattern/LoadCase.h new file mode 100644 index 0000000000..3e4ee2ed28 --- /dev/null +++ b/SRC/domain/pattern/LoadCase.h @@ -0,0 +1,74 @@ +# pragma once +#include "LoadPattern.h" +#include +#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 diff --git a/SRC/domain/pattern/LoadPattern.cpp b/SRC/domain/pattern/LoadPattern.cpp index 41f13b1bf5..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; @@ -308,7 +311,6 @@ LoadPattern::applyLoad(double pseudoTime) { Load *nodLoad; NodalLoadIter &theNodalIter = this->getNodalLoads(); - while ((nodLoad = theNodalIter()) != nullptr) nodLoad->applyLoad(loadFactor); } @@ -713,7 +715,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 +760,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 +856,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 +869,9 @@ void LoadPattern::Print(OPS_Stream &s, int flag) } } -LoadPattern *LoadPattern::getCopy() + +LoadPattern * +LoadPattern::getCopy() { LoadPattern *theCopy = new LoadPattern(this->getTag()); @@ -875,7 +882,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 +932,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 +1001,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 +1064,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 +1126,7 @@ int LoadPattern::activateParameter(int parameterID) } } else { - opserr << "LoadPattern::gradient() -- error in identifier. " << endln; + opserr << "LoadPattern::gradient() -- error in identifier. " << "\n"; } } } @@ -1125,7 +1134,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 +1154,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 +1180,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 +1196,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 +1212,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..f20dbd0e6f 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 @@ -124,21 +126,20 @@ class LoadPattern : // 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; +// - // 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; i +#include +#include +#include +#include +#include +#include +#include + +StaticPattern::StaticPattern(int tag, double 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 new file mode 100644 index 0000000000..6a6dc4004d --- /dev/null +++ b/SRC/domain/pattern/StaticPattern.h @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// xara +// https://xara.so +// +//===----------------------------------------------------------------------===// +// +// Copyright (c) 2025, OpenSees/Xara Developers +// All rights reserved. No warranty, explicit or implicit, is provided. +// +//===----------------------------------------------------------------------===// +// +#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; + 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; + + // methods to remove loads + NodalLoad *removeNodalLoad(int tag) final; + ElementalLoad *removeElementalLoad(int tag) final; + void clearAll(); +#endif +private: + // 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; + + int currentGeoTag; + int lastGeoSendTag; +}; \ No newline at end of file diff --git a/SRC/domain/subdomain/Makefile b/SRC/domain/subdomain/Makefile deleted file mode 100644 index e59f597b30..0000000000 --- a/SRC/domain/subdomain/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -include ../../../Makefile.def - - -OBJS = Subdomain.o SubdomainNodIter.o ShadowSubdomain.o ActorSubdomain.o - -# ShadowSubdomain.o ShadowSubdomainActor.o ActorSubdomain.o - -# Compilation control - -all: $(OBJS) - -actor: - $(LINKER) $(LINKFLAGS) ShadowSubdomainActor.o ActorSubdomain.o \ - $(OO_LIBRARY) $(LINKLIBS) -o ShadowSubdomainActor - -# Miscellaneous -tidy: - @$(RM) $(RMFLAGS) Makefile.bak *~ #*# core - -clean: tidy - @$(RM) $(RMFLAGS) $(OBJS) *.o ShadowSubdomainActor - -spotless: clean - -wipe: spotless - -# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/SRC/domain/subdomain/ShadowSubdomain.cpp b/SRC/domain/subdomain/ShadowSubdomain.cpp index 610da5ce15..ad543f1107 100644 --- a/SRC/domain/subdomain/ShadowSubdomain.cpp +++ b/SRC/domain/subdomain/ShadowSubdomain.cpp @@ -72,7 +72,8 @@ ShadowSubdomain::ShadowSubdomain(int tag, MachineBroker &theMachineBroker, FEM_ObjectBroker &theObjectBroker) : Shadow(ACTOR_TAGS_SUBDOMAIN, theObjectBroker, theMachineBroker, 0), - Subdomain(tag), msgData(4), theElements(0, 128), theNodes(0, 128), + Subdomain(tag), + msgData(4), theElements(0, 128), theNodes(0, 128), theExternalNodes(0, 128), theLoadCases(0, 128), theShadowSPs(0), theShadowMPs(0), theShadowLPs(0), numDOF(0), numElements(0), numNodes(0), numExternalNodes(0), numSPs(0), numMPs(0), buildRemote(false), @@ -799,7 +800,7 @@ void ShadowSubdomain::setCommittedTime(double time) this->sendVector(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 665e51a94b..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) @@ -377,13 +332,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/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/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/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 & 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; diff --git a/SRC/element/Frame/ExactFrame3d.tpp b/SRC/element/Frame/ExactFrame3d.tpp index 687216aaeb..e2b4f0bb8a 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], @@ -639,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); @@ -783,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); } diff --git a/SRC/element/Frame/ForceFrame3d.h b/SRC/element/Frame/ForceFrame3d.h index 641484e2b0..9e6832b2b9 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 * @@ -181,11 +181,15 @@ class ForceFrame3d: public BasicFrame3d, LocalForce = 2, BasicForce = 7, BasicStiff =19, + ResultantGradient=76, + ResultantStiffness=1001 }; // // 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..6569c5c92d 100644 --- a/SRC/element/Frame/ForceFrame3d.tpp +++ b/SRC/element/Frame/ForceFrame3d.tpp @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -194,9 +195,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 +371,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; @@ -429,8 +435,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)); @@ -490,10 +497,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: @@ -617,6 +623,8 @@ public: } } } +private: + MatrixND B; }; } @@ -624,6 +632,399 @@ 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{}; + { + const Vector& dvb = basic_system->getBasicIncrDeltaDisp(); + for (int i=0; i<6; i++) { + dv_total[i] = dvb[i]; + } + } + + + // Basic DOFs + VectorND v0{}; + { + const Vector& v = basic_system->getBasicTrialDisp(); + for (int i=0; i<6; i++) + v0[i] = v[i] - dv_total[i]; + } + + { + // Warping DOFs + Node** nodes = this->getNodePtrs(); + for (int i=0; igetTrialDisp(); + const Vector& duj = nodes[j]->getIncrDeltaDisp(); + 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]; + } + } + } + + // + // + // + if ((state_flag != 0) && + (dv_total.norm() <= DBL_EPSILON) && + (eleLoads.size()==0) && + (frame_loads.size()==0)) + return 0; + + + // VectorND dv = dv_total; + VectorND dv_trial = dv_total; + const VectorND Dv = dv_total; + + static constexpr int max_subdivision= 10; + 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::InitialThenNewton, Strategy::InitialIterations, + }; + + int subdivision = 0; + bool converged = false; + + ForceInterpolation interp{}; + + const int nip = points.size(); + 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; + sr_trial[i] = points[i].sr; + } + + if (state_flag == 2) + continue; + + VectorND q_trial = q_pres; + + q_trial += K_pres*dv_trial; + + for (int j = 0; j < numIters; j++) { + + VectorND vr{}; // element residual deformations + MatrixND F{}; // element flexibility matrix + double DWi = 0.0; + + // + // 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& 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 + // + // 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 - s0; + + // 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 - s0; + + // B' * des + vr.addMatrixTransposeVector(1.0, b, Fs*ds+es_trial[i], wtL); + + DWi += ds.dot(Fs*ds)*wtL; + } + + } // Gauss loop + + + // dv = Dv + dv_trial - vr + VectorND dv = v0; + 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)+DWi; + 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; + 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 { + // We've converged but we have more to do; + // reset variables for start of next subdivision + + // 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; + } + + // 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 == solve_strategy.back())) { + dv_trial /= factor; + subdivision++; + opserr << " Element " << this->getTag() + << ": Attempting substep " << subdivision + << " with " + << " dW = " << dW + << ", tol = " << tol << "\n"; + } + } + } // for (iteration) + } // for (strategy) + +iterations_completed: + ; + + } // while (converged == false) + + + if (converged == false) [[unlikely]] { + opserr << " Element " + << this->getTag() + << ": failed to converge with " + << " dW = " << dW + << ", tol = " << tol + << ", % dv = " << 100.0*dv_trial.norm()/Dv.norm() + << "\n"; + return -1; + } + else { + if (subdivision > 0) { + 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; + + return 0; +} + + +template +int +ForceFrame3d::update02() { constexpr static double TOL_SUBDIV = DBL_EPSILON*10; @@ -683,6 +1084,7 @@ ForceFrame3d::update() 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; @@ -712,6 +1114,7 @@ ForceFrame3d::update() int subdivision = 1; bool converged = false; + ForceInterpolation interp{}; const int nip = points.size(); while ((converged == false) && (subdivision <= max_subdivision)) { @@ -737,7 +1140,6 @@ ForceFrame3d::update() VectorND vr{}; // element residual deformations MatrixND F{}; // element flexibility matrix - ForceInterpolation interp; // // Gauss Loop @@ -748,9 +1150,9 @@ ForceFrame3d::update() // 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); + const MatrixND& b = interp.b(xL, L); // // a. Calculate section force by interpolation of q_trial @@ -778,7 +1180,7 @@ ForceFrame3d::update() // 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; @@ -833,7 +1235,7 @@ ForceFrame3d::update() { // 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]; @@ -859,7 +1261,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 +1282,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 { @@ -958,8 +1360,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 @@ -1001,8 +1403,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, Transform::Total);//&~Transform::Logarithm); this->addLoadTangent(kl, 1.0); return Wrapper; } @@ -1014,7 +1415,6 @@ ForceFrame3d::addLoadTangent(MatrixND<2*NDF,2*NDF>& K, d { double L = basic_system->getInitialLength(); - double jsx = 1.0 / L; // // Gauss Loop // @@ -1022,9 +1422,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 +1437,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 @@ -1121,8 +1486,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; } @@ -1135,7 +1499,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) { @@ -1459,102 +1824,18 @@ ForceFrame3d::getInitialFlexibility(MatrixND& f fe.zero(); double L = basic_system->getInitialLength(); - double jsx = 1.0 / L; const int numSections = points.size(); + ForceInterpolation interp{}; 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); - 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; } @@ -1865,14 +2146,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(); } @@ -1926,7 +2215,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()); @@ -1987,6 +2276,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); @@ -2036,12 +2332,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()); @@ -2183,12 +2473,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); @@ -2290,6 +2579,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 +2669,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; @@ -2780,8 +3072,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(); @@ -2797,49 +3089,39 @@ 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()); } // 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);//&~(Transform::Logarithm)); 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 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, diff --git a/SRC/element/Frame/MixedFrame3d.cpp b/SRC/element/Frame/MixedFrame3d.cpp index b1e2205afc..9514756c5c 100644 --- a/SRC/element/Frame/MixedFrame3d.cpp +++ b/SRC/element/Frame/MixedFrame3d.cpp @@ -67,17 +67,10 @@ #include #include -#include -#include -#include -#include -#include -#include 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 +78,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 +197,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 +209,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 +307,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 +319,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 +500,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 +529,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 +576,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 +621,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 +687,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 +742,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 +792,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; @@ -1227,31 +1176,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); } } 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]; 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) << "], "; 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 diff --git a/SRC/element/Frame/PrismFrame3d.cpp b/SRC/element/Frame/PrismFrame3d.cpp index a27880738c..1212f4c6c3 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); @@ -466,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::Total); + 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; } 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" 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 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; } 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: 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/Point/ZeroLength.cpp b/SRC/element/Point/ZeroLength.cpp index b39f6432fd..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 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; + } } 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++) { 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/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/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/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. 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); 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/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; j), - 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; }; diff --git a/SRC/material/Frame/FrameTraceSection3d.cpp b/SRC/material/Frame/FrameTraceSection3d.cpp new file mode 100644 index 0000000000..68ee8e486d --- /dev/null +++ b/SRC/material/Frame/FrameTraceSection3d.cpp @@ -0,0 +1,1248 @@ +//===----------------------------------------------------------------------===// +// +// 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); + } + } +} 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 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) { 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; } 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 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]; 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() 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(); 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); 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 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) 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 0.) && (Tstress == 0)) { //from positive to negative - if ((strain < Tnugr) && ((strain-Tnugr) > -LGap)) { - fd0 = 0.; + fd0 = 0.; } } 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; diff --git a/SRC/matrix/MatrixND.tpp b/SRC/matrix/MatrixND.tpp index 30ec5d8773..85a974f064 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 @@ -219,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) { @@ -271,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); @@ -299,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); @@ -350,6 +368,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 @@ -372,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); @@ -423,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; @@ -451,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; @@ -471,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; 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; 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. diff --git a/SRC/recorder/NodeRecorderRMS.cpp b/SRC/recorder/NodeRecorderRMS.cpp index 235e463eca..660e62b0c0 100644 --- a/SRC/recorder/NodeRecorderRMS.cpp +++ b/SRC/recorder/NodeRecorderRMS.cpp @@ -696,8 +696,8 @@ NodeRecorderRMS::initialize(void) // need to create the data description, i.e. what each column of data is // - char outputData[128]; - char dataType[128]; + char outputData[256]; + char dataType[256]; if (dataFlag == NodeData::DisplTrial) { strcpy(dataType,"D"); @@ -750,9 +750,9 @@ NodeRecorderRMS::initialize(void) int nodeTag = (*theNodalTags)(i); Node *theNode = theDomain->getNode(nodeTag); if (theNode != 0) { - xmlOrder(nodeCount++) = i+1; - for (int j=0; j #include #include -#include #include #include #include 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); } diff --git a/SRC/runtime/commands/analysis/analysis.cpp b/SRC/runtime/commands/analysis/analysis.cpp index a0aa81e5ef..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); @@ -140,7 +142,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; } @@ -311,6 +313,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 +344,9 @@ eigenAnalysis(ClientData clientData, return TCL_ERROR; } } - + else if (strcmp(argv[loc], "-solver")==0) { + ; + } else { opserr << "Unknown option: " << argv[loc] << OpenSees::SignalMessageEnd; @@ -675,9 +680,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/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; diff --git a/SRC/runtime/commands/analysis/integrator.cpp b/SRC/runtime/commands/analysis/integrator.cpp index a4dc41c9c9..51821ea7d2 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 @@ -217,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; @@ -259,33 +261,151 @@ 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; if (argc < 3) { opserr << "WARNING incorrect # args - integrator LoadControl dlam \n"; - return TCL_ERROR;; + return TCL_ERROR; + } + 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); + } } - 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: 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; 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 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; +} 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); 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..4dce09f089 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; @@ -817,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; @@ -854,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; 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/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); 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..7b936daaac 100644 --- a/SRC/runtime/commands/modeling/constraint.cpp +++ b/SRC/runtime/commands/modeling/constraint.cpp @@ -21,9 +21,11 @@ #include #include #include +#include +#include #include - +#include #include #include #include @@ -143,6 +145,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 +190,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 +236,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 +277,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 +466,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 +527,268 @@ 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) +{ + assert(clientData != nullptr); + ModelRegistry *builder = static_cast(clientData); + Domain *domain = builder->getDomain(); + + // Usage: + // 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; + + if (argc < 3) { + opserr << OpenSees::PromptValueError + << "insufficient arguments.\n" + << "Usage: constrain Translation Rnode Cnode {d1 d2 ...} <-rotate {v1 v2 v3}>" + << OpenSees::SignalMessageEnd; + 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] + << 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 = 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: " + << RnodeID << " " << CnodeID + << OpenSees::SignalMessageEnd; + return TCL_ERROR; + } + + const int numDOF = builder->getNDF(); + + // Prepare IDs and store 0-based indices of requested DOFs + ID rDOF(numDOF); + ID cDOF(numDOF); + + for (int i=0; i= 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], &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] + << 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 { + // Compute 3x3 rotation R = Exp(v) using Rodrigues’ formula + Matrix3D R = ExpSO3(v); + + 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; + } + } + } + + // Create and add MP (multi-point) constraint + MP_Constraint *theMP = new MP_Constraint(RnodeID, CnodeID, Ccr, cDOF, rDOF); + + if (domain->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); + + 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; + } - Tcl_SetObjResult(interp, Tcl_NewIntObj(theMP->getTag())); - return TCL_OK; + 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 +797,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 +813,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 +845,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 +874,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/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 || diff --git a/SRC/runtime/commands/modeling/element/frames.cpp b/SRC/runtime/commands/modeling/element/frames.cpp index 51e004fec3..0b02239a4d 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 @@ -66,6 +76,7 @@ #include #include #include +#include #include #include @@ -107,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); @@ -158,7 +196,6 @@ CreateFrame(ModelRegistry& builder, const std::array& shear_center, Options& options) { - std::vector sections; // Finalize sections @@ -194,7 +231,7 @@ CreateFrame(ModelRegistry& builder, // // Create the element // - Element *theElement = nullptr; + Element *theElement = nullptr; int iNode = nodev[0], jNode = nodev[1]; @@ -256,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) { @@ -277,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, @@ -300,11 +339,48 @@ 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) { + 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 +392,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,16 +405,17 @@ 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()) + << "too many sections for element: " + << static_cast(sections.size()) << OpenSees::SignalMessageEnd; return nullptr; } 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 +427,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, @@ -409,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], @@ -437,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 {...} @@ -490,7 +568,6 @@ CreateFrame(ModelRegistry& builder, // // "-transform" $Tag // "-vertical" {} -// "-horizontal" {} // // "-sections" $SectionTags // - if cannot split $SectionTags as list, then @@ -535,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(); @@ -580,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 @@ -589,7 +712,6 @@ TclBasicBuilder_addForceBeamColumn(ClientData clientData, Tcl_Interp *interp, } int argi = 5; - // bool multi_node = false; std::vector multi_nodes; { int list_argc; @@ -626,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 // @@ -647,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) { @@ -668,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; } @@ -698,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; } @@ -717,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) || @@ -740,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; + return TCL_ERROR; } - - 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; - } - - section_tags.push_back(sec_tag); - argi++; + received.transform = true; } else if (strcmp(argv[argi], "-shearCenter") == 0) { @@ -833,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) { @@ -933,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) { @@ -957,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) { @@ -993,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; } @@ -1001,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) { @@ -1081,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 // 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; diff --git a/SRC/runtime/commands/modeling/material/boucwen.cpp b/SRC/runtime/commands/modeling/material/boucwen.cpp index dd04552a5b..a58e2ea211 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; } } @@ -629,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); } 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; } 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 diff --git a/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp b/SRC/runtime/commands/modeling/transform/FrameTransformBuilder.hpp index 0791db32e1..40524d2a3c 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; } @@ -63,17 +62,21 @@ 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 nullptr; + return new EuclidFrameTransf> (tag, vz, offset_array, offset_flags); } else if (strstr(name, "PDelta") != nullptr) @@ -91,13 +94,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); + + else if (strcmp(name, "Corotational04") == 0) 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; } diff --git a/SRC/runtime/commands/utilities/linalg.hh b/SRC/runtime/commands/utilities/linalg.hh index 5674718228..92a91aab38 100644 --- a/SRC/runtime/commands/utilities/linalg.hh +++ b/SRC/runtime/commands/utilities/linalg.hh @@ -19,25 +19,29 @@ 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" + 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" } } diff --git a/SRC/runtime/runtime/BasicAnalysisBuilder.cpp b/SRC/runtime/runtime/BasicAnalysisBuilder.cpp index 677fcf08c0..c25253a3ea 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 @@ -77,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), @@ -140,7 +138,7 @@ BasicAnalysisBuilder::wipe() } if (theAnalysisModel != nullptr) { delete theAnalysisModel; - theAnalysisModel = new AnalysisModel(); + theAnalysisModel = new AnalysisModel(*context.getDomain()); } } @@ -155,14 +153,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 +176,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 +201,7 @@ BasicAnalysisBuilder::initialize() switch (this->CurrentAnalysisFlag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: break; case STATIC_ANALYSIS: @@ -234,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. @@ -323,6 +320,7 @@ BasicAnalysisBuilder::domainChanged() int BasicAnalysisBuilder::analyze(int num_steps, double size_steps, int flag) { + int status = -1; switch (this->CurrentAnalysisFlag) { @@ -338,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; } @@ -803,6 +802,7 @@ BasicAnalysisBuilder::fillDefaults(BasicAnalysisBuilder::CurrentAnalysis flag) switch (flag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: break; case STATIC_ANALYSIS: @@ -868,12 +868,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 +886,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; @@ -983,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; } @@ -1077,6 +1081,7 @@ BasicAnalysisBuilder::analyzeGradient() { switch (this->CurrentAnalysisFlag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: return -1; case STATIC_ANALYSIS: @@ -1096,6 +1101,7 @@ BasicAnalysisBuilder::setGradientType(int flag) { switch (this->CurrentAnalysisFlag) { case EMPTY_ANALYSIS: + case EIGEN_ANALYSIS: return -1; case STATIC_ANALYSIS: @@ -1113,4 +1119,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..fc9bc4cc8d 100644 --- a/SRC/runtime/runtime/BasicAnalysisBuilder.h +++ b/SRC/runtime/runtime/BasicAnalysisBuilder.h @@ -48,6 +48,11 @@ class EigenSOE; class StaticIntegrator; class TransientIntegrator; class ConvergenceTest; +namespace OpenSees { +class LoadCase; +} + +#include class BasicAnalysisBuilder { @@ -57,6 +62,7 @@ class BasicAnalysisBuilder enum CurrentAnalysis { EMPTY_ANALYSIS, + EIGEN_ANALYSIS, STATIC_ANALYSIS, TRANSIENT_ANALYSIS }; @@ -71,8 +77,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(); @@ -84,8 +96,12 @@ class BasicAnalysisBuilder Domain* getDomain(); + AnalysisModel& getAnalysisModel() { + return *theAnalysisModel; + } int initialize(); + int domainChanged(); int setStaticAnalysis(); int setTransientAnalysis(); @@ -95,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); @@ -103,6 +118,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); @@ -112,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: @@ -143,7 +161,6 @@ class BasicAnalysisBuilder bool freeSOE = true; bool freeTI = true; - }; #endif 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; }; diff --git a/SRC/runtime/runtime/TclPackageClassBroker.cpp b/SRC/runtime/runtime/TclPackageClassBroker.cpp index 1ee863903c..a179745a6d 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" @@ -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(); @@ -1421,8 +1404,8 @@ LoadPattern * TclPackageClassBroker::getNewLoadPattern(int classTag) { switch (classTag) { - case PATTERN_TAG_LoadPattern: - return new LoadPattern(); + // case PATTERN_TAG_LoadPattern: + // return new StaticPattern(); case PATTERN_TAG_UniformExcitation: return new UniformExcitation(); 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); 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 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 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/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..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; @@ -55,23 +56,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; 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) { 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; diff --git a/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/FullGenEigenSolver.cpp index e7035094b4..0befd40d2a 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 #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; } @@ -126,13 +134,13 @@ int 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 @@ -168,54 +176,53 @@ int 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; + // quick checks + if (theSOE == 0) { + opserr << "FullGenEigenSolver::solveI()- No EigenSOE object has been set yet\n"; + return -1; + } + if (nEigen < 1) { + numEigen = 0; + return 0; + } - 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; + // problem size + int n = theSOE->size; + 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; + } + + // 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::setEigenSOE(FullGenEigenSOE &thesoe) +int +FullGenEigenSolver::setSize() { - theSOE = &thesoe; + int size = theSOE->size; - return 0; + 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; + } + } + + return 0; } -const Vector& FullGenEigenSolver::getEigenvector(int mode) +int +FullGenEigenSolver::setEigenSOE(FullGenEigenSOE &thesoe) { - if (mode <= 0 || mode > numEigen) { - opserr << "FullGenEigenSolver::getEigenVector() - mode " - << mode << " is out of range (1 - " << numEigen << ")\n"; - eigenV->Zero(); - return *eigenV; - } + theSOE = &thesoe; - int size = theSOE->size; - int index = size*sortingID[mode-1]; + return 0; +} - if (eigenvector != 0) { - for (int i=0; iZero(); - } - return *eigenV; +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"; + theVector.Zero(); + return -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; - } - - if (eigenvalue != 0) { - return eigenvalue[mode-1]; - } - else { - opserr << "FullGenEigenSolver::getEigenvalue() - " + 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; - } + return 0.0; + } } 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; } @@ -333,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; } } } 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/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. diff --git a/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp b/SRC/system_of_eqn/eigenSOE/SymBandEigenSolver.cpp index 81d0bbc0bc..b9ce1c91b2 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() @@ -291,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 a64b1bd489..ac67e902f3 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 @@ -330,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; @@ -343,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); 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; 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. 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 #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/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); } - - diff --git a/SRC/tagged/storage/ArrayOfTaggedObjects.h b/SRC/tagged/storage/ArrayOfTaggedObjects.h index 1b13e7892b..92d187b82d 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,25 @@ 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(); + + Iterator& getIterRef() { + myIter.reset(); + return myIter; + } - 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: 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); } - - - 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/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/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. 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: 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(); } 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; 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 - - - - -