void TestVerifyBoundaryCondition2d() throw(Exception) { // Create a cell population CylindricalHoneycombMeshGenerator generator(4, 4, 0, 1.0); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true); MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices); // Store the node locations std::map<Node<2>*, c_vector<double, 2> > node_locations_before; for (unsigned node_index=0; node_index<p_mesh->GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } // Now move the first cell (which should be on y=0) down a bit crypt.GetNode(0)->rGetModifiableLocation()[1] = -0.1; // Create a boundary condition object CryptSimulationBoundaryCondition<2> boundary_condition(&crypt); // Before imposing the boundary condition, it should not be satisfied TS_ASSERT_EQUALS(boundary_condition.VerifyBoundaryCondition(), false); boundary_condition.ImposeBoundaryCondition(node_locations_before); // After imposing the boundary condition, it should be satisfied TS_ASSERT_EQUALS(boundary_condition.VerifyBoundaryCondition(), true); }
void TestImposeBoundaryConditionWithNoWnt1d() throw(Exception) { // Create 1D cell population unsigned num_cells = 5; MutableMesh<1,1> mesh; mesh.ConstructLinearMesh(num_cells-1); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); MeshBasedCellPopulation<1> crypt(mesh, cells); // Store the node locations std::map<Node<1>*, c_vector<double, 1> > node_locations_before; for (unsigned node_index=0; node_index<mesh.GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } // Now move the first cell (which should be on x=0, and a stem cell) to the left a bit AbstractCellPopulation<1>::Iterator cell_iter = crypt.Begin(); // Check is a stem cell TS_ASSERT_EQUALS(cell_iter->GetCellProliferativeType()->IsType<StemCellProliferativeType>(), true); // Check initially at x=0 TS_ASSERT_DELTA(crypt.GetLocationOfCellCentre(*cell_iter)[0], 0.0, 1e-6); // Now move to the left a bit crypt.GetNode(0)->rGetModifiableLocation()[0] = -0.1; TS_ASSERT_LESS_THAN(crypt.GetLocationOfCellCentre(*cell_iter)[0], 0.0); // Pass this cell population to a boundary condition object CryptSimulationBoundaryCondition<1> boundary_condition(&crypt); // Impose the boundary condition without a Wnt stimulus boundary_condition.ImposeBoundaryCondition(node_locations_before); /* * The first cell should have been pulled back to x=0 since it is a stem cell and * there is no Wnt stimulus. It should be unaffected by jiggling, which is not imposed * in 1D. */ TS_ASSERT_DELTA(0.0, crypt.GetLocationOfCellCentre(*cell_iter)[0], 1e-3); // The nodes should all now be at their original locations std::map<Node<1>*, c_vector<double, 1> > node_locations_after; for (unsigned node_index=0; node_index<mesh.GetNumNodes(); node_index++) { node_locations_after[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } for (unsigned node_index=0; node_index<mesh.GetNumNodes(); node_index++) { TS_ASSERT_DELTA(node_locations_before[crypt.GetNode(node_index)](0), node_locations_after[crypt.GetNode(node_index)](0), 1e-3); } }
void TestImposeBoundaryConditionWithNoWntButWithJiggling() throw(Exception) { // Create a cell population CylindricalHoneycombMeshGenerator generator(4, 4, 0, 1.0); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; MAKE_PTR(TransitCellProliferativeType, p_transit_type); CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true); MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices); // Store the node locations std::map<Node<2>*, c_vector<double, 2> > node_locations_before; for (unsigned node_index=0; node_index<p_mesh->GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } // Move the first cell (which should be on y=0, and is a stem cell) down a bit AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); crypt.GetNode(0)->rGetModifiableLocation()[1] = -0.1; // Also move the second cell (which should be on y=0, and we make a transit cell) ++cell_iter; TS_ASSERT_EQUALS(cell_iter->GetCellProliferativeType()->IsType<StemCellProliferativeType>(), true); cell_iter->SetCellProliferativeType(p_transit_type); TS_ASSERT_EQUALS(cell_iter->GetCellProliferativeType()->IsType<TransitCellProliferativeType>(), true); TS_ASSERT_DELTA(crypt.GetLocationOfCellCentre(*cell_iter)[1], 0.0, 1e-6); crypt.GetNode(1)->rGetModifiableLocation()[1] = -0.1; TS_ASSERT_LESS_THAN(crypt.GetLocationOfCellCentre(*cell_iter)[1], 0.0); // Create a boundary condition object CryptSimulationBoundaryCondition<2> boundary_condition(&crypt); boundary_condition.SetUseJiggledBottomCells(true); // Impose the boundary condition without a Wnt stimulus but with jiggled bottom cells boundary_condition.ImposeBoundaryCondition(node_locations_before); /* * The first cell should have been pulled up to y=0 since it is a stem cell and * there is no Wnt stimulus. It should then be unaffected by the jiggling. The * second cell should not have been pulled up since it is a stem cell, but should * then have been moved to above y=0 by the jiggling. */ AbstractCellPopulation<2>::Iterator cell_iter2 = crypt.Begin(); TS_ASSERT_DELTA(0.0, crypt.GetLocationOfCellCentre(*cell_iter2)[1], 1e-3); ++cell_iter2; TS_ASSERT_LESS_THAN(0.0, crypt.GetLocationOfCellCentre(*cell_iter2)[1]); }
void TestImposeBoundaryConditionWithWntButNoJiggling() throw(Exception) { // Create a cell population CylindricalHoneycombMeshGenerator generator(4, 4, 0, 1.0); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true); MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices); // Store the node locations std::map<Node<2>*, c_vector<double, 2> > node_locations_before; for (unsigned node_index=0; node_index<p_mesh->GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } // Move the first cell (which should be on y=0) down a bit AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); crypt.GetNode(0)->rGetModifiableLocation()[1] = -0.1; c_vector<double, 2> perturbed_location = crypt.GetLocationOfCellCentre(*cell_iter); // Create a boundary condition object CryptSimulationBoundaryCondition<2> boundary_condition(&crypt); boundary_condition.SetUseJiggledBottomCells(false); // Set up a WntConcentration singleton object WntConcentration<2>* p_wnt = WntConcentration<2>::Instance(); WntConcentration<2>::Instance()->SetType(LINEAR); WntConcentration<2>::Instance()->SetCellPopulation(crypt); WntConcentration<2>::Instance()->SetCryptLength(crypt.GetWidth(1)); TS_ASSERT_EQUALS(p_wnt->IsWntSetUp(), true); // Impose the boundary condition with a Wnt stimulus but without jiggled bottom cells boundary_condition.ImposeBoundaryCondition(node_locations_before); /* * The first cell should not have been moved by the boundary condition object, * and hence should remain in its perturbed location. */ c_vector<double, 2> location_after = crypt.GetLocationOfCellCentre(*cell_iter); TS_ASSERT_DELTA(location_after[0], perturbed_location[0], 1e-3); TS_ASSERT_DELTA(location_after[1], location_after[1], 1e-3); // Tidy up WntConcentration<2>::Destroy(); }
void TestImposeBoundaryConditionWithNoWntOrJiggling2d() throw(Exception) { // Create a cell population CylindricalHoneycombMeshGenerator generator(4, 4, 0, 1.0); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true); MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices); // Store the node locations std::map<Node<2>*, c_vector<double, 2> > node_locations_before; for (unsigned node_index=0; node_index<p_mesh->GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } // Now move the first cell (which should be on y=0) down a bit AbstractCellPopulation<2>::Iterator cell_iter = crypt.Begin(); TS_ASSERT_DELTA(crypt.GetLocationOfCellCentre(*cell_iter)[1], 0.0, 1e-6); crypt.GetNode(0)->rGetModifiableLocation()[1] = -0.1; TS_ASSERT_LESS_THAN(crypt.GetLocationOfCellCentre(*cell_iter)[1], 0.0); // Create a boundary condition object CryptSimulationBoundaryCondition<2> boundary_condition(&crypt); boundary_condition.SetUseJiggledBottomCells(false); // Impose the boundary condition without a Wnt stimulus or jiggled bottom cells boundary_condition.ImposeBoundaryCondition(node_locations_before); // The first cell should have been moved back by the boundary condition object TS_ASSERT_DELTA(crypt.GetLocationOfCellCentre(*cell_iter)[1], 0.0, 1e-4); // The nodes should all now be at their original locations std::map<Node<2>*, c_vector<double, 2> > node_locations_after; for (unsigned node_index=0; node_index<p_mesh->GetNumNodes(); node_index++) { node_locations_after[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } for (unsigned node_index=0; node_index<p_mesh->GetNumNodes(); node_index++) { TS_ASSERT_DELTA(node_locations_before[crypt.GetNode(node_index)](0), node_locations_after[crypt.GetNode(node_index)](0), 1e-3); TS_ASSERT_DELTA(node_locations_before[crypt.GetNode(node_index)](1), node_locations_after[crypt.GetNode(node_index)](1), 1e-3); } }
void TestImposeBoundaryConditionWithWnt1d() throw(Exception) { // Create 1D cell population unsigned num_cells = 5; MutableMesh<1,1> mesh; mesh.ConstructLinearMesh(num_cells-1); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); MeshBasedCellPopulation<1> crypt(mesh, cells); // Set up a WntConcentration singleton object WntConcentration<1>* p_wnt = WntConcentration<1>::Instance(); WntConcentration<1>::Instance()->SetType(LINEAR); WntConcentration<1>::Instance()->SetCellPopulation(crypt); WntConcentration<1>::Instance()->SetCryptLength(crypt.GetWidth(0)); TS_ASSERT_EQUALS(p_wnt->IsWntSetUp(), true); // Store the node locations std::map<Node<1>*, c_vector<double, 1> > node_locations_before; for (unsigned node_index=0; node_index<mesh.GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } // Now move the first cell (which should be on x=0) to the left a bit AbstractCellPopulation<1>::Iterator cell_iter = crypt.Begin(); // Check initially at x=0 TS_ASSERT_DELTA(crypt.GetLocationOfCellCentre(*cell_iter)[0], 0.0, 1e-6); // Now move to the left a bit crypt.GetNode(0)->rGetModifiableLocation()[0] = -0.1; TS_ASSERT_DELTA(-0.1, crypt.GetLocationOfCellCentre(*cell_iter)[0], 1e-3); // Pass this cell population to a boundary condition object CryptSimulationBoundaryCondition<1> boundary_condition(&crypt); // Impose the boundary condition with a Wnt stimulus boundary_condition.ImposeBoundaryCondition(node_locations_before); // This node will be moved back to 0.0 TS_ASSERT_DELTA(0.0, crypt.GetLocationOfCellCentre(*cell_iter)[0], 1e-3); // Tidy up WntConcentration<1>::Destroy(); }
void TestConstructorWithCellPopulation2d() throw (Exception) { // Create a 2d mesh-based cell population CylindricalHoneycombMeshGenerator generator(4, 4, 0, 1.0); Cylindrical2dMesh* p_mesh = generator.GetCylindricalMesh(); std::vector<unsigned> location_indices = generator.GetCellLocationIndices(); std::vector<CellPtr> cells; CryptCellsGenerator<FixedDurationGenerationBasedCellCycleModel> cells_generator; cells_generator.Generate(cells, p_mesh, std::vector<unsigned>(), true); MeshBasedCellPopulationWithGhostNodes<2> crypt(*p_mesh, cells, location_indices); // Pass this cell population to a boundary condition object CryptSimulationBoundaryCondition<2> boundary_condition(&crypt); // Test access to the cell population const AbstractCellPopulation<2>* p_population = boundary_condition.GetCellPopulation(); TS_ASSERT(p_population != NULL); }
void TestVerifyBoundaryCondition1d() throw(Exception) { // Create 1D cell population unsigned num_cells = 5; MutableMesh<1,1> mesh; mesh.ConstructLinearMesh(num_cells-1); std::vector<CellPtr> cells; CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator; cells_generator.GenerateBasic(cells, mesh.GetNumNodes()); MeshBasedCellPopulation<1> crypt(mesh, cells); // Set up a WntConcentration singleton object WntConcentration<1>* p_wnt = WntConcentration<1>::Instance(); WntConcentration<1>::Instance()->SetType(LINEAR); WntConcentration<1>::Instance()->SetCellPopulation(crypt); WntConcentration<1>::Instance()->SetCryptLength(crypt.GetWidth(0)); TS_ASSERT_EQUALS(p_wnt->IsWntSetUp(), true); // Store the node locations std::map<Node<1>*, c_vector<double, 1> > node_locations_before; for (unsigned node_index=0; node_index<mesh.GetNumNodes(); node_index++) { node_locations_before[crypt.GetNode(node_index)] = crypt.GetNode(node_index)->rGetLocation(); } crypt.GetNode(0)->rGetModifiableLocation()[0] = -0.1; // Create a boundary condition object CryptSimulationBoundaryCondition<1> boundary_condition(&crypt); // Before imposing the boundary condition, it should not be satisfied TS_ASSERT_EQUALS(boundary_condition.VerifyBoundaryCondition(), false); boundary_condition.ImposeBoundaryCondition(node_locations_before); // After imposing the boundary condition, it should be satisfied TS_ASSERT_EQUALS(boundary_condition.VerifyBoundaryCondition(), true); }
void TestOutputParameters2d() throw(Exception) { std::string output_directory = "TestOutputParameters2d"; OutputFileHandler output_file_handler(output_directory, false); CryptSimulationBoundaryCondition<2> boundary_condition(NULL); TS_ASSERT_EQUALS(boundary_condition.GetIdentifier(), "CryptSimulationBoundaryCondition-2"); out_stream boundary_condition_parameter_file = output_file_handler.OpenOutputFile("results2d.parameters"); boundary_condition.OutputCellPopulationBoundaryConditionParameters(boundary_condition_parameter_file); boundary_condition_parameter_file->close(); std::string boundary_condition_results_dir = output_file_handler.GetOutputDirectoryFullPath(); FileComparison( boundary_condition_results_dir + "results2d.parameters", "crypt/test/data/TestCryptSimulationBoundaryCondition/results2d.parameters").CompareFiles(); // Test OutputCellPopulationBoundaryConditionInfo() method out_stream boundary_condition_info_file = output_file_handler.OpenOutputFile("results2d.info"); boundary_condition.OutputCellPopulationBoundaryConditionInfo(boundary_condition_info_file); boundary_condition_info_file->close(); FileComparison( boundary_condition_results_dir + "results2d.info", "crypt/test/data/TestCryptSimulationBoundaryCondition/results2d.info").CompareFiles(); }
void TestArchiving2d() throw (Exception) { // Set up singleton classes OutputFileHandler handler("archive", false); // don't erase contents of folder std::string archive_filename = handler.GetOutputDirectoryFullPath() + "CryptSimulationBoundaryCondition2.arch"; { // Create an output archive CryptSimulationBoundaryCondition<2> boundary_condition(NULL); boundary_condition.SetUseJiggledBottomCells(true); std::ofstream ofs(archive_filename.c_str()); boost::archive::text_oarchive output_arch(ofs); // Serialize via pointer AbstractCellPopulationBoundaryCondition<2>* const p_boundary_condition = &boundary_condition; output_arch << p_boundary_condition; } { // Create an input archive std::ifstream ifs(archive_filename.c_str(), std::ios::binary); boost::archive::text_iarchive input_arch(ifs); AbstractCellPopulationBoundaryCondition<2>* p_boundary_condition; // Restore from the archive input_arch >> p_boundary_condition; // Test we have restored the plane geometry correctly TS_ASSERT_EQUALS(static_cast<CryptSimulationBoundaryCondition<2>*>(p_boundary_condition)->GetUseJiggledBottomCells(), true); // Tidy up delete p_boundary_condition; } }
void update ( int id, int p ) /******************************************************************************/ /* Purpose: UPDATE computes the solution of the heat equation. Discussion: If there is only one processor ( P == 1 ), then the program writes the values of X and H to files. Parameters: Input, int ID, the id of this processor. Input, int P, the number of processors. */ { double cfl; double *h; FILE *h_file; double *h_new; int i; int j; int j_min = 0; int j_max = 400; double k = 0.002; int n = 11; MPI_Status status; int tag; double time; double time_delta; double time_max = 10.0; double time_min = 0.0; double time_new; double *x; double x_delta; FILE *x_file; double x_max = 1.0; double x_min = 0.0; /* Have process 0 print out some information. */ if ( id == 0 ) { printf ( "\n" ); printf ( " Compute an approximate solution to the time dependent\n" ); printf ( " one dimensional heat equation:\n" ); printf ( "\n" ); printf ( " dH/dt - K * d2H/dx2 = f(x,t)\n" ); printf ( "\n" ); printf ( " for %f = x_min < x < x_max = %f\n", x_min, x_max ); printf ( "\n" ); printf ( " and %f = time_min < t <= t_max = %f\n", time_min, time_max ); printf ( "\n" ); printf ( " Boundary conditions are specified at x_min and x_max.\n" ); printf ( " Initial conditions are specified at time_min.\n" ); printf ( "\n" ); printf ( " The finite difference method is used to discretize the\n" ); printf ( " differential equation.\n" ); printf ( "\n" ); printf ( " This uses %d equally spaced points in X\n", p * n ); printf ( " and %d equally spaced points in time.\n", j_max ); printf ( "\n" ); printf ( " Parallel execution is done using %d processors.\n", p ); printf ( " Domain decomposition is used.\n" ); printf ( " Each processor works on %d nodes, \n", n ); printf ( " and shares some information with its immediate neighbors.\n" ); } /* Set the X coordinates of the N nodes. We don't actually need ghost values of X but we'll throw them in as X[0] and X[N+1]. */ x = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) ); for ( i = 0; i <= n + 1; i++ ) { x[i] = ( ( double ) ( id * n + i - 1 ) * x_max + ( double ) ( p * n - id * n - i ) * x_min ) / ( double ) ( p * n - 1 ); } /* In single processor mode, write out the X coordinates for display. */ if ( p == 1 ) { x_file = fopen ( "x_data.txt", "w" ); for ( i = 1; i <= n; i++ ) { fprintf ( x_file, " %f", x[i] ); } fprintf ( x_file, "\n" ); fclose ( x_file ); } /* Set the values of H at the initial time. */ time = time_min; h = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) ); h_new = ( double * ) malloc ( ( n + 2 ) * sizeof ( double ) ); h[0] = 0.0; for ( i = 1; i <= n; i++ ) { h[i] = initial_condition ( x[i], time ); } h[n+1] = 0.0; time_delta = ( time_max - time_min ) / ( double ) ( j_max - j_min ); x_delta = ( x_max - x_min ) / ( double ) ( p * n - 1 ); /* Check the CFL condition, have processor 0 print out its value, and quit if it is too large. */ cfl = k * time_delta / x_delta / x_delta; if ( id == 0 ) { printf ( "\n" ); printf ( "UPDATE\n" ); printf ( " CFL stability criterion value = %f\n", cfl ); } if ( 0.5 <= cfl ) { if ( id == 0 ) { printf ( "\n" ); printf ( "UPDATE - Warning!\n" ); printf ( " Computation cancelled!\n" ); printf ( " CFL condition failed.\n" ); printf ( " 0.5 <= K * dT / dX / dX = %f\n", cfl ); } return; } /* In single processor mode, write out the values of H. */ if ( p == 1 ) { h_file = fopen ( "h_data.txt", "w" ); for ( i = 1; i <= n; i++ ) { fprintf ( h_file, " %f", h[i] ); } fprintf ( h_file, "\n" ); } /* Compute the values of H at the next time, based on current data. */ for ( j = 1; j <= j_max; j++ ) { time_new = ( ( double ) ( j - j_min ) * time_max + ( double ) ( j_max - j ) * time_min ) / ( double ) ( j_max - j_min ); /* Send H[1] to ID-1. */ if ( 0 < id ) { tag = 1; MPI_Send ( &h[1], 1, MPI_DOUBLE, id-1, tag, MPI_COMM_WORLD ); } /* Receive H[N+1] from ID+1. */ if ( id < p-1 ) { tag = 1; MPI_Recv ( &h[n+1], 1, MPI_DOUBLE, id+1, tag, MPI_COMM_WORLD, &status ); } /* Send H[N] to ID+1. */ if ( id < p-1 ) { tag = 2; MPI_Send ( &h[n], 1, MPI_DOUBLE, id+1, tag, MPI_COMM_WORLD ); } /* Receive H[0] from ID-1. */ if ( 0 < id ) { tag = 2; MPI_Recv ( &h[0], 1, MPI_DOUBLE, id-1, tag, MPI_COMM_WORLD, &status ); } /* Update the temperature based on the four point stencil. */ for ( i = 1; i <= n; i++ ) { h_new[i] = h[i] + ( time_delta * k / x_delta / x_delta ) * ( h[i-1] - 2.0 * h[i] + h[i+1] ) + time_delta * rhs ( x[i], time ); } /* H at the extreme left and right boundaries was incorrectly computed using the differential equation. Replace that calculation by the boundary conditions. */ if ( 0 == id ) { h_new[1] = boundary_condition ( x[1], time_new ); } if ( id == p - 1 ) { h_new[n] = boundary_condition ( x[n], time_new ); } /* Update time and temperature. */ time = time_new; for ( i = 1; i <= n; i++ ) { h[i] = h_new[i]; } /* In single processor mode, add current solution data to output file. */ if ( p == 1 ) { for ( i = 1; i <= n; i++ ) { fprintf ( h_file, " %f", h[i] ); } fprintf ( h_file, "\n" ); } } if ( p == 1 ) { fclose ( h_file ); } free ( h ); free ( h_new ); free ( x ); return; }
//--------------------------------------------------------- int main(int argc, char **argv) { TPS<double> rbf; Polinomio<double> pol; Matrix<double> A,B; Vector<double> x,y,f; Vector<double> lambda,b; Vector<double> xnew,ynew,fnew; double c=0.01; int n,ni,m; //make the data in the square [0,1] x [0,1] make_data(0,1,0,1, 21, 21, x, y, ni, n); //stablish the exponent in: r^beta log(r) rbf.set_beta(4); //configure the associate polynomial // pol.make( data_dimension, degree_pol) pol.make(2 , rbf.get_degree_pol()); //show the rbf and pol info cout<<rbf; cout<<pol; //show the number of nodes cout<<endl; cout<<"total nodes N = "<<n<<endl; cout<<"interior nodes ni = "<<ni<<endl; cout<<"boundary nodes nf = "<<n-ni<<endl; cout<<endl; //get the number of elements in the polynomial base m = pol.get_M(); //resize the matrices to store the partial derivatives A.Resize(n+m,n+m); A = 0.0; B.Resize(n+m,n+m); B = 0.0; //Recall that this problem has the general form // (Uxx+Uyy) (Pxx+Pyy) = f interior nodes 0..ni // U P_b = g boundary nodes ni..n // P^transpose 0 = 0 momentun conditions in P // // P is the polynomial wit size n x m // P_b is the polynomial working in the boundary nodes, size nf x m // Pxx+Pyy has size ni x m //make the matriz derivatives fill_matrix( "dxx" , rbf , pol , c , x , y, 0 , ni , A); fill_matrix( "dyy" , rbf , pol , c , x , y, 0 , ni , B); A = A + B; // A <- Uxx + Uyy //Add the submatriz for the boundary nodes: U , P_b boundary nodes ni..n fill_matrix( "normal" , rbf , pol , c , x , y, ni, n , A); //Add the submatriz P^transpose at the end: P^transpose fill_matrix( "pol_trans" , rbf , pol , c , x , y, n , n+m, A); //resize the vector to store the right_size of the PDE b.Resize(n+m); b = 0.0; //fill with f for(int i=0;i<ni;i++) b(i) = right_side(x(i), y(i)); //fill with the boundary condition for(int i=ni;i<n;i++) b(i) = boundary_condition(x(i),y(i)); //solve the linear system of equations lambda = gauss(A,b); //make the new data grid int ni2,n2; make_data(0,1,0,1, 41, 41, xnew, ynew, ni2, n2); //interpolate on this new data grid (xnew,ynew) fnew = interpolate(rbf,pol,c,lambda,x,y,xnew,ynew); //determine the maximum error double e=0.0; for(int i=0;i<ni2;i++) { e = max(e, fabs(fnew(i) - sin(2*M_PI*xnew(i))*cos(2*M_PI*ynew(i))) ); } //show the error cout<<endl; cout<<"The maximum error: e_max = "<<e<<endl<<endl; //store the interpolated data save_gnu_data("data",xnew,ynew,fnew); return 0; }