double *update ( int id, int p, int n_global, int n_local, int nsteps, double dt ) /******************************************************************************/ /* Purpose: UPDATE advances the solution a given number of time steps. Licensing: This code is distributed under the GNU LGPL license. Modified: 17 November 2013 Author: John Burkardt Parameters: Input, int ID, the identifier of this process. Input, int P, the number of processes. Input, int N_GLOBAL, the total number of points. Input, int N_LOCAL, the number of points visible to this process. Input, int NSTEPS, the number of time steps. Input, double DT, the size of the time step. Output, double UPDATE[N_LOCAL], the portion of the solution at the last time, as evaluated by this process. */ { double alpha; double c; double dx; int i; int i_global; int i_global_hi; int i_global_lo; int i_local; int i_local_hi; int i_local_lo; int j; int ltor = 20; int rtol = 10; MPI_Status status; double t; double *u0_local; double *u1_local; double *u2_local; double x; /* Determine the value of ALPHA. */ c = 1.0; dx = 1.0 / ( double ) ( n_global - 1 ); alpha = c * dt / dx; if ( 1.0 <= fabs ( alpha ) ) { if ( id == 0 ) { fprintf ( stderr, "\n" ); fprintf ( stderr, "UPDATE - Warning!\n" ); fprintf ( stderr, " 1 <= |ALPHA| = | C * dT / dX |.\n" ); fprintf ( stderr, " C = %g\n", c ); fprintf ( stderr, " dT = %g\n", dt ); fprintf ( stderr, " dX = %g\n", dx ); fprintf ( stderr, " ALPHA = %g\n", alpha ); fprintf ( stderr, " Computation will not be stable!\n" ); } MPI_Finalize ( ); exit ( 1 ); } /* The global array of N_GLOBAL points must be divided up among the processes. Each process stores about 1/P of the total + 2 extra slots. */ i_global_lo = ( id * ( n_global - 1 ) ) / p; i_global_hi = ( ( id + 1 ) * ( n_global - 1 ) ) / p; if ( 0 < id ) { i_global_lo = i_global_lo - 1; } i_local_lo = 0; i_local_hi = i_global_hi - i_global_lo; u0_local = ( double * ) malloc ( n_local * sizeof ( double ) ); u1_local = ( double * ) malloc ( n_local * sizeof ( double ) ); u2_local = ( double * ) malloc ( n_local * sizeof ( double ) ); t = 0.0; for ( i_global = i_global_lo; i_global <= i_global_hi; i_global++ ) { x = ( double ) ( i_global ) / ( double ) ( n_global - 1 ); i_local = i_global - i_global_lo; u1_local[i_local] = exact ( x, t ); } for ( i_local = i_local_lo; i_local <= i_local_hi; i_local++ ) { u0_local[i_local] = u1_local[i_local]; } /* Take NSTEPS time steps. */ for ( i = 1; i <= nsteps; i++ ) { t = dt * ( double ) i; /* For the first time step, we need to use the initial derivative information. */ if ( i == 1 ) { for ( i_local = i_local_lo + 1; i_local < i_local_hi; i_local++ ) { i_global = i_global_lo + i_local; x = ( double ) ( i_global ) / ( double ) ( n_global - 1 ); u2_local[i_local] = + 0.5 * alpha * alpha * u1_local[i_local-1] + ( 1.0 - alpha * alpha ) * u1_local[i_local] + 0.5 * alpha * alpha * u1_local[i_local+1] + dt * dudt ( x, t ); } } /* After the first time step, we can use the previous two solution estimates. */ else { for ( i_local = i_local_lo + 1; i_local < i_local_hi; i_local++ ) { u2_local[i_local] = + alpha * alpha * u1_local[i_local-1] + 2.0 * ( 1.0 - alpha * alpha ) * u1_local[i_local] + alpha * alpha * u1_local[i_local+1] - u0_local[i_local]; } } /* Exchange data with "left-hand" neighbor. */ if ( 0 < id ) { MPI_Send ( &u2_local[i_local_lo+1], 1, MPI_DOUBLE, id - 1, rtol, MPI_COMM_WORLD ); MPI_Recv ( &u2_local[i_local_lo], 1, MPI_DOUBLE, id - 1, ltor, MPI_COMM_WORLD, &status ); } else { x = 0.0; u2_local[i_local_lo] = exact ( x, t ); } /* Exchange data with "right-hand" neighbor. */ if ( id < p - 1 ) { MPI_Send ( &u2_local[i_local_hi-1], 1, MPI_DOUBLE, id + 1, ltor, MPI_COMM_WORLD ); MPI_Recv ( &u2_local[i_local_hi], 1, MPI_DOUBLE, id + 1, rtol, MPI_COMM_WORLD, &status ); } else { x = 1.0; u2_local[i_local_hi] = exact ( x, t ); } /* Shift data for next time step. */ for ( i_local = i_local_lo; i_local <= i_local_hi; i_local++ ) { u0_local[i_local] = u1_local[i_local]; u1_local[i_local] = u2_local[i_local]; } } /* Free memory. */ free ( u0_local ); free ( u2_local ); return u1_local; }
/// Main program of uncertainty propagation of the ODE model parameters via intrusive spectral projection (ISP) int main() { // Model parameters Array1D<double> modelparams; // Model parameter names Array1D<string> modelparamnames; // Auxiliary parameters: final time and time step of integration Array1D<double> modelauxparams; // Read the xml tree RefPtr<XMLElement> xmlTree=readXMLTree("lorenz.in.xml"); // Read the model-specific input readXMLModelInput(xmlTree,modelparams, modelparamnames, modelauxparams); // Total nuber of input parameters int fulldim=modelparams.XSize(); // Read the output preferences dumpInfo* outPrint=new dumpInfo; readXMLDumpInfo( xmlTree, &(outPrint->dumpInt), &(outPrint->fdumpInt), &(outPrint->dumpfile) ); // Output PC order int order; // PC type string pcType; // A 2d array (each row is an array of coefficients for the corresponding uncertain input parameter) Array2D<double> allPCcoefs; // The indices of the uncertain model parameters in the list of model parameters Array1D<int> uncParamInd; // Read the UQ-specific information from the xml tree readXMLUncInput(xmlTree,allPCcoefs,uncParamInd , &order, &pcType); // Stochastic dimensionality int dim=uncParamInd.XSize(); // Instantiate a PC object for ISP computations PCSet myPCSet("ISP",order,dim,pcType,0.0,1.0); // The number of PC terms const int nPCTerms = myPCSet.GetNumberPCTerms(); cout << "The number of PC terms in an expansion is " << nPCTerms << endl; // Print the multiindices on screen myPCSet.PrintMultiIndex(); // Initial time double t0 = 0.0; // Final time double tf = modelauxparams(0); // Time step double dTym = modelauxparams(1); // Number of steps int nStep=(int) tf / dTym; // Initial conditions of zero coverage (based on Makeev:2002) Array1D<double> u(nPCTerms,0.e0); Array1D<double> v(nPCTerms,0.e0); Array1D<double> w(nPCTerms,0.e0); Array1D<double> z(nPCTerms,0.e0); // Array to hold the PC representation of the number 1 Array1D<double> one(nPCTerms,0.e0); one(0)=1.0; // The z-species is described as z=1-u-v-w z=one; myPCSet.SubtractInPlace(z,u); myPCSet.SubtractInPlace(z,v); myPCSet.SubtractInPlace(z,w); // Right-hand sides Array1D<double> dudt(nPCTerms,0.e0); Array1D<double> dvdt(nPCTerms,0.e0); Array1D<double> dwdt(nPCTerms,0.e0); // Array of arrays to hold the input parameter PC representations in the output PC // Each element is an array of coefficients for the corresponding input parameter, whether deterministic or uncertain // The size of the array is the total number input parameters Array1D< Array1D<double> > modelparamPCs(fulldim); printf("\nInput parameter PC coefficients are given below\n"); for (int i=0; i<fulldim; i++){ printf("%s: ",modelparamnames(i).c_str()); modelparamPCs(i).Resize(nPCTerms,0.e0); for (int j=0; j<nPCTerms; j++){ modelparamPCs(i)(j)=allPCcoefs(j,i); printf(" %lg ",modelparamPCs(i)(j)); } printf("\n"); } printf("\n"); // Initial time and time step counter int step=0; double tym=t0; // Work arrays for integration Array1D<double> u_o(nPCTerms,0.e0); Array1D<double> v_o(nPCTerms,0.e0); Array1D<double> w_o(nPCTerms,0.e0); Array1D<double> tmp_u(nPCTerms,0.e0); Array1D<double> tmp_v(nPCTerms,0.e0); Array1D<double> tmp_w(nPCTerms,0.e0); // File to write the mean and stdev, name read from xml FILE *f_dump,*modes_dump; if(!(f_dump = fopen(outPrint->dumpfile.c_str(),"w"))){ printf("Could not open file '%s'\n",outPrint->dumpfile.c_str()); exit(1); } // File to dump the PC modes, name hardwired string modes_dumpfile = "solution_ISP_modes.dat"; if(!(modes_dump = fopen(modes_dumpfile.c_str(),"w"))){ printf("Could not open file '%s'\n",modes_dumpfile.c_str()); exit(1); } // write time, u, v, w (all modes) to file WriteModesToFilePtr(tym, u.GetArrayPointer(), v.GetArrayPointer(), w.GetArrayPointer(), nPCTerms, modes_dump); // Write out initial step // Get standard deviations double uStDv = myPCSet.StDv(u); double vStDv = myPCSet.StDv(v); double wStDv = myPCSet.StDv(w); // write u, v, w (mean and standard deviation) to file WriteMeanStdDevToFilePtr(tym, u(0), v(0), w(0), uStDv, vStDv, wStDv, f_dump); // write u, v, w (mean and standard deviation) to screen WriteMeanStdDevToStdOut(step, tym, u(0), v(0), w(0), uStDv, vStDv, wStDv); // Forward run while(tym < tf) { // Integrate with 2nd order Runge Kutta // Save solution at current time step myPCSet.Copy(u_o,u); myPCSet.Copy(v_o,v); myPCSet.Copy(w_o,w); // Compute right hand sides GetRHS(myPCSet,modelparamPCs(0).GetArrayPointer(),modelparamPCs(1).GetArrayPointer(),modelparamPCs(2).GetArrayPointer(),u.GetArrayPointer(),v.GetArrayPointer(),w.GetArrayPointer(),dudt.GetArrayPointer(),dvdt.GetArrayPointer(),dwdt.GetArrayPointer()); // Advance u, v, w to mid-point myPCSet.Multiply(dudt,0.5*dTym,tmp_u); // 0.5*dTym*dudt myPCSet.Multiply(dvdt,0.5*dTym,tmp_v); // 0.5*dTym*dvdt myPCSet.Multiply(dwdt,0.5*dTym,tmp_w); // 0.5*dTym*dwdt myPCSet.Add(u_o,tmp_u,u); // u = u_o + 0.5*dTym*dudt myPCSet.Add(v_o,tmp_v,v); // v = v_o + 0.5*dTym*dvdt myPCSet.Add(w_o,tmp_w,w); // w = w_o + 0.5*dTym*dwdt // Compute z = 1 - u - v - w z=one; myPCSet.SubtractInPlace(z,u); myPCSet.SubtractInPlace(z,v); myPCSet.SubtractInPlace(z,w); // Compute right hand sides GetRHS(myPCSet,modelparamPCs(0).GetArrayPointer(),modelparamPCs(1).GetArrayPointer(),modelparamPCs(2).GetArrayPointer(),u.GetArrayPointer(),v.GetArrayPointer(),w.GetArrayPointer(),dudt.GetArrayPointer(),dvdt.GetArrayPointer(),dwdt.GetArrayPointer()); // Advance u, v, w to next time step myPCSet.Multiply(dudt,dTym,tmp_u); // dTym*dudt myPCSet.Multiply(dvdt,dTym,tmp_v); // dTym*dvdt myPCSet.Multiply(dwdt,dTym,tmp_w); // dTym*dwdt myPCSet.Add(u_o,tmp_u,u); // u = u_o + dTym*dudt myPCSet.Add(v_o,tmp_v,v); // v = v_o + dTym*dvdt myPCSet.Add(w_o,tmp_w,w); // w = w_o + dTym*dwdt // Compute z = 1 - u - v - w z=one; myPCSet.SubtractInPlace(z,u); myPCSet.SubtractInPlace(z,v); myPCSet.SubtractInPlace(z,w); // Advance time and step counter tym += dTym; step+=1; // write time, u, v, w (all modes) to file if(step % outPrint->fdumpInt == 0){ WriteModesToFilePtr(tym, u.GetArrayPointer(), v.GetArrayPointer(), w.GetArrayPointer(), nPCTerms, modes_dump); } // Get standard deviations uStDv = myPCSet.StDv(u); vStDv = myPCSet.StDv(v); wStDv = myPCSet.StDv(w); // write u, v, w (mean and standard deviation) to file if(step % outPrint->fdumpInt == 0){ WriteMeanStdDevToFilePtr(tym, u(0), v(0), w(0), uStDv, vStDv, wStDv, f_dump); } // write u, v, w (mean and standard deviation) to screen if(step % outPrint->dumpInt == 0){ WriteMeanStdDevToStdOut(step, tym, u(0), v(0), w(0), uStDv, vStDv, wStDv); } } // Close output file if(fclose(f_dump)){ printf("Could not close file '%s'\n",outPrint->dumpfile.c_str()); exit(1); } // Close output file if(fclose(modes_dump)){ printf("Could not close file '%s'\n",modes_dumpfile.c_str()); exit(1); } return 0; }
void convert::force(int nn,double D,double rho,double Cd,double Cm){ // Define Pi // const double PI = 4.0*atan(1.0); // To cover-up for previous lazyness are we now making local // copies of the fields we need - sorry! // std::vector<double> tmp_; tmp_.resize(nt); for (int i=0;i<nt;i++){ tmp_[i] = eta[i*nx*ny+nn]; } // deta/dt // std::vector<double> detadt; detadt.resize(nt); gradient(detadt,tmp_,dt,nt); // dz/dt // Double2d dzdt(boost::extents[nz][nt]); for (int k=0;k<nz;k++){ for (int i=0;i<nt;i++){ dzdt[k][i] = detadt[i]*sigma[k]; } } // du/dt on the sigma grid // Double2d dudt(boost::extents[nz][nt]); for (int k=0;k<nz;k++){ for (int i=0;i<nt;i++){ tmp_[i] = u[i*nx*ny*nz+nn*nz+k]; } gradient(&dudt[k][0],tmp_,dt,nt); // To-do: this is super sluppy and error prone } // Acceleration // Double2d acc(boost::extents[nz][nt]); for (int k=0;k<nz;k++){ for (int i=0;i<nt;i++){ acc[k][i] = dudt[k][i]-uz[i*nx*ny*nz+nn*nz+k]*dzdt[k][i]; } } // The inline force // double dz,Fd,Fi; int index; F.resize(nt); for (int i=0;i<nt;i++){ F[i] = 0; for (int k=1;k<nz-1;k++){// we ignore the ghost points index = i*nx*ny*nz+nn*nz+k; dz = (sigma[k+1]-sigma[k])*(eta[i*nx*ny+nn]+h[nn]); Fd = 0.5*rho*Cd*D*(u[index]*std::abs(u[index])+u[index+1]*std::abs(u[index+1]))/2; Fi = rho*Cm*(PI/4)*pow(D,2)*(acc[k][i]+acc[k+1][i])/2; F[i] += (Fd+Fi)*dz; } } QFileInfo fileInfo = QFileInfo(fileName); std::ofstream morisonForce; morisonForce.open(fileInfo.baseName().toLatin1() + ".force"); morisonForce << "time F" << std::endl; QVector<double> QV_t,QV_F; QV_t.resize(nt); QV_F.resize(nt); for (int i=1;i<nt-1;i++){ morisonForce << std::setiosflags(std::ios::fixed) << std::setprecision(10) << t[i] << " " << F[i] << std::endl; QV_t[i] = t[i]; QV_F[i] = F[i]; } morisonForce.close(); // plot solution QCustomPlot *cPlot = new QCustomPlot; QWidget *plotWindow = new QWidget; QHBoxLayout *plotWindow_layout = new QHBoxLayout; plotWindow_layout->addWidget(cPlot); plotWindow->setLayout(plotWindow_layout); plotWindow->resize(800,400); plotWindow->show(); cPlot->clearGraphs(); cPlot->addGraph(); cPlot->graph()->setData(QV_t,QV_F); cPlot->xAxis->setLabel("Time, t s"); cPlot->yAxis->setLabel("Inline force, F N"); QVector<double>::iterator Xmin = std::min_element(QV_t.begin(), QV_t.end()); QVector<double>::iterator Xmax = std::max_element(QV_t.begin(), QV_t.end()); QVector<double>::iterator Ymin = std::min_element(QV_F.begin(), QV_F.end()); QVector<double>::iterator Ymax = std::max_element(QV_F.begin(), QV_F.end()); cPlot->xAxis->setRange(*Xmin,*Xmax); cPlot->yAxis->setRange(*Ymin,*Ymax); cPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables); cPlot->replot(); }