void FE2FluidMaterial :: giveDeviatoricPressureStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp)); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { answer = ms->giveDeviatoricPressureTangent(); #ifdef DEBUG_TANGENT // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig, sigh; double epspvol, pressure = 0.0; double h = 1.00; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector (sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector (sigh, epspvol, gp, strain, pressure+h, tStep); FloatArray dsigh; dsigh.beDifferenceOf(sigh,sig); dsigh.times(1/h); printf("Analytical deviatoric pressure tangent = "); answer.printYourself(); printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself(); dsigh.subtract(answer); double norm = dsigh.computeNorm(); if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) { OOFEM_ERROR("Error in deviatoric pressure tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
bool BeamElementErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. if ( tStep->giveNumber() != tstep ) { return true; } FloatArray val; Element *element = domain->giveGlobalElement(number); if ( !element ) { if ( domain->giveEngngModel()->isParallel() ) { return true; } else { OOFEM_WARNING("Element %d not found.", number); return false; } } if ( element->giveParallelMode() != Element_local ) { return true; } if (ist == BET_localEndDisplacement) { element->computeVectorOf(VM_Total, tStep, val); } else if (ist == BET_localEndForces) { if(Beam2d* b = dynamic_cast<Beam2d*>(element)) b->giveEndForcesVector(val, tStep); else if(Beam3d* b = dynamic_cast<Beam3d*>(element)) b->giveEndForcesVector(val, tStep); else { OOFEM_WARNING("Element %d has no beam interface.", number); return false; } } if ( component > val.giveSize() || component < 1 ) { OOFEM_WARNING("Check failed in: beam_element %d, ist %d, component %d:\n" "Component not found!", number, ist, component); val.printYourself(); return false; } double elementValue = val.at(component); bool check = checkValue(elementValue); if ( !check ) { OOFEM_WARNING("Check failed in: tstep %d, beam_element %d, ist %d, component %d:\n" "value is %.8e, but should be %.8e ( error is %e but tolerance is %e )", tstep, number, ist, component, elementValue, value, fabs(elementValue-value), tolerance ); val.printYourself(); } return check; }
void PrescribedGradientBCWeak :: giveMirroredPointOnGammaMinus(FloatArray &oPosMinus, const FloatArray &iPosPlus) const { //#if 0 if(mMirrorFunction == 0) { oPosMinus = iPosPlus; const double distTol = 1.0e-12; // if ( iPosPlus.distance(mUC) < distTol ) { // printf("iPosPlus: %.12e %.12e\n", iPosPlus [ 0 ], iPosPlus [ 1 ]); // OOFEM_ERROR("Unmappable point.") // } bool mappingPerformed = false; if ( iPosPlus [ 0 ] > mUC [ 0 ] - distTol ) { oPosMinus [ 0 ] = mLC [ 0 ]; mappingPerformed = true; return; } if ( iPosPlus [ 1 ] > mUC [ 1 ] - distTol ) { oPosMinus [ 1 ] = mLC [ 1 ]; mappingPerformed = true; return; } if ( !mappingPerformed ) { iPosPlus.printYourself(); OOFEM_ERROR("Mapping failed.") }
void GnuplotExportModule::outputBoundaryCondition(PrescribedGradientBCNeumann &iBC, TimeStep *tStep) { FloatArray stress; iBC.computeField(stress, tStep); printf("Mean stress computed in Gnuplot export module: "); stress.printYourself(); double time = 0.0; TimeStep *ts = emodel->giveCurrentStep(); if ( ts != NULL ) { time = ts->giveTargetTime(); } int bcIndex = iBC.giveNumber(); std :: stringstream strMeanStress; strMeanStress << "PrescribedGradientGnuplotMeanStress" << bcIndex << "Time" << time << ".dat"; std :: string nameMeanStress = strMeanStress.str(); std::vector<double> componentArray, stressArray; for(int i = 1; i <= stress.giveSize(); i++) { componentArray.push_back(i); stressArray.push_back(stress.at(i)); } XFEMDebugTools::WriteArrayToGnuplot(nameMeanStress, componentArray, stressArray); // Homogenized strain FloatArray grad; iBC.giveGradientVoigt(grad); outputGradient(iBC.giveNumber(), *iBC.giveDomain(), grad, tStep); }
bool ElementErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. if ( tStep->giveNumber() != tstep ) { return true; } FloatArray ipval; Element *element = domain->giveGlobalElement(number); if ( !element ) { if ( domain->giveEngngModel()->isParallel() ) { return true; } else { OOFEM_WARNING("Element %d not found.", number); return false; } } if ( element->giveParallelMode() != Element_local ) { return true; } // note! GPs are numbered from 0 internally, but written with 1-index, inconsistent! GaussPoint *gp = element->giveIntegrationRule(irule)->getIntegrationPoint(gpnum-1); element->giveIPValue(ipval, gp, ist, tStep); if ( component > ipval.giveSize() || component < 1 ) { OOFEM_WARNING("Check failed in: element %d, gpnum %d, ist %d, component %d:\n" "Component not found!", number, gpnum, ist, component); ipval.printYourself(); return false; } double elementValue = ipval.at(component); bool check = checkValue(elementValue); if ( !check ) { OOFEM_WARNING("Check failed in: tstep %d, element %d, gpnum %d, ist %d, component %d:\n" "value is %.8e, but should be %.8e ( error is %e but tolerance is %e )", tstep, number, gpnum, ist, component, elementValue, value, fabs(elementValue-value), tolerance ); ipval.printYourself(); } return check; }
void FE2FluidMaterial :: giveVolumetricDeviatoricStiffness(FloatArray &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast<FE2FluidMaterialStatus*> (this->giveStatus(gp)); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { answer = ms->giveVolumetricDeviatoricTangent(); #ifdef DEBUG_TANGENT // Numerical ATS for debugging FloatArray tempStrain(3); tempStrain.zero(); FloatArray sig, strain; double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector (sig, epspvol, gp, tempStrain, pressure, tStep); strain = tempStrain; strain.at(1) += h; computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); strain = tempStrain; strain.at(2) += h; computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); strain = tempStrain; strain.at(3) += h; computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); FloatArray dvol(3); dvol.at(1) = (epspvol11 - epspvol)/h; dvol.at(2) = (epspvol22 - epspvol)/h; dvol.at(3) = (epspvol12 - epspvol)/h; dvol.at(1) += 1.0; dvol.at(2) += 1.0; printf("Analytical volumetric deviatoric tangent = "); answer.printYourself(); printf("Numerical volumetric deviatoric tangent = "); dvol.printYourself(); dvol.subtract(answer); double norm = dvol.computeNorm(); if (norm > answer.computeNorm()*DEBUG_ERR && norm > 0.0) { OOFEM_ERROR("Error in volumetric deviatoric tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
void GnuplotExportModule::outputGradient(int bc, Domain &d, FloatArray &grad, TimeStep *tStep) { // Homogenized strain double timeFactor = d.giveBc(bc)->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime()); printf("timeFactor: %e\n", timeFactor ); grad.times(timeFactor); printf("Mean grad computed in Gnuplot export module: "); grad.printYourself(); double time = tStep->giveTargetTime(); std :: stringstream strMeanGrad; strMeanGrad << "PrescribedGradientGnuplotMeanGrad" << bc << "Time" << time << ".dat"; std :: string nameMeanGrad = strMeanGrad.str(); std::vector<double> componentArrayGrad, gradArray; for(int i = 1; i <= grad.giveSize(); i++) { componentArrayGrad.push_back(i); gradArray.push_back(grad.at(i)); } XFEMDebugTools::WriteArrayToGnuplot(nameMeanGrad, componentArrayGrad, gradArray); }
void FE2FluidMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); ms->computeTangents(tStep); if ( mode == TangentStiffness ) { dsdd = ms->giveDeviatoricTangent(); dsdp = ms->giveDeviatoricPressureTangent(); dedd = ms->giveVolumetricDeviatoricTangent(); dedp = ms->giveVolumetricPressureTangent(); #if 0 // Numerical ATS for debugging FloatMatrix numericalATS(6, 6); FloatArray dsig; FloatArray tempStrain(6); tempStrain.zero(); FloatArray sig, strain, sigPert; double epspvol; computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep); double h = 0.001; // Linear problem, size of this doesn't matter. for ( int k = 1; k <= 6; ++k ) { strain = tempStrain; strain.at(k) += h; double tmp = strain.at(1) + strain.at(2) + strain.at(3); strain.at(1) -= tmp/3.0; strain.at(2) -= tmp/3.0; strain.at(3) -= tmp/3.0; strain.printYourself(); computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep); sigPert.printYourself(); dsig.beDifferenceOf(sigPert, sig); numericalATS.setColumn(dsig, k); } numericalATS.times(1. / h); printf("Analytical deviatoric tangent = "); dsdd.printYourself(); printf("Numerical deviatoric tangent = "); numericalATS.printYourself(); numericalATS.subtract(dsdd); double norm = numericalATS.computeFrobeniusNorm(); if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig, sigh; double epspvol, pressure = 0.0; double h = 1.00; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep); FloatArray dsigh; dsigh.beDifferenceOf(sigh, sig); dsigh.times(1 / h); printf("Analytical deviatoric pressure tangent = "); dsdp.printYourself(); printf("Numerical deviatoric pressure tangent = "); dsigh.printYourself(); dsigh.subtract(dsdp); double norm = dsigh.computeNorm(); if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in deviatoric pressure tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray tempStrain(3); tempStrain.zero(); FloatArray sig, strain; double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep); strain = tempStrain; strain.at(1) += h; computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); strain = tempStrain; strain.at(2) += h; computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); strain = tempStrain; strain.at(3) += h; computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); FloatArray dvol(3); dvol.at(1) = ( epspvol11 - epspvol ) / h; dvol.at(2) = ( epspvol22 - epspvol ) / h; dvol.at(3) = ( epspvol12 - epspvol ) / h; dvol.at(1) += 1.0; dvol.at(2) += 1.0; printf("Analytical volumetric deviatoric tangent = "); dedd.printYourself(); printf("Numerical volumetric deviatoric tangent = "); dvol.printYourself(); dvol.subtract(dedd); double norm = dvol.computeNorm(); if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in volumetric deviatoric tangent"); } #endif #if 0 // Numerical ATS for debugging FloatArray strain(3); strain.zero(); FloatArray sig; double epspvol, epspvolh, pressure = 0.0; double h = 1.0; // Linear problem, size of this doesn't matter. computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep); double dvol = -( epspvolh - epspvol ) / h; printf("Analytical volumetric pressure tangent = %e\n", dedp); printf("Numerical volumetric pressure tangent = %e\n", dvol); double norm = fabs(dvol - dedp); if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) { OOFEM_ERROR("Error in volumetric pressure tangent"); } #endif } else { OOFEM_ERROR("Mode not implemented"); } }
void GnuplotExportModule::outputBoundaryCondition(PrescribedGradientBCWeak &iBC, TimeStep *tStep) { FloatArray stress; iBC.computeField(stress, tStep); printf("Mean stress computed in Gnuplot export module: "); stress.printYourself(); double time = 0.0; TimeStep *ts = emodel->giveCurrentStep(); if ( ts != NULL ) { time = ts->giveTargetTime(); } int bcIndex = iBC.giveNumber(); std :: stringstream strMeanStress; strMeanStress << "PrescribedGradientGnuplotMeanStress" << bcIndex << "Time" << time << ".dat"; std :: string nameMeanStress = strMeanStress.str(); std::vector<double> componentArray, stressArray; for(int i = 1; i <= stress.giveSize(); i++) { componentArray.push_back(i); stressArray.push_back(stress.at(i)); } XFEMDebugTools::WriteArrayToGnuplot(nameMeanStress, componentArray, stressArray); // Homogenized strain FloatArray grad; iBC.giveGradientVoigt(grad); outputGradient(iBC.giveNumber(), *iBC.giveDomain(), grad, tStep); #if 0 FloatArray grad; iBC.giveGradientVoigt(grad); double timeFactor = iBC.giveTimeFunction()->evaluate(ts, VM_Total); printf("timeFactor: %e\n", timeFactor ); grad.times(timeFactor); printf("Mean grad computed in Gnuplot export module: "); grad.printYourself(); std :: stringstream strMeanGrad; strMeanGrad << "PrescribedGradientGnuplotMeanGrad" << bcIndex << "Time" << time << ".dat"; std :: string nameMeanGrad = strMeanGrad.str(); std::vector<double> componentArrayGrad, gradArray; for(int i = 1; i <= grad.giveSize(); i++) { componentArrayGrad.push_back(i); gradArray.push_back(grad.at(i)); } XFEMDebugTools::WriteArrayToGnuplot(nameMeanGrad, componentArrayGrad, gradArray); #endif if(mExportBoundaryConditionsExtra) { // Traction node coordinates std::vector< std::vector<FloatArray> > nodePointArray; size_t numTracEl = iBC.giveNumberOfTractionElements(); for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> points; FloatArray xS, xE; iBC.giveTractionElCoord(i, xS, xE); points.push_back(xS); points.push_back(xE); nodePointArray.push_back(points); } std :: stringstream strTractionNodes; strTractionNodes << "TractionNodesGnuplotTime" << time << ".dat"; std :: string nameTractionNodes = strTractionNodes.str(); WritePointsToGnuplot(nameTractionNodes, nodePointArray); // Traction element normal direction std::vector< std::vector<FloatArray> > nodeNormalArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> points; FloatArray n,t; iBC.giveTractionElNormal(i, n,t); points.push_back(n); points.push_back(n); nodeNormalArray.push_back(points); } std :: stringstream strTractionNodeNormals; strTractionNodeNormals << "TractionNodeNormalsGnuplotTime" << time << ".dat"; std :: string nameTractionNodeNormals = strTractionNodeNormals.str(); WritePointsToGnuplot(nameTractionNodeNormals, nodeNormalArray); // Traction (x,y) std::vector< std::vector<FloatArray> > nodeTractionArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> tractions; FloatArray tS, tE; iBC.giveTraction(i, tS, tE, VM_Total, tStep); tractions.push_back(tS); tractions.push_back(tE); nodeTractionArray.push_back(tractions); } std :: stringstream strTractions; strTractions << "TractionsGnuplotTime" << time << ".dat"; std :: string nameTractions = strTractions.str(); WritePointsToGnuplot(nameTractions, nodeTractionArray); // Arc position along the boundary std::vector< std::vector<FloatArray> > arcPosArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> arcPos; double xiS = 0.0, xiE = 0.0; iBC.giveTractionElArcPos(i, xiS, xiE); arcPos.push_back( FloatArray{xiS} ); arcPos.push_back( FloatArray{xiE} ); arcPosArray.push_back(arcPos); } std :: stringstream strArcPos; strArcPos << "ArcPosGnuplotTime" << time << ".dat"; std :: string nameArcPos = strArcPos.str(); WritePointsToGnuplot(nameArcPos, arcPosArray); // Traction (normal, tangent) std::vector< std::vector<FloatArray> > nodeTractionNTArray; for(size_t i = 0; i < numTracEl; i++) { std::vector<FloatArray> tractions; FloatArray tS, tE; iBC.giveTraction(i, tS, tE, VM_Total, tStep); FloatArray n,t; iBC.giveTractionElNormal(i, n, t); double tSn = tS.dotProduct(n,2); double tSt = tS.dotProduct(t,2); tractions.push_back( {tSn ,tSt} ); double tEn = tE.dotProduct(n,2); double tEt = tE.dotProduct(t,2); tractions.push_back( {tEn, tEt} ); nodeTractionNTArray.push_back(tractions); } std :: stringstream strTractionsNT; strTractionsNT << "TractionsNormalTangentGnuplotTime" << time << ".dat"; std :: string nameTractionsNT = strTractionsNT.str(); WritePointsToGnuplot(nameTractionsNT, nodeTractionNTArray); // Boundary points and displacements IntArray boundaries, bNodes; iBC.giveBoundaries(boundaries); std::vector< std::vector<FloatArray> > bndNodes; for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = iBC.giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); std::vector<FloatArray> bndSegNodes; // Add the start and end nodes of the segment DofManager *startNode = e->giveDofManager( bNodes[0] ); FloatArray xS = *(startNode->giveCoordinates()); Dof *dSu = startNode->giveDofWithID(D_u); double dU = dSu->giveUnknown(VM_Total, tStep); xS.push_back(dU); Dof *dSv = startNode->giveDofWithID(D_v); double dV = dSv->giveUnknown(VM_Total, tStep); xS.push_back(dV); bndSegNodes.push_back(xS); DofManager *endNode = e->giveDofManager( bNodes[1] ); FloatArray xE = *(endNode->giveCoordinates()); Dof *dEu = endNode->giveDofWithID(D_u); dU = dEu->giveUnknown(VM_Total, tStep); xE.push_back(dU); Dof *dEv = endNode->giveDofWithID(D_v); dV = dEv->giveUnknown(VM_Total, tStep); xE.push_back(dV); bndSegNodes.push_back(xE); bndNodes.push_back(bndSegNodes); } std :: stringstream strBndNodes; strBndNodes << "BndNodesGnuplotTime" << time << ".dat"; std :: string nameBndNodes = strBndNodes.str(); WritePointsToGnuplot(nameBndNodes, bndNodes); } }
NM_Status GJacobi :: solve(FloatMatrix &a, FloatMatrix &b, FloatArray &eigv, FloatMatrix &x) // // this function solve the generalized eigenproblem using the Generalized // jacobi iteration // // { int nsweep, nr; double eps, eptola, eptolb, akk, ajj, ab, check, sqch, d1, d2, den, ca, cg, ak, bk, xj, xk; double aj, bj; int jm1, kp1, km1, jp1; if ( a.giveNumberOfRows() != b.giveNumberOfRows() || !a.isSquare() || !b.isSquare() ) { OOFEM_ERROR("A matrix, B mtrix -> size mismatch"); } int n = a.giveNumberOfRows(); eigv.resize(n); x.resize(n, n); // // Create temporary arrays // FloatArray d(n); // // Initialize EigenValue and EigenVector Matrices // for ( int i = 1; i <= n; i++ ) { // if((a.at(i,i) <= 0. ) && (b.at(i,i) <= 0.)) // OOFEM_ERROR("Matrices are not positive definite"); d.at(i) = a.at(i, i) / b.at(i, i); eigv.at(i) = d.at(i); } x.beUnitMatrix(); if ( n == 1 ) { return NM_Success; } // // Initialize sweep counter and begin iteration // nsweep = 0; nr = n - 1; do { nsweep++; # ifdef DETAILED_REPORT OOFEM_LOG_DEBUG("*GJacobi*: sweep number %4d\n", nsweep); #endif // // check if present off-diagonal element is large enough to require zeroing // eps = pow(0.01, ( double ) nsweep); eps *= eps; for ( int j = 1; j <= nr; j++ ) { int jj = j + 1; for ( int k = jj; k <= n; k++ ) { eptola = ( a.at(j, k) * a.at(j, k) ) / ( a.at(j, j) * a.at(k, k) ); eptolb = ( b.at(j, k) * b.at(j, k) ) / ( b.at(j, j) * b.at(k, k) ); if ( ( eptola < eps ) && ( eptolb < eps ) ) { continue; } // // if zeroing is required, calculate the rotation matrix elements ca and cg // akk = a.at(k, k) * b.at(j, k) - b.at(k, k) * a.at(j, k); ajj = a.at(j, j) * b.at(j, k) - b.at(j, j) * a.at(j, k); ab = a.at(j, j) * b.at(k, k) - a.at(k, k) * b.at(j, j); check = ( ab * ab + 4.0 * akk * ajj ) / 4.0; if ( fabs(check) < GJacobi_ZERO_CHECK_TOL ) { check = fabs(check); } else if ( check < 0.0 ) { OOFEM_ERROR("Matrices are not positive definite"); } sqch = sqrt(check); d1 = ab / 2. + sqch; d2 = ab / 2. - sqch; den = d1; if ( fabs(d2) > fabs(d1) ) { den = d2; } if ( den != 0.0 ) { // strange ! ca = akk / den; cg = -ajj / den; } else { ca = 0.0; cg = -a.at(j, k) / a.at(k, k); } // // perform the generalized rotation to zero // if ( ( n - 2 ) != 0 ) { jp1 = j + 1; jm1 = j - 1; kp1 = k + 1; km1 = k - 1; if ( ( jm1 - 1 ) >= 0 ) { for ( int i = 1; i <= jm1; i++ ) { aj = a.at(i, j); bj = b.at(i, j); ak = a.at(i, k); bk = b.at(i, k); a.at(i, j) = aj + cg * ak; b.at(i, j) = bj + cg * bk; a.at(i, k) = ak + ca * aj; b.at(i, k) = bk + ca * bj; } } if ( ( kp1 - n ) <= 0 ) { for ( int i = kp1; i <= n; i++ ) { // label 140 aj = a.at(j, i); bj = b.at(j, i); ak = a.at(k, i); bk = b.at(k, i); a.at(j, i) = aj + cg * ak; b.at(j, i) = bj + cg * bk; a.at(k, i) = ak + ca * aj; b.at(k, i) = bk + ca * bj; } } if ( ( jp1 - km1 ) <= 0 ) { // label 160 for ( int i = jp1; i <= km1; i++ ) { aj = a.at(j, i); bj = b.at(j, i); ak = a.at(i, k); bk = b.at(i, k); a.at(j, i) = aj + cg * ak; b.at(j, i) = bj + cg * bk; a.at(i, k) = ak + ca * aj; b.at(i, k) = bk + ca * bj; } } } // label 190 ak = a.at(k, k); bk = b.at(k, k); a.at(k, k) = ak + 2.0 *ca *a.at(j, k) + ca *ca *a.at(j, j); b.at(k, k) = bk + 2.0 *ca *b.at(j, k) + ca *ca *b.at(j, j); a.at(j, j) = a.at(j, j) + 2.0 *cg *a.at(j, k) + cg * cg * ak; b.at(j, j) = b.at(j, j) + 2.0 *cg *b.at(j, k) + cg * cg * bk; a.at(j, k) = 0.0; b.at(j, k) = 0.0; // // update the eigenvector matrix after each rotation // for ( int i = 1; i <= n; i++ ) { xj = x.at(i, j); xk = x.at(i, k); x.at(i, j) = xj + cg * xk; x.at(i, k) = xk + ca * xj; } // label 200 } } // label 210 // // update the eigenvalues after each sweep // #ifdef DETAILED_REPORT OOFEM_LOG_DEBUG("GJacobi: a,b after sweep\n"); a.printYourself(); b.printYourself(); #endif for ( int i = 1; i <= n; i++ ) { // in original uncommented // if ((a.at(i,i) <= 0.) || (b.at(i,i) <= 0.)) // error ("solveYourselfAt: Matrices are not positive definite"); eigv.at(i) = a.at(i, i) / b.at(i, i); } // label 220 # ifdef DETAILED_REPORT OOFEM_LOG_DEBUG("GJacobi: current eigenvalues are:\n"); eigv.printYourself(); OOFEM_LOG_DEBUG("GJacobi: current eigenvectors are:\n"); x.printYourself(); # endif // // check for convergence // for ( int i = 1; i <= n; i++ ) { // label 230 double tol = rtol * d.at(i); double dif = ( eigv.at(i) - d.at(i) ); if ( fabs(dif) > tol ) { goto label280; } } // label 240 // // check all off-diagonal elements to see if another sweep is required // eps = rtol * rtol; for ( int j = 1; j <= nr; j++ ) { int jj = j + 1; for ( int k = jj; k <= n; k++ ) { double epsa = ( a.at(j, k) * a.at(j, k) ) / ( a.at(j, j) * a.at(k, k) ); double epsb = ( b.at(j, k) * b.at(j, k) ) / ( b.at(j, j) * b.at(k, k) ); if ( ( epsa < eps ) && ( epsb < eps ) ) { continue; } goto label280; } } // label 250 // // fill out bottom triangle of resultant matrices and scale eigenvectors // break; // goto label255 ; // // update d matrix and start new sweep, if allowed // label280: d = eigv; } while ( nsweep < nsmax ); // label255: for ( int i = 1; i <= n; i++ ) { for ( int j = 1; j <= n; j++ ) { a.at(j, i) = a.at(i, j); b.at(j, i) = b.at(i, j); } // label 260 } for ( int j = 1; j <= n; j++ ) { double bb = sqrt( fabs( b.at(j, j) ) ); for ( int k = 1; k <= n; k++ ) { x.at(k, j) /= bb; } } // label 270 return NM_Success; }