int PFEMIntegrator::saveSensitivity(const Vector & dVNew,int gradNum,int numGrads) { // Recover sensitivity results from previous step int vectorSize = U->Size(); Vector dUn(vectorSize); dVn.resize(vectorSize); dVn.Zero(); AnalysisModel *myModel = this->getAnalysisModel(); DOF_GrpIter &theDOFs = myModel->getDOFs(); DOF_Group *dofPtr; while ((dofPtr = theDOFs()) != 0) { const ID &id = dofPtr->getID(); int idSize = id.Size(); const Vector &dispSens = dofPtr->getDispSensitivity(gradNumber); for (int i=0; i < idSize; i++) { int loc = id(i); if (loc >= 0) { dUn(loc) = dispSens(i); } } const Vector &velSens = dofPtr->getVelSensitivity(gradNumber); for (int i=0; i < idSize; i++) { int loc = id(i); if (loc >= 0) { dVn(loc) = velSens(i); } } } // Compute new acceleration and velocity vectors: Vector dUNew(vectorSize); Vector dANew(vectorSize); // dudotdot = 1/dt*dv{n+1} - 1/dt*dvn dANew.addVector(0.0, dVNew, c3); dANew.addVector(1.0, dVn, -c3); // du = dun + dt*dv{n+1} dUNew.addVector(0.0, dVNew, c1); dUNew.addVector(1.0, dUn, 1.0); // Now we can save vNew, vdotNew and vdotdotNew DOF_GrpIter &theDOFGrps = myModel->getDOFs(); DOF_Group *dofPtr1; while ( (dofPtr1 = theDOFGrps() ) != 0) { dofPtr1->saveSensitivity(dUNew,dVNew,dANew,gradNum,numGrads); } return 0; }
int NewmarkSensitivityIntegrator::formEleResidual(FE_Element *theEle) { if (sensitivityFlag == 0) { // NO SENSITIVITY ANALYSIS this->Newmark::formEleResidual(theEle); } else { // (ASSEMBLE ALL TERMS) theEle->zeroResidual(); // Compute the time-stepping parameters on the form // udotdot = a1*ui+1 + a2*ui + a3*udoti + a4*udotdoti // udot = a5*ui+1 + a6*ui + a7*udoti + a8*udotdoti // (see p. 166 of Chopra) // The constants are: // a1 = 1.0/(beta*dt*dt) // a2 = -1.0/(beta*dt*dt) // a3 = -1.0/beta*dt // a4 = 1.0 - 1.0/(2.0*beta) // a5 = gamma/(beta*dt) // a6 = -gamma/(beta*dt) // a7 = 1.0 - gamma/beta // a8 = 1.0 - gamma/(2.0*beta) // We can make use of the data members c2 and c3 of this class. // As long as disp==true, they are defined as: // c2 = gamma/(beta*dt) // c3 = 1.0/(beta*dt*dt) // So, the constants can be computed as follows: if (displ==false) { opserr << "ERROR: Newmark::formEleResidual() -- the implemented" << " scheme only works if the displ variable is set to true." << endln; } double a2 = -c3; double a3 = -c2/gamma; double a4 = 1.0 - 1.0/(2.0*beta); double a6 = -c2; double a7 = 1.0 - gamma/beta; double dt = gamma/(beta*c2); double a8 = dt*(1.0 - gamma/(2.0*beta)); // Obtain sensitivity vectors from previous step int vectorSize = U->Size(); Vector V(vectorSize); Vector Vdot(vectorSize); Vector Vdotdot(vectorSize); int i, loc; AnalysisModel *myModel = this->getAnalysisModel(); DOF_GrpIter &theDOFs = myModel->getDOFs(); DOF_Group *dofPtr; while ((dofPtr = theDOFs()) != 0) { const ID &id = dofPtr->getID(); int idSize = id.Size(); const Vector &dispSens = dofPtr->getDispSensitivity(gradNumber); for (i=0; i < idSize; i++) { loc = id(i); if (loc >= 0) { V(loc) = dispSens(i); } } const Vector &velSens = dofPtr->getVelSensitivity(gradNumber); for (i=0; i < idSize; i++) { loc = id(i); if (loc >= 0) { Vdot(loc) = velSens(i); } } const Vector &accelSens = dofPtr->getAccSensitivity(gradNumber); for (i=0; i < idSize; i++) { loc = id(i); if (loc >= 0) { Vdotdot(loc) = accelSens(i); } } } // Pre-compute the vectors involving a2, a3, etc. //Vector tmp1 = V*a2 + Vdot*a3 + Vdotdot*a4; Vector tmp1(vectorSize); tmp1.addVector(0.0, V, a2); tmp1.addVector(1.0, Vdot, a3); tmp1.addVector(1.0, Vdotdot, a4); //Vector tmp2 = V*a6 + Vdot*a7 + Vdotdot*a8; Vector tmp2(vectorSize); tmp2.addVector(0.0, V, a6); tmp2.addVector(1.0, Vdot, a7); tmp2.addVector(1.0, Vdotdot, a8); if (massMatrixMultiplicator == 0) massMatrixMultiplicator = new Vector(tmp1.Size()); if (dampingMatrixMultiplicator == 0) dampingMatrixMultiplicator = new Vector(tmp2.Size()); (*massMatrixMultiplicator) = tmp1; (*dampingMatrixMultiplicator) = tmp2; // Now we're ready to make calls to the FE Element: // The term -dPint/dh|u fixed theEle->addResistingForceSensitivity(gradNumber); // The term -dM/dh*acc theEle->addM_ForceSensitivity(gradNumber, *Udotdot, -1.0); // The term -M*(a2*v + a3*vdot + a4*vdotdot) theEle->addM_Force(*massMatrixMultiplicator,-1.0); // The term -C*(a6*v + a7*vdot + a8*vdotdot) theEle->addD_Force(*dampingMatrixMultiplicator,-1.0); // The term -dC/dh*vel theEle->addD_ForceSensitivity(gradNumber, *Udot,-1.0); } return 0; }
int PFEMIntegrator::formEleResidual(FE_Element *theEle) { if (sensitivityFlag == 0) { // NO SENSITIVITY ANALYSIS this->TransientIntegrator::formEleResidual(theEle); } else { // (ASSEMBLE ALL TERMS) theEle->zeroResidual(); // Compute the time-stepping parameters on the form // udotdot = 1/dt*vn+1 - 1/dt*vn // u = un + dt*vn+1 // Obtain sensitivity vectors from previous step dVn.resize(U->Size()); dVn.Zero(); Vector dUn(U->Size()); AnalysisModel *myModel = this->getAnalysisModel(); DOF_GrpIter &theDOFs = myModel->getDOFs(); DOF_Group *dofPtr = 0; while ((dofPtr = theDOFs()) != 0) { const ID &id = dofPtr->getID(); int idSize = id.Size(); const Vector &dispSens = dofPtr->getDispSensitivity(gradNumber); for (int i=0; i < idSize; i++) { int loc = id(i); if (loc >= 0) { dUn(loc) = dispSens(i); } } const Vector &velSens = dofPtr->getVelSensitivity(gradNumber); for (int i=0; i < idSize; i++) { int loc = id(i); if (loc >= 0) { dVn(loc) = velSens(i); } } } // Now we're ready to make calls to the FE Element: // The term -dPint/dh|u fixed theEle->addResistingForceSensitivity(gradNumber); // The term -dM/dh*acc theEle->addM_ForceSensitivity(gradNumber, *Udotdot, -1.0); // The term -M*(-1/dt*dvn) theEle->addM_Force(dVn, c3); // The term -K*(dun) theEle->addK_Force(dUn, -1.0); // The term -dC/dh*vel theEle->addD_ForceSensitivity(gradNumber, *Udot,-1.0); } return 0; }
int NewmarkSensitivityIntegrator::saveSensitivity(const Vector & vNew,int gradNum,int numGrads) { // Compute Newmark parameters in general notation double a1 = c3; double a2 = -c3; double a3 = -c2/gamma; double a4 = 1.0 - 1.0/(2.0*beta); double a5 = c2; double a6 = -c2; double a7 = 1.0 - gamma/beta; double dt = gamma/(beta*c2); double a8 = dt*(1.0 - gamma/(2.0*beta)); // Recover sensitivity results from previous step int vectorSize = U->Size(); Vector V(vectorSize); Vector Vdot(vectorSize); Vector Vdotdot(vectorSize); int i, loc; AnalysisModel *myModel = this->getAnalysisModel(); DOF_GrpIter &theDOFs = myModel->getDOFs(); DOF_Group *dofPtr; while ((dofPtr = theDOFs()) != 0) { const ID &id = dofPtr->getID(); int idSize = id.Size(); const Vector &dispSens = dofPtr->getDispSensitivity(gradNumber); for (i=0; i < idSize; i++) { loc = id(i); if (loc >= 0) { V(loc) = dispSens(i); } } const Vector &velSens = dofPtr->getVelSensitivity(gradNumber); for (i=0; i < idSize; i++) { loc = id(i); if (loc >= 0) { Vdot(loc) = velSens(i); } } const Vector &accelSens = dofPtr->getAccSensitivity(gradNumber); for (i=0; i < idSize; i++) { loc = id(i); if (loc >= 0) { Vdotdot(loc) = accelSens(i); } } } // Compute new acceleration and velocity vectors: Vector vdotNew(vectorSize); Vector vdotdotNew(vectorSize); //(*vdotdotNewPtr) = vNew*a1 + V*a2 + Vdot*a3 + Vdotdot*a4; vdotdotNew.addVector(0.0, vNew, a1); vdotdotNew.addVector(1.0, V, a2); vdotdotNew.addVector(1.0, Vdot, a3); vdotdotNew.addVector(1.0, Vdotdot, a4); //(*vdotNewPtr) = vNew*a5 + V*a6 + Vdot*a7 + Vdotdot*a8; vdotNew.addVector(0.0, vNew, a5); vdotNew.addVector(1.0, V, a6); vdotNew.addVector(1.0, Vdot, a7); vdotNew.addVector(1.0, Vdotdot, a8); // Now we can save vNew, vdotNew and vdotdotNew DOF_GrpIter &theDOFGrps = myModel->getDOFs(); DOF_Group *dofPtr1; while ( (dofPtr1 = theDOFGrps() ) != 0) { dofPtr1->saveSensitivity(vNew,vdotNew,vdotdotNew,gradNum,numGrads); } return 0; }