static double strikezHIII (MagComp component, const fault_params *fault, const magnetic_params *mag, double xi, double et, double qq, double y, double z) { double val; double h = mag->dcurier; double qd = y * sd + (fault->fdepth - h) * cd; double K3_val = K3 (component, 1.0, xi, et, qq); double log_re_val = log_re (component, 1.0, xi, et, qq); double M2_val = M2 (component, 1.0, xi, et, qq); double M3_val = M3 (component, 1.0, xi, et, qq); val = alpha5 * K3_val + fault->alpha * log_re_val * cd + alpha3 * (qd * M3_val - (z - h) * M2_val * sd); return val; }
// Runge-Kutta 4 algorithm void System::RK4(){ vec2dN K1(nObj), K2(nObj), K3(nObj), K4(nObj); vec2dN L1(nObj), L2(nObj), L3(nObj), L4(nObj); vec2dN NewR(nObj), NewV(nObj); if (nObj == 1){ // If only ONE object K1 = h*derX(vec2dN(nObj)); L1 = h*(SunInf(vec2dN(nObj))); K2 = h*derX(L1*0.5); L2 = h*(SunInf(K1*0.5)); K3 = h*derX(L2*0.5); L3 = h*(SunInf(K2*0.5)); K4 = h*derX(L3); L4 = h*(SunInf(K3)); } else { // If more than one object if (!statSun){ // Sun mobile or not pressent K1 = h*derX(vec2dN(nObj)); L1 = h*derV(vec2dN(nObj)); K2 = h*derX(L1*0.5); L2 = h*derV(K1*0.5); K3 = h*derX(L2*0.5); L3 = h*derV(L2*0.5); K4 = h*derX(L3); L4 = h*derV(K4); } else { // If the sun is stationary K1 = h*derX(vec2dN(nObj)); L1 = h*(derV(vec2dN(nObj)) + SunInf(vec2dN(nObj))); K2 = h*derX(L1*0.5); L2 = h*(derV(K1*0.5) + SunInf(K1*0.5)); K3 = h*derX(L2*0.5); L3 = h*(derV(K2*0.5) + SunInf(K2*0.5)); K4 = h*derX(L3); L4 = h*(derV(K3) + SunInf(K3)); } } for (int i = 0 ; i < nObj ; i++){ NewR[i] = sys[i].relR + (K1[i] + 2*K2[i] + 2*K3[i] + K4[i])/(double)6; NewV[i] = sys[i].relV + (L1[i] + 2*L2[i] + 2*L3[i] + L4[i])/(double)6; } calc_potential(); for (int i = 0 ; i < nObj ; i++){ sys[i].update(NewR[i], NewV[i], sys[i].relT+h); } }
static double strikezH0 (MagComp component, const fault_params *fault, const magnetic_params *mag, double xi, double et, double qq, double y, double z) { double val; double h = mag->dcurier; double qd = y * sd + (fault->fdepth - h) * cd; double K3_val = K3 (component, 1.0, xi, et, qq); double log_re_val = log_re (component, 1.0, xi, et, qq); double M2_val = M2 (component, 1.0, xi, et, qq); double M3_val = M3 (component, 1.0, xi, et, qq); double M3y_val = M3y (component, 1.0, xi, et, qq); double M3z_val = M3z (component, 1.0, xi, et, qq); val = - (2.0 + alpha5) * K3_val - fault->alpha * log_re_val * cd - alpha3 * (qd * M3_val - (z - h) * M2_val * sd) + 2.0 * fault->alpha * h * (M3_val * cd + M2_val * sd) - 4.0 * alpha1 * h * M2_val * sd - 2.0 * alpha2 * h * M2_val * sd - 2.0 * alpha2 * h * ((qd + h * cd) * M3z_val - (z - 2.0 * h) * M3y_val * sd); return val; }
static double strikez0 (MagComp component, double xi, double et, double qq) { return 2.0 * K3 (component, 1.0, xi, et, qq); }
vector<SPACETYPE> RungeKutta4::Solve(vector<SPACETYPE> initialValue, TIMETYPE finalTime) { // N is the number of spatial gridpoints int N = initialValue.size(); if (_spatialSolver==NULL) return initialValue; //mSolution.push_back(initialValue); // vector<vector<complex<double> > > mSolution(_timeSteps); double time=0; double h = finalTime/(_timeSteps-1); vector<SPACETYPE> K1(N), K2(N), K3(N), K4(N), Temp(N), Unew(N); for(int i=1; i<_timeSteps; i++) { time+=h; //K1 K1 = _spatialSolver->GetSpatialSolution(initialValue); for(int j=0;j<N;j++) { K1[j] = h*K1[j]; } //K2 for(int j=0;j<N;j++) { Temp[j] = initialValue[j] + K1[j]/2.0; } Temp = _spatialSolver->GetSpatialSolution(Temp); for(int j=0;j<N;j++) { K2[j] = h*Temp[j]; } //K3 for(int j=0;j<N;j++) { Temp[j] = initialValue[j] + K2[j]/2.0; } Temp = _spatialSolver->GetSpatialSolution(Temp); for(int j=0;j<N;j++) { K3[j] = h*Temp[j]; } //K4 for(int j=0;j<N;j++) { Temp[j] = initialValue[j] + K3[j]; } Temp = _spatialSolver->GetSpatialSolution(Temp); for(int j=0;j<N;j++) { K4[j] = h*Temp[j]; } //New for(int j=0;j<N;j++) { Unew[j] = initialValue[j]+(1/6.0)*(K1[j]+2.0*(K2[j]+K3[j])+K4[j]); } //mSolution.push_back(Unew); initialValue = Unew; } return initialValue; }
void rk4( Vector &Xcurrent, const double t, const double stepSize, Vector &Xnext, orbiterEquationsOfMotion &derivatives ) { const double h = stepSize; const int numberOfElements = Xcurrent.size( ); // Evaluate K1 step in RK4 algorithm. Vector dXdtCurrent( numberOfElements ); Vector K1( numberOfElements ); derivatives( t, Xcurrent, dXdtCurrent ); for( int i = 0; i < numberOfElements; i++ ) { K1[ i ] = h * dXdtCurrent[ i ]; } // Evaluate K2 step in RK4 algorithm. Vector dXdt_K2( numberOfElements ); Vector K2( numberOfElements ); const double t_K2 = t + 0.5 * h; Vector X_K2( numberOfElements ); for( int i = 0; i < numberOfElements; i++ ) { X_K2[ i ] = Xcurrent[ i ] + 0.5 * K1[ i ]; } derivatives( t_K2, X_K2, dXdt_K2 ); for( int i = 0; i < numberOfElements; i++ ) { K2[ i ] = h * dXdt_K2[ i ]; } // Evaluate K3 step in RK4 algorithm. Vector dXdt_K3( numberOfElements ); Vector K3( numberOfElements ); const double t_K3 = t + 0.5 * h; Vector X_K3( numberOfElements ); for( int i = 0; i < numberOfElements; i++ ) { X_K3[ i ] = Xcurrent[ i ] + 0.5 * K2[ i ]; } derivatives( t_K3, X_K3, dXdt_K3 ); for( int i = 0; i < numberOfElements; i++ ) { K3[ i ] = h * dXdt_K3[ i ]; } // Evaluate K4 step in RK4 algorithm. Vector dXdt_K4( numberOfElements ); Vector K4( numberOfElements ); const double t_K4 = t + h; Vector X_K4( numberOfElements ); for( int i = 0; i < numberOfElements; i++ ) { X_K4[ i ] = Xcurrent[ i ] + K3[ i ]; } derivatives( t_K4, X_K4, dXdt_K4 ); for( int i = 0; i < numberOfElements; i++ ) { K4[ i ] = h * dXdt_K4[ i ]; } // Final step, evaluate the weighted summation. for( int i = 0; i < numberOfElements; i++ ) { Xnext[ i ] = Xcurrent[ i ] + ( 1.0 / 6.0 ) * K1[ i ] + ( 1.0 / 3.0 ) * K2[ i ] + ( 1.0 / 3.0 ) * K3[ i ] + ( 1.0 / 6.0 ) * K4[ i ]; } }
void Foam::kineticTheoryModel::solve(const volTensorField& gradUat) { if (!kineticTheory_) { return; } const scalar sqrtPi = sqrt(constant::mathematical::pi); surfaceScalarField phi(1.5*rhoa_*phia_*fvc::interpolate(alpha_)); volTensorField dU(gradUat.T()); //fvc::grad(Ua_); volSymmTensorField D(symm(dU)); // NB, drag = K*alpha*beta, // (the alpha and beta has been extracted from the drag function for // numerical reasons) volScalarField Ur(mag(Ua_ - Ub_)); volScalarField betaPrim(alpha_*(1.0 - alpha_)*draga_.K(Ur)); // Calculating the radial distribution function (solid volume fraction is // limited close to the packing limit, but this needs improvements) // The solution is higly unstable close to the packing limit. gs0_ = radialModel_->g0 ( min(max(alpha_, scalar(1e-6)), alphaMax_ - 0.01), alphaMax_ ); // particle pressure - coefficient in front of Theta (Eq. 3.22, p. 45) volScalarField PsCoeff ( granularPressureModel_->granularPressureCoeff ( alpha_, gs0_, rhoa_, e_ ) ); // 'thermal' conductivity (Table 3.3, p. 49) kappa_ = conductivityModel_->kappa(alpha_, Theta_, gs0_, rhoa_, da_, e_); // particle viscosity (Table 3.2, p.47) mua_ = viscosityModel_->mua(alpha_, Theta_, gs0_, rhoa_, da_, e_); dimensionedScalar Tsmall ( "small", dimensionSet(0 , 2 ,-2 ,0 , 0, 0, 0), 1.0e-6 ); dimensionedScalar TsmallSqrt = sqrt(Tsmall); volScalarField ThetaSqrt(sqrt(Theta_)); // dissipation (Eq. 3.24, p.50) volScalarField gammaCoeff ( 12.0*(1.0 - sqr(e_))*sqr(alpha_)*rhoa_*gs0_*(1.0/da_)*ThetaSqrt/sqrtPi ); // Eq. 3.25, p. 50 Js = J1 - J2 volScalarField J1(3.0*betaPrim); volScalarField J2 ( 0.25*sqr(betaPrim)*da_*sqr(Ur) /(max(alpha_, scalar(1e-6))*rhoa_*sqrtPi*(ThetaSqrt + TsmallSqrt)) ); // bulk viscosity p. 45 (Lun et al. 1984). lambda_ = (4.0/3.0)*sqr(alpha_)*rhoa_*da_*gs0_*(1.0+e_)*ThetaSqrt/sqrtPi; // stress tensor, Definitions, Table 3.1, p. 43 volSymmTensorField tau(2.0*mua_*D + (lambda_ - (2.0/3.0)*mua_)*tr(D)*I); if (!equilibrium_) { // construct the granular temperature equation (Eq. 3.20, p. 44) // NB. note that there are two typos in Eq. 3.20 // no grad infront of Ps // wrong sign infront of laplacian fvScalarMatrix ThetaEqn ( fvm::ddt(1.5*alpha_*rhoa_, Theta_) + fvm::div(phi, Theta_, "div(phi,Theta)") == fvm::SuSp(-((PsCoeff*I) && dU), Theta_) + (tau && dU) + fvm::laplacian(kappa_, Theta_, "laplacian(kappa,Theta)") + fvm::Sp(-gammaCoeff, Theta_) + fvm::Sp(-J1, Theta_) + fvm::Sp(J2/(Theta_ + Tsmall), Theta_) ); ThetaEqn.relax(); ThetaEqn.solve(); } else { // equilibrium => dissipation == production // Eq. 4.14, p.82 volScalarField K1(2.0*(1.0 + e_)*rhoa_*gs0_); volScalarField K3 ( 0.5*da_*rhoa_* ( (sqrtPi/(3.0*(3.0-e_))) *(1.0 + 0.4*(1.0 + e_)*(3.0*e_ - 1.0)*alpha_*gs0_) +1.6*alpha_*gs0_*(1.0 + e_)/sqrtPi ) ); volScalarField K2 ( 4.0*da_*rhoa_*(1.0 + e_)*alpha_*gs0_/(3.0*sqrtPi) - 2.0*K3/3.0 ); volScalarField K4(12.0*(1.0 - sqr(e_))*rhoa_*gs0_/(da_*sqrtPi)); volScalarField trD(tr(D)); volScalarField tr2D(sqr(trD)); volScalarField trD2(tr(D & D)); volScalarField t1(K1*alpha_ + rhoa_); volScalarField l1(-t1*trD); volScalarField l2(sqr(t1)*tr2D); volScalarField l3 ( 4.0 *K4 *max(alpha_, scalar(1e-6)) *(2.0*K3*trD2 + K2*tr2D) ); Theta_ = sqr((l1 + sqrt(l2 + l3))/(2.0*(alpha_ + 1.0e-4)*K4)); } Theta_.max(1.0e-15); Theta_.min(1.0e+3); volScalarField pf ( frictionalStressModel_->frictionalPressure ( alpha_, alphaMinFriction_, alphaMax_, Fr_, eta_, p_ ) ); PsCoeff += pf/(Theta_+Tsmall); PsCoeff.min(1.0e+10); PsCoeff.max(-1.0e+10); // update particle pressure pa_ = PsCoeff*Theta_; // frictional shear stress, Eq. 3.30, p. 52 volScalarField muf ( frictionalStressModel_->muf ( alpha_, alphaMax_, pf, D, phi_ ) ); // add frictional stress mua_ += muf; mua_.min(1.0e+2); mua_.max(0.0); Info<< "kinTheory: max(Theta) = " << max(Theta_).value() << endl; volScalarField ktn(mua_/rhoa_); Info<< "kinTheory: min(nua) = " << min(ktn).value() << ", max(nua) = " << max(ktn).value() << endl; Info<< "kinTheory: min(pa) = " << min(pa_).value() << ", max(pa) = " << max(pa_).value() << endl; }