SolutionInstance TubeMCM::Integrate(d dt){ // Integrate using // MacCormack method d t=sol.getTime(); d newt=t+dt; d lambda=dt/dx; SolutionInstance predictor(gp); { // Predictor step const vd& oldrho=sol.rho(); const vd& oldm=sol.m(); const vd& oldrhoE=sol.rhoE(); vd& prho=predictor.rho_ref(); vd& pm=predictor.m_ref(); vd& prhoE=predictor.rhoE_ref(); // Fluxes from previous solution vd Cflux=sol.Cflux(); vd Mflux=sol.Mflux(); vd Eflux=sol.Eflux(); // Density prho.tail(gp-1)=oldrho.tail(gp-1) -lambda*(Cflux.tail(gp-1)-Cflux.head(gp-1)); // The first element prho(0)=oldrho(0)-lambda*(Cflux(1)-Cflux(0)); // Momentum d oldu0=oldm(0)/oldrho(0); d momfluxl = pow(oldm(0), 2)/oldrho(0) + pleft(t); pm.tail(gp-1)=oldm.tail(gp-1) -lambda*(Mflux.tail(gp-1)-Mflux.head(gp-1)); // The first element pm(0)=oldm(0)-lambda*(Mflux(1)-momfluxl); pm(gp-1)=0; // Energy prhoE.tail(gp-1)=oldrhoE.tail(gp-1) -lambda*(Eflux.tail(gp-1)-Eflux.head(gp-1)); // The first element prhoE(0)=oldrhoE(0)-lambda*(Eflux(1)-Eflux(0)); } SolutionInstance corrector(gp); // Temp test hack: corrector=predictor; corrector.setTime(newt); return corrector; } // Integrate(dt)
void Cconfig::iterate(double time_step) { dt=time_step; dt_on_2 = dt/2.; dt2_on_2=dt*dt/2.; predictor(); //motion integration update_contact(); //find contact and get the force and torque sum_force(); //sum the force moment of each contact on particle if(simule_thermal_conduction) sum_heat(); //Heat transfer //AK addition if(MELT_SURFTEN){melt_dist();} cell.rigid_velocity *= 0.0; corrector(); //acceleration of particles according to the sum of force/moment they experience cell.rigid_velocity /= parameter.total_mass; // Velocity offset by rigid motion #pragma omp parallel for num_threads(NTHREADS) // YG, MPI for(int ip=0; ip< P.size(); ip++) P[ip].V -= cell.rigid_velocity; }
void Cconfig::iterate(double time_step) { dt=time_step; dt_on_2 = dt/2.; dt2_on_2=dt*dt/2.; predictor(); //motion integration update_contact(); //find contact and get the force and torque sum_force(); //sum the force moment of each contact on particle if(simule_thermal_conduction) sum_heat(); //Heat transfer if(LIQUID_TRANSFER) liquid_transfer(); // water input, controlling water volume if(LIQUID_TRANSFER){ for(int ip=0; ip< P.size(); ip++) { // initial if(dt==0) P[ip].water_volume = parameter.INITIAL_SATURATION * P[ip].void_volume; if(P[ip].X.x[0]>=-0.5 && P[ip].X.x[0]<=0.5) P[ip].water_volume = parameter.FIXED_SATURATION * P[ip].void_volume; //exp P[ip].saturation = P[ip].water_volume/P[ip].void_volume; // update the saturation of each cell if(P[ip].saturation > MAX_SATURATION) P[ip].saturation = MAX_SATURATION; //exp }} cell.rigid_velocity *= 0.0; corrector(); //acceleration of particles according to the sum of force/moment they experience cell.rigid_velocity /= parameter.total_mass; // Velocity offset by rigid motion //#pragma omp parallel for num_threads(NTHREADS) // YG, MPI // for(int ip=0; ip< P.size(); ip++) // P[ip].V -= cell.rigid_velocity; if(dt==0) { for(int ip=0; ip< P.size(); ip++) P[ip].V *= 0.0;} for(int ip=0; ip< P.size(); ip++) { P[ip].V *= (1.0 - 1.0*dt); // Global damping P[ip].Ome *= (1.0 - 1.0*dt); } // calculation of global and local water pressure. cap_pressure=0; for(int ip=0; ip< P.size(); ip++) { P[ip].water_pressure = 0.0;} for(int ic=0;ic<C.size();ic++) if(C[ic].fcap >0) { // cap_pressure -= C[ic].fcap * C[ic].dx; P[C[ic].A].water_pressure -= C[ic].fcap * C[ic].dx * P[C[ic].A].R /(P[C[ic].A].R+P[C[ic].B].R); P[C[ic].B].water_pressure -= C[ic].fcap * C[ic].dx * P[C[ic].B].R /(P[C[ic].A].R+P[C[ic].B].R); } for(int ip=0; ip< P.size(); ip++) { // Modified effective stress term with the degree of saturation (micro-scale). if(P[ip].voronoi_volume>1.0e-10) P[ip].water_pressure /= (3.0 *P[ip].voronoi_volume); P[ip].positive_pressure = 0.0; if(P[ip].saturation > 1.0) { P[ip].positive_pressure = WATER_K*parameter.SURFACE_TENSION *(P[ip].saturation - 1.0); // positive pressure P[ip].water_pressure += P[ip].positive_pressure; } if(P[ip].saturation>=1.0e-10) P[ip].water_pressure /= P[ip].saturation; } //Overall saturation and pressure saturation = 0.0; // cap_pressure = 0.0; double void_volume=0.0; double water_volume=0.0; for(int ip=0; ip< P.size(); ip++){ void_volume += P[ip].void_volume; water_volume += P[ip].water_volume; // Modified effective stress term with the degree of saturation (macro-scale). // if(P[ip].saturation <= 1.0) cap_pressure -= P[ip].water_pressure * P[ip].water_volume; // modified cap pressure // else cap_pressure -= P[ip].water_pressure * P[ip].void_volume; cap_pressure -= P[ip].water_pressure * P[ip].saturation *P[ip].voronoi_volume; } saturation = water_volume / void_volume; if(saturation<1.0e-10) saturation = 1.e-10; double total_volume = cell.L.x[0]* cell.L.x[1]* cell.L.x[2]; cap_pressure /= saturation * total_volume; water_content = water_volume /total_volume; }
void Cconfig::iterate(double time_step) { dt=time_step; dt_on_2 = dt/2.; dt2_on_2=dt*dt/2.; predictor(); //motion integration update_contact(); //find contact and get the force and torque sum_force(); //sum the force moment of each contact on particle if(simule_thermal_conduction) sum_heat(); //Heat transfer if(LIQUID_TRANSFER) liquid_transfer(); // water input, controlling water volume if(LIQUID_TRANSFER){ if(dt==0) flag_wetting = true; for(int ip=0; ip< P.size(); ip++) { // initial if(dt==0) {P[ip].water_volume = parameter.INITIAL_SATURATION * P[ip].void_volume; P[ip].water_volume_old = P[ip].water_volume; } if(P[ip].void_volume <= 1e-3 * P[ip].grain_volume) P[ip].void_volume = 1e-3 * P[ip].grain_volume; // avoid negative Void volume P[ip].saturation = P[ip].water_volume/P[ip].void_volume; // update the saturation of each cell if(P[ip].saturation > MAX_SATURATION) P[ip].saturation = MAX_SATURATION; //exp }} if(!LIQUID_TRANSFER){ // for pre-packing stage for(int ip=0; ip< P.size(); ip++) { P[ip].saturation = 0.1; P[ip].water_volume = 0.1 * P[ip].void_volume; }} cell.rigid_velocity *= 0.0; corrector(); //acceleration of particles according to the sum of force/moment they experience cell.rigid_velocity /= parameter.total_mass; // Velocity offset by rigid motion //#pragma omp parallel for num_threads(NTHREADS) // YG, MPI for(int ip=0; ip< P.size(); ip++) P[ip].V -= cell.rigid_velocity; if(dt==0) { for(int ip=0; ip< P.size(); ip++) P[ip].V *= 0.0;} for(int ip=0; ip< P.size(); ip++) { P[ip].V *= (1.0 - GLOBAL_DAMPING*dt); // Global damping P[ip].Ome *= (1.0 - GLOBAL_DAMPING*dt); } // calculation of global and local water pressure. for(int ip=0; ip< P.size(); ip++) { P[ip].water_pressure = 0.0;} for(int ic=0;ic<C.size();ic++) if(C[ic].fcap >0) { P[C[ic].A].water_pressure -= C[ic].fcap * C[ic].dx * P[C[ic].A].R /(P[C[ic].A].R+P[C[ic].B].R); P[C[ic].B].water_pressure -= C[ic].fcap * C[ic].dx * P[C[ic].B].R /(P[C[ic].A].R+P[C[ic].B].R); } for(int ip=0; ip< P.size(); ip++) { // Modified effective stress term with the degree of saturation (micro-scale). if(P[ip].voronoi_volume>1.0e-10) P[ip].water_pressure /= (3.0 *P[ip].voronoi_volume); P[ip].positive_pressure = 0.0; if(P[ip].saturation > MAX_SATURATION_AIR && P[ip].saturation < 1.0) { P[ip].positive_pressure = AIR_K *(P[ip].saturation - MAX_SATURATION_AIR)/(1.0 - P[ip].saturation); // positive pressure P[ip].water_pressure += P[ip].positive_pressure*1.0; // air compression the whole cell experiencing the pressure } if(P[ip].saturation>=1.0e-10) P[ip].water_pressure /= P[ip].saturation; } //Overall saturation and pressure saturation = 0.0; cap_pressure = 0.0; double void_volume=0.0; double water_volume=0.0; double total_volume_mid = 0.0; cap_pressure_mid = 0.0; double void_volume_mid=0.0; double water_volume_mid=0.0; for(int ip=0; ip< P.size(); ip++){ void_volume += P[ip].void_volume; water_volume += P[ip].water_volume; // Modified effective stress term with the degree of saturation (macro-scale). // if(P[ip].saturation <= 1.0) cap_pressure -= P[ip].water_pressure * P[ip].water_volume; // modified cap pressure // else cap_pressure -= P[ip].water_pressure * P[ip].void_volume; cap_pressure -= P[ip].water_pressure * P[ip].saturation *P[ip].voronoi_volume; if(P[ip].X.x[1] <= 5.0 && P[ip].X.x[1] >= -5.0){ void_volume_mid += P[ip].void_volume; water_volume_mid += P[ip].water_volume; cap_pressure_mid -= P[ip].water_pressure * P[ip].saturation *P[ip].voronoi_volume; total_volume_mid += P[ip].voronoi_volume; } } saturation = water_volume / void_volume; if(saturation < 1.0e-10) saturation = 1.e-10; double total_volume = cell.L.x[0]* cell.L.x[1]* cell.L.x[2]; cap_pressure /= saturation * total_volume; water_content = water_volume /total_volume; saturation_mid = water_volume_mid / void_volume_mid; if(saturation_mid<1.0e-10) saturation_mid = 1.e-10; if(total_volume_mid > 0.0){ cap_pressure_mid /= saturation_mid * total_volume_mid; water_content_mid = water_volume_mid /total_volume_mid; } if(saturation >= MAX_SCAN && t>1.0 && flag_wetting) flag_wetting=false; if(saturation <= MIN_SCAN && t>1.0 && !flag_wetting) flag_wetting=true; }
// asynchronous step solver int e_trsolver::stepsolve_async(nr_double_t steptime) { // Start to sweep through time. int error = 0; convError = 0; time = steptime; // update the interpolation time of any externally controlled // components which require it. updateExternalInterpTime(time); // make the stored histories for all ircuits that have // requested them at least as long as the next major time // step so we can reject the step later if needed and // restore all the histories to their previous state updateHistoryAges (time - lastasynctime); //delta = (steptime - time) / 10; //if (progress) logprogressbar (i, swp->getSize (), 40); #if DEBUG && 0 messagefcn (LOG_STATUS, "NOTIFY: %s: solving netlist for t = %e\n", getName (), (double) time); #endif do { #if STEPDEBUG if (delta == deltaMin) { messagefcn (LOG_ERROR, "WARNING: %s: minimum delta h = %.3e at t = %.3e\n", getName (), (double) delta, (double) current); } #endif // update the integration coefficients updateCoefficients (delta); // Run predictor to get a start value for the solution vector for // the successive iterative corrector process error += predictor (); // restart Newton iteration if (rejected) { restart (); // restart non-linear devices rejected = 0; } // Run corrector process with appropriate exception handling. // The corrector iterates through the solutions of the integration // process until a certain error tolerance has been reached. try_running () // #defined as: do { { error += corrector (); } catch_exception () // #defined as: } while (0); if (estack.top ()) switch (estack.top()->getCode ()) { case EXCEPTION_NO_CONVERGENCE: pop_exception (); // Reduce step-size (by half) if failed to converge. if (current > 0) current -= delta; delta /= 2; if (delta <= deltaMin) { delta = deltaMin; adjustOrder (1); } if (current > 0) current += delta; // Update statistics. statRejected++; statConvergence++; rejected++; converged = 0; error = 0; // Start using damped Newton-Raphson. convHelper = CONV_SteepestDescent; convError = 2; #if DEBUG messagefcn (LOG_ERROR, "WARNING: delta rejected at t = %.3e, h = %.3e " "(no convergence)\n", (double) saveCurrent, (double) delta); #endif break; default: // Otherwise return. estack.print (); error++; break; } if (error) return -1; if (rejected) continue; // check whether Jacobian matrix is still non-singular if (!A->isFinite ()) { messagefcn (LOG_ERROR, "ERROR: %s: Jacobian singular at t = %.3e, " "aborting %s analysis\n", getName (), (double) current, getDescription ().c_str()); return -1; } // Update statistics and no more damped Newton-Raphson. statIterations += iterations; if (--convError < 0) convHelper = 0; // Now advance in time or not... if (running > 1) { adjustDelta (time); adjustOrder (); } else { fillStates (); nextStates (); rejected = 0; } saveCurrent = current; current += delta; running++; converged++; // Tell integrators to be running. setMode (MODE_NONE); // Initialize or update history. if (running > 1) { updateHistory (saveCurrent); } else { initHistory (saveCurrent); } } while (saveCurrent < time); // Hit a requested time point? return 0; }
/* synchronous step solver for external ode routine * * This function solves the circuit for a single time delta provided * by an external source. Convergence issues etc. are expected to * be handled by the external solver, as it is in full control of the * time stepping. */ int e_trsolver::stepsolve_sync(nr_double_t synctime) { int error = 0; convError = 0; time = synctime; // update the interpolation time of any externally controlled // components which require it. updateExternalInterpTime(time); // copy the externally chosen time step to delta delta = time - lastsynctime; // get the current solution time //current += delta; // updates the integrator coefficients, and updates the array of prev // 8 deltas with the new delta for this step updateCoefficients (delta); // Run predictor to get a start value for the solution vector for // the successive iterative corrector process error += predictor (); // restart Newton iteration restart (); // restart non-linear devices // Attempt to solve the circuit with the given delta try_running () // #defined as: do { { //error += solve_nonlinear_step (); error += corrector (); } catch_exception () // #defined as: } while (0); if (estack.top ()) switch (estack.top()->getCode ()) { case EXCEPTION_NO_CONVERGENCE: pop_exception (); // Retry using damped Newton-Raphson. this->convHelper = CONV_SteepestDescent; convError = 2; #if DEBUG messagefcn (LOG_ERROR, "WARNING: delta rejected at t = %.3e, h = %.3e " "(no convergence)\n", (double) saveCurrent, (double) delta); #endif try_running () // #defined as: do { { // error += solve_nonlinear_step (); error += solve_nonlinear (); } catch_exception () // #defined as: } while (0); if (estack.top ()) switch (estack.top()->getCode ()) { case EXCEPTION_NO_CONVERGENCE: pop_exception (); // Update statistics. statRejected++; statConvergence++; rejected++; converged = 0; error = 0; break; default: // Otherwise return. estack.print (); error++; break; } // Update statistics and no more damped Newton-Raphson. // statIterations += iterations; // if (--convError < 0) this->convHelper = 0; break; default: // Otherwise return. estack.print (); error++; break; } // if there was an error other than non-convergence, return -1 if (error) return -1; // check whether Jacobian matrix is still non-singular if (!A->isFinite ()) { // messagefcn (LOG_ERROR, "ERROR: %s: Jacobian singular at t = %.3e, " // "aborting %s analysis\n", getName (), (double) current, // getDescription ()); return -1; } return 0; }