void Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8) // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components. FloatMatrix b, d; FloatArray n, strain, stress; FloatArray shellUnknowns(20), drillUnknowns(4), unknowns; this->computeVectorOf(EID_MomentumBalance, VM_Total, tStep, unknowns); // Split this for practical reasons into normal shell dofs and drilling dofs for ( int i = 0; i < 4; ++i ) { shellUnknowns(0 + i*5) = unknowns(0 + i*6); shellUnknowns(1 + i*5) = unknowns(1 + i*6); shellUnknowns(2 + i*5) = unknowns(2 + i*6); shellUnknowns(3 + i*5) = unknowns(3 + i*6); shellUnknowns(4 + i*5) = unknowns(4 + i*6); drillUnknowns(i) = unknowns(5 + i*6); } FloatArray shellForces(20), drillMoment(4); shellForces.zero(); drillMoment.zero(); StructuralCrossSection *cs = this->giveStructuralCrossSection(); double drillCoeff = cs->give(CS_DrillingStiffness); IntegrationRule *iRule = integrationRulesArray [ 0 ]; for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) { GaussPoint *gp = iRule->getIntegrationPoint(i); this->computeBmatrixAt(gp, b); double dV = this->computeVolumeAround(gp); if ( useUpdatedGpRecord ) { stress = static_cast< StructuralMaterialStatus * >( this->giveMaterial()->giveStatus(gp) )->giveStressVector(); } else { strain.beProductOf(b, shellUnknowns); cs->giveRealStress_Shell(stress, gp, strain, tStep); } shellForces.plusProduct(b, stress, dV); // Drilling stiffness is here for improved numerical properties if (drillCoeff > 0.) { this->interp.evalN(n, *gp->giveCoordinates(), FEIVoidCellGeometry()); for ( int j = 0; j < 4; j++) { n(j) -= 0.25; } double dtheta = n.dotProduct(drillUnknowns); drillMoment.add(drillCoeff * dV * dtheta, n); ///@todo Decide on how to alpha should be defined. } } answer.resize(24); answer.zero(); answer.assemble(shellForces, this->shellOrdering); if (drillCoeff > 0.) { answer.assemble(drillMoment, this->drillOrdering); } }
void Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8) // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components. FloatMatrix b, d; FloatArray n, strain, stress; FloatArray shellUnknowns, drillUnknowns, unknowns; bool drillCoeffFlag = false; // Split this for practical reasons into normal shell dofs and drilling dofs this->computeVectorOf({D_u, D_v, D_w, R_u, R_v}, VM_Total, tStep, shellUnknowns); this->computeVectorOf({R_w}, VM_Total, tStep, drillUnknowns); FloatArray shellForces, drillMoment; StructuralCrossSection *cs = this->giveStructuralCrossSection(); for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { this->computeBmatrixAt(gp, b); double dV = this->computeVolumeAround(gp); double drillCoeff = cs->give(CS_DrillingStiffness, gp); if ( useUpdatedGpRecord ) { stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); } else { strain.beProductOf(b, shellUnknowns); cs->giveGeneralizedStress_Shell(stress, gp, strain, tStep); } shellForces.plusProduct(b, stress, dV); // Drilling stiffness is here for improved numerical properties if ( drillCoeff > 0. ) { this->interp.evalN( n, * gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); for ( int j = 0; j < 4; j++ ) { n(j) -= 0.25; } double dtheta = n.dotProduct(drillUnknowns); drillMoment.add(drillCoeff * dV * dtheta, n); ///@todo Decide on how to alpha should be defined. drillCoeffFlag = true; } } answer.resize(24); answer.zero(); answer.assemble(shellForces, this->shellOrdering); if ( drillCoeffFlag ) { answer.assemble(drillMoment, this->drillOrdering); } }
bool DKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness { // get node coordinates double x1, x2, x3, y1, y2, y3, z1, z2, z3; this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); // Fetch local coordinates. bool ok = this->interp_lin.global2local( answer, coords, FEIElementGeometryWrapper(this) ) > 0; //check that the point is in the element and set flag for ( int i = 1; i <= 3; i++ ) { if ( answer.at(i) < ( 0. - POINT_TOL ) ) { return false; } if ( answer.at(i) > ( 1. + POINT_TOL ) ) { return false; } } //get midplane location at this point double midplZ; midplZ = z1 * answer.at(1) + z2 * answer.at(2) + z3 * answer.at(3); //check that the z is within the element StructuralCrossSection *cs = this->giveStructuralCrossSection(); double elthick = cs->give(CS_Thickness, & answer, NULL, this); if ( elthick / 2.0 + midplZ - fabs( coords.at(3) ) < -POINT_TOL ) { answer.zero(); return false; } return ok; }
bool RerShell :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) { //set size of return value to 3 area coordinates answer.resize(3); //rotate the input point Coordinate System into the element CS FloatArray inputCoords_ElCS; this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) ); //Nodes are defined in the global CS, so they also need to be rotated into the element CS, therefore get the node points and //rotate them into the element CS FloatArray nodeCoords; double x1, x2, x3, y1, y2, y3, z1, z2, z3; this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(1)->giveCoordinates() ) ); x1 = nodeCoords.at(1); y1 = nodeCoords.at(2); z1 = nodeCoords.at(3); this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(2)->giveCoordinates() ) ); x2 = nodeCoords.at(1); y2 = nodeCoords.at(2); z2 = nodeCoords.at(3); this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(3)->giveCoordinates() ) ); x3 = nodeCoords.at(1); y3 = nodeCoords.at(2); z3 = nodeCoords.at(3); //Compute the area coordinates corresponding to this point double area; area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ); answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * inputCoords_ElCS.at(1) + ( x3 - x2 ) * inputCoords_ElCS.at(2) ) / 2. / area; answer.at(2) = ( ( x3 * y1 - x1 * y3 ) + ( y3 - y1 ) * inputCoords_ElCS.at(1) + ( x1 - x3 ) * inputCoords_ElCS.at(2) ) / 2. / area; answer.at(3) = ( ( x1 * y2 - x2 * y1 ) + ( y1 - y2 ) * inputCoords_ElCS.at(1) + ( x2 - x1 ) * inputCoords_ElCS.at(2) ) / 2. / area; //get midplane location at this point double midplZ; midplZ = z1 * answer.at(1) + z2 *answer.at(2) + z3 *answer.at(3); //check that the z is within the element StructuralCrossSection *cs = this->giveStructuralCrossSection(); GaussPoint _gp(NULL, 1, new FloatArray ( answer ), 1.0, _2dPlate); double elthick; elthick = cs->give(CS_Thickness, & _gp); if ( elthick / 2.0 + midplZ - fabs( inputCoords_ElCS.at(3) ) < -POINT_TOL ) { answer.zero(); return false; } //check that the point is in the element and set flag for ( int i = 1; i <= 3; i++ ) { if ( answer.at(i) < ( 0. - POINT_TOL ) ) { return false; } if ( answer.at(i) > ( 1. + POINT_TOL ) ) { return false; } } return true; }