void PrescribedGradientBCPeriodic :: computeField(FloatArray &sigma, TimeStep *tStep) { DofIDEquationNumbering pnum(true, strain_id); EngngModel *emodel = this->giveDomain()->giveEngngModel(); FloatArray tmp, sig_tmp; int npeq = strain_id.giveSize(); // sigma = residual (since we use the slave dofs) = f_ext - f_int sig_tmp.resize(npeq); sig_tmp.zero(); emodel->assembleVector(sig_tmp, tStep, InternalForceAssembler(), VM_Total, pnum, this->domain); tmp.resize(npeq); tmp.zero(); emodel->assembleVector(tmp, tStep, ExternalForceAssembler(), VM_Total, pnum, this->domain); sig_tmp.subtract(tmp); // Divide by the RVE-volume sig_tmp.times(1.0 / ( this->domainSize(this->giveDomain(), this->set) + this->domainSize(this->giveDomain(), this->masterSet) )); sigma.resize(sig_tmp.giveSize()); if ( sig_tmp.giveSize() == 9 ) { sigma.assemble(sig_tmp, {1, 9, 8, 6, 2, 7, 5, 4, 3}); } else if ( sig_tmp.giveSize() == 4 ) { sigma.assemble(sig_tmp, {1, 4, 3, 2}); } else { sigma = sig_tmp; } }
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); } }
void Tr21Stokes :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep) { IntegrationRule *iRule = this->integrationRulesArray [ 0 ]; GaussPoint *gp; FloatArray N, gVector, *lcoords, temparray(15); double dA, detJ, rho; load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { for ( int k = 0; k < iRule->getNumberOfIntegrationPoints(); k++ ) { gp = iRule->getIntegrationPoint(k); lcoords = gp->giveCoordinates(); rho = this->giveMaterial()->giveCharacteristicValue(MRM_Density, gp, tStep); detJ = fabs( this->interpolation_quad.giveTransformationJacobian(* lcoords, FEIElementGeometryWrapper(this)) ); dA = detJ * gp->giveWeight(); this->interpolation_quad.evalN(N, * lcoords, FEIElementGeometryWrapper(this)); for ( int j = 0; j < 6; j++ ) { temparray(2 * j) += N(j) * rho * gVector(0) * dA; temparray(2 * j + 1) += N(j) * rho * gVector(1) * dA; } } } answer.resize(15); answer.zero(); answer.assemble( temparray, this->ordering ); }
void ContactDefinition :: computeContactForces(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) { //Loop through all the contact elements and let them return their internal forces vector FloatArray Fc; IntArray locArray; // TODO ask masters that are potentially in contact and not everyone for ( ContactElement *master : this->masterElementList ) { // These acts as external forces so move them to the lhs master->computeContactForces(Fc, tStep, type, mode, s, domain, eNorms); Fc.negated(); if ( Fc.giveSize() ) { master->giveLocationArray(locArray, s); answer.assemble(Fc, locArray); if ( eNorms ) { eNorms->assembleSquared( Fc, locArray ); } } } }
void NonStationaryTransportProblem :: assembleDirichletBcRhsVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode, const UnknownNumberingScheme &ns, Domain *d) { IntArray loc, dofids; FloatArray rp, charVec; FloatMatrix s; FloatMatrix capacity; int nelem = d->giveNumberOfElements(); for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *element = d->giveElement(ielem); element->giveElementDofIDMask(dofids); element->computeVectorOfPrescribed(dofids, mode, tStep, rp); if ( rp.containsOnlyZeroes() ) { continue; } else { element->giveCharacteristicMatrix(s, TangentStiffnessMatrix, tStep); element->giveCharacteristicMatrix(capacity, lumpedCapacityStab ? LumpedMassMatrix : MassMatrix, tStep); s.times(this->alpha); s.add(1. / tStep->giveTimeIncrement(), capacity); charVec.beProductOf(s, rp); charVec.negated(); element->giveLocationArray(loc, ns); answer.assemble(charVec, loc); } } // end element loop }
void SurfaceTensionBoundaryCondition :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) { if ( type != ExternalForcesVector ) { return; } FloatArray fe; IntArray loc, masterdofids, bNodes; Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, s, & masterdofids); this->computeLoadVectorFromElement(fe, e, boundary, tStep); answer.assemble(fe, loc); if ( eNorms ) { eNorms->assembleSquared(fe, masterdofids); } } }
void NonStationaryTransportProblem :: assembleDirichletBcRhsVector(FloatArray &answer, TimeStep *tStep, EquationID ut, ValueModeType mode, CharType lhsType, const UnknownNumberingScheme &ns, Domain *d) { int ielem; IntArray loc; Element *element; FloatArray rp, charVec; FloatMatrix s, bcMtrx; int nelem = d->giveNumberOfElements(); for ( ielem = 1; ielem <= nelem; ielem++ ) { element = d->giveElement(ielem); element->computeVectorOfPrescribed(EID_ConservationEquation, mode, tStep, rp); if ( rp.containsOnlyZeroes() ) { continue; } else { this->giveElementCharacteristicMatrix(s, ielem, lhsType, tStep, d); element->giveCharacteristicMatrix(bcMtrx, LHSBCMatrix, tStep); s.add(bcMtrx); charVec.beProductOf(s, rp); charVec.negated(); element->giveLocationArray(loc, ut, ns); answer.assemble(charVec, loc); } } // end element loop }
void Tr21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) { if ( type != ExternalForcesVector ) { answer.clear(); return; } FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); FloatArray N, gVector, temparray(12); load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double rho = mat->give('d', gp); double detJ = fabs( this->interpolation_quad.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) ); double dA = detJ * gp->giveWeight(); this->interpolation_quad.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); for ( int j = 0; j < 6; j++ ) { temparray(2 * j) += N(j) * rho * gVector(0) * dA; temparray(2 * j + 1) += N(j) * rho * gVector(1) * dA; } } } answer.resize(15); answer.zero(); answer.assemble(temparray, this->momentum_ordering); }
void GradDpElement :: computeForceLoadVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) { //set displacement and nonlocal location array this->setDisplacementLocationArray(); this->setNonlocalLocationArray(); FloatArray localForces(locSize); FloatArray nlForces(nlSize); answer.resize(totalSize); this->computeLocForceLoadVector(localForces, tStep, mode); answer.assemble(localForces, locU); answer.assemble(nlForces, locK); }
void TR_SHELL02 :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) // // returns characteristics vector of receiver accordind to mtrx // { FloatArray aux; answer.resize(18); answer.zero(); plate->giveCharacteristicVector(aux, mtrx, mode, tStep); if ( !aux.isEmpty() ) answer.assemble(aux, loc_plate); membrane->giveCharacteristicVector(aux, mtrx, mode, tStep); if ( !aux.isEmpty() ) answer.assemble(aux, loc_membrane); }
void TR_SHELL01 :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) // // returns characteristics vector of receiver accordind to mtrx // { IntArray loc(9); FloatArray aux; answer.resize(18); answer.zero(); plate->giveCharacteristicVector(aux, mtrx, mode, tStep); loc.setValues(9, 3,4,5, 9,10,11, 15,16,17); answer.assemble(aux, loc); membrane->giveCharacteristicVector(aux, mtrx, mode, tStep); loc.setValues(9, 1,2,6, 7,8,12, 13,14,18); answer.assemble(aux, loc); }
void Tr21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) { FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); FloatArray a_pressure, a_velocity, devStress, epsp, Nh, dNv(12); double r_vol, pressure; FloatMatrix dN, B(3, 12); B.zero(); this->computeVectorOfVelocities(VM_Total, tStep, a_velocity); this->computeVectorOfPressures(VM_Total, tStep, a_pressure); FloatArray momentum, conservation; for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); this->interpolation_lin.evalN( Nh, lcoords, FEIElementGeometryWrapper(this) ); double dA = detJ * gp->giveWeight(); for ( int j = 0, k = 0; j < dN.giveNumberOfRows(); j++, k += 2 ) { dNv(k) = B(0, k) = B(2, k + 1) = dN(j, 0); dNv(k + 1) = B(1, k + 1) = B(2, k) = dN(j, 1); } pressure = Nh.dotProduct(a_pressure); epsp.beProductOf(B, a_velocity); mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); momentum.plusProduct(B, devStress, dA); momentum.add(-pressure * dA, dNv); conservation.add(r_vol * dA, Nh); } answer.resize(15); answer.zero(); answer.assemble(momentum, this->momentum_ordering); answer.assemble(conservation, this->conservation_ordering); }
void Tr21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) { IntegrationRule *iRule = integrationRulesArray [ 0 ]; FluidDynamicMaterial *mat = ( FluidDynamicMaterial * ) this->domain->giveMaterial(this->material); FloatArray a_pressure, a_velocity, devStress, epsp, BTs, Nh, dNv(12); double r_vol, pressure; FloatMatrix dN, B(3, 12); B.zero(); this->computeVectorOf(EID_MomentumBalance, VM_Total, tStep, a_velocity); this->computeVectorOf(EID_ConservationEquation, VM_Total, tStep, a_pressure); FloatArray momentum(12), conservation(3); momentum.zero(); conservation.zero(); GaussPoint *gp; for ( int i = 0; i < iRule->getNumberOfIntegrationPoints(); i++ ) { gp = iRule->getIntegrationPoint(i); FloatArray *lcoords = gp->giveCoordinates(); double detJ = fabs(this->interpolation_quad.giveTransformationJacobian(* lcoords, FEIElementGeometryWrapper(this))); this->interpolation_quad.evaldNdx(dN, * lcoords, FEIElementGeometryWrapper(this)); this->interpolation_lin.evalN(Nh, * lcoords, FEIElementGeometryWrapper(this)); double dA = detJ * gp->giveWeight(); for ( int j = 0, k = 0; j < 6; j++, k += 2 ) { dNv(k) = B(0, k) = B(2, k + 1) = dN(j, 0); dNv(k + 1) = B(1, k + 1) = B(2, k) = dN(j, 1); } pressure = Nh.dotProduct(a_pressure); epsp.beProductOf(B, a_velocity); mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); BTs.beTProductOf(B, devStress); momentum.add(dA, BTs); momentum.add(-pressure*dA, dNv); conservation.add(r_vol*dA, Nh); } FloatArray temp(15); temp.zero(); temp.addSubVector(momentum, 1); temp.addSubVector(conservation, 13); answer.resize(15); answer.zero(); answer.assemble(temp, this->ordering); }
void Tr1Darcy :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep) { /* * Given the load *load, return it's contribution. * */ answer.resize(3); answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) BoundaryLoad *boundaryLoad; boundaryLoad = ( BoundaryLoad * ) load; int numberOfEdgeIPs; numberOfEdgeIPs = ( int ) ceil( ( boundaryLoad->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); GaussPoint *gp; FloatArray N, loadValue, reducedAnswer; reducedAnswer.resize(3); reducedAnswer.zero(); IntArray mask; iRule.setUpIntegrationPoints(_Line, numberOfEdgeIPs, _Unknown); for ( int i = 0; i < iRule.getNumberOfIntegrationPoints(); i++ ) { gp = iRule.getIntegrationPoint(i); FloatArray *lcoords = gp->giveCoordinates(); this->interpolation_lin.edgeEvalN(N, *lcoords, FEIElementGeometryWrapper(this)); double dV = this->computeEdgeVolumeAround(gp, iEdge); if ( boundaryLoad->giveFormulationType() == BoundaryLoad :: BL_EntityFormulation ) { // Edge load in xi-eta system boundaryLoad->computeValueAt(loadValue, tStep, *lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_lin.edgeLocal2global(gcoords, iEdge, *lcoords, FEIElementGeometryWrapper(this)); boundaryLoad->computeValueAt(loadValue, tStep, gcoords, VM_Total); } reducedAnswer.add(loadValue.at(1) * dV, N); } this->interpolation_lin.computeLocalEdgeMapping(mask, iEdge); answer.assemble(reducedAnswer, mask); } }
void Tet21Stokes :: computeBoundaryLoadVector(FloatArray &answer, BoundaryLoad *load, int iSurf, CharType type, ValueModeType mode, TimeStep *tStep) { if ( type != ExternalForcesVector ) { answer.clear(); return; } answer.resize(34); answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) int numberOfSurfaceIPs = ( int ) ceil( ( load->giveApproxOrder() + 1. ) / 2. ) * 2; ///@todo Check this. GaussIntegrationRule iRule(1, this, 1, 1); FloatArray N, t, f(18); f.zero(); iRule.SetUpPointsOnTriangle(numberOfSurfaceIPs, _Unknown); for ( GaussPoint *gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.surfaceEvalN( N, iSurf, lcoords, FEIElementGeometryWrapper(this) ); double dA = gp->giveWeight() * this->interpolation_quad.surfaceGiveTransformationJacobian( iSurf, lcoords, FEIElementGeometryWrapper(this) ); if ( load->giveFormulationType() == Load :: FT_Entity ) { // load in xi-eta system load->computeValueAt(t, tStep, lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_quad.surfaceLocal2global( gcoords, iSurf, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(t, tStep, gcoords, VM_Total); } // Reshape the vector for ( int j = 0; j < N.giveSize(); j++ ) { f(3 * j + 0) += N(j) * t(0) * dA; f(3 * j + 1) += N(j) * t(1) * dA; f(3 * j + 2) += N(j) * t(2) * dA; } } answer.assemble(f, this->surf_ordering [ iSurf - 1 ]); } else { OOFEM_ERROR("Strange boundary condition type"); } }
void Tr21Stokes :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep) { answer.resize(15); answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) BoundaryLoad *boundaryLoad = ( BoundaryLoad * ) load; int numberOfEdgeIPs = ( int ) ceil( ( boundaryLoad->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); GaussPoint *gp; FloatArray N, t, f(6); IntArray edge_mapping; f.zero(); iRule.setUpIntegrationPoints(_Line, numberOfEdgeIPs, _Unknown); for ( int i = 0; i < iRule.getNumberOfIntegrationPoints(); i++ ) { gp = iRule.getIntegrationPoint(i); FloatArray *lcoords = gp->giveCoordinates(); this->interpolation_quad.edgeEvalN(N, * lcoords, FEIElementGeometryWrapper(this)); double detJ = fabs(this->interpolation_quad.edgeGiveTransformationJacobian(iEdge, * lcoords, FEIElementGeometryWrapper(this))); double dS = gp->giveWeight() * detJ; if ( boundaryLoad->giveFormulationType() == BoundaryLoad :: BL_EntityFormulation ) { // Edge load in xi-eta system boundaryLoad->computeValueAt(t, tStep, * lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_quad.edgeLocal2global(gcoords, iEdge, * lcoords, FEIElementGeometryWrapper(this)); boundaryLoad->computeValueAt(t, tStep, gcoords, VM_Total); } // Reshape the vector for ( int j = 0; j < 3; j++ ) { f(2 * j) += N(j) * t(0) * dS; f(2 * j + 1) += N(j) * t(1) * dS; } } answer.assemble(f, this->edge_ordering [ iEdge - 1 ]); } else { OOFEM_ERROR("Tr21Stokes :: computeEdgeBCSubVectorAt - Strange boundary condition type"); } }
void Tr21Stokes :: computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) { if ( type != ExternalForcesVector ) { answer.clear(); return; } if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) int numberOfEdgeIPs = ( int ) ceil( ( load->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); FloatArray N, t, f(6); f.zero(); iRule.SetUpPointsOnLine(numberOfEdgeIPs, _Unknown); for ( GaussPoint *gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.edgeEvalN( N, boundary, lcoords, FEIElementGeometryWrapper(this) ); double detJ = fabs( this->interpolation_quad.boundaryGiveTransformationJacobian( boundary, lcoords, FEIElementGeometryWrapper(this) ) ); double dS = gp->giveWeight() * detJ; if ( load->giveFormulationType() == Load :: FT_Entity ) { // Edge load in xi-eta system load->computeValueAt(t, tStep, lcoords, VM_Total); } else { // Edge load in x-y system FloatArray gcoords; this->interpolation_quad.boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(t, tStep, gcoords, VM_Total); } // Reshape the vector for ( int j = 0; j < 3; j++ ) { f(2 * j) += N(j) * t(0) * dS; f(2 * j + 1) += N(j) * t(1) * dS; } } answer.resize(15); answer.zero(); answer.assemble(f, this->edge_ordering [ boundary - 1 ]); } else { OOFEM_ERROR("Strange boundary condition type"); } }
void StructuralInterfaceElementPhF :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // Computes the internal forces corresponding to the two fields u & d IntArray IdMask_u, IdMask_d; this->giveDofManDofIDMask_u( IdMask_u ); this->giveDofManDofIDMask_d( IdMask_d ); this->getLocationArray_u(loc_u); this->getLocationArray_d(loc_d); int ndofs = this->computeNumberOfDofs(); answer.resize( ndofs); answer.zero(); FloatArray answer_u(0); FloatArray answer_d(0); this->giveInternalForcesVector_u(answer_u, tStep, useUpdatedGpRecord); this->giveInternalForcesVector_d(answer_d, tStep, useUpdatedGpRecord); answer.assemble(answer_u, loc_u); answer.assemble(answer_d, loc_d); }
void GradDpElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { answer.resize(totalSize); answer.zero(); FloatArray answerU; answerU.resize(locSize); answer.zero(); FloatArray answerK(nlSize); answerK.zero(); ///@todo This code relies on locU and locK already exists. Design seems highly unsafe. /// Instead locU and locK shoulld be statically determined (cf. with the Taylor-Hood elements) / Mikael this->giveNonlocalInternalForcesVector(answerK, tStep, useUpdatedGpRecord); this->giveLocalInternalForcesVector(answerU, tStep, useUpdatedGpRecord); answer.assemble(answerU, locU); answer.assemble(answerK, locK); }
void StructuralInterfaceElementPhF :: giveInternalForcesVector_d(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // computes int_A ( N^t * ( d + l*f ) + B^t * l^2 * gradd(d) )* dA FloatArray BStress, Nd, BS, a_d, grad_d; FloatMatrix B; answer.clear(); this->computeDamageUnknowns( a_d, VM_Total, tStep ); double l = this->giveInternalLength(); for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { // Part 1 StructuralInterfaceMaterialPhF *mat = static_cast< StructuralInterfaceMaterialPhF * >( this->giveInterfaceCrossSection()->giveInterfaceMaterial() ); double d = computeDamageAt( ip, VM_Total, tStep ); double facN = d + l * mat->giveDrivingForce(ip); this->giveInterpolation()->evalN(Nd, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this)); double dA = this->computeAreaAround(ip); answer.add(facN*dA, Nd); // Part 2 this->computeBd_matrixAt(ip, B ); grad_d.beProductOf(B, { a_d.at(1), a_d.at(2) }); BStress = grad_d * l * l; BS.beTProductOf(B, BStress); answer.add(dA, BS); } FloatArray temp; temp = answer; answer.resize(4); answer.zero(); answer.assemble(temp,{1,2}); answer.assemble(temp,{3,4}); }
void PrescribedMean :: giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s) { computeDomainSize(); FloatArray temp; IntArray lambdaLoc; temp.resize(1); temp.at(1) = c; lambdaDman->giveLocationArray(lambdaIDs, lambdaLoc, s); answer.assemble(temp, lambdaLoc); // Finally, compute value of loadtimefunction double factor; factor = this->giveTimeFunction()->evaluate(tStep, mode); answer.times(factor); }
void NonStationaryTransportProblem :: assembleAlgorithmicPartOfRhs(FloatArray &answer, EquationID ut, const UnknownNumberingScheme &s, TimeStep *tStep) { IntArray loc; FloatMatrix charMtrx, bcMtrx; FloatArray unknownVec, contrib, intSource; Element *element; Domain *domain = this->giveDomain(1); int nelem = domain->giveNumberOfElements(); for ( int i = 1; i <= nelem; i++ ) { element = domain->giveElement(i); #ifdef __PARALLEL_MODE // skip remote elements (these are used as mirrors of remote elements on other domains // when nonlocal constitutive models are used. They introduction is necessary to // allow local averaging on domains without fine grain communication between domains). if ( element->giveParallelMode() == Element_remote ) { continue; } #endif element->giveLocationArray(loc, ut, s); //(alpha-1)*K+C/dt this->giveElementCharacteristicMatrix(charMtrx, i, NSTP_MidpointRhs, tStep, domain); //contribution from previous boundary convection element->giveCharacteristicMatrix(bcMtrx, LHSBCMatrix, tStep); bcMtrx.times(this->alpha - 1.0); if ( bcMtrx.isNotEmpty() ) { charMtrx.add(bcMtrx); } if ( charMtrx.isNotEmpty() ) { element->computeVectorOf(EID_ConservationEquation, VM_Total, tStep, unknownVec); contrib.beProductOf(charMtrx, unknownVec); answer.assemble(contrib, loc); } } }
void LinearConstraintBC :: assembleVector(FloatArray &answer, TimeStep *tStep, EquationID eid, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) { IntArray loc, lambdaeq(1); FloatArray vec(1); double factor=1.; if (!this->rhsType.contains((int) type)) return ; if (!this->isImposed(tStep)) return; if (type == InternalForcesVector) { // compute true residual int size = this->weights.giveSize(); Dof *idof; // assemble location array for ( int _i = 1; _i <= size; _i++ ) { factor=1.; if(weightsLtf.giveSize()){ factor = domain->giveLoadTimeFunction(weightsLtf.at(_i))->__at(tStep->giveIntrinsicTime()); } idof = this->domain->giveDofManager( this->dofmans.at(_i) )->giveDof( this->dofs.at(_i) ); answer.at(s.giveDofEquationNumber(idof)) += md->giveDof(1)->giveUnknown(mode, tStep) * this->weights.at(_i)*factor; answer.at(s.giveDofEquationNumber( md->giveDof(1) )) += idof->giveUnknown(mode, tStep) * this->weights.at(_i)*factor; } } else { // use rhs value if(rhsLtf){ factor = domain->giveLoadTimeFunction(rhsLtf)->__at(tStep->giveIntrinsicTime()); } this->giveLocArray(s, loc, lambdaeq.at(1)); vec.at(1) = rhs*factor; answer.assemble(vec, lambdaeq); } }
void NonStationaryTransportProblem :: assembleAlgorithmicPartOfRhs(FloatArray &answer, const UnknownNumberingScheme &s, TimeStep *tStep) { IntArray loc; FloatMatrix charMtrx, charMtrx2; FloatArray unknownVec, contrib, intSource; Element *element; Domain *domain = this->giveDomain(1); int nelem = domain->giveNumberOfElements(); for ( int i = 1; i <= nelem; i++ ) { element = domain->giveElement(i); // skip remote elements (these are used as mirrors of remote elements on other domains // when nonlocal constitutive models are used. They introduction is necessary to // allow local averaging on domains without fine grain communication between domains). if ( element->giveParallelMode() == Element_remote ) { continue; } element->giveLocationArray(loc, s); //(alpha-1)*K+C/dt element->giveCharacteristicMatrix(charMtrx, TangentStiffnessMatrix, tStep); element->giveCharacteristicMatrix(charMtrx2, lumpedCapacityStab ? LumpedMassMatrix : MassMatrix, tStep); charMtrx.times(this->alpha - 1.0); charMtrx.add(1. / tStep->giveTimeIncrement(), charMtrx2); if ( charMtrx.isNotEmpty() ) { element->computeVectorOf(VM_Total, tStep, unknownVec); contrib.beProductOf(charMtrx, unknownVec); answer.assemble(contrib, loc); } } }
void tet21ghostsolid :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ]; #ifdef __FM_MODULE FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); #endif FloatMatrix Kf, G, Kx, B, Ed, dNx; FloatArray Strain, Stress, Nlin, dNv, a, aVelocity, aPressure, aGhostDisplacement, fluidStress, epsf; FloatArray momentum, conservation, auxstress; double pressure, epsvol; this->computeVectorOf( VM_Total, tStep, a); if (!tStep->isTheFirstStep()) { // a.printYourself(); } aVelocity.beSubArrayOf(a, momentum_ordering); aPressure.beSubArrayOf(a, conservation_ordering); aGhostDisplacement.beSubArrayOf(a, ghostdisplacement_ordering); for (int j = 0; j<iRule->giveNumberOfIntegrationPoints(); j++) { GaussPoint *gp = iRule->getIntegrationPoint(j); double detJ = fabs( ( this->interpolation.giveTransformationJacobian( * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ) ); double weight = gp->giveWeight(); this->interpolation.evaldNdx( dNx, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); this->interpolation_lin.evalN( Nlin, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); dNv.resize(30); for (int k = 0; k<dNx.giveNumberOfColumns(); k++) { dNv.at(k*3+1) = dNx.at(1,k+1); dNv.at(k*3+2) = dNx.at(2,k+1); dNv.at(k*3+3) = dNx.at(3,k+1); } if (nlGeometry == 0) { this->computeBmatrixAt(gp, B); epsf.beProductOf(B, aVelocity); pressure = Nlin.dotProduct(aPressure); // Fluid part gp->setMaterialMode(_3dFlow); #ifdef __FM_MODULE fluidMaterial->computeDeviatoricStressVector(fluidStress, epsvol, gp, epsf, pressure, tStep); #else OOFEM_ERROR("Missing FM module"); #endif gp->setMaterialMode(_3dMat); momentum.plusProduct(B, fluidStress, detJ*weight); momentum.add(-pressure * detJ * weight, dNv); conservation.add(epsvol * detJ * weight, Nlin); // Ghost solid part Strain.beProductOf(B, aGhostDisplacement); Stress.beProductOf(Dghost, Strain); auxstress.plusProduct(B, Stress, detJ * weight); } else { OOFEM_ERROR("No support for large deformations yet!"); } } answer.resize(64); answer.zero(); #if USEUNCOUPLED == 1 // Totaly uncoupled answer.assemble(momentum, momentum_ordering); answer.assemble(conservation, conservation_ordering); answer.assemble(auxstress, ghostdisplacement_ordering); #else answer.assemble(momentum, ghostdisplacement_ordering); answer.assemble(conservation, conservation_ordering); answer.assemble(auxstress, momentum_ordering); #endif // Test linear /* if (this->giveNumber() == 364) { FloatMatrix K; FloatArray ans; this->computeStiffnessMatrix(K, TangentStiffness, tStep); ans.beProductOf(K, a); ans.printYourself(); answer.printYourself(); } */ }
void tet21ghostsolid :: computeLoadVector(FloatArray &answer, Load *load, CharType type, ValueModeType mode, TimeStep *tStep) { answer.resize(64); answer.zero(); if ( type != ExternalForcesVector ) { answer.resize(0); return; } #ifdef __FM_MODULE FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); #endif IntegrationRule *iRule = this->integrationRulesArray [ 0 ]; FloatArray N, gVector, temparray(30), dNv, u, inc, u_prev, vload; FloatMatrix dNx, G; load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); vload.resize(4); vload.zero(); this->giveDisplacementsIncrementData(u_prev, u, inc, tStep); for ( int k = 0; k < iRule->giveNumberOfIntegrationPoints(); k++ ) { GaussPoint *gp = iRule->getIntegrationPoint(k); FloatArray *lcoords = gp->giveNaturalCoordinates(); double detJ = fabs( this->interpolation.giveTransformationJacobian( * lcoords, FEIElementGeometryWrapper(this) ) ); double dA = detJ * gp->giveWeight(); // Body load if ( gVector.giveSize() ) { #ifdef __FM_MODULE double rho = mat->give('d', gp); #else OOFEM_ERROR("Missing FM module"); double rho = 1.0; #endif this->interpolation.evalN( N, * lcoords, FEIElementGeometryWrapper(this) ); for ( int j = 0; j < N.giveSize(); j++ ) { temparray(3 * j + 0) += N(j) * rho * gVector(0) * dA; temparray(3 * j + 1) += N(j) * rho * gVector(1) * dA; temparray(3 * j + 2) += N(j) * rho * gVector(2) * dA; } } // "load" from previous step this->interpolation.evaldNdx( dNx, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); this->interpolation_lin.evalN( N, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); dNv.resize(30); for (int k = 0; k<dNx.giveNumberOfColumns(); k++) { dNv.at(k*3+1) = dNx.at(1,k+1); dNv.at(k*3+2) = dNx.at(2,k+1); dNv.at(k*3+3) = dNx.at(3,k+1); } G.plusDyadUnsym(N, dNv, dA); FloatMatrix GT; GT.beTranspositionOf(G); vload.plusProduct(GT, u_prev, -0.0 ); //vload.printYourself(); } #if USEUNCOUPLED == 1 // Totaly uncoupled answer.assemble(temparray, this->momentum_ordering); #else answer.assemble(temparray, this->ghostdisplacement_ordering); answer.assemble(vload, this->conservation_ordering); #endif // answer.printYourself(); }
NM_Status StaggeredSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, FloatArray &Xtotal, FloatArray &dXtotal, FloatArray &F, const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, int &nite, TimeStep *tStep) { // residual, iteration increment of solution, total external force FloatArray RHS, rhs, ddXtotal, RT; double RRTtotal; int neq = Xtotal.giveSize(); NM_Status status; bool converged, errorOutOfRangeFlag; ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() ); if ( engngModel->giveProblemScale() == macroScale ) { OOFEM_LOG_INFO("StaggeredSolver: Iteration"); if ( rtolf.at(1) > 0.0 ) { OOFEM_LOG_INFO(" ForceError"); } if ( rtold.at(1) > 0.0 ) { OOFEM_LOG_INFO(" DisplError"); } OOFEM_LOG_INFO("\n----------------------------------------------------------------------------\n"); } l = 1.0; status = NM_None; this->giveLinearSolver(); // compute total load R = R+R0 RT = R; if ( R0 ) { RT.add(* R0); } RRTtotal = parallel_context->localNorm(RT); RRTtotal *= RRTtotal; ddXtotal.resize(neq); ddXtotal.zero(); // Fetch the matrix before evaluating internal forces. // This is intentional, since its a simple way to drastically increase convergence for nonlinear problems. // (This old tangent is just used) // This improves convergence for many nonlinear problems, but not all. It may actually // cause divergence for some nonlinear problems. Therefore a flag is used to determine if // the stiffness should be evaluated before the residual (default yes). /ES //------------------------------------------------- // Compute external forces int numDofIdGroups = this->UnknownNumberingSchemeList.size(); FloatArray RRT(numDofIdGroups); for ( int dG = 0; dG < numDofIdGroups; dG++ ) { this->fExtList[dG].beSubArrayOf( RT, locArrayList[dG] ); RRT(dG) = this->fExtList[dG].computeSquaredNorm(); } int nStaggeredIter = 0; do { // Staggered iterations for ( int dG = 0; dG < (int)this->UnknownNumberingSchemeList.size(); dG++ ) { printf("\nSolving for dof group %d \n", dG+1); engngModel->updateComponent(tStep, NonLinearLhs, domain); this->stiffnessMatrixList[dG] = k.giveSubMatrix( locArrayList[dG], locArrayList[dG]); if ( this->prescribedDofsFlag ) { if ( !prescribedEqsInitFlag ) { this->initPrescribedEqs(); } applyConstraintsToStiffness(k); } nite = 0; do { // Compute the residual engngModel->updateComponent(tStep, InternalRhs, domain); RHS.beDifferenceOf(RT, F); this->fIntList[dG].beSubArrayOf( F, locArrayList[dG] ); rhs.beDifferenceOf(this->fExtList[dG], this->fIntList[dG]); RHS.zero(); RHS.assemble(rhs, locArrayList[dG]); if ( this->prescribedDofsFlag ) { this->applyConstraintsToLoadIncrement(nite, k, rhs, rlm, tStep); } // convergence check IntArray &idArray = UnknownNumberingSchemeList[dG].dofIdArray; converged = this->checkConvergenceDofIdArray(RT, F, RHS, ddXtotal, Xtotal, RRTtotal, internalForcesEBENorm, nite, errorOutOfRangeFlag, tStep, idArray); if ( errorOutOfRangeFlag ) { status = NM_NoSuccess; OOFEM_WARNING("Divergence reached after %d iterations", nite); break; } else if ( converged && ( nite >= minIterations ) ) { break; } else if ( nite >= nsmax ) { OOFEM_LOG_DEBUG("Maximum number of iterations reached\n"); break; } if ( nite > 0 || !mCalcStiffBeforeRes ) { if ( ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) { engngModel->updateComponent(tStep, NonLinearLhs, domain); this->stiffnessMatrixList[dG] = k.giveSubMatrix( locArrayList[dG], locArrayList[dG]); applyConstraintsToStiffness(*this->stiffnessMatrixList[dG]); } } if ( ( nite == 0 ) && ( deltaL < 1.0 ) ) { // deltaL < 1 means no increment applied, only equilibrate current state rhs.zero(); R.zero(); ddX[dG] = rhs; } else { status = linSolver->solve(*this->stiffnessMatrixList[dG], rhs, ddX[dG]); } // // update solution // if ( this->lsFlag && ( nite > 0 ) ) { // Why not nite == 0 ? // line search LineSearchNM :: LS_status LSstatus; double eta; this->giveLineSearchSolver()->solve( X[dG], ddX[dG], fIntList[dG], fExtList[dG], R0, prescribedEqs, 1.0, eta, LSstatus, tStep); } else if ( this->constrainedNRFlag && ( nite > this->constrainedNRminiter ) ) { if ( this->forceErrVec.computeSquaredNorm() > this->forceErrVecOld.computeSquaredNorm() ) { printf("Constraining increment to be %e times full increment...\n", this->constrainedNRalpha); ddX[dG].times(this->constrainedNRalpha); } } X[dG].add(ddX[dG]); dX[dG].add(ddX[dG]); // Update total solution (containing all dofs) Xtotal.assemble(ddX[dG], locArrayList[dG]); dXtotal.assemble(ddX[dG], locArrayList[dG]); ddXtotal.zero(); ddXtotal.assemble(ddX[dG], locArrayList[dG]); tStep->incrementStateCounter(); // update solution state counter tStep->incrementSubStepNumber(); nite++; // iteration increment engngModel->giveExportModuleManager()->doOutput(tStep, true); } while ( true ); // end of iteration } printf("\nStaggered iteration (all dof id's) \n"); // Check convergence of total system RHS.beDifferenceOf(RT, F); converged = this->checkConvergence(RT, F, RHS, ddXtotal, Xtotal, RRTtotal, internalForcesEBENorm, nStaggeredIter, errorOutOfRangeFlag); if ( converged && ( nStaggeredIter >= minIterations ) ) { break; } nStaggeredIter++; } while ( true ); // end of iteration status |= NM_Success; solved = 1; // Modify Load vector to include "quasi reaction" if ( R0 ) { for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) { R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R0->at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) ); } } else { for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) { R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) ); } } this->lastReactions.resize(numberOfPrescribedDofs); #ifdef VERBOSE if ( numberOfPrescribedDofs ) { // print quasi reactions if direct displacement control used OOFEM_LOG_INFO("\n"); OOFEM_LOG_INFO("StaggeredSolver: Quasi reaction table \n"); OOFEM_LOG_INFO("StaggeredSolver: Node Dof Displacement Force\n"); double reaction; for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) { reaction = R->at( prescribedEqs.at(i) ); if ( R0 ) { reaction += R0->at( prescribedEqs.at(i) ); } lastReactions.at(i) = reaction; OOFEM_LOG_INFO("StaggeredSolver: %-15d %-15d %-+15.5e %-+15.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i), X.at( prescribedEqs.at(i) ), reaction); } OOFEM_LOG_INFO("\n"); } #endif return status; }
void GradDpElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { NLStructuralElement *elem = this->giveNLStructuralElement(); StructuralCrossSection *cs = elem->giveStructuralCrossSection(); FloatArray answerU, answerK; double localCumulatedStrain = 0.; FloatMatrix stiffKappa, B; FloatArray Nk, aux, dKappa, stress; FloatMatrix lStiff; FloatMatrix Bk; FloatArray gKappa, L_gKappa; //set displacement and nonlocal location array this->setDisplacementLocationArray(); this->setNonlocalLocationArray(); this->computeNonlocalDegreesOfFreedom(dKappa, tStep); int nlGeo = elem->giveGeometryMode(); for ( auto &gp: *elem->giveIntegrationRule(0) ) { GradDpMaterialExtensionInterface *dpmat = dynamic_cast< GradDpMaterialExtensionInterface * >( cs->giveMaterialInterface(GradDpMaterialExtensionInterfaceType, gp) ); if ( !dpmat ) { OOFEM_ERROR("Material doesn't implement the required DpGrad interface!"); } double dV = elem->computeVolumeAround(gp); if ( nlGeo == 0 || elem->domain->giveEngngModel()->giveFormulation() == AL ) { elem->computeBmatrixAt(gp, B); } else if ( nlGeo == 1 ) { elem->computeBHmatrixAt(gp, B); } this->computeStressVectorAndLocalCumulatedStrain(stress, localCumulatedStrain, gp, tStep); answerU.plusProduct(B, stress, dV); // Gradient part: this->computeNkappaMatrixAt(gp, Nk); this->computeBkappaMatrixAt(gp, Bk); dpmat->givePDGradMatrix_kk(lStiff, TangentStiffness, gp, tStep); double kappa = Nk.dotProduct(dKappa); gKappa.beProductOf(Bk, dKappa); answerK.add(-dV * localCumulatedStrain, Nk); answerK.add(kappa * dV, Nk); if ( dpmat->giveAveragingType() == 0 || dpmat->giveAveragingType() == 1 ) { double l = lStiff.at(1, 1); answerK.plusProduct(Bk, gKappa, l * l * dV); } else if ( dpmat->giveAveragingType() == 2 ) { L_gKappa.beProductOf(lStiff, gKappa); answerK.plusProduct(Bk, L_gKappa, dV); } } //this->computeStiffnessMatrix_kk(stiffKappa, TangentStiffness, tStep); //answerK.beProductOf(stiffKappa, dKappa); answerK.add(aux); answer.resize(totalSize); answer.zero(); answer.assemble(answerU, locU); answer.assemble(answerK, locK); }
void NLTransientTransportProblem :: assembleAlgorithmicPartOfRhs(FloatArray &answer, const UnknownNumberingScheme &ns, TimeStep *tStep) { // // Computes right hand side on all nodes // double t = tStep->giveTargetTime(); IntArray loc; FloatMatrix charMtrxCond, charMtrxCap; FloatArray r, drdt, contrib, help; Element *element; TimeStep *previousStep = this->givePreviousStep(); //r_t TimeStep *currentStep = this->giveCurrentStep(); //r_{t+\Delta t}. Note that *tStep is a Tau step between r_t and r_{t+\Delta t} Domain *domain = this->giveDomain(1); int nelem = domain->giveNumberOfElements(); for ( int i = 1; i <= nelem; i++ ) { element = domain->giveElement(i); // skip remote elements (these are used as mirrors of remote elements on other domains // when nonlocal constitutive models are used. They introduction is necessary to // allow local averaging on domains without fine grain communication between domains). if ( element->giveParallelMode() == Element_remote ) { continue; } if ( !element->isActivated(tStep) ) { continue; } element->giveLocationArray(loc, ns); element->giveCharacteristicMatrix(charMtrxCond, TangentStiffnessMatrix, tStep); element->giveCharacteristicMatrix(charMtrxCap, CapacityMatrix, tStep); /* * element -> computeVectorOf (VM_Total, tStep, r); * element -> computeVectorOf (VM_Velocity, tStep, drdt); */ if ( ( t >= previousStep->giveTargetTime() ) && ( t <= currentStep->giveTargetTime() ) ) { FloatArray rp, rc; element->computeVectorOf(VM_Total, currentStep, rc); element->computeVectorOf(VM_Total, previousStep, rp); //approximate derivative with a difference drdt.beDifferenceOf(rc, rp); drdt.times( 1. / currentStep->giveTimeIncrement() ); //approximate current solution from linear interpolation rp.times(1 - alpha); rc.times(alpha); r = rc; r.add(rp); } else { OOFEM_ERROR("unsupported time value"); } if ( lumpedCapacityStab ) { int size = charMtrxCap.giveNumberOfRows(); double s; for ( int j = 1; j <= size; j++ ) { s = 0.0; for ( int k = 1; k <= size; k++ ) { s += charMtrxCap.at(j, k); charMtrxCap.at(j, k) = 0.0; } charMtrxCap.at(j, j) = s; } } help.beProductOf(charMtrxCap, drdt); contrib.beProductOf(charMtrxCond, r); contrib.add(help); contrib.negated(); answer.assemble(contrib, loc); } }