// Updates the current Lhs and rhs based of the m_newVelocities guess bool ImplicitStepper::updateLinearSystem( const VecXx solverForces ) { //DK: this is where the lineic stretch gets checked and a possible update is applied StrandDynamics& dynamics = m_strand.dynamics(); m_strand.requireExactJacobian( false ); dynamics.setDisplacements( m_dt * m_futureVelocities ); // updated in NonLinearForce from Bogus, pushing updates const Scalar stretchE = getLineicStretch(); bool needUpdate = stretchE > m_stretchingFailureThreshold; Scalar residual = 0; if( !needUpdate ) { computeRHS(); dynamics.getScriptingController()->fixRHS( m_rhs ); m_usedNonlinearSolver = true; //Below should be present, turning off because usually causes needUpdate to occur when stretching is small residual = ( m_rhs + solverForces ).squaredNorm() / m_rhs.rows(); // needUpdate = residual > m_costretchResidualFailureThreshold; } if( needUpdate ) // DK: if residual or stretchE too big. { // solveLinear causes less stretching solveLinear(); // solveNonLinear(); } // std::cout << needUpdate << " stretchE: " << stretchE << " | " << m_stretchingFailureThreshold << " ||| residual: " << residual << " | " << m_costretchResidualFailureThreshold << std::endl; return needUpdate; // DK: now returns true if needs update }
void ImplicitStepper::solveLinear() { computeRHS(); computeLHS(); Lhs().multiply( m_rhs, 1.0, m_futureVelocities ); m_strand.dynamics().getScriptingController()->fixLHSAndRHS( Lhs(), m_rhs, m_dt ); m_linearSolver.store( Lhs() ); }
void stepSolution(char *stepType,GRID *g,SOLN *s,double dt,double *l2norm) { double coef; static int istep=0; int i,k,l; int nsubiter=20; double CFL; // create temp variable for CFL number CFL = g->CFL; if (strcmp(stepType,"euler")==0) { computeRHS(g,s,l2norm); coef = 1.0; updateSoln(s->q,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); } else if (strcmp(stepType,"rk3") == 0) { // RK step 1 computeRHS(g,s,l2norm); coef=0.25; updateSoln(s->q,s->qt,s->r,s->sigma,dt,CFL,coef,g->ncells); coef=8.0/15; updateSoln(s->q,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); // RK step 2 computeRHS(g,s,l2norm); coef=5.0/12; updateSoln(s->qt,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); // RK step 3 computeRHS(g,s,l2norm); coef=3.0/4.0; updateSoln(s->qt,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); } else if (strcmp(stepType,"ADI")==0) { computeRHSk(g,s,l2norm); ADI(g,s,s->cflnum,dt); } else if (strcmp(stepType,"DADI")==0) { computeRHSk(g,s,l2norm); DADI(g,s,s->cflnum,dt); } else if (strcmp(stepType,"Gauss-Seidel") == 0) { computeRHSkv(g,s,l2norm); gaussSeidel(g,s,s->cflnum,dt); } else if (strcmp(stepType,"line-Gauss-Seidel") == 0) { if (g->visc) computeRHSkv(g,s,l2norm); else computeRHSk(g,s,l2norm); lineGaussSeidel(g,s,s->cflnum,dt); } istep++; }
// =================================================== // Methods // =================================================== Real OneDFSIFunctionSolverDefinedWindkessel3::operator() ( const Real& time, const Real& timeStep ) { UInt W_outID; Real W_out; switch ( M_bcType ) { case OneDFSI::W1: W_outID = 1; W_out = computeRHS ( timeStep ); break; case OneDFSI::W2: W_outID = 0; W_out = computeRHS ( timeStep ); break; default: std::cout << "Warning: bcType \"" << M_bcType << "\"not available!" << std::endl; break; } Real A ( M_bcU[0] ); Real Q ( M_bcU[1] ); if ( M_absorbing ) { Real b1 ( M_fluxPtr->physics()->dPdW ( A, Q, 0, M_bcNode ) ); // dP / dW1 - Missing W_outID ??? Real b2 ( A / 2 ); // dQ / dW1 M_resistance1 = b1 / b2; } // Trapezoidal rule for given integral // // \int_0^t ( pv/(R2*C) + (R1+R2)/(R2*C) Q(s) + R1 dQ(s)/ds ) exp( s / (R2*C) ) ds // // this gives: \int_0^t(n+1) = \int_0^t(n) + \int_t(n)^t(n+1) // // \int_0^t(n) is stored from previous time step // \int_t(n)^t(n+1) f(s) exp( a * s ) ds = // = dt/2 * ( f(t(n+1)) exp( a * t(n+1) ) + f(t(n)) exp( a * t(n) ) ) + O( dt^2 ) // = dt/2 * [ exp(a*t(n)) * ( f(t(n+1))*exp(a*dt) + f(t(n)) ) ] + O( dt^2 ) Real a ( 1 / ( M_compliance * M_resistance2 ) ); Real dQdt ( ( Q - M_Q_tn ) / timeStep ); Real F ( a * M_venousPressure + a * (M_resistance1 + M_resistance2) * Q + M_resistance1 * dQdt ); Real Fn ( a * M_venousPressure + a * (M_resistance1 + M_resistance2) * M_Q_tn + M_resistance1 * M_dQdt_tn ); Real EXP ( std::exp ( a * time ) ); Real EXPdt ( std::exp ( a * timeStep ) ); Real integral ( M_integral_tn + ( timeStep / 2 ) * ( EXP * ( F * EXPdt + Fn ) ) ); // Compute the solution of circuital ODE // P(t) = P(0) + [ \int_0^t ( pv/(R2*C) + (R1+R2)/(R2*C) Q(s) // + R1 dQ(s)/ds ) exp( s / (R2*C) ) ds ] * exp( - t / (R2*C) ) Real P ( M_P0 + integral / EXP ); // Update variable for the next time step M_integral_tn = integral; M_dQdt_tn = dQdt; M_Q_tn = Q; // Remove this call to fromPToW it is not compatible with viscoelasticity! return M_fluxPtr->physics()->fromPToW ( P, W_out, W_outID, M_bcNode ); // W_in }
void ImplicitStepper::solveNonLinear() { StrandDynamics& dynamics = m_strand.dynamics() ; Scalar minErr = 1.e99, prevErr = 1.e99; m_newtonIter = 0; JacobianMatrixType bestLHS; VecXx bestRhs, prevRhs; Scalar alpha = 0.5; // Current step length const Scalar minAlpha = 0.1; // Minimum step length bool foundOneSPD = false; m_strand.requireExactJacobian( false ); // Newton loop -- try to zero-out m_rhs for( m_newtonIter = 0; m_newtonIter < m_params.m_maxNewtonIterations; ++m_newtonIter ) { dynamics.setDisplacements( m_dt * m_futureVelocities ); prevRhs = m_rhs; computeRHS(); if( m_newtonIter ) { VecXx residual = m_rhs; dynamics.getScriptingController()->fixRHS( residual ); const Scalar err = residual.squaredNorm() / residual.size(); if( err < minErr || ( !foundOneSPD && !m_linearSolver.notSPD() ) ) { foundOneSPD = !m_linearSolver.notSPD(); minErr = err; if( isSmall( err ) || ( m_newtonIter > 3 && minErr < 1.e-6 ) ) { m_rhs = prevRhs; break; } bestLHS = Lhs(); bestRhs = prevRhs; } // Decrease or increase the step length based on current convergence if( err < prevErr ){ alpha = std::min( 1.0, 1.5 * alpha ); } else{ alpha = std::max( minAlpha, 0.5 * alpha ); } prevErr = err; } computeLHS(); m_rhs = m_rhs * alpha; Lhs().multiply( m_rhs, 1., m_futureVelocities ); dynamics.getScriptingController()->fixLHSAndRHS( Lhs(), m_rhs, m_dt ); m_linearSolver.store( Lhs() ); m_notSPD = m_linearSolver.notSPD(); m_linearSolver.solve( m_futureVelocities, m_rhs ); } // If the non-linear solve failed, returns to the the least problematic step if( m_newtonIter == m_params.m_maxNewtonIterations ) { m_rhs = bestRhs; Lhs() = bestLHS; m_linearSolver.store( Lhs() ); m_linearSolver.solve( m_futureVelocities, rhs() ); m_notSPD = m_linearSolver.notSPD(); } m_usedNonlinearSolver = true; }
void stepSolution(char *stepType,GRID *g,SOLN *s,double dt,double *l2norm, double *linfnorm, int myid) { double coef; static int istep=0; int i,k,l; int nsubiter=20; double CFL; CFL=g->CFL; if (strcmp(stepType,"euler")==0) { communication(g,s,myid); if(g->visc) { computeRHSv(g,s,l2norm,linfnorm,myid); } else { computeRHS(g,s,l2norm,linfnorm,myid); } coef=1.0; updateSoln(s->q,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); } else if (strcmp(stepType,"rk3") == 0){ /* RK step 1 */ communication(g,s,myid); computeRHS(g,s,l2norm,linfnorm,myid); coef=0.25; updateSoln(s->q,s->qt,s->r,s->sigma,dt,CFL,coef,g->ncells); coef=8.0/15; updateSoln(s->q,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); /* RK step 2 */ communication(g,s,myid); computeRHS(g,s,l2norm,linfnorm,myid); coef=5.0/12; updateSoln(s->qt,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); /* RK step 3 */ communication(g,s,myid); computeRHS(g,s,l2norm,linfnorm,myid); coef=3.0/4.0; updateSoln(s->qt,s->q,s->r,s->sigma,dt,CFL,coef,g->ncells); } else if (strcmp(stepType,"ADI")==0){ // communication communication(g,s,myid); computeRHSk(g,s,l2norm,linfnorm,myid); ADI(g,s,s->cflnum,dt,myid); } else if (strcmp(stepType,"DADI")==0){ // communication communication(g,s,myid); computeRHSk(g,s,l2norm,linfnorm,myid); DADI(g,s,s->cflnum,dt,myid); } else if (strcmp(stepType,"Gauss-Seidel") == 0) { // communication communication(g,s,myid); computeRHSkv(g,s,l2norm,myid); gaussSeidel(g,s,s->cflnum,dt,myid); } else if (strcmp(stepType,"line-Gauss-Seidel") == 0) { // communication communication(g,s,myid); if (g->visc) { computeRHSkv(g,s,l2norm,myid); } else { computeRHSk(g,s,l2norm,linfnorm,myid); } lineGaussSeidel(g,s,s->cflnum,dt,myid); } istep++; }
// ################################################################## // // step solution // // ################################################################## void SOLVER::stepSolution(void) { double coef; // // Euler explicit // if (strcmp(stepType,"euler") == 0 ) { if (sb->visc) { cout << "Not yet implemented. exit.\n"; exit(1); // computeRHSv; } else computeRHS("explicit"); coef = 1.; updateSolution(sb->q,sb->q,coef); } // // Runge - Kutta 3 // else if (strcmp(stepType,"rk3") == 0 ) { // RK step 1 computeRHS("explicit"); coef=0.25; updateSolution(sb->q,sb->qt,coef); coef=8.0/15; updateSolution(sb->q,sb->q,coef); // RK step 2 computeRHS("explicit"); coef=5.0/12; updateSolution(sb->qt,sb->q,coef); // RK step 3 computeRHS("explicit"); coef=3.0/4.0; updateSolution(sb->qt,sb->q,coef); } // // ADI ( Alternating Direction Implicit) // else if (strcmp(stepType,"ADI")==0) { // if(sb->idual==0) // { computeRHS("implicit"); ADI(); // } // else //dual time stepping // { // printf("Error. Dual Time stepping not yet implemented.\n"); // exit(1); // // for (i = 0; i < NQ*mb->nCell; i++) sb->pq[i] = sb->q[i]; // // for(k = 0; k < sb->ndual; k++) // // { // // DualcomputeRHSk(g,s,l2norm,s->cflnum); // // DualADI(g,s,s->cflnum,dt); // // } // // for (i=0;i<NVAR*g->ncells;i++) s->q[i] = s->pq[i]; // } } }