void TestNonlinearEquationPde() { ChastePoint<1> zero1(0); ChastePoint<2> zero2(0,0); ChastePoint<3> zero3(0,0,0); double u = 2.0; NonlinearEquationPde<1> heat_equation1; NonlinearEquationPde<2> heat_equation2; NonlinearEquationPde<3> heat_equation3; TS_ASSERT_DELTA(heat_equation1.ComputeNonlinearSourceTerm(zero1,u),0.0,1e-12); TS_ASSERT_DELTA(heat_equation2.ComputeNonlinearSourceTerm(zero2,u),0.0,1e-12); TS_ASSERT_DELTA(heat_equation3.ComputeNonlinearSourceTerm(zero3,u),0.0,1e-12); // Diffusion matrices should be equal to identity * u; c_matrix<double, 1, 1> diff1 = heat_equation1.ComputeDiffusionTerm(zero1,u); c_matrix<double, 2, 2> diff2 = heat_equation2.ComputeDiffusionTerm(zero2,u); c_matrix<double, 3, 3> diff3 = heat_equation3.ComputeDiffusionTerm(zero3,u); TS_ASSERT_DELTA(diff1(0,0),u,1e-12); TS_ASSERT_DELTA(diff2(0,0),u,1e-12); TS_ASSERT_DELTA(diff2(1,1),u,1e-12); TS_ASSERT_DELTA(diff2(0,1),0,1e-12); TS_ASSERT_DELTA(diff3(0,0),u,1e-12); TS_ASSERT_DELTA(diff3(1,1),u,1e-12); TS_ASSERT_DELTA(diff3(2,2),u,1e-12); TS_ASSERT_DELTA(diff3(0,1),0,1e-12); TS_ASSERT_DELTA(diff3(0,2),0,1e-12); TS_ASSERT_DELTA(diff3(1,2),0,1e-12); }
TEST(VectorTest, Normalize) { Point p(3, -4, 0); const Point p1(3.0/5, -4.0/5, 0); EXPECT_EQ( &p, &( p.normalize() ) ); // It actually returns point itself EXPECT_EQ( p1, p ); // Test normalizing when norm is 0 Point zero1(0, 0, 0); const Point zero2(0, 0, 0); suppress_warnings(); zero1.normalize(); unsuppress_warnings(); EXPECT_EQ( zero2, zero1 ); }
void TestHeatEquation() { ChastePoint<1> zero1(0); ChastePoint<2> zero2(0,0); ChastePoint<3> zero3(0,0,0); double u = 2.0; HeatEquation<1> pde1; HeatEquation<2> pde2; HeatEquation<3> pde3; TS_ASSERT_DELTA(pde1.ComputeSourceTerm(zero1,u), 0.0, 1e-12); TS_ASSERT_DELTA(pde2.ComputeSourceTerm(zero2,u), 0.0, 1e-12); TS_ASSERT_DELTA(pde3.ComputeSourceTerm(zero3,u), 0.0, 1e-12); TS_ASSERT_DELTA(pde1.ComputeDuDtCoefficientFunction(zero1), 1.0, 1e-12); TS_ASSERT_DELTA(pde2.ComputeDuDtCoefficientFunction(zero2), 1.0, 1e-12); TS_ASSERT_DELTA(pde3.ComputeDuDtCoefficientFunction(zero3), 1.0, 1e-12); // Diffusion matrices should be equal to identity c_matrix<double, 1, 1> diff1 = pde1.ComputeDiffusionTerm(zero1); c_matrix<double, 2, 2> diff2 = pde2.ComputeDiffusionTerm(zero2); c_matrix<double, 3, 3> diff3 = pde3.ComputeDiffusionTerm(zero3); TS_ASSERT_DELTA(diff1(0,0), 1, 1e-12); TS_ASSERT_DELTA(diff2(0,0), 1, 1e-12); TS_ASSERT_DELTA(diff2(1,1), 1, 1e-12); TS_ASSERT_DELTA(diff2(0,1), 0, 1e-12); TS_ASSERT_DELTA(diff3(0,0), 1, 1e-12); TS_ASSERT_DELTA(diff3(1,1), 1, 1e-12); TS_ASSERT_DELTA(diff3(2,2), 1, 1e-12); TS_ASSERT_DELTA(diff3(0,1), 0, 1e-12); TS_ASSERT_DELTA(diff3(0,2), 0, 1e-12); TS_ASSERT_DELTA(diff3(1,2), 0, 1e-12); Node<1> node(0, zero1); TS_ASSERT_DELTA(pde1.ComputeSourceTermAtNode(node,u), 0.0, 1e-12); }
void TestHeatEquationWithElementDependentSourceTerm() { // The PDE is set to give elements with index = 0 a source of zero // and a source of 1 otherwise. std::vector<Node<1>*> one_d_nodes; one_d_nodes.push_back(new Node<1>(0, false, 2.0)); one_d_nodes.push_back(new Node<1>(1, false, 2.5)); Element<1,1> one_d_element(0u, one_d_nodes); ChastePoint<1> zero1(0); std::vector<Node<2>*> two_d_nodes; two_d_nodes.push_back(new Node<2>(0, false, 0.0, 0.0)); two_d_nodes.push_back(new Node<2>(1, false, 1.0, 0.0)); two_d_nodes.push_back(new Node<2>(2, false, 0.0, 1.0)); Element<2,2> two_d_element(0u, two_d_nodes); ChastePoint<2> zero2(0,0); std::vector<Node<3>*> three_d_nodes; three_d_nodes.push_back(new Node<3>(0, false, 0.0, 0.0, 0.0)); three_d_nodes.push_back(new Node<3>(1, false, 1.0, 0.0, 0.0)); three_d_nodes.push_back(new Node<3>(2, false, 0.0, 1.0, 0.0)); three_d_nodes.push_back(new Node<3>(3, false, 0.0, 0.0, 1.0)); Element<3,3> three_d_element(0u, three_d_nodes); ChastePoint<3> zero3(0,0,0); double u = 2.0; HeatEquationWithElementDependentSourceTerm<1> pde1; HeatEquationWithElementDependentSourceTerm<2> pde2; HeatEquationWithElementDependentSourceTerm<3> pde3; TS_ASSERT_DELTA(pde1.ComputeSourceTerm(zero1, u, &one_d_element), 0.0, 1e-12); one_d_element.ResetIndex(1u); TS_ASSERT_DELTA(pde1.ComputeSourceTerm(zero1, u, &one_d_element), 1.0, 1e-12); TS_ASSERT_DELTA(pde2.ComputeSourceTerm(zero2, u, &two_d_element), 0.0, 1e-12); two_d_element.ResetIndex(1u); TS_ASSERT_DELTA(pde2.ComputeSourceTerm(zero2, u, &two_d_element), 1.0, 1e-12); TS_ASSERT_DELTA(pde3.ComputeSourceTerm(zero3, u, &three_d_element), 0.0, 1e-12); three_d_element.ResetIndex(1u); TS_ASSERT_DELTA(pde3.ComputeSourceTerm(zero3, u, &three_d_element), 1.0, 1e-12); TS_ASSERT_DELTA(pde1.ComputeDuDtCoefficientFunction(zero1), 1.0, 1e-12); TS_ASSERT_DELTA(pde2.ComputeDuDtCoefficientFunction(zero2), 1.0, 1e-12); TS_ASSERT_DELTA(pde3.ComputeDuDtCoefficientFunction(zero3), 1.0, 1e-12); // Diffusion matrices should be equal to identity c_matrix<double, 1, 1> diff1 = pde1.ComputeDiffusionTerm(zero1); c_matrix<double, 2, 2> diff2 = pde2.ComputeDiffusionTerm(zero2); c_matrix<double, 3, 3> diff3 = pde3.ComputeDiffusionTerm(zero3); TS_ASSERT_DELTA(diff1(0,0), 1, 1e-12); TS_ASSERT_DELTA(diff2(0,0), 1, 1e-12); TS_ASSERT_DELTA(diff2(1,1), 1, 1e-12); TS_ASSERT_DELTA(diff2(0,1), 0, 1e-12); TS_ASSERT_DELTA(diff3(0,0), 1, 1e-12); TS_ASSERT_DELTA(diff3(1,1), 1, 1e-12); TS_ASSERT_DELTA(diff3(2,2), 1, 1e-12); TS_ASSERT_DELTA(diff3(0,1), 0, 1e-12); TS_ASSERT_DELTA(diff3(0,2), 0, 1e-12); TS_ASSERT_DELTA(diff3(1,2), 0, 1e-12); delete one_d_nodes[0]; delete one_d_nodes[1]; delete two_d_nodes[0]; delete two_d_nodes[1]; delete two_d_nodes[2]; delete three_d_nodes[0]; delete three_d_nodes[1]; delete three_d_nodes[2]; delete three_d_nodes[3]; }
int main(int argc, char *argv[]) { bool cmplx, abc, taper; int ix, iz, it, itau, n2, m2; int nx, nz, ntau, nt, pad1, nb, nx2, nz2, nzx2, fnx, fnz, fnzx, nk; float dt, dtau, par, dz, dx, thresh; float tau0, tau; float **lt, **rt; float *curr, *prev; float ***dd, ***mm, **v0; sf_axis ax, az, atau; sf_file tgather, cgather, left, right; int cpuid, numprocs, nth; float *sendbuf, *recvbuf; MPI_Comm comm=MPI_COMM_WORLD; sf_init(argc, argv); MPI_Init(&argc, &argv); MPI_Comm_rank(comm, &cpuid); MPI_Comm_size(comm, &numprocs); #ifdef _OPENMP #pragma omp parallel { nth=omp_get_num_threads(); } sf_warning(">>> Using %d threads <<<", nth); #endif tgather=sf_input("--input"); cgather=sf_output("--output"); left=sf_input("left"); right=sf_input("right"); az=sf_iaxa(tgather, 1); ax=sf_iaxa(tgather, 2); atau=sf_iaxa(tgather, 3); nz=sf_n(az); dz = sf_d(az); nx=sf_n(ax); dx = sf_d(ax); ntau=sf_n(atau); dtau=sf_d(atau); tau0=sf_o(atau); if(cpuid==0){ sf_oaxa(cgather, az, 1); sf_oaxa(cgather, ax, 2); sf_oaxa(cgather, atau, 3); } if(!sf_getfloat("dt", &dt)) dt=0.001; /* time interval */ if(!sf_getint("nb", &nb)) nb=60; /* boundary width */ if(!sf_getfloat("par", &par)) par=0.01; /* absorbing boundary coefficient */ if(!sf_getbool("cmplx", &cmplx)) cmplx=false; /* use complex FFT */ if(!sf_getbool("abc", &abc)) abc=true; /* absorbing boundary condition */ if(!sf_getint("pad1", &pad1)) pad1=1; /* padding factor on the first axis */ if(!sf_getbool("taper", &taper)) taper=true; /* tapering */ if(!sf_getfloat("thresh", &thresh)) thresh=0.92; /* thresholding */ nx2=nx+2*nb; nz2=nz+2*nb; nk=fft2_init(cmplx,pad1,nz2,nx2,&fnz,&fnx); nzx2=nz2*nx2; fnzx=fnz*fnx; if (!sf_histint(left,"n1",&n2) || n2 != nzx2) sf_error("Need n1=%d in left",nzx2); if (!sf_histint(left,"n2",&m2)) sf_error("Need n2= in left"); if (!sf_histint(right,"n1",&n2) || n2 != m2) sf_error("Need n1=%d in right",m2); if (!sf_histint(right,"n2",&n2) || n2 != nk) sf_error("Need n2=%d in right",nk); lt = sf_floatalloc2(nzx2,m2); rt = sf_floatalloc2(m2,nk); sf_floatread(lt[0],nzx2*m2,left); sf_floatread(rt[0],m2*nk,right); dd=sf_floatalloc3(nz, nx, ntau); mm=sf_floatalloc3(nz, nx, ntau); v0=sf_floatalloc2(nz2, nx2); curr=sf_floatalloc(fnzx); prev=sf_floatalloc(fnzx); /* broad cast input time-shift gather */ if(cpuid==0) sf_floatread(dd[0][0], ntau*nx*nz, tgather); for(itau=0; itau<ntau; itau++){ MPI_Bcast(dd[itau][0], nx*nz, MPI_FLOAT, 0, comm); } /* initialize corrected time-shift gather */ #ifdef _OPENMP #pragma omp parallel for private(itau, ix, iz) #endif for(itau=0; itau<ntau; itau++) for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) mm[itau][ix][iz]=0.; /* initialize functions */ lrinit(nx2, nz2, m2, cmplx, pad1, nb, par, abc, lt, rt, taper, thresh, dz, dx); /* tau loop */ for(itau=cpuid; itau<ntau; itau+=numprocs){ sf_warning("itau=%d/%d", itau+1, ntau); tau=tau0+itau*dtau; // tau=0 if(itau==(ntau-1)/2){ for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) mm[itau][ix][iz]=dd[itau][ix][iz]; continue; } // calculate v0 (derivative with respect to tau) zero2(v0, nz2, nx2); if(itau==0){ for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ v0[ix+nb][iz+nb]=(dd[1][ix][iz]-dd[0][ix][iz])/dtau; } } } else if (itau==ntau-1){ for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ v0[ix+nb][iz+nb]=(dd[ntau-1][ix][iz]-dd[ntau-2][ix][iz])/dtau; } } } else { #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ v0[ix+nb][iz+nb]=(dd[itau+1][ix][iz]-dd[itau-1][ix][iz])/dtau/2.0; } } } // calculate u1 zero1(curr, fnzx); zero1(prev, fnzx); #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++) for(iz=0; iz<nz; iz++) curr[(ix+nb)*fnz+iz+nb]=dd[itau][ix][iz]; // tau>0 if(itau>(ntau-1)/2){ // calculate u(t-lt) for (ix=0; ix<nx2; ix++) for (iz=0; iz<nz2; iz++) prev[ix*fnz+iz]=2.*v0[ix][iz]*dt; lrupdate(curr,prev); for (ix=0; ix<fnzx; ix++) curr[ix]=curr[ix]/2.; // it loop nt=tau/dt+0.5; for(it=1; it<nt; it++){ // sf_warning("it=%d/%d;", it+1, nt); lrupdate(curr,prev); } //end of it #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ mm[itau][ix][iz]=curr[(ix+nb)*fnz+iz+nb]; } } } // end of positive tau // tau<0 if(itau<(ntau-1)/2){ //calculate u(t+lt) for (ix=0; ix<nx2; ix++) for(iz=0; iz<nz2; iz++) prev[ix*fnz+iz]=-2.*v0[ix][iz]*dt; lrupdate(curr, prev); for (ix=0; ix<fnzx; ix++) curr[ix]=curr[ix]/2.; // it loop nt=-tau/dt+0.5; for(it=1; it<nt; it++){ //sf_warning("it=%d/%d;", it+1, nt); lrupdate(curr, prev); }//end of it #ifdef _OPENMP #pragma omp parallel for private(ix, iz) #endif for(ix=0; ix<nx; ix++){ for(iz=0; iz<nz; iz++){ mm[itau][ix][iz]=curr[(ix+nb)*fnz+iz+nb]; } } }// end of negative tau } //end of itau MPI_Barrier(comm); /* corrected time-shift gather reduction */ for(itau=0; itau<ntau; itau++){ if(cpuid==0){ sendbuf=MPI_IN_PLACE; recvbuf=mm[itau][0]; }else{ sendbuf=mm[itau][0]; recvbuf=NULL; } MPI_Reduce(sendbuf, recvbuf, nz*nx, MPI_FLOAT, MPI_SUM, 0, comm); } if(cpuid==0) sf_floatwrite(mm[0][0], ntau*nz*nx, cgather); lrclose(); MPI_Finalize(); }