bool NOX::Solver::TensorBased::computeCurvilinearStep(NOX::Abstract::Vector& dir, const NOX::Abstract::Group& soln, const NOX::Solver::Generic& s, double& lambda) { double qval = 0; double lambdaBar = 1; double beta1 = calculateBeta(sTinvJa, 1, sTinvJF, qval, lambdaBar, lambda); double betaFactor = ( (beta == 0.0) ? 0.0 : beta1*beta1 / (beta*beta)); dir.update(lambda - betaFactor, *newtonVecPtr, betaFactor, *tensorVecPtr, 0.0); #if DEBUG_LEVEL > 0 double sDotD = dir.innerProduct(sVec); if (utilsPtr->isPrintType(NOX::Utils::Details)) { utilsPtr->out() << " Beta = " << utilsPtr->sciformat(beta, 6) << " std = " << utilsPtr->sciformat(sDotD, 6) << " qval = " << qval << " lambdaBar = " << lambdaBar << std::endl; utilsPtr->out() << " betaFactor = " << utilsPtr->sciformat(betaFactor,6) << " beta1 = " << utilsPtr->sciformat(beta1, 6) << std::endl; } #endif return true; }
int FitNullModel(Matrix& Xnull, Matrix& Y) { G_to_Eigen(Xnull, &this->x); G_to_Eigen(Y, &this->y); // append identity matrix AppendIdentity(); // initialize beta and sigma2 sigma2.resize(kinship.size()); for (size_t i = 0; i < sigma2.size(); ++i) { sigma2[i] = 1.0; } calculateSigmaMat(); calculateBeta(); // fit null model calculateLLK(); double oldLLK = llk; int time = 1; double diff; while (true) { calculateSigma2(); diff = llk - oldLLK; if (diff < 1e-6) { #ifdef DEBUG fprintf(stderr, "Model converges or llk cannot be improved\n"); #endif break; } oldLLK = llk; time ++; if (time > 100) { #ifdef DEBUG fprintf(stderr, "Model probably do not converge at 100 times, llk = %g", llk); #endif break; } } return 0; }
bool NOX::Solver::TensorBased::computeTensorDirection(NOX::Abstract::Group& soln, const NOX::Solver::Generic& solver) { NOX::Abstract::Group::ReturnType dir_status; Teuchos::ParameterList& linearParams = paramsPtr->sublist("Direction"). sublist(paramsPtr->sublist("Direction"). get("Method","Tensor")). sublist("Linear Solver"); // Compute F at current solution. dir_status = soln.computeF(); if (dir_status != NOX::Abstract::Group::Ok) throwError("computeTensorDirection", "Unable to compute F"); // Compute Jacobian at current solution. dir_status = soln.computeJacobian(); if (dir_status != NOX::Abstract::Group::Ok) throwError("computeTensorDirection", "Unable to compute Jacobian"); // Begin processing for the tensor step, if necessary. double sDotS = 0.0; int tempVal1 = 0; if ((nIter > 0) && (requestedBaseStep == TensorStep)) { // Compute the tensor term s = x_{k-1} - x_k *sVecPtr = soln.getX(); sVecPtr->update(1.0, solver.getPreviousSolutionGroup().getX(), -1.0); double normS = sVecPtr->norm(); sDotS = normS * normS; // Form the tensor term a = (F_{k-1} - F_k - J*s) / (s^T s)^2 soln.applyJacobian(*sVecPtr, *aVecPtr); numJvMults++; aVecPtr->update(1.0, solver.getPreviousSolutionGroup().getF(), -1.0); aVecPtr->update(-1.0, soln.getF(), 1.0); if (sDotS != 0) aVecPtr->scale(1.0 / (sDotS * sDotS)); // Save old Newton step as initial guess to second system *tmpVecPtr = *newtonVecPtr; tmpVecPtr->scale(-1.0); // Rewrite to avoid this? // Compute residual of linear system using initial guess... soln.applyJacobian(*tmpVecPtr, *residualVecPtr); numJvMults++; residualVecPtr->update(1.0, solver.getPreviousSolutionGroup().getF(),-1.0); double residualNorm = residualVecPtr->norm(); #if DEBUG_LEVEL > 0 double tmpVecNorm = tmpVecPtr->norm(); double residualNormRel = residualNorm / solver.getPreviousSolutionGroup().getNormF(); if (utilsPtr->isPrintType(NOX::Utils::Details)) { utilsPtr->out() << " Norm of initial guess: " << utilsPtr->sciformat(tmpVecNorm, 6) << std::endl; utilsPtr->out() << " initg norm of model residual = " << utilsPtr->sciformat(residualNorm, 6) << " (abs) " << utilsPtr->sciformat(residualNormRel, 6) << " (rel)" << std::endl; } #endif // Save some parameters and use them later... double tol = linearParams.get("Tolerance", 1e-4); double relativeResidual = residualNorm / solver.getPreviousSolutionGroup().getNormF(); // Decide whether to use initial guess... bool isInitialGuessGood = false; #ifdef USE_INITIAL_GUESS_LOGIC if (relativeResidual < 1.0) { if (utilsPtr->isPrintType(NOX::Utils::Details)) utilsPtr->out() << " Initial guess is good..." << std::endl; isInitialGuessGood = true; // RPP - Brett please make sure the line below is correct. *tensorVecPtr = *tmpVecPtr; double newTol = tol / relativeResidual; if (newTol > 0.99) newTol = 0.99; // force at least one iteration linearParams.set("Tolerance", newTol); if (utilsPtr->isPrintType(NOX::Utils::Details)) utilsPtr->out() << " Setting tolerance to " << utilsPtr->sciformat(newTol,6) << std::endl; } else #endif // USE_INITIAL_GUESS_LOGIC { //utilsPtr->out() << " Initial guess is BAD... do not use!\n"; isInitialGuessGood = false; *residualVecPtr = solver.getPreviousSolutionGroup().getF(); } // Compute the term inv(J)*Fp.... tmpVecPtr->init(0.0); dir_status = soln.applyJacobianInverse(linearParams, *residualVecPtr, *tmpVecPtr); // If it didn't converge, maybe we can recover. if (dir_status != NOX::Abstract::Group::Ok) { if (doRescue == false) throwError("computeTensorDirection", "Unable to apply Jacobian inverse"); else if ((doRescue == true) && (utilsPtr->isPrintType(NOX::Utils::Warning))) utilsPtr->out() << "WARNING: NOX::Solver::TensorBased::computeTensorDirection() - " << "Linear solve failed to achieve convergence - " << "using the step anyway " << "since \"Rescue Bad Newton Solve\" is true." << std::endl; } // Continue processing #ifdef USE_INITIAL_GUESS_LOGIC if (isInitialGuessGood) { tmpVecPtr->update(1.0, *tensorVecPtr, 1.0); linearParams.set("Tolerance", tol); } #endif // Save iteration count for comparison later if (linearParams.sublist("Output"). isParameter("Number of Linear Iterations")) tempVal1 = linearParams.sublist("Output"). get("Number of Linear Iterations",0); #if DEBUG_LEVEL > 0 // Compute residual of linear system with initial guess... soln.applyJacobian(*tmpVecPtr, *residualVecPtr); numJvMults++; residualVec.update(-1.0, solver.getPreviousSolutionGroup().getF(),1.0); double residualNorm2 = residualVec.norm(); double residualNorm2Rel = residualNorm2 / solver.getPreviousSolutionGroup().getNormF(); if (utilsPtr->isPrintType(NOX::Utils::Details)) utilsPtr->out() << " jifp norm of model residual = " << utilsPtr->sciformat(residualNorm2, 6) << " (abs) " << utilsPtr->sciformat(residualNorm2Rel, 6) << " (rel)" << std::endl; #endif } // Compute the Newton direction dir_status = soln.computeNewton(linearParams); // If it didn't converge, maybe we can recover. if (dir_status != NOX::Abstract::Group::Ok) { if (doRescue == false) throwError("computeTensorDirection", "Unable to apply Jacobian inverse"); else if ((doRescue == true) && (utilsPtr->isPrintType(NOX::Utils::Warning))) utilsPtr->out() << "WARNING: NOX::Solver::TensorBased::computeTensorDirection() - " << "Linear solve failed to achieve convergence - " << "using the step anyway " << "since \"Rescue Bad Newton Solve\" is true." << std::endl; } // Set Newton direction *newtonVecPtr = soln.getNewton(); // Update counter int tempVal2 = 0; if (linearParams.sublist("Output"). isParameter("Number of Linear Iterations")) tempVal2 = linearParams.sublist("Output"). get("Number of Linear Iterations",0); numJ2vMults += (tempVal1 > tempVal2) ? tempVal1 : tempVal2; #ifdef CHECK_RESIDUALS printDirectionInfo("newtonVec", *newtonVecPtr, soln, false); #endif // CHECK_RESIDUALS // Continue processing the tensor step, if necessary if ((nIter > 0) && (requestedBaseStep == TensorStep)) { // Form the term inv(J)*a... (note that a is not multiplied by 2) // The next line does not work in some implementations for some reason //tmpVec.update(1.0, newtonVec, -1.0, sVec, 1.0); tmpVecPtr->update(1.0, *newtonVecPtr, 1.0); tmpVecPtr->update(-1.0, *sVecPtr, 1.0); if (sDotS != 0.0) tmpVecPtr->scale( 1.0 / (sDotS * sDotS)); // Calculate value of beta sTinvJF = -sVecPtr->innerProduct(*newtonVecPtr); sTinvJa = sVecPtr->innerProduct(*tmpVecPtr); double qval = 0; double lambdaBar = 1; beta = calculateBeta(sTinvJa, 1.0, sTinvJF, qval, lambdaBar); double sVecNorm = sVecPtr->norm(); double aVecNorm = aVecPtr->norm(); if (utilsPtr->isPrintType(NOX::Utils::Details)) { utilsPtr->out() << " sTinvJF = " << utilsPtr->sciformat(sTinvJF, 6) << " sTinvJa = " << utilsPtr->sciformat(sTinvJa, 6) << std::endl; utilsPtr->out() << " norm(s) = " << utilsPtr->sciformat(sVecNorm, 6) << " norm(a) = " << utilsPtr->sciformat(aVecNorm, 6) << std::endl; } if (useModifiedMethod) { double alpha2 = lambdaBar; if (utilsPtr->isPrintType(NOX::Utils::Details)) utilsPtr->out() << " Beta = " << utilsPtr->sciformat(beta, 6) << " Alpha2 = " << utilsPtr->sciformat(alpha2, 6) << std::endl; if (alpha2 != 1.0) { if (utilsPtr->isPrintType(NOX::Utils::Details)) utilsPtr->out() << " *** Scaling tensor term a ***" << std::endl; aVecPtr->scale(alpha2); tmpVecPtr->scale(alpha2); sTinvJa *= alpha2; beta /= alpha2; lambdaBar = 1.0; qval = 0; } } // Form the tensor step tensorVecPtr->update(1.0, *newtonVecPtr, -beta*beta, *tmpVecPtr, 0.0); #ifdef CHECK_RESIDUALS printDirectionInfo("tensorVec", *tensorVecPtr, soln, true); #endif // CHECK_RESIDUALS #if DEBUG_LEVEL > 0 double sDotT = tensorVecPtr->innerProduct(sVec); if (utilsPtr->isPrintType(NOX::Utils::Details)) utilsPtr->out() << " Beta = " << utilsPtr->sciformat(beta, 6) << " std = " << utilsPtr->sciformat(sDotT, 6) << " qval = " << utilsPtr->sciformat(qval, 2) << " lambdaBar = " << lambdaBar << std::endl; #endif } else *tensorVecPtr = *newtonVecPtr; return true; }