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;
       }
    }
예제 #11
0
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;
}
예제 #12
0
파일: poisson.cpp 프로젝트: yllan/RadialXX
//---------------------------------------------------------
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;
}