Exemplo n.º 1
0
// ------------------------------------------------------------
// MetisPartitioner implementation
void MetisPartitioner::_do_partition (MeshBase& mesh,
				      const unsigned int n_pieces)
{
  libmesh_assert_greater (n_pieces, 0);
  libmesh_assert (mesh.is_serial());

  // Check for an easy return
  if (n_pieces == 1)
    {
      this->single_partition (mesh);
      return;
    }

// What to do if the Metis library IS NOT present
#ifndef LIBMESH_HAVE_METIS

  libmesh_here();
  libMesh::err << "ERROR: The library has been built without"    << std::endl
	        << "Metis support.  Using a space-filling curve"  << std::endl
	        << "partitioner instead!"                         << std::endl;

  SFCPartitioner sfcp;

  sfcp.partition (mesh, n_pieces);

// What to do if the Metis library IS present
#else

  START_LOG("partition()", "MetisPartitioner");

  const unsigned int n_active_elem = mesh.n_active_elem();

  // build the graph
  // std::vector<int> options(5);
  std::vector<int> vwgt(n_active_elem);
  std::vector<int> part(n_active_elem);

  int
    n = static_cast<int>(n_active_elem),  // number of "nodes" (elements)
                                          //   in the graph
//    wgtflag = 2,                          // weights on vertices only,
//                                          //   none on edges
//    numflag = 0,                          // C-style 0-based numbering
    nparts  = static_cast<int>(n_pieces), // number of subdomains to create
    edgecut = 0;                          // the numbers of edges cut by the
                                          //   resulting partition

  // Set the options
  // options[0] = 0; // use default options

  // Metis will only consider the active elements.
  // We need to map the active element ids into a
  // contiguous range.  Further, we want the unique range indexing to be
  // independednt of the element ordering, otherwise a circular dependency
  // can result in which the partitioning depends on the ordering which
  // depends on the partitioning...
  std::map<const Elem*, unsigned int> global_index_map;
  {
    std::vector<unsigned int> global_index;

    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    MeshCommunication().find_global_indices (MeshTools::bounding_box(mesh),
					     it, end, global_index);

    libmesh_assert_equal_to (global_index.size(), n_active_elem);

    for (unsigned int cnt=0; it != end; ++it)
      {
	const Elem *elem = *it;
	libmesh_assert (!global_index_map.count(elem));

	global_index_map[elem]  = global_index[cnt++];
      }
    libmesh_assert_equal_to (global_index_map.size(), n_active_elem);
  }


  // build the graph in CSR format.  Note that
  // the edges in the graph will correspond to
  // face neighbors
  std::vector<int> xadj, adjncy;
  {
    std::vector<const Elem*> neighbors_offspring;

    MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::element_iterator elem_end = mesh.active_elements_end();

    // This will be exact when there is no refinement and all the
    // elements are of the same type.
    unsigned int graph_size=0;
    std::vector<std::vector<unsigned int> > graph(n_active_elem);

    for (; elem_it != elem_end; ++elem_it)
      {
	const Elem* elem = *elem_it;

	libmesh_assert (global_index_map.count(elem));

	const unsigned int elem_global_index =
	  global_index_map[elem];

	libmesh_assert_less (elem_global_index, vwgt.size());
	libmesh_assert_less (elem_global_index, graph.size());

	// maybe there is a better weight?
	// The weight is used to define what a balanced graph is
        if(!_weights)
          vwgt[elem_global_index] = elem->n_nodes();
        else
          vwgt[elem_global_index] = static_cast<int>((*_weights)[elem->id()]);

	// Loop over the element's neighbors.  An element
	// adjacency corresponds to a face neighbor
	for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
	  {
	    const Elem* neighbor = elem->neighbor(ms);

	    if (neighbor != NULL)
	      {
		// If the neighbor is active treat it
		// as a connection
		if (neighbor->active())
		  {
		    libmesh_assert (global_index_map.count(neighbor));

		    const unsigned int neighbor_global_index =
		      global_index_map[neighbor];

		    graph[elem_global_index].push_back(neighbor_global_index);
		    graph_size++;
		  }

#ifdef LIBMESH_ENABLE_AMR

		// Otherwise we need to find all of the
		// neighbor's children that are connected to
		// us and add them
		else
		  {
		    // The side of the neighbor to which
		    // we are connected
		    const unsigned int ns =
		      neighbor->which_neighbor_am_i (elem);
                    libmesh_assert_less (ns, neighbor->n_neighbors());

		    // Get all the active children (& grandchildren, etc...)
		    // of the neighbor.
		    neighbor->active_family_tree (neighbors_offspring);

		    // Get all the neighbor's children that
		    // live on that side and are thus connected
		    // to us
		    for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
		      {
			const Elem* child =
			  neighbors_offspring[nc];

			// This does not assume a level-1 mesh.
			// Note that since children have sides numbered
			// coincident with the parent then this is a sufficient test.
			if (child->neighbor(ns) == elem)
			  {
			    libmesh_assert (child->active());
			    libmesh_assert (global_index_map.count(child));

			    const unsigned int child_global_index =
			      global_index_map[child];

			    graph[elem_global_index].push_back(child_global_index);
			    graph_size++;
			  }
		      }
		  }

#endif /* ifdef LIBMESH_ENABLE_AMR */

	      }
	  }
      }

    // Convert the graph into the format Metis wants
    xadj.reserve(n_active_elem+1);
    adjncy.reserve(graph_size);

    for (unsigned int r=0; r<graph.size(); r++)
      {
	xadj.push_back(adjncy.size());
	std::vector<unsigned int> graph_row; // build this emtpy
	graph_row.swap(graph[r]); // this will deallocate at the end of scope
	adjncy.insert(adjncy.end(),
		      graph_row.begin(),
		      graph_row.end());
      }

    // The end of the adjacency array for the last elem
    xadj.push_back(adjncy.size());

    libmesh_assert_equal_to (adjncy.size(), graph_size);
    libmesh_assert_equal_to (xadj.size(), n_active_elem+1);
  } // done building the graph


  if (adjncy.empty())
    adjncy.push_back(0);

  int ncon = 1;

  // Select which type of partitioning to create

  // Use recursive if the number of partitions is less than or equal to 8
  if (n_pieces <= 8)
    Metis::METIS_PartGraphRecursive(&n, &ncon, &xadj[0], &adjncy[0], &vwgt[0], NULL,
				    NULL, &nparts, NULL, NULL, NULL,
				    &edgecut, &part[0]);

  // Otherwise  use kway
  else
    Metis::METIS_PartGraphKway(&n, &ncon, &xadj[0], &adjncy[0], &vwgt[0], NULL,
			       NULL, &nparts, NULL, NULL, NULL,
			       &edgecut, &part[0]);


  // Assign the returned processor ids.  The part array contains
  // the processor id for each active element, but in terms of
  // the contiguous indexing we defined above
  {
    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    for (; it!=end; ++it)
      {
	Elem* elem = *it;

	libmesh_assert (global_index_map.count(elem));

	const unsigned int elem_global_index =
	  global_index_map[elem];

	libmesh_assert_less (elem_global_index, part.size());
	const unsigned int elem_procid =  static_cast<short int>(part[elem_global_index]);

        elem->processor_id() = elem_procid;
      }
  }

  STOP_LOG("partition()", "MetisPartitioner");
#endif
}
Exemplo n.º 2
0
void OFFIO::read_stream(std::istream& in)
{
  // This is a serial-only process for now;
  // the Mesh should be read on processor 0 and
  // broadcast later
  libmesh_assert_equal_to (this->mesh().processor_id(), 0);

  // Get a reference to the mesh
  MeshBase& the_mesh = MeshInput<MeshBase>::mesh();

  // Clear any existing mesh data
  the_mesh.clear();

  // Check the input buffer
  libmesh_assert (in.good());

  unsigned int nn, ne, nf;

  std::string label;

  // Read the first string.  It should say "OFF"
  in >> label;

  libmesh_assert_equal_to (label, "OFF");

  // read the number of nodes, faces, and edges
  in >> nn >> nf >> ne;


  Real x=0., y=0., z=0.;

  // Read the nodes
  for (unsigned int n=0; n<nn; n++)
    {
      libmesh_assert (in.good());

      in >> x
         >> y
         >> z;

      the_mesh.add_point ( Point(x,y,z), n );
    }

  unsigned int nv, nid;

  // Read the elements
  for (unsigned int e=0; e<nf; e++)
    {
      libmesh_assert (in.good());

      // The number of vertices in the element
      in >> nv;

      libmesh_assert(nv == 2 || nv == 3);
      if (e == 0)
        {
          the_mesh.set_mesh_dimension(nv-1);
          if (nv == 3)
            {
#if LIBMESH_DIM < 2
              libmesh_error_msg("Cannot open dimension 2 mesh file when configured without 2D support.");
#endif
            }
        }

      Elem* elem;
      switch (nv)
        {
        case 2:
          elem = new Edge2;
          break;

        case 3:
          elem = new Tri3;
          break;

        default:
          libmesh_error_msg("Unsupported nv = " << nv);
        }

      elem->set_id(e);
      the_mesh.add_elem (elem);

      for (unsigned int i=0; i<nv; i++)
        {
          in >> nid;
          elem->set_node(i) = the_mesh.node_ptr(nid);
        }
    }
}
Exemplo n.º 3
0
void Partitioner::partition_unpartitioned_elements (MeshBase & mesh,
                                                    const unsigned int n_subdomains)
{
  MeshBase::element_iterator       it  = mesh.unpartitioned_elements_begin();
  const MeshBase::element_iterator end = mesh.unpartitioned_elements_end();

  const dof_id_type n_unpartitioned_elements = MeshTools::n_elem (it, end);

  // the unpartitioned elements must exist on all processors. If the range is empty on one
  // it is empty on all, and we can quit right here.
  if (!n_unpartitioned_elements) return;

  // find the target subdomain sizes
  std::vector<dof_id_type> subdomain_bounds(mesh.n_processors());

  for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
    {
      dof_id_type tgt_subdomain_size = 0;

      // watch out for the case that n_subdomains < n_processors
      if (pid < n_subdomains)
        {
          tgt_subdomain_size = n_unpartitioned_elements/n_subdomains;

          if (pid < n_unpartitioned_elements%n_subdomains)
            tgt_subdomain_size++;

        }

      //libMesh::out << "pid, #= " << pid << ", " << tgt_subdomain_size << std::endl;
      if (pid == 0)
        subdomain_bounds[0] = tgt_subdomain_size;
      else
        subdomain_bounds[pid] = subdomain_bounds[pid-1] + tgt_subdomain_size;
    }

  libmesh_assert_equal_to (subdomain_bounds.back(), n_unpartitioned_elements);

  // create the unique mapping for all unpartitioned elements independent of partitioning
  // determine the global indexing for all the unpartitoned elements
  std::vector<dof_id_type> global_indices;

  // Calling this on all processors a unique range in [0,n_unpartitioned_elements) is constructed.
  // Only the indices for the elements we pass in are returned in the array.
  MeshCommunication().find_global_indices (mesh.comm(),
                                           MeshTools::bounding_box(mesh), it, end,
                                           global_indices);

  for (dof_id_type cnt=0; it != end; ++it)
    {
      Elem * elem = *it;

      libmesh_assert_less (cnt, global_indices.size());
      const dof_id_type global_index =
        global_indices[cnt++];

      libmesh_assert_less (global_index, subdomain_bounds.back());
      libmesh_assert_less (global_index, n_unpartitioned_elements);

      const processor_id_type subdomain_id =
        cast_int<processor_id_type>
        (std::distance(subdomain_bounds.begin(),
                       std::upper_bound(subdomain_bounds.begin(),
                                        subdomain_bounds.end(),
                                        global_index)));
      libmesh_assert_less (subdomain_id, n_subdomains);

      elem->processor_id() = subdomain_id;
      //libMesh::out << "assigning " << global_index << " to " << subdomain_id << std::endl;
    }
}
Exemplo n.º 4
0
// The main program
int main(int argc, char** argv)
{
  //for record-keeping
  std::cout << "Running: " << argv[0];
  for (int i=1; i<argc; i++)
    std::cout << " " << argv[i];
  std::cout << std::endl << std::endl;

  clock_t begin = std::clock();
  
  // Initialize libMesh
  LibMeshInit init(argc, argv);
  
  // Parameters
  GetPot solverInfile("fem_system_params.in");
  const bool transient                  = solverInfile("transient", false);
  unsigned int n_timesteps              = solverInfile("n_timesteps", 1);
  const int nx                          = solverInfile("nx",100);
  const int ny                          = solverInfile("ny",100);
  const int nz                          = solverInfile("nz",100);
  GetPot infile("contamTrans.in");
  //std::string find_mesh_here            = infile("initial_mesh","mesh.exo");
  bool doContinuation                   = infile("do_continuation",false);
  bool splitSuperAdj                    = infile("split_super_adjoint",true); //solve as single adjoint or two forwards
  int maxIter                           = infile("max_model_refinements",0);  //maximum number of model refinements
  double refStep                        = infile("refinement_step",0.1); //additional proportion of domain refined per step
    //this refers to additional basis functions...number of elements will be more...
  double qoiErrorTol                    = infile("relative_error_tolerance",0.01); //stopping criterion
  //bool doDivvyMatlab                    = infile("do_divvy_in_Matlab",false); //output files to determine next refinement in Matlab
  bool avoid_sides                      = infile("avoid_sides",false); //DEBUG, whether to avoid sides while refining

  if(refStep*maxIter > 1)
    maxIter = round(ceil(1./refStep));

  Mesh mesh(init.comm());
  Mesh mesh2(init.comm()); 
  
  //create mesh
  unsigned int dim;
  if(nz == 0){ //to check if oscillations happen in 2D as well...
    dim = 2;
    MeshTools::Generation::build_square(mesh, nx, ny, 0., 2300., 0., 1650., QUAD9);
    MeshTools::Generation::build_square(mesh2, nx, ny, 0., 2300., 0., 1650., QUAD9);
  }else{
    dim = 3;
    MeshTools::Generation::build_cube(mesh, nx, ny, nz, 0., 2300., 0., 1650., 0., 100., HEX27);
    MeshTools::Generation::build_cube(mesh2, nx, ny, nz, 0., 2300., 0., 1650., 0., 100., HEX27);
  }
  
  mesh.print_info(); //DEBUG
  
  // Create an equation systems object.
  EquationSystems equation_systems (mesh);
  EquationSystems equation_systems_mix(mesh2);
  
  //name system
  ConvDiff_PrimarySys & system_primary = 
    equation_systems.add_system<ConvDiff_PrimarySys>("ConvDiff_PrimarySys"); //for primary variables
  ConvDiff_AuxSys & system_aux = 
    equation_systems.add_system<ConvDiff_AuxSys>("ConvDiff_AuxSys"); //for auxiliary variables
  ConvDiff_MprimeSys & system_mix = 
    equation_systems_mix.add_system<ConvDiff_MprimeSys>("Diff_ConvDiff_MprimeSys"); //for superadj
  ConvDiff_PrimarySadjSys & system_sadj_primary = 
    equation_systems.add_system<ConvDiff_PrimarySadjSys>("ConvDiff_PrimarySadjSys"); //for split superadj
  ConvDiff_AuxSadjSys & system_sadj_aux = 
    equation_systems.add_system<ConvDiff_AuxSadjSys>("ConvDiff_AuxSadjSys"); //for split superadj
    
  //steady-state problem  
  system_primary.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system_primary));
  system_aux.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system_aux));
  system_mix.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system_mix));
  system_sadj_primary.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system_sadj_primary));
  system_sadj_aux.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system_sadj_aux));
  libmesh_assert_equal_to (n_timesteps, 1);
  
  // Initialize the system
  equation_systems.init ();
  equation_systems_mix.init();
  
  //initial guess for primary state
  read_initial_parameters();
  system_primary.project_solution(initial_value, initial_grad,
                          equation_systems.parameters);
  finish_initialization();

  //nonlinear solver options
  NewtonSolver *solver_sadj_primary = new NewtonSolver(system_sadj_primary); 
  system_sadj_primary.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_sadj_primary); 
  solver_sadj_primary->quiet = solverInfile("solver_quiet", true);
  solver_sadj_primary->verbose = !solver_sadj_primary->quiet;
  solver_sadj_primary->max_nonlinear_iterations =
    solverInfile("max_nonlinear_iterations", 15);
  solver_sadj_primary->relative_step_tolerance =
    solverInfile("relative_step_tolerance", 1.e-3);
  solver_sadj_primary->relative_residual_tolerance =
    solverInfile("relative_residual_tolerance", 0.0);
  solver_sadj_primary->absolute_residual_tolerance =
    solverInfile("absolute_residual_tolerance", 0.0);
  NewtonSolver *solver_sadj_aux = new NewtonSolver(system_sadj_aux); 
  system_sadj_aux.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_sadj_aux); 
  solver_sadj_aux->quiet = solverInfile("solver_quiet", true);
  solver_sadj_aux->verbose = !solver_sadj_aux->quiet;
  solver_sadj_aux->max_nonlinear_iterations =
    solverInfile("max_nonlinear_iterations", 15);
  solver_sadj_aux->relative_step_tolerance =
    solverInfile("relative_step_tolerance", 1.e-3);
  solver_sadj_aux->relative_residual_tolerance =
    solverInfile("relative_residual_tolerance", 0.0);
  solver_sadj_aux->absolute_residual_tolerance =
    solverInfile("absolute_residual_tolerance", 0.0);
  NewtonSolver *solver_primary = new NewtonSolver(system_primary); 
  system_primary.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_primary); 
  solver_primary->quiet = solverInfile("solver_quiet", true);
  solver_primary->verbose = !solver_primary->quiet;
  solver_primary->max_nonlinear_iterations =
    solverInfile("max_nonlinear_iterations", 15);
  solver_primary->relative_step_tolerance =
    solverInfile("relative_step_tolerance", 1.e-3);
  solver_primary->relative_residual_tolerance =
    solverInfile("relative_residual_tolerance", 0.0);
  solver_primary->absolute_residual_tolerance =
    solverInfile("absolute_residual_tolerance", 0.0);
  NewtonSolver *solver_aux = new NewtonSolver(system_aux); 
  system_aux.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver_aux); 
  solver_aux->quiet = solverInfile("solver_quiet", true);
  solver_aux->verbose = !solver_aux->quiet;
  solver_aux->max_nonlinear_iterations =
    solverInfile("max_nonlinear_iterations", 15);
  solver_aux->relative_step_tolerance =
    solverInfile("relative_step_tolerance", 1.e-3);
  solver_aux->relative_residual_tolerance =
    solverInfile("relative_residual_tolerance", 0.0);
  solver_aux->absolute_residual_tolerance =
    solverInfile("absolute_residual_tolerance", 0.0);
  solver_primary->require_residual_reduction = solverInfile("require_residual_reduction",true);
  solver_sadj_primary->require_residual_reduction = solverInfile("require_residual_reduction",true);
  solver_aux->require_residual_reduction = solverInfile("require_residual_reduction",true);
  solver_sadj_aux->require_residual_reduction = solverInfile("require_residual_reduction",true);  
  
  //linear solver options
  solver_primary->max_linear_iterations       = solverInfile("max_linear_iterations",10000);
  solver_primary->initial_linear_tolerance    = solverInfile("initial_linear_tolerance",1.e-13);
  solver_primary->minimum_linear_tolerance    = solverInfile("minimum_linear_tolerance",1.e-13);
  solver_primary->linear_tolerance_multiplier = solverInfile("linear_tolerance_multiplier",1.e-3);
  solver_aux->max_linear_iterations           = solverInfile("max_linear_iterations",10000);
  solver_aux->initial_linear_tolerance        = solverInfile("initial_linear_tolerance",1.e-13);
  solver_aux->minimum_linear_tolerance        = solverInfile("minimum_linear_tolerance",1.e-13);
  solver_aux->linear_tolerance_multiplier     = solverInfile("linear_tolerance_multiplier",1.e-3);
  solver_sadj_primary->max_linear_iterations       = solverInfile("max_linear_iterations",10000);
  solver_sadj_primary->initial_linear_tolerance    = solverInfile("initial_linear_tolerance",1.e-13);
  solver_sadj_primary->minimum_linear_tolerance    = solverInfile("minimum_linear_tolerance",1.e-13);
  solver_sadj_primary->linear_tolerance_multiplier = solverInfile("linear_tolerance_multiplier",1.e-3);
  solver_sadj_aux->max_linear_iterations           = solverInfile("max_linear_iterations",10000);
  solver_sadj_aux->initial_linear_tolerance        = solverInfile("initial_linear_tolerance",1.e-13);
  solver_sadj_aux->minimum_linear_tolerance        = solverInfile("minimum_linear_tolerance",1.e-13);
  solver_sadj_aux->linear_tolerance_multiplier     = solverInfile("linear_tolerance_multiplier",1.e-3);
  
  /*if(doDivvyMatlab){
    //DOF maps and such to help visualize
    std::ofstream output_global_dof("global_dof_map.dat");
    for(unsigned int i = 0 ; i < system_mix.get_mesh().n_elem(); i++){
      std::vector< dof_id_type > di;
      system_mix.get_dof_map().dof_indices(system_mix.get_mesh().elem(i), di);
      if(output_global_dof.is_open()){
        output_global_dof << i << " ";
        for(unsigned int j = 0; j < di.size(); j++)
          output_global_dof << di[j] << " ";
        output_global_dof << "\n";
      }
    }
    output_global_dof.close();
    std::ofstream output_elem_cent("elem_centroids.dat");
    for(unsigned int i = 0 ; i < system_mix.get_mesh().n_elem(); i++){
      Point elem_cent = system_mix.get_mesh().elem(i)->centroid();
      if(output_elem_cent.is_open()){
        output_elem_cent << elem_cent(0) << " " << elem_cent(1) << "\n";
      }
    }
    output_elem_cent.close();
  }*/
  
  //inverse dof map (elements in support of each node, assuming every 6 dofs belong to same node)
  std::vector<std::set<dof_id_type> > node_to_elem; 
  node_to_elem.resize(round(system_mix.n_dofs()/6.));
  for(unsigned int i = 0 ; i < system_mix.get_mesh().n_elem(); i++){
    std::vector< dof_id_type > di;
    system_mix.get_dof_map().dof_indices(system_mix.get_mesh().elem(i), di);
    for(unsigned int j = 0; j < di.size(); j++)
      node_to_elem[round(floor(di[j]/6.))].insert(i);
  }

  int refIter = 0;
  double relError = 2.*qoiErrorTol;
  while(refIter <= maxIter && relError > qoiErrorTol){
    if(!doContinuation){ //clear out previous solutions
      system_primary.solution->zero();
      system_aux.solution->zero();
      system_sadj_primary.solution->zero();
      system_sadj_aux.solution->zero();
    }
    system_mix.solution->zero();
    
    clock_t begin_inv = std::clock();
    system_primary.solve();
    system_primary.clearQoI();
    clock_t end_inv = std::clock();
    clock_t begin_err_est = std::clock();
    std::cout << "\n End primary solve, begin auxiliary solve..." << std::endl;
    system_aux.solve();
    std::cout << "\n End auxiliary solve..." << std::endl;
    clock_t end_aux = std::clock();
    
    system_primary.postprocess();
    system_aux.postprocess();
    
    system_sadj_primary.set_c_vals(system_primary.get_c_vals());
    system_sadj_aux.set_auxc_vals(system_aux.get_auxc_vals());

    equation_systems_mix.reinit();
    //combine primary and auxiliary variables into psi
    DirectSolutionTransfer sol_transfer(init.comm()); 
    sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_c")),
      system_mix.variable(system_mix.variable_number("aux_c")));
    sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_zc")),
      system_mix.variable(system_mix.variable_number("aux_zc")));
    sol_transfer.transfer(system_aux.variable(system_aux.variable_number("aux_fc")),
      system_mix.variable(system_mix.variable_number("aux_fc")));
    AutoPtr<NumericVector<Number> > just_aux = system_mix.solution->clone();
    sol_transfer.transfer(system_primary.variable(system_primary.variable_number("c")),
      system_mix.variable(system_mix.variable_number("c")));
    sol_transfer.transfer(system_primary.variable(system_primary.variable_number("zc")),
      system_mix.variable(system_mix.variable_number("zc")));
    sol_transfer.transfer(system_primary.variable(system_primary.variable_number("fc")),
      system_mix.variable(system_mix.variable_number("fc")));

    if(!splitSuperAdj){ //solve super-adjoint as single adjoint
      system_mix.assemble_qoi_sides = true; //QoI doesn't involve sides
      
      std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve start ~*~*~*~*~*~*~*~*~\n" << std::endl;
      std::pair<unsigned int, Real> adjsolve = system_mix.adjoint_solve();
      std::cout << "number of iterations to solve adjoint: " << adjsolve.first << std::endl;
      std::cout << "final residual of adjoint solve: " << adjsolve.second << std::endl;
      std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve end ~*~*~*~*~*~*~*~*~" << std::endl;
  
      NumericVector<Number> &dual_sol = system_mix.get_adjoint_solution(0); //DEBUG
      
      system_mix.assemble(); //calculate residual to correspond to solution
      
      //std::cout << "\n sadj norm: " << system_mix.calculate_norm(dual_sol, L2) << std::endl; //DEBUG
      //std::cout << system_mix.calculate_norm(dual_sol, 0, L2) << std::endl; //DEBUG
      //std::cout << system_mix.calculate_norm(dual_sol, 1, L2) << std::endl; //DEBUG
      //std::cout << system_mix.calculate_norm(dual_sol, 2, L2) << std::endl; //DEBUG
      //std::cout << system_mix.calculate_norm(dual_sol, 3, L2) << std::endl; //DEBUG
      //std::cout << system_mix.calculate_norm(dual_sol, 4, L2) << std::endl; //DEBUG
      //std::cout << system_mix.calculate_norm(dual_sol, 5, L2) << std::endl; //DEBUG
    }else{ //solve super-adjoint as
      system_mix.assemble(); //calculate residual to correspond to solution
      std::cout << "\n Begin primary super-adjoint solve...\n" << std::endl;
      system_sadj_primary.solve();
      std::cout << "\n End primary super-adjoint solve, begin auxiliary super-adjoint solve...\n" << std::endl;
      system_sadj_aux.solve();
      std::cout << "\n End auxiliary super-adjoint solve...\n" << std::endl;
      const std::string & adjoint_solution0_name = "adjoint_solution0";
      system_mix.add_vector(adjoint_solution0_name, false, GHOSTED);
      system_mix.set_vector_as_adjoint(adjoint_solution0_name,0);
      NumericVector<Number> &eep = system_mix.add_adjoint_rhs(0);
      system_mix.set_adjoint_already_solved(true);
      NumericVector<Number> &dual_sol = system_mix.get_adjoint_solution(0);
      NumericVector<Number> &primal_sol = *system_mix.solution;
      dual_sol.swap(primal_sol);
      sol_transfer.transfer(system_sadj_aux.variable(system_sadj_aux.variable_number("sadj_aux_c")),
        system_mix.variable(system_mix.variable_number("aux_c")));
      sol_transfer.transfer(system_sadj_aux.variable(system_sadj_aux.variable_number("sadj_aux_zc")),
        system_mix.variable(system_mix.variable_number("aux_zc")));
      sol_transfer.transfer(system_sadj_aux.variable(system_sadj_aux.variable_number("sadj_aux_fc")),
        system_mix.variable(system_mix.variable_number("aux_fc")));
      sol_transfer.transfer(system_sadj_primary.variable(system_sadj_primary.variable_number("sadj_c")),
        system_mix.variable(system_mix.variable_number("c")));
      sol_transfer.transfer(system_sadj_primary.variable(system_sadj_primary.variable_number("sadj_zc")),
        system_mix.variable(system_mix.variable_number("zc")));
      sol_transfer.transfer(system_sadj_primary.variable(system_sadj_primary.variable_number("sadj_fc")),
        system_mix.variable(system_mix.variable_number("fc")));
      //std::cout << "\n sadj norm: " << system_mix.calculate_norm(primal_sol, L2) << std::endl; //DEBUG
      dual_sol.swap(primal_sol);
      //std::cout << "\n sadj norm: " << system_mix.calculate_norm(primal_sol, L2) << std::endl; //DEBUG
      //std::cout << system_sadj_primary.calculate_norm(*system_sadj_primary.solution, 0, L2) << std::endl; //DEBUG
      //std::cout << system_sadj_primary.calculate_norm(*system_sadj_primary.solution, 1, L2) << std::endl; //DEBUG
      //std::cout << system_sadj_primary.calculate_norm(*system_sadj_primary.solution, 2, L2) << std::endl; //DEBUG
      //std::cout << system_sadj_aux.calculate_norm(*system_sadj_aux.solution, 0, L2) << std::endl; //DEBUG
      //std::cout << system_sadj_aux.calculate_norm(*system_sadj_aux.solution, 1, L2) << std::endl; //DEBUG
      //std::cout << system_sadj_aux.calculate_norm(*system_sadj_aux.solution, 2, L2) << std::endl; //DEBUG
    }
    NumericVector<Number> &dual_solution = system_mix.get_adjoint_solution(0);
/*  
    NumericVector<Number> &primal_solution = *system_mix.solution; //DEBUG
    primal_solution.swap(dual_solution); //DEBUG
    ExodusII_IO(mesh).write_timestep("super_adjoint.exo",
                                   equation_systems,
                                   1, /  his number indicates how many time steps are being written to the file
                                   system_mix.time); //DEBUG
    primal_solution.swap(dual_solution); //DEBUG
*/
    //adjoint-weighted residual
    AutoPtr<NumericVector<Number> > adjresid = system_mix.solution->zero_clone();
    adjresid->pointwise_mult(*system_mix.rhs,dual_solution); 
    adjresid->scale(-0.5);
    std::cout << "\n -0.5*M'_HF(psiLF)(superadj): " << adjresid->sum() << std::endl; //DEBUG
    
    //LprimeHF(psiLF)
    AutoPtr<NumericVector<Number> > LprimeHF_psiLF = system_mix.solution->zero_clone();
    LprimeHF_psiLF->pointwise_mult(*system_mix.rhs,*just_aux);
    std::cout << " L'_HF(psiLF): " << LprimeHF_psiLF->sum() << std::endl; //DEBUG
    
    //QoI and error estimate
    std::cout << "QoI: " << std::setprecision(17) << system_primary.getQoI() << std::endl;
    std::cout << "QoI Error estimate: " << std::setprecision(17) 
        << adjresid->sum()+LprimeHF_psiLF->sum() << std::endl; 
        
    relError = fabs((adjresid->sum()+LprimeHF_psiLF->sum())/system_primary.getQoI());
    
    //print out information
    std::cout << "Estimated absolute relative qoi error: " << relError << std::endl << std::endl;
    std::cout << "Estimated HF QoI: " << std::setprecision(17) << system_primary.getQoI()+adjresid->sum()+LprimeHF_psiLF->sum() << std::endl;
    clock_t end = clock();
    std::cout << "Time so far: " << double(end-begin)/CLOCKS_PER_SEC << " seconds..." << std::endl;
    std::cout << "Time for inverse problem: " << double(end_inv-begin_inv)/CLOCKS_PER_SEC << " seconds..." << std::endl;
    std::cout << "Time for extra error estimate bits: " << double(end-begin_err_est)/CLOCKS_PER_SEC << " seconds..." << std::endl;
    std::cout << "    Time to get auxiliary problems: " << double(end_aux-begin_err_est)/CLOCKS_PER_SEC << " seconds..." << std::endl;
    std::cout << "    Time to get superadjoint: " << double(end-end_aux)/CLOCKS_PER_SEC << " seconds...\n" << std::endl;
    
    //proportion of domain refined at this iteration
    MeshBase::element_iterator       elem_it  = mesh.elements_begin();
    const MeshBase::element_iterator elem_end = mesh.elements_end();
    double numMarked = 0.;
    for (; elem_it != elem_end; ++elem_it){
      Elem* elem = *elem_it;
      numMarked += elem->subdomain_id();
    }
    std::cout << "Refinement fraction: " << numMarked/system_mix.get_mesh().n_elem() << std::endl << std::endl;

    
    //output at each iteration
    std::stringstream ss;
    ss << refIter;
    std::string str = ss.str();
    std::string write_error_basis_blame = 
      (infile("error_est_output_file_basis_blame", "error_est_breakdown_basis_blame")) + str + ".dat";
    std::ofstream output2(write_error_basis_blame);
    for(unsigned int i = 0 ; i < adjresid->size(); i++){
      if(output2.is_open())
        output2 << (*adjresid)(i) + (*LprimeHF_psiLF)(i) << "\n";
    }
    output2.close();
    
    if(refIter < maxIter && relError > qoiErrorTol){ //if further refinement needed
    
      //collapse error contributions into nodes
      std::vector<std::pair<Number,dof_id_type> > node_errs(round(system_mix.n_dofs()/6.));
      for(unsigned int node_num = 0; node_num < node_errs.size(); node_num++){
        node_errs[node_num] = std::pair<Number,dof_id_type>
                             (fabs((*adjresid)(6*node_num) + (*LprimeHF_psiLF)(6*node_num)
                            + (*adjresid)(6*node_num+1) + (*LprimeHF_psiLF)(6*node_num+1)
                            + (*adjresid)(6*node_num+2) + (*LprimeHF_psiLF)(6*node_num+2)
                            + (*adjresid)(6*node_num+3) + (*LprimeHF_psiLF)(6*node_num+3)
                            + (*adjresid)(6*node_num+4) + (*LprimeHF_psiLF)(6*node_num+4)
                            + (*adjresid)(6*node_num+5) + (*LprimeHF_psiLF)(6*node_num+5)), node_num);
      }
  
      //find nodes contributing the most
      //double refPcnt = std::min((refIter+1)*refStep,1.);
      double refPcnt = std::min(refStep,1.); //additional refinement (compared to previous iteration)
      int cutoffLoc = round(node_errs.size()*refPcnt);
      std::sort(node_errs.begin(), node_errs.end()); 
      std::reverse(node_errs.begin(), node_errs.end()); 
      
      //find elements in support of worst offenders
      std::vector<dof_id_type> markMe;
      markMe.reserve(cutoffLoc*8);
      for(int i = 0; i < cutoffLoc; i++){
        markMe.insert(markMe.end(), node_to_elem[node_errs[i].second].begin(), node_to_elem[node_errs[i].second].end());
      }
  
      //mark those elements for refinement.
      for(int i = 0; i < markMe.size(); i++){
        if(!avoid_sides || (avoid_sides && !mesh.elem(markMe[i])->on_boundary()))
          mesh.elem(markMe[i])->subdomain_id() = 1; //assuming HF regions marked with 1
      }
  
      //to test whether assignment matches matlab's
      /*std::string stash_assign = "divvy_c_poke.txt";
      std::ofstream output_dbg(stash_assign.c_str());
      MeshBase::element_iterator       elem_it  = mesh.elements_begin();
      const MeshBase::element_iterator elem_end = mesh.elements_end();
      for (; elem_it != elem_end; ++elem_it){
        Elem* elem = *elem_it;
            
        if(output_dbg.is_open()){
          output_dbg << elem->id() << " " << elem->subdomain_id() << "\n";
        }
      }
      output_dbg.close();*/
      
#ifdef LIBMESH_HAVE_EXODUS_API
    std::stringstream ss2;
    ss2 << refIter + 1;
    std::string str = ss2.str();
    std::string write_divvy = "divvy" + str + ".exo";
    ExodusII_IO (mesh).write_equation_systems(write_divvy,equation_systems); //DEBUG
#endif // #ifdef LIBMESH_HAVE_EXODUS_API
    }
    refIter += 1;
  }
  
  std::string stash_assign = "divvy_final.txt";
  std::ofstream output_dbg(stash_assign.c_str());
  MeshBase::element_iterator       elem_it  = mesh.elements_begin();
  const MeshBase::element_iterator elem_end = mesh.elements_end();
  double numMarked = 0.;
  for (; elem_it != elem_end; ++elem_it){
    Elem* elem = *elem_it;
    numMarked += elem->subdomain_id();
    if(output_dbg.is_open()){
      output_dbg << elem->id() << " " << elem->subdomain_id() << "\n";
    }
  }
  output_dbg.close();
  
  std::cout << "\nRefinement concluded..." << std::endl;
  std::cout << "Final refinement fraction: " << numMarked/system_mix.get_mesh().n_elem() << std::endl;
  std::cout << "Final estimated relative error: " << relError << std::endl;
  
  return 0; //done

} //end main
Exemplo n.º 5
0
Real FE<1,LAGRANGE>::shape_second_deriv(const ElemType,
                                        const Order order,
                                        const unsigned int i,
                                        const unsigned int libmesh_dbg_var(j),
                                        const Point & p)
{
  // Don't need to switch on j.  1D shape functions
  // depend on xi only!

  const Real xi = p(0);
  libmesh_assert_equal_to (j, 0);

  switch (order)
    {
      // linear Lagrange shape functions
    case FIRST:
      {
        // All second derivatives of linears are zero....
        return 0.;
      }

      // quadratic Lagrange shape functions
    case SECOND:
      {
        switch (i)
          {
          case 0:
            return 1.;

          case 1:
            return 1.;

          case 2:
            return -2.;

          default:
            libmesh_error_msg("Invalid shape function index i = " << i);
          }
      } // end case SECOND

    case THIRD:
      {
        switch (i)
          {
          case 0:
            return -9./16.*(6.*xi-2);

          case 1:
            return -9./16.*(-6*xi-2.);

          case 2:
            return 27./16.*(6*xi-2./3.);

          case 3:
            return 27./16.*(-6*xi-2./3.);

          default:
            libmesh_error_msg("Invalid shape function index i = " << i);
          }
      } // end case THIRD


    default:
      libmesh_error_msg("ERROR: Unsupported polynomial order = " << order);
    } // end switch (order)

  libmesh_error_msg("We'll never get here!");
  return 0.;
}
Exemplo n.º 6
0
int main(int argc, char** argv){

  //initialize libMesh
  LibMeshInit init(argc, argv);
  
  //parameters
  GetPot infile("fem_system_params.in");
  const bool transient                  = infile("transient", true);
  const Real deltat                     = infile("deltat", 0.005);
  unsigned int n_timesteps              = infile("n_timesteps", 20);
  const int nx                          = infile("nx",100);
  const int ny                          = infile("ny",100);
  const int nz                          = infile("nz",100);
  //const unsigned int dim                = 3;
  const unsigned int max_r_steps        = infile("max_r_steps", 3);
  const unsigned int max_r_level        = infile("max_r_level", 3);
  const Real refine_percentage          = infile("refine_percentage", 0.1);
  const Real coarsen_percentage         = infile("coarsen_percentage", 0.0);
  const std::string indicator_type      = infile("indicator_type", "kelly");
  const bool write_error                = infile("write_error",false);
  const bool flag_by_elem_frac          = infile("flag_by_elem_frac",true);
  
  const bool printJ                     = infile("print_jac",false); //DEBUG
      
#ifdef LIBMESH_HAVE_EXODUS_API
  const unsigned int write_interval    = infile("write_interval", 5);
#endif

  // Create a mesh, with dimension to be overridden later, distributed
  // across the default MPI communicator.
  Mesh mesh(init.comm());
  
  //create mesh
  unsigned int dim;
  if(nz == 0){ //to check if oscillations happen in 2D as well...
    dim = 2;
    MeshTools::Generation::build_square(mesh, nx, ny, 497150.0, 501750.0, 537350.0, 540650.0, QUAD9);
  }else{
    dim = 3;
    MeshTools::Generation::build_cube(mesh, 
                                      nx, ny, nz, 
                                      497150.0, 501750.0, 
                                      537350.0, 540650.0, 
                                      0.0, 100.0, 
                                      HEX27);
    //MeshTools::Generation::build_cube (mesh, 
    //                                      15, 3, 3,
    //                                     -0.0, 5.0,
    //                                    -0.0, 1.0,
    //                                     -0.0, 1.0,
    //                                    HEX27); //DEBUG
  }
  
  // Print information about the mesh to the screen.
  mesh.print_info();
  
  // Create an equation systems object.
  EquationSystems equation_systems (mesh);
  
  //name system
  ContamTransSysInv & system = 
    equation_systems.add_system<ContamTransSysInv>("ContamTransInv");
    
  //solve as steady or transient
  if(transient){
    //system.time_solver = AutoPtr<TimeSolver>(new EulerSolver(system)); //backward Euler
    system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system));
    std::cout << "\n\nAaahhh transience not yet available!\n" << std::endl;
    n_timesteps = 1;
  }
  else{
    system.time_solver = AutoPtr<TimeSolver>(new SteadySolver(system));
    libmesh_assert_equal_to (n_timesteps, 1); //this doesn't seem to work?
  }
  
  // Initialize the system
  equation_systems.init ();
  
  //initial conditions
  read_initial_parameters();
  system.project_solution(initial_value, initial_grad,
                          equation_systems.parameters);
  finish_initialization();

  // Set the time stepping options...
  system.deltat = deltat;
  
  //...and the nonlinear solver options...
  NewtonSolver *solver = new NewtonSolver(system); 
  system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); 
  solver->quiet = infile("solver_quiet", true);
  solver->verbose = !solver->quiet;
  solver->max_nonlinear_iterations =
    infile("max_nonlinear_iterations", 15);
  solver->relative_step_tolerance =
    infile("relative_step_tolerance", 1.e-3);
  solver->relative_residual_tolerance =
    infile("relative_residual_tolerance", 0.0);
  solver->absolute_residual_tolerance =
    infile("absolute_residual_tolerance", 0.0);

  // And the linear solver options
  solver->max_linear_iterations           = infile("max_linear_iterations", 10000);
  solver->initial_linear_tolerance        = infile("initial_linear_tolerance",1.e-13);
  solver->minimum_linear_tolerance        = infile("minimum_linear_tolerance",1.e-13);
  solver->linear_tolerance_multiplier     = infile("linear_tolerance_multiplier",1.e-3);
    
  // Mesh Refinement object - to test effect of constant refined mesh (not refined at every timestep)
  MeshRefinement mesh_refinement(mesh);
  mesh_refinement.refine_fraction() = refine_percentage;
  mesh_refinement.coarsen_fraction() = coarsen_percentage;
  mesh_refinement.max_h_level() = max_r_level;
  
#ifdef LIBMESH_HAVE_GMV
  GMVIO(equation_systems.get_mesh()).write_equation_systems(std::string("invLF.gmv"), equation_systems); //DEBUG
#endif

  // Print information about the system to the screen.
  equation_systems.print_info();
  
  ExodusII_IO exodusIO = ExodusII_IO(mesh); //for writing multiple timesteps to one file
  
  for (unsigned int r_step=0; r_step<max_r_steps; r_step++)
    {
      std::cout << "\nBeginning Solve " << r_step+1 << std::endl;
      
      for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
        {
      
          std::cout << "\n\nSolving time step " << t_step << ", time = "
                    << system.time << std::endl;
          
          system.solve();
          system.postprocess();
          
          // Advance to the next timestep in a transient problem
          system.time_solver->advance_timestep();
   
      } //end stepping through time loop
      
      std::cout << "\n  Refining the mesh..." << std::endl;
      
      // The \p ErrorVector is a particular \p StatisticsVector
      // for computing error information on a finite element mesh.
      ErrorVector error;
      
      if (indicator_type == "patch")
        {
          // The patch recovery estimator should give a
          // good estimate of the solution interpolation
          // error.
          PatchRecoveryErrorEstimator error_estimator;
          error_estimator.set_patch_reuse(false); //anisotropy trips up reuse
          error_estimator.estimate_error (system, error);
        }
      else if (indicator_type == "kelly")
        {

          // The Kelly error estimator is based on
          // an error bound for the Poisson problem
          // on linear elements, but is useful for
          // driving adaptive refinement in many problems
          KellyErrorEstimator error_estimator;

          error_estimator.estimate_error (system, error);
        }
      
      // Write out the error distribution
      if(write_error){
        std::ostringstream ss;
        ss << r_step;
#ifdef LIBMESH_HAVE_EXODUS_API
        std::string error_output = "error_"+ss.str()+".e";
#else
        std::string error_output = "error_"+ss.str()+".gmv";
#endif
        error.plot_error( error_output, mesh );
      }
      
      // This takes the error in \p error and decides which elements
      // will be coarsened or refined. 
      if(flag_by_elem_frac)
        mesh_refinement.flag_elements_by_elem_fraction(error);
      else
        mesh_refinement.flag_elements_by_error_fraction (error);
      
      // This call actually refines and coarsens the flagged
      // elements.
      mesh_refinement.refine_and_coarsen_elements();
      
      // This call reinitializes the \p EquationSystems object for
      // the newly refined mesh.  One of the steps in the
      // reinitialization is projecting the \p solution,
      // \p old_solution, etc... vectors from the old mesh to
      // the current one.
      equation_systems.reinit ();
      
      std::cout << "System has: " << equation_systems.n_active_dofs()
                << " degrees of freedom."
                << std::endl;

    } //end refinement loop
    
  //use that final refinement
  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
    {
  
      std::cout << "\n\nSolving time step " << t_step << ", time = "
                << system.time << std::endl;
      
      system.solve();
      system.postprocess();
      
      //DEBUG
      if(printJ){ //aahhh this doesn't print if solve not successful...
        std::ostringstream Jfile_name;
        Jfile_name << "J.dat";
        std::ofstream outputJ(Jfile_name.str());
        system.matrix->print(outputJ);
        outputJ.close();
      }
      
      Number QoI_computed = system.get_QoI_value("computed", 0);
      std::cout<< "Computed QoI is " << std::setprecision(17) << QoI_computed << std::endl;
      
      // Advance to the next timestep in a transient problem
      system.time_solver->advance_timestep();

    } //end stepping through time loop
    
    
#ifdef LIBMESH_HAVE_EXODUS_API
  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
    {
      // Write out this timestep if we're requested to
      if ((t_step+1)%write_interval == 0)
        {
          std::ostringstream ex_file_name;
          std::ostringstream tplot_file_name;

          // We write the file in the ExodusII format.
          //ex_file_name << "out_"
          //            << std::setw(3)
          //            << std::setfill('0')
          //            << std::right
          //            << t_step+1
          //            << ".e";
                      
          tplot_file_name << "out_"
                      << std::setw(3)
                      << std::setfill('0')
                      << std::right
                      << t_step+1
                      << ".plt";

          //ExodusII_IO(mesh).write_timestep(ex_file_name.str(),
          //                                 equation_systems,
          //                                 1, /* This number indicates how many time steps
          //                                       are being written to the file */
          //                                 system.time);
          exodusIO.write_timestep("output.exo", equation_systems, t_step+1, system.time); //outputs all timesteps in one file
          TecplotIO(mesh).write_equation_systems(tplot_file_name.str(), equation_systems);
        }
    }
#endif // #ifdef LIBMESH_HAVE_EXODUS_API     

  // All done.
  return 0;
  
} //end main
Exemplo n.º 7
0
void ParmetisPartitioner::build_graph (const MeshBase& mesh)
{
  // build the graph in distributed CSR format.  Note that
  // the edges in the graph will correspond to
  // face neighbors
  const dof_id_type n_active_local_elem  = mesh.n_active_local_elem();

  // If we have boundary elements in this mesh, we want to account for
  // the connectivity between them and interior elements.  We can find
  // interior elements from boundary elements, but we need to build up
  // a lookup map to do the reverse.

  typedef LIBMESH_BEST_UNORDERED_MAP<const Elem *, const Elem *>
    map_type;
  map_type interior_to_boundary_map;

  {
    MeshBase::const_element_iterator       elem_it  = mesh.active_elements_begin();
    const MeshBase::const_element_iterator elem_end = mesh.active_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
        const Elem* elem = *elem_it;

        // If we don't have an interior_parent then there's nothing to look us
        // up.
        if ((elem->dim() >= LIBMESH_DIM) ||
            !elem->interior_parent())
          continue;

        // get all relevant interior elements
        std::set<const Elem*> neighbor_set;
        elem->find_interior_neighbors(neighbor_set);

        std::set<const Elem*>::iterator n_it = neighbor_set.begin();
        for (; n_it != neighbor_set.end(); ++n_it)
          {
            // FIXME - non-const versions of the Elem set methods
            // would be nice
            Elem* neighbor = const_cast<Elem*>(*n_it);

#if defined(LIBMESH_HAVE_UNORDERED_MAP) || defined(LIBMESH_HAVE_TR1_UNORDERED_MAP) || defined(LIBMESH_HAVE_HASH_MAP) || defined(LIBMESH_HAVE_EXT_HASH_MAP)
            interior_to_boundary_map.insert
              (std::make_pair(neighbor, elem));
#else
            interior_to_boundary_map.insert
              (interior_to_boundary_map.begin(),
               std::make_pair(neighbor, elem));
#endif
          }
      }
  }

#ifdef LIBMESH_ENABLE_AMR
  std::vector<const Elem*> neighbors_offspring;
#endif

  std::vector<std::vector<dof_id_type> > graph(n_active_local_elem);
  dof_id_type graph_size=0;

  const dof_id_type first_local_elem = _pmetis->vtxdist[mesh.processor_id()];

  MeshBase::const_element_iterator       elem_it  = mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end();

  for (; elem_it != elem_end; ++elem_it)
    {
      const Elem* elem = *elem_it;

      libmesh_assert (_global_index_by_pid_map.count(elem->id()));
      const dof_id_type global_index_by_pid =
        _global_index_by_pid_map[elem->id()];

      const dof_id_type local_index =
        global_index_by_pid - first_local_elem;
      libmesh_assert_less (local_index, n_active_local_elem);

      std::vector<dof_id_type> &graph_row = graph[local_index];

      // Loop over the element's neighbors.  An element
      // adjacency corresponds to a face neighbor
      for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
        {
          const Elem* neighbor = elem->neighbor(ms);

          if (neighbor != NULL)
            {
              // If the neighbor is active treat it
              // as a connection
              if (neighbor->active())
                {
                  libmesh_assert(_global_index_by_pid_map.count(neighbor->id()));
                  const dof_id_type neighbor_global_index_by_pid =
                    _global_index_by_pid_map[neighbor->id()];

                  graph_row.push_back(neighbor_global_index_by_pid);
                  graph_size++;
                }

#ifdef LIBMESH_ENABLE_AMR

              // Otherwise we need to find all of the
              // neighbor's children that are connected to
              // us and add them
              else
                {
                  // The side of the neighbor to which
                  // we are connected
                  const unsigned int ns =
                    neighbor->which_neighbor_am_i (elem);
                  libmesh_assert_less (ns, neighbor->n_neighbors());

                  // Get all the active children (& grandchildren, etc...)
                  // of the neighbor

                  // FIXME - this is the wrong thing, since we
                  // should be getting the active family tree on
                  // our side only.  But adding too many graph
                  // links may cause hanging nodes to tend to be
                  // on partition interiors, which would reduce
                  // communication overhead for constraint
                  // equations, so we'll leave it.

                  neighbor->active_family_tree (neighbors_offspring);

                  // Get all the neighbor's children that
                  // live on that side and are thus connected
                  // to us
                  for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
                    {
                      const Elem* child =
                        neighbors_offspring[nc];

                      // This does not assume a level-1 mesh.
                      // Note that since children have sides numbered
                      // coincident with the parent then this is a sufficient test.
                      if (child->neighbor(ns) == elem)
                        {
                          libmesh_assert (child->active());
                          libmesh_assert (_global_index_by_pid_map.count(child->id()));
                          const dof_id_type child_global_index_by_pid =
                            _global_index_by_pid_map[child->id()];

                          graph_row.push_back(child_global_index_by_pid);
                          graph_size++;
                        }
                    }
                }

#endif /* ifdef LIBMESH_ENABLE_AMR */


            }
        }

      if ((elem->dim() < LIBMESH_DIM) &&
          elem->interior_parent())
        {
          // get all relevant interior elements
          std::set<const Elem*> neighbor_set;
          elem->find_interior_neighbors(neighbor_set);

          std::set<const Elem*>::iterator n_it = neighbor_set.begin();
          for (; n_it != neighbor_set.end(); ++n_it)
            {
              // FIXME - non-const versions of the Elem set methods
              // would be nice
              Elem* neighbor = const_cast<Elem*>(*n_it);

              const dof_id_type neighbor_global_index_by_pid =
                _global_index_by_pid_map[neighbor->id()];

              graph_row.push_back(neighbor_global_index_by_pid);
              graph_size++;
            }
        }

      // Check for any boundary neighbors
      typedef map_type::iterator map_it_type;
      std::pair<map_it_type, map_it_type>
        bounds = interior_to_boundary_map.equal_range(elem);

      for (map_it_type it = bounds.first; it != bounds.second; ++it)
        {
          const Elem* neighbor = it->second;

          const dof_id_type neighbor_global_index_by_pid =
            _global_index_by_pid_map[neighbor->id()];

          graph_row.push_back(neighbor_global_index_by_pid);
          graph_size++;
        }
    }

  // Reserve space in the adjacency array
  _pmetis->xadj.clear();
  _pmetis->xadj.reserve (n_active_local_elem + 1);
  _pmetis->adjncy.clear();
  _pmetis->adjncy.reserve (graph_size);

  for (std::size_t r=0; r<graph.size(); r++)
    {
      _pmetis->xadj.push_back(_pmetis->adjncy.size());
      std::vector<dof_id_type> graph_row; // build this emtpy
      graph_row.swap(graph[r]); // this will deallocate at the end of scope
      _pmetis->adjncy.insert(_pmetis->adjncy.end(),
                             graph_row.begin(),
                             graph_row.end());
    }

  // The end of the adjacency array for the last elem
  _pmetis->xadj.push_back(_pmetis->adjncy.size());

  libmesh_assert_equal_to (_pmetis->xadj.size(), n_active_local_elem+1);
  libmesh_assert_equal_to (_pmetis->adjncy.size(), graph_size);
}
Exemplo n.º 8
0
void LaspackMatrix<T>::update_sparsity_pattern (const SparsityPattern::Graph & sparsity_pattern)
{
  // clear data, start over
  this->clear ();

  // big trouble if this fails!
  libmesh_assert(this->_dof_map);

  const numeric_index_type n_rows = sparsity_pattern.size();

  // Initialize the _row_start data structure,
  // allocate storage for the _csr array
  {
    std::size_t size = 0;

    for (numeric_index_type row=0; row<n_rows; row++)
      size += sparsity_pattern[row].size();

    _csr.resize       (size);
    _row_start.reserve(n_rows + 1);
  }


  // Initize the _csr data structure.
  {
    std::vector<numeric_index_type>::iterator position = _csr.begin();

    _row_start.push_back (position);

    for (numeric_index_type row=0; row<n_rows; row++)
      {
        // insert the row indices
        for (SparsityPattern::Row::const_iterator col = sparsity_pattern[row].begin();
             col != sparsity_pattern[row].end(); ++col)
          {
            libmesh_assert (position != _csr.end());
            *position = *col;
            ++position;
          }

        _row_start.push_back (position);
      }
  }


  // Initialize the matrix
  libmesh_assert (!this->initialized());
  this->init ();
  libmesh_assert (this->initialized());
  //libMesh::out << "n_rows=" << n_rows << std::endl;
  //libMesh::out << "m()=" << m() << std::endl;
  libmesh_assert_equal_to (n_rows, this->m());

  // Tell the matrix about its structure.  Initialize it
  // to zero.
  for (numeric_index_type i=0; i<n_rows; i++)
    {
      const std::vector<numeric_index_type>::const_iterator
        rs = _row_start[i];

      const numeric_index_type length = _row_start[i+1] - rs;

      Q_SetLen (&_QMat, i+1, length);

      for (numeric_index_type l=0; l<length; l++)
        {
          const numeric_index_type j = *(rs+l);

          // sanity check
          //libMesh::out << "m()=" << m() << std::endl;
          //libMesh::out << "(i,j,l) = (" << i
          //          << "," << j
          //          << "," << l
          //           << ")" << std::endl;
          //libMesh::out << "pos(i,j)=" << pos(i,j)
          //              << std::endl;
          libmesh_assert_equal_to (this->pos(i,j), l);
          Q_SetEntry (&_QMat, i+1, l, j+1, 0.);
        }
    }

  // That's it!
  //libmesh_here();
}
Exemplo n.º 9
0
void Tet::select_diagonal (const Diagonal diag) const
{
  libmesh_assert_equal_to (_diagonal_selection, INVALID_DIAG);
  _diagonal_selection = diag;
}
Exemplo n.º 10
0
void TimeSolver::solve ()
{
    libmesh_assert(this->diff_solver().get());
    libmesh_assert_equal_to (&(this->diff_solver()->system()), &(this->system()));
    this->diff_solver()->solve();
}
Exemplo n.º 11
0
// The main program
int main(int argc, char** argv)
{
  // Initialize libMesh
  LibMeshInit init(argc, argv);
	
  // Parameters
  GetPot infile("fem_system_params.in");
  const Real global_tolerance          = infile("global_tolerance", 0.);
  const unsigned int nelem_target      = infile("n_elements", 400);
  const bool transient                 = infile("transient", true);
  const Real deltat                    = infile("deltat", 0.005);
  unsigned int n_timesteps             = infile("n_timesteps", 1);
  //const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
  const unsigned int coarserefinements = infile("coarserefinements", 0);
  const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
  //const unsigned int dim               = 2;
  
#ifdef LIBMESH_HAVE_EXODUS_API
  const unsigned int write_interval    = infile("write_interval", 5);
#endif

  // Create a mesh, with dimension to be overridden later, distributed
  // across the default MPI communicator.
  Mesh mesh(init.comm());
  Mesh mesh_dummy(init.comm());
  GetPot infileForMesh("convdiff_mprime.in");
  std::string find_mesh_here = infileForMesh("mesh","psiLF_mesh.xda");
  mesh.read(find_mesh_here);
  mesh_dummy.read(find_mesh_here);
	
  std::cout << "Read in mesh from: " << find_mesh_here << "\n\n";

  // And an object to refine it
  MeshRefinement mesh_refinement(mesh);
  //mesh_refinement.coarsen_by_parents() = true;
  //mesh_refinement.absolute_global_tolerance() = global_tolerance;
  //mesh_refinement.nelem_target() = nelem_target;
  //mesh_refinement.refine_fraction() = 0.3;
  //mesh_refinement.coarsen_fraction() = 0.3;
  //mesh_refinement.coarsen_threshold() = 0.1;

  //mesh_refinement.uniformly_refine(coarserefinements);
  
  // Print information about the mesh to the screen.
  mesh.print_info();

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);
  EquationSystems eqSysDummy(mesh_dummy);
 
  // Name system
  ConvDiff_MprimeSys & system = 
    equation_systems.add_system<ConvDiff_MprimeSys>("ConvDiff_MprimeSys");
  ConvDiff_MprimeSys & system_dummy = 
    eqSysDummy.add_system<ConvDiff_MprimeSys>("ConvDiff_MprimeSys");
      
  // Steady-state problem	
  system.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system));
  system_dummy.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system));

  // Sanity check that we are indeed solving a steady problem
  libmesh_assert_equal_to (n_timesteps, 1);

  // Read in all the equation systems data from the LF solve (system, solutions, rhs, etc)
  std::string find_psiLF_here = infileForMesh("psiLF_file","psiLF.xda");
  std::cout << "Looking for psiLF at: " << find_psiLF_here << "\n" << std::endl;
  
  eqSysDummy.read(find_psiLF_here, READ,
			EquationSystems::READ_HEADER |
			EquationSystems::READ_DATA |
			EquationSystems::READ_ADDITIONAL_DATA);
  
  // Check that the norm of the solution read in is what we expect it to be
  //Real readin_L2 = system.calculate_norm(*system.solution, L2);  
  //std::cout << "Read in solution norm: "<< readin_L2 << std::endl << std::endl;

	//DEBUG
  //equation_systems.write("right_back_out.xda", WRITE, EquationSystems::WRITE_DATA |
	//		 EquationSystems::WRITE_ADDITIONAL_DATA);
#ifdef LIBMESH_HAVE_GMV
  //GMVIO(equation_systems.get_mesh()).write_equation_systems(std::string("right_back_out.gmv"), equation_systems);
#endif

  // Initialize the system
  equation_systems.init ();  
  DirectSolutionTransfer sol_transfer(init.comm()); 
	sol_transfer.transfer(system_dummy.variable(system_dummy.variable_number("c")),
		system.variable(system.variable_number("c")));
	sol_transfer.transfer(system_dummy.variable(system_dummy.variable_number("zc")),
		system.variable(system.variable_number("zc")));
	sol_transfer.transfer(system_dummy.variable(system_dummy.variable_number("fc")),
		system.variable(system.variable_number("fc")));
	sol_transfer.transfer(system_dummy.variable(system_dummy.variable_number("aux_c")),
		system.variable(system.variable_number("aux_c")));
	sol_transfer.transfer(system_dummy.variable(system_dummy.variable_number("aux_zc")),
		system.variable(system.variable_number("aux_zc")));
	sol_transfer.transfer(system_dummy.variable(system_dummy.variable_number("aux_fc")),
		system.variable(system.variable_number("aux_fc")));

std::cout << "c: " << system.calculate_norm(*system.solution, 0, L2) << std::endl;
std::cout << "zc: " << system.calculate_norm(*system.solution, 1, L2) << std::endl;
std::cout << "fc: " << system.calculate_norm(*system.solution, 2, L2) << std::endl;
std::cout << "aux_c: " << system.calculate_norm(*system.solution, 3, L2) << std::endl;
std::cout << "aux_zc: " << system.calculate_norm(*system.solution, 4, L2) << std::endl;
std::cout << "aux_fc: " << system.calculate_norm(*system.solution, 5, L2) << std::endl;
	
	//save values of scalar variables; FEMSystem::point_value doesn't work for scalars...?!
	//Point p(0.0333333, 0.0333333);
	//system.stash_constants(
	//	system_dummy.point_value(system_dummy.variable_number("fconst"),p),
	//	system_dummy.point_value(system_dummy.variable_number("aux_fconst"),p));
	int endind = (*system_dummy.solution).size();
	system.stash_constants((*system_dummy.solution)(endind-2),(*system_dummy.solution)(endind-1));

  // And the nonlinear solver options
  NewtonSolver *solver = new NewtonSolver(system); 
  system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); 
  solver->quiet = infile("solver_quiet", true);
  solver->verbose = !solver->quiet;
  solver->max_nonlinear_iterations =
    infile("max_nonlinear_iterations", 15);
  solver->relative_step_tolerance =
    infile("relative_step_tolerance", 1.e-3);
  solver->relative_residual_tolerance =
    infile("relative_residual_tolerance", 0.0);
  solver->absolute_residual_tolerance =
    infile("absolute_residual_tolerance", 0.0);

  // And the linear solver options
  solver->max_linear_iterations =
    infile("max_linear_iterations", 50000);
  solver->initial_linear_tolerance =
    infile("initial_linear_tolerance", 1.e-3);

  // Print information about the system to the screen.
  equation_systems.print_info();

  // Now we begin the timestep loop to compute the time-accurate
  // solution of the equations...not that this is transient, but eh, why not...
  for (unsigned int t_step=0; t_step != n_timesteps; ++t_step)
    {
      // A pretty update message
      std::cout << "\n\nSolving time step " << t_step << ", time = "
		<< system.time << std::endl;
      
      // Adaptively solve the timestep
      unsigned int a_step = 0;
      for (; a_step != max_adaptivesteps; ++a_step)
	{ // VESTIGIAL for now ('vestigial' eh ? ;) )
      
	  std::cout << "\n\n I should be skipped what are you doing here lalalalalalala *!**!*!*!*!*!* \n\n";
	  
	  system.solve();
	  system.postprocess();
	  ErrorVector error;
	  AutoPtr<ErrorEstimator> error_estimator;

	  // To solve to a tolerance in this problem we
	  // need a better estimator than Kelly
	  if (global_tolerance != 0.)
	    {
	      // We can't adapt to both a tolerance and a mesh
	      // size at once
	      libmesh_assert_equal_to (nelem_target, 0);
	      
	      UniformRefinementEstimator *u =
		new UniformRefinementEstimator;
	      
	      // The lid-driven cavity problem isn't in H1, so
	      // lets estimate L2 error
	      u->error_norm = L2;
	      
	      error_estimator.reset(u);
	    }
	  else
	    {
	      // If we aren't adapting to a tolerance we need a
	      // target mesh size
	      libmesh_assert_greater (nelem_target, 0);
	      
	      // Kelly is a lousy estimator to use for a problem
	      // not in H1 - if we were doing more than a few
	      // timesteps we'd need to turn off or limit the
	      // maximum level of our adaptivity eventually
	      error_estimator.reset(new KellyErrorEstimator);
	    }

	  // Calculate error
	  std::vector<Real> weights(9,1.0);  // based on u, v, p, c, their adjoints, and source parameter
	  
	  // Keep the same default norm type.
	  std::vector<FEMNormType>
	    norms(1, error_estimator->error_norm.type(0));
	  error_estimator->error_norm = SystemNorm(norms, weights);

	  error_estimator->estimate_error(system, error);
	  
	  // Print out status at each adaptive step.
	  Real global_error = error.l2_norm();
	  std::cout << "Adaptive step " << a_step << ": " << std::endl;
	  if (global_tolerance != 0.)
	    std::cout << "Global_error = " << global_error
		      << std::endl;
	  if (global_tolerance != 0.)
	    std::cout << "Worst element error = " << error.maximum()
		      << ", mean = " << error.mean() << std::endl;
	  
	  if (global_tolerance != 0.)
          {
            // If we've reached our desired tolerance, we
            // don't need any more adaptive steps
            if (global_error < global_tolerance)
              break;
            mesh_refinement.flag_elements_by_error_tolerance(error);
          }
	  else
	    {
	      // If flag_elements_by_nelem_target returns true, this
	      // should be our last adaptive step.
	      if (mesh_refinement.flag_elements_by_nelem_target(error))
		{
		  mesh_refinement.refine_and_coarsen_elements();
		  equation_systems.reinit();
		  a_step = max_adaptivesteps;
		  break;
		}
	    }

	  // Carry out the adaptive mesh refinement/coarsening
	  mesh_refinement.refine_and_coarsen_elements();
	  equation_systems.reinit();
	  
	  std::cout << "Refined mesh to "
		    << mesh.n_active_elem()
		    << " active elements and "
		    << equation_systems.n_active_dofs()
		    << " active dofs." << std::endl;
	} // End loop over adaptive steps
      
      // Do one last solve if necessary
      if (a_step == max_adaptivesteps)
	{	  
	  QoISet qois;
	  std::vector<unsigned int> qoi_indices;
	  
	  qoi_indices.push_back(0);
	  qois.add_indices(qoi_indices);
	  
	  qois.set_weight(0, 1.0);

	  system.assemble_qoi_sides = true; //QoI doesn't involve sides
	  
	  std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve start ~*~*~*~*~*~*~*~*~\n" << std::endl;
	  std::pair<unsigned int, Real> adjsolve = system.adjoint_solve();
	  std::cout << "number of iterations to solve adjoint: " << adjsolve.first << std::endl;
	  std::cout << "final residual of adjoint solve: " << adjsolve.second << std::endl;
 		std::cout << "\n~*~*~*~*~*~*~*~*~ adjoint solve end ~*~*~*~*~*~*~*~*~" << std::endl;
 		
	  NumericVector<Number> &dual_solution = system.get_adjoint_solution(0);
	  NumericVector<Number> &primal_solution = *system.solution;
				
	  primal_solution.swap(dual_solution);
	  ExodusII_IO(mesh).write_timestep("super_adjoint.exo",
	                                 equation_systems,
	                                 1, /* This number indicates how many time steps
	                                       are being written to the file */
	                                 system.time);
	  primal_solution.swap(dual_solution);

    system.assemble(); //overwrite residual read in from psiLF solve
        
	  // The total error estimate
	  system.postprocess(); //to compute M_HF(psiLF) and M_LF(psiLF) terms
	  Real QoI_error_estimate = (-0.5*(system.rhs)->dot(dual_solution)) + system.get_MHF_psiLF() - system.get_MLF_psiLF();
	  std::cout << "\n\n 0.5*M'_HF(psiLF)(superadj): " << std::setprecision(17) << 0.5*(system.rhs)->dot(dual_solution) << "\n";
	  std::cout << " M_HF(psiLF): " << std::setprecision(17) << system.get_MHF_psiLF() << "\n";
  	std::cout << " M_LF(psiLF): " << std::setprecision(17) << system.get_MLF_psiLF() << "\n";
	  std::cout << "\n\n Residual L2 norm: " << system.calculate_norm(*system.rhs, L2) << "\n"; 
	  std::cout << " Residual discrete L2 norm: " << system.calculate_norm(*system.rhs, DISCRETE_L2) << "\n";
	  std::cout << " Super-adjoint L2 norm: " << system.calculate_norm(dual_solution, L2) << "\n";
	  std::cout << " Super-adjoint discrete L2 norm: " << system.calculate_norm(dual_solution, DISCRETE_L2) << "\n";
	  std::cout << "\n\n QoI error estimate: " << std::setprecision(17) << QoI_error_estimate << "\n\n";
	  
	  //DEBUG
	  std::cout << "\n------------ herp derp ------------" << std::endl;
	  //libMesh::out.precision(16);
	  //dual_solution.print();
	  //system.get_adjoint_rhs().print();

		AutoPtr<NumericVector<Number> > adjresid = system.solution->clone();
		(system.matrix)->vector_mult(*adjresid,system.get_adjoint_solution(0));
		SparseMatrix<Number>& adjmat = *system.matrix; 
		(system.matrix)->get_transpose(adjmat);
		adjmat.vector_mult(*adjresid,system.get_adjoint_solution(0));
		//std::cout << "******************** matrix-superadj product (libmesh) ************************" << std::endl;
		//adjresid->print();
		adjresid->add(-1.0, system.get_adjoint_rhs(0));
		//std::cout << "******************** superadjoint system residual (libmesh) ***********************" << std::endl;
		//adjresid->print();
		std::cout << "\n\nadjoint system residual (discrete L2): " << system.calculate_norm(*adjresid,DISCRETE_L2) << std::endl;
		std::cout << "adjoint system residual (L2, all): " << system.calculate_norm(*adjresid,L2) << std::endl;
		std::cout << "adjoint system residual (L2, 0): " << system.calculate_norm(*adjresid,0,L2) << std::endl;
		std::cout << "adjoint system residual (L2, 1): " << system.calculate_norm(*adjresid,1,L2) << std::endl;
		std::cout << "adjoint system residual (L2, 2): " << system.calculate_norm(*adjresid,2,L2) << std::endl;
		std::cout << "adjoint system residual (L2, 3): " << system.calculate_norm(*adjresid,3,L2) << std::endl;
		std::cout << "adjoint system residual (L2, 4): " << system.calculate_norm(*adjresid,4,L2) << std::endl;
		std::cout << "adjoint system residual (L2, 5): " << system.calculate_norm(*adjresid,5,L2) << std::endl;
	/*	
		AutoPtr<NumericVector<Number> > sadj_matlab = system.solution->clone();
		AutoPtr<NumericVector<Number> > adjresid_matlab = system.solution->clone();
		if(FILE *fp=fopen("superadj_matlab.txt","r")){
	  	Real value;
	  	int counter = 0;
	  	int flag = 1;
	  	while(flag != -1){
	  		flag = fscanf(fp,"%lf",&value);
	  		if(flag != -1){
					sadj_matlab->set(counter, value);
					counter += 1;
	  		}
	  	}
	  	fclose(fp);
		}
		(system.matrix)->vector_mult(*adjresid_matlab,*sadj_matlab);
		//std::cout << "******************** matrix-superadj product (matlab) ***********************" << std::endl;
		//adjresid_matlab->print();
		adjresid_matlab->add(-1.0, system.get_adjoint_rhs(0));
		//std::cout << "******************** superadjoint system residual (matlab) ***********************" << std::endl;
		//adjresid_matlab->print();
		std::cout << "\n\nmatlab import adjoint system residual (discrete L2): " << system.calculate_norm(*adjresid_matlab,DISCRETE_L2) << "\n" << std::endl;
	*/
	/*	
		AutoPtr<NumericVector<Number> > sadj_fwd_hack = system.solution->clone();
		AutoPtr<NumericVector<Number> > adjresid_fwd_hack = system.solution->clone();
		if(FILE *fp=fopen("superadj_forward_hack.txt","r")){
	  	Real value;
	  	int counter = 0;
	  	int flag = 1;
	  	while(flag != -1){
	  		flag = fscanf(fp,"%lf",&value);
	  		if(flag != -1){
					sadj_fwd_hack->set(counter, value);
					counter += 1;
	  		}
	  	}
	  	fclose(fp);
		}
		(system.matrix)->vector_mult(*adjresid_fwd_hack,*sadj_fwd_hack);
		//std::cout << "******************** matrix-superadj product (fwd_hack) ***********************" << std::endl;
		//adjresid_fwd_hack->print();
		adjresid_fwd_hack->add(-1.0, system.get_adjoint_rhs(0));
		//std::cout << "******************** superadjoint system residual (fwd_hack) ***********************" << std::endl;
		//adjresid_fwd_hack->print();
		std::cout << "\n\nfwd_hack import adjoint system residual (discrete L2): " << system.calculate_norm(*adjresid_fwd_hack,DISCRETE_L2) << "\n" << std::endl;
		std::cout << "fwd_hack adjoint system residual (L2, 0): " << system.calculate_norm(*adjresid_fwd_hack,0,L2) << std::endl;
		std::cout << "fwd_hack adjoint system residual (L2, 1): " << system.calculate_norm(*adjresid_fwd_hack,1,L2) << std::endl;
		std::cout << "fwd_hack adjoint system residual (L2, 2): " << system.calculate_norm(*adjresid_fwd_hack,2,L2) << std::endl;
		std::cout << "fwd_hack adjoint system residual (L2, 3): " << system.calculate_norm(*adjresid_fwd_hack,3,L2) << std::endl;
		std::cout << "fwd_hack adjoint system residual (L2, 4): " << system.calculate_norm(*adjresid_fwd_hack,4,L2) << std::endl;
		std::cout << "fwd_hack adjoint system residual (L2, 5): " << system.calculate_norm(*adjresid_fwd_hack,5,L2) << std::endl;
	*/	
		//std::cout << "************************ system.matrix ***********************" << std::endl;
		//system.matrix->print();
		
	  std::cout << "\n------------ herp derp ------------" << std::endl;

	  // The cell wise breakdown
	  ErrorVector cell_wise_error;
	  cell_wise_error.resize((system.rhs)->size());
	  for(unsigned int i = 0; i < (system.rhs)->size() ; i++)
	    {
	      if(i < system.get_mesh().n_elem())
			    cell_wise_error[i] = fabs(-0.5*((system.rhs)->el(i) * dual_solution(i)) 
			    		+ system.get_MHF_psiLF(i) - system.get_MLF_psiLF(i)); 
    		else
    			cell_wise_error[i] = fabs(-0.5*((system.rhs)->el(i) * dual_solution(i)));
	      		
	      /*csv from 'save data' from gmv output gives a few values at each node point (value 
	      for every element that shares that node), yet paraview display only seems to show one 
	      of them -> the value in an element is given at each of the nodes that it has, hence the 
	      repetition; what is displayed in paraview is each element's value; even though MHF_psiLF 
	      and MLF_psiLF are stored by element this seems to give elemental contributions that 
	      agree with if we had taken the superadj-residual dot product by integrating over elements*/
	      
	      /*at higher mesh resolutions and lower k, weird-looking artifacts start to appear and
	      it no longer agrees with output from manual integration of superadj-residual...*/
	    }
	  // Plot it
	  std::ostringstream error_gmv;
	  error_gmv << "error.gmv";
	  cell_wise_error.plot_error(error_gmv.str(), equation_systems.get_mesh());
	  
	  //alternate element-wise breakdown, outputed as values matched to element centroids; for matlab plotz
	  primal_solution.swap(dual_solution);
	 	system.postprocess(1);
	 	primal_solution.swap(dual_solution);
	 	system.postprocess(2);
	 	std::cout << "\n\n -0.5*M'_HF(psiLF)(superadj): " << std::setprecision(17) << system.get_half_adj_weighted_resid() << "\n";
	 	primal_solution.swap(dual_solution);
	 	
	 	std::string write_error_here = infileForMesh("error_est_output_file", "error_est_breakdown.dat");
    std::ofstream output(write_error_here);
		for(unsigned int i = 0 ; i < system.get_mesh().n_elem(); i++){
			Point elem_cent = system.get_mesh().elem(i)->centroid();
			if(output.is_open()){
				output << elem_cent(0) << " " << elem_cent(1) << " " 
					<< fabs(system.get_half_adj_weighted_resid(i) + system.get_MHF_psiLF(i) - system.get_MLF_psiLF(i)) << "\n";
			}
		}
		output.close();
	  
	} // End if at max adaptive steps
      
#ifdef LIBMESH_HAVE_EXODUS_API
    // Write out this timestep if we're requested to
      if ((t_step+1)%write_interval == 0)
	{
        std::ostringstream file_name;
	/*
        // We write the file in the ExodusII format.
        file_name << "out_"
                  << std::setw(3)
                  << std::setfill('0')
                  << std::right
                  << t_step+1
                  << ".e";
				//this should write out the primal which should be the same as what's read in...
				ExodusII_IO(mesh).write_timestep(file_name.str(),
								                        equation_systems,
								                        1, //number of time steps written to file
								                        system.time);
	*/
	}
#endif // #ifdef LIBMESH_HAVE_EXODUS_API
    }
  
  // All done.
  return 0;
  
} //end main
Exemplo n.º 12
0
void InverseDistanceInterpolation<KDDim>::interpolate (const Point               & /* pt */,
                                                       const std::vector<size_t> &src_indices,
                                                       const std::vector<Real>   &src_dist_sqr,
                                                       std::vector<Number>::iterator &out_it) const
{
  // We explicitly assume that the input source points are sorted from closest to
  // farthests.  assert that assumption in DEBUG mode.
#ifdef DEBUG
  if (!src_dist_sqr.empty())
    {
      Real min_dist = src_dist_sqr.front();
      std::vector<Real>::const_iterator it = src_dist_sqr.begin();

      for (++it; it!= src_dist_sqr.end(); ++it)
        {
          if (*it < min_dist) libmesh_error();
          min_dist = *it;
        }
    }
#endif


  libmesh_assert_equal_to (src_dist_sqr.size(), src_indices.size());


  // Compute the interpolation weights & interpolated value
  const unsigned int n_fv = this->n_field_variables();
  _vals.resize(n_fv); /**/ std::fill (_vals.begin(), _vals.end(), Number(0.));

  Real tot_weight = 0.;

  std::vector<Real>::const_iterator src_dist_sqr_it=src_dist_sqr.begin();
  std::vector<size_t>::const_iterator src_idx_it=src_indices.begin();

  // Loop over source points
  while ((src_dist_sqr_it != src_dist_sqr.end()) &&
         (src_idx_it      != src_indices.end()))
    {
      libmesh_assert_greater_equal (*src_dist_sqr_it, 0.);

      const Real
        dist_sq = std::max(*src_dist_sqr_it, std::numeric_limits<Real>::epsilon()),
        weight = 1./std::pow(dist_sq, _half_power);

      tot_weight += weight;

      const unsigned int src_idx = *src_idx_it;

      // loop over field variables
      for (unsigned int v=0; v<n_fv; v++)
        {
          libmesh_assert_less (src_idx*n_fv+v, _src_vals.size());
          _vals[v] += _src_vals[src_idx*n_fv+v]*weight;
        }

      ++src_dist_sqr_it;
      ++src_idx_it;
    }

  // don't forget normalizing term & set the output buffer!
  for (unsigned int v=0; v<n_fv; v++, ++out_it)
    {
      _vals[v] /= tot_weight;

      *out_it = _vals[v];
    }
}
Exemplo n.º 13
0
void InverseDistanceInterpolation<KDDim>::interpolate_field_data (const std::vector<std::string> &field_names,
                                                                  const std::vector<Point>  &tgt_pts,
                                                                  std::vector<Number> &tgt_vals) const
{
  libmesh_experimental();

  // forcibly initialize, if needed
#ifdef LIBMESH_HAVE_NANOFLANN
  if (_kd_tree.get() == NULL)
    const_cast<InverseDistanceInterpolation<KDDim>*>(this)->construct_kd_tree();
#endif

  START_LOG ("interpolate_field_data()", "InverseDistanceInterpolation<>");

  libmesh_assert_equal_to (field_names.size(), this->n_field_variables());

  // If we already have field variables, we assume we are appending.
  // that means the names and ordering better be identical!
  if (_names.size() != field_names.size())
    {
      libMesh::err << "ERROR:  when adding field data to an existing list the\n"
                   << "varaible list must be the same!\n";
      libmesh_error();
    }
  for (unsigned int v=0; v<_names.size(); v++)
    if (_names[v] != field_names[v])
      {
        libMesh::err << "ERROR:  when adding field data to an existing list the\n"
                     << "varaible list must be the same!\n";
        libmesh_error();
      }

  tgt_vals.resize (tgt_pts.size()*this->n_field_variables());

#ifdef LIBMESH_HAVE_NANOFLANN
  {
    std::vector<Number>::iterator out_it = tgt_vals.begin();

    const size_t num_results = std::min((size_t) _n_interp_pts, _src_pts.size());

    std::vector<size_t> ret_index(num_results);
    std::vector<Real>   ret_dist_sqr(num_results);

    for (std::vector<Point>::const_iterator tgt_it=tgt_pts.begin();
         tgt_it != tgt_pts.end(); ++tgt_it)
      {
        const Point &tgt(*tgt_it);
        const Real query_pt[] = { tgt(0), tgt(1), tgt(2) };

        _kd_tree->knnSearch(&query_pt[0], num_results, &ret_index[0], &ret_dist_sqr[0]);

        this->interpolate (tgt, ret_index, ret_dist_sqr, out_it);

        // libMesh::out << "knnSearch(): num_results=" << num_results << "\n";
        // for (size_t i=0;i<num_results;i++)
        //   libMesh::out << "idx[" << i << "]="
        //       << std::setw(6) << ret_index[i]
        //       << "\t dist["<< i << "]=" << ret_dist_sqr[i]
        //       << "\t val[" << std::setw(6) << ret_index[i] << "]=" << _src_vals[ret_index[i]]
        //       << std::endl;
        // libMesh::out << "\n";

        // libMesh::out << "ival=" << _vals[0] << '\n';
      }
  }
#else

  libMesh::err << "ERROR:  This functionality requires the library to be configured\n"
               << "with nanoflann KD-Tree approximate nearest neighbor support!\n"
               << std::endl;
  libmesh_error();

#endif

  STOP_LOG ("interpolate_field_data()", "InverseDistanceInterpolation<>");
}
Exemplo n.º 14
0
void MeshfreeInterpolation::gather_remote_data ()
{
#ifndef LIBMESH_HAVE_MPI

  // no MPI -- no-op
  return;

#else

  // This function must be run on all processors at once
  parallel_object_only();

  START_LOG ("gather_remote_data()", "MeshfreeInterpolation");

  // block to avoid incorrect completion if called in quick succession on
  // two different MeshfreeInterpolation objects
  this->comm().barrier();

  std::vector<Real> send_buf, recv_buf;

  libmesh_assert_equal_to (_src_vals.size(),
                           _src_pts.size()*this->n_field_variables());

  send_buf.reserve (_src_pts.size()*(3 + this->n_field_variables()));

  // Everyone packs their data at the same time
  for (unsigned int p_idx=0, v_idx=0; p_idx<_src_pts.size(); p_idx++)
    {
      const Point &pt(_src_pts[p_idx]);

      send_buf.push_back(pt(0));
      send_buf.push_back(pt(1));
      send_buf.push_back(pt(2));

      for (unsigned int var=0; var<this->n_field_variables(); var++)
        {
          libmesh_assert_less (v_idx, _src_vals.size());
#ifdef LIBMESH_USE_COMPLEX_NUMBERS
          send_buf.push_back (_src_vals[v_idx].real());
          send_buf.push_back (_src_vals[v_idx].imag());
          v_idx++;

#else
          send_buf.push_back (_src_vals[v_idx++]);
#endif
        }
    }

  // Send our data to everyone else.  Note that MPI-1 said you could not
  // use the same buffer in nonblocking sends, but that restriction has
  // recently been removed.
  std::vector<Parallel::Request> send_request(this->n_processors()-1);

  // Use a tag for best practices.  In debug mode parallel_only() blocks above
  // so we can be sure there is no other shenanigarry going on, but in optimized
  // mode there is no such guarantee - other prcoessors could be somewhere else
  // completing some other communication, and we don't want to intercept that.
  Parallel::MessageTag tag = this->comm().get_unique_tag ( 6000 );

  for (unsigned int proc=0, cnt=0; proc<this->n_processors(); proc++)
    if (proc != this->processor_id())
      this->comm().send (proc, send_buf, send_request[cnt++], tag);

  // All data has been sent.  Receive remote data in any order
  for (processor_id_type comm_step=0; comm_step<(this->n_processors()-1); comm_step++)
    {
      // blocking receive
      this->comm().receive (Parallel::any_source, recv_buf, tag);

      // Add their data to our list
      Point  pt;
      Number val;
      std::vector<Real>::const_iterator it=recv_buf.begin();
      while (it != recv_buf.end())
        {
          pt(0) = *it, ++it;
          pt(1) = *it, ++it;
          pt(2) = *it, ++it;

          _src_pts.push_back(pt);

          for (unsigned int var=0; var<this->n_field_variables(); var++)
            {
#ifdef LIBMESH_USE_COMPLEX_NUMBERS
              Real re = *it; ++it;
              Real im = *it; ++it;

              val = Number(re,im);
#else
              val = *it, ++it;
#endif
              _src_vals.push_back(val);
            }
        }
    }

  Parallel::wait (send_request);

  STOP_LOG  ("gather_remote_data()", "MeshfreeInterpolation");

#endif // LIBMESH_HAVE_MPI
}
Exemplo n.º 15
0
void EnsightIO::write_vector_ascii(const std::string &sys, const std::vector<std::string> &vec, const std::string &var_name)
{
  std::ostringstream vec_file;
  vec_file<<_ensight_file_name<<"_"<<var_name<<".vec";

  vec_file << std::setw(3)
           << std::setprecision(0)
           << std::setfill('0')
           << std::right
           << _time_steps.size()-1;

  FILE * fout = fopen(vec_file.str().c_str(),"w");
  fprintf(fout,"Per vector per value\n");
  fprintf(fout,"part\n");
  fprintf(fout,"%10d\n",1);
  fprintf(fout,"coordinates\n");

  // Get a constant reference to the mesh object.
  const MeshBase& the_mesh = MeshOutput<MeshBase>::mesh();

  // The dimension that we are running
  const unsigned int dim = the_mesh.mesh_dimension();

  const System &system = _equation_systems.get_system(sys);

  const DofMap& dof_map = system.get_dof_map();

  const unsigned int u_var = system.variable_number(vec[0]);
  const unsigned int v_var = system.variable_number(vec[1]);
  const unsigned int w_var = (dim==3) ? system.variable_number(vec[2]) : 0;

  std::vector<dof_id_type> dof_indices;
  std::vector<dof_id_type> dof_indices_u;
  std::vector<dof_id_type> dof_indices_v;
  std::vector<dof_id_type> dof_indices_w;

  // Now we will loop over all the elements in the mesh.
  MeshBase::const_element_iterator       el     = the_mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator end_el = the_mesh.active_local_elements_end();

  typedef std::map<int,std::vector<Real> > map_local_soln;
  typedef map_local_soln::iterator  local_soln_iterator;

  map_local_soln local_soln;

  for ( ; el != end_el ; ++el){

    const Elem* elem = *el;

    const FEType& fe_type    = system.variable_type(u_var);

    dof_map.dof_indices (elem, dof_indices);
    dof_map.dof_indices (elem, dof_indices_u,u_var);
    dof_map.dof_indices (elem, dof_indices_v,v_var);
    if(dim==3)  dof_map.dof_indices (elem, dof_indices,w_var);


    std::vector<Number>       elem_soln_u;
    std::vector<Number>       elem_soln_v;
    std::vector<Number>       elem_soln_w;

    std::vector<Number>       nodal_soln_u;
    std::vector<Number>       nodal_soln_v;
    std::vector<Number>       nodal_soln_w;

    elem_soln_u.resize(dof_indices_u.size());
    elem_soln_v.resize(dof_indices_v.size());
    if(dim == 3) elem_soln_w.resize(dof_indices_w.size());

    for (unsigned int i = 0; i < dof_indices_u.size(); i++)
      {
        elem_soln_u[i] = system.current_solution(dof_indices_u[i]);
        elem_soln_v[i] = system.current_solution(dof_indices_v[i]);
        if(dim==3) elem_soln_w[i] = system.current_solution(dof_indices_w[i]);
      }

    FEInterface::nodal_soln (dim,fe_type,elem,elem_soln_u,nodal_soln_u);
    FEInterface::nodal_soln (dim,fe_type,elem,elem_soln_v,nodal_soln_v);
    if(dim == 3) FEInterface::nodal_soln (dim,fe_type,elem,elem_soln_w,nodal_soln_w);


    libmesh_assert_equal_to (nodal_soln_u.size(), elem->n_nodes());
    libmesh_assert_equal_to (nodal_soln_v.size(), elem->n_nodes());

#ifdef LIBMESH_ENABLE_COMPLEX
    libMesh::err << "Complex-valued Ensight output not yet supported" << std::endl;
    libmesh_not_implemented()
#endif

      for (unsigned int n=0; n<elem->n_nodes(); n++)
        {
          std::vector<Real> node_vec(3);
          node_vec[0]= libmesh_real(nodal_soln_u[n]);
          node_vec[1]= libmesh_real(nodal_soln_v[n]);
          node_vec[2]=0.0;
          if(dim==3) node_vec[2]= libmesh_real(nodal_soln_w[n]);
          local_soln[elem->node(n)] = node_vec;
        }

  }

  local_soln_iterator sol = local_soln.begin();
  const local_soln_iterator sol_end = local_soln.end();

  for(; sol != sol_end; ++sol)
    fprintf(fout,"%12.5e\n",static_cast<double>((*sol).second[0]));
  sol = local_soln.begin();
  for(; sol != sol_end; ++sol)
    fprintf(fout,"%12.5e\n",static_cast<double>((*sol).second[1]));
  sol = local_soln.begin();
  for(; sol != sol_end; ++sol)
    fprintf(fout,"%12.5e\n",static_cast<double>((*sol).second[2]));

  fclose(fout);

}
Exemplo n.º 16
0
bool FEMPhysics::eulerian_residual (bool request_jacobian,
                                    DiffContext & /*c*/)
{
  // Only calculate a mesh movement residual if it's necessary
  if (!_mesh_sys)
    return request_jacobian;

  libmesh_not_implemented();

#if 0
  FEMContext & context = cast_ref<FEMContext &>(c);

  // This function only supports fully coupled mesh motion for now
  libmesh_assert_equal_to (_mesh_sys, this);

  unsigned int n_qpoints = (context.get_element_qrule())->n_points();

  const unsigned int n_x_dofs = (_mesh_x_var == libMesh::invalid_uint) ?
    0 : context.dof_indices_var[_mesh_x_var].size();
  const unsigned int n_y_dofs = (_mesh_y_var == libMesh::invalid_uint) ?
    0 : context.dof_indices_var[_mesh_y_var].size();
  const unsigned int n_z_dofs = (_mesh_z_var == libMesh::invalid_uint) ?
    0 : context.dof_indices_var[_mesh_z_var].size();

  const unsigned int mesh_xyz_var = n_x_dofs ? _mesh_x_var :
    (n_y_dofs ? _mesh_y_var :
     (n_z_dofs ? _mesh_z_var :
      libMesh::invalid_uint));

  // If we're our own _mesh_sys, we'd better be in charge of
  // at least one coordinate, and we'd better have the same
  // FE type for all coordinates we are in charge of
  libmesh_assert_not_equal_to (mesh_xyz_var, libMesh::invalid_uint);
  libmesh_assert(!n_x_dofs || context.element_fe_var[_mesh_x_var] ==
                 context.element_fe_var[mesh_xyz_var]);
  libmesh_assert(!n_y_dofs || context.element_fe_var[_mesh_y_var] ==
                 context.element_fe_var[mesh_xyz_var]);
  libmesh_assert(!n_z_dofs || context.element_fe_var[_mesh_z_var] ==
                 context.element_fe_var[mesh_xyz_var]);

  const std::vector<std::vector<Real>>     & psi =
    context.element_fe_var[mesh_xyz_var]->get_phi();

  for (unsigned int var = 0; var != context.n_vars(); ++var)
    {
      // Mesh motion only affects time-evolving variables
      if (this->is_time_evolving(var))
        continue;

      // The mesh coordinate variables themselves are Lagrangian,
      // not Eulerian, and no convective term is desired.
      if (/*_mesh_sys == this && */
          (var == _mesh_x_var ||
           var == _mesh_y_var ||
           var == _mesh_z_var))
        continue;

      // Some of this code currently relies on the assumption that
      // we can pull mesh coordinate data from our own system
      if (_mesh_sys != this)
        libmesh_not_implemented();

      // This residual should only be called by unsteady solvers:
      // if the mesh is steady, there's no mesh convection term!
      UnsteadySolver * unsteady;
      if (this->time_solver->is_steady())
        return request_jacobian;
      else
        unsteady = cast_ptr<UnsteadySolver*>(this->time_solver.get());

      const std::vector<Real> & JxW =
        context.element_fe_var[var]->get_JxW();

      const std::vector<std::vector<Real>> & phi =
        context.element_fe_var[var]->get_phi();

      const std::vector<std::vector<RealGradient>> & dphi =
        context.element_fe_var[var]->get_dphi();

      const unsigned int n_u_dofs = context.dof_indices_var[var].size();

      DenseSubVector<Number> & Fu = *context.elem_subresiduals[var];
      DenseSubMatrix<Number> & Kuu = *context.elem_subjacobians[var][var];

      DenseSubMatrix<Number> * Kux = n_x_dofs ?
        context.elem_subjacobians[var][_mesh_x_var] : nullptr;
      DenseSubMatrix<Number> * Kuy = n_y_dofs ?
        context.elem_subjacobians[var][_mesh_y_var] : nullptr;
      DenseSubMatrix<Number> * Kuz = n_z_dofs ?
        context.elem_subjacobians[var][_mesh_z_var] : nullptr;

      std::vector<Real> delta_x(n_x_dofs, 0.);
      std::vector<Real> delta_y(n_y_dofs, 0.);
      std::vector<Real> delta_z(n_z_dofs, 0.);

      for (unsigned int i = 0; i != n_x_dofs; ++i)
        {
          unsigned int j = context.dof_indices_var[_mesh_x_var][i];
          delta_x[i] = libmesh_real(this->current_solution(j)) -
            libmesh_real(unsteady->old_nonlinear_solution(j));
        }

      for (unsigned int i = 0; i != n_y_dofs; ++i)
        {
          unsigned int j = context.dof_indices_var[_mesh_y_var][i];
          delta_y[i] = libmesh_real(this->current_solution(j)) -
            libmesh_real(unsteady->old_nonlinear_solution(j));
        }

      for (unsigned int i = 0; i != n_z_dofs; ++i)
        {
          unsigned int j = context.dof_indices_var[_mesh_z_var][i];
          delta_z[i] = libmesh_real(this->current_solution(j)) -
            libmesh_real(unsteady->old_nonlinear_solution(j));
        }

      for (unsigned int qp = 0; qp != n_qpoints; ++qp)
        {
          Gradient grad_u = context.interior_gradient(var, qp);
          RealGradient convection(0.);

          for (unsigned int i = 0; i != n_x_dofs; ++i)
            convection(0) += delta_x[i] * psi[i][qp];
          for (unsigned int i = 0; i != n_y_dofs; ++i)
            convection(1) += delta_y[i] * psi[i][qp];
          for (unsigned int i = 0; i != n_z_dofs; ++i)
            convection(2) += delta_z[i] * psi[i][qp];

          for (unsigned int i = 0; i != n_u_dofs; ++i)
            {
              Number JxWxPhiI = JxW[qp] * phi[i][qp];
              Fu(i) += (convection * grad_u) * JxWxPhiI;
              if (request_jacobian)
                {
                  Number JxWxPhiI = JxW[qp] * phi[i][qp];
                  for (unsigned int j = 0; j != n_u_dofs; ++j)
                    Kuu(i,j) += JxWxPhiI * (convection * dphi[j][qp]);

                  Number JxWxPhiIoverDT = JxWxPhiI/this->deltat;

                  Number JxWxPhiIxDUDXoverDT = JxWxPhiIoverDT * grad_u(0);
                  for (unsigned int j = 0; j != n_x_dofs; ++j)
                    (*Kux)(i,j) += JxWxPhiIxDUDXoverDT * psi[j][qp];

                  Number JxWxPhiIxDUDYoverDT = JxWxPhiIoverDT * grad_u(1);
                  for (unsigned int j = 0; j != n_y_dofs; ++j)
                    (*Kuy)(i,j) += JxWxPhiIxDUDYoverDT * psi[j][qp];

                  Number JxWxPhiIxDUDZoverDT = JxWxPhiIoverDT * grad_u(2);
                  for (unsigned int j = 0; j != n_z_dofs; ++j)
                    (*Kuz)(i,j) += JxWxPhiIxDUDZoverDT * psi[j][qp];
                }
            }
        }
    }
#endif // 0

  return request_jacobian;
}
Exemplo n.º 17
0
bool Edge2::is_node_on_edge(const unsigned int,
                            const unsigned int libmesh_dbg_var(e)) const
{
  libmesh_assert_equal_to (e, 0);
  return true;
}
Exemplo n.º 18
0
void MEDITIO::write_ascii (const std::string & fname,
                           const std::vector<Number> * vec,
                           const std::vector<std::string> * solution_names)
{
  // Current lacks in implementation:
  //  (i)   only 3D meshes.
  //  (ii)  only QUAD4, TRI3, TET4 elements, others are omitted !
  //  (iii) no distinction between materials.
  //  (iv)  no vector output, just first scalar as output

  // libmesh_assert three dimensions (should be extended later)
  libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().mesh_dimension(), 3);

  // Open the output file stream
  std::ofstream out_stream (fname.c_str());

  // Make sure it opened correctly
  if (!out_stream.good())
    libmesh_file_error(fname.c_str());

  // Get a reference to the mesh
  const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();

  // Begin interfacing with the MEdit data file
  {
    // header:
    out_stream << "MeshVersionFormatted  1\n";
    out_stream << "Dimension  3\n";
    out_stream << "# Mesh generated by libmesh\n\n";

    // write the nodes:
    out_stream << "# Set of mesh vertices\n";
    out_stream << "Vertices\n";
    out_stream << the_mesh.n_nodes() << "\n";

    for (unsigned int v=0; v<the_mesh.n_nodes(); v++)
      out_stream << the_mesh.point(v)(0) << " " << the_mesh.point(v)(1) << " " << the_mesh.point(v)(2) << " 0\n";
  }

  {
    // write the connectivity:
    out_stream << "\n# Set of Polys\n\n";

    // count occurrences of output elements:
    int n_tri3  = 0;
    int n_quad4 = 0;
    int n_tet4  = 0;

    for (const auto & elem : the_mesh.active_element_ptr_range())
      {
        if (elem->type() == TRI3)  n_tri3++;
        if (elem->type() == QUAD4) n_quad4++;
        if (elem->type() == QUAD9) n_quad4+=4; // (QUAD9 is written as 4 QUAD4.)
        if (elem->type() == TET4)  n_tet4++;
      }

    // First: write out TRI3 elements:
    out_stream << "Triangles\n";
    out_stream << n_tri3 << "\n";

    for (const auto & elem : the_mesh.active_element_ptr_range())
      if (elem->type() == TRI3)
        out_stream << elem->node_id(0)+1  << " "
                   << elem->node_id(1)+1  << " "
                   << elem->node_id(2)+1  << " 0\n";

    // Second: write out QUAD4 elements:
    out_stream << "Quadrilaterals\n";
    out_stream << n_quad4 << "\n";

    for (const auto & elem : the_mesh.active_element_ptr_range())
      {
        if (elem->type() == QUAD4)
          {
            out_stream << elem->node_id(0)+1  << " "
                       << elem->node_id(1)+1  << " "
                       << elem->node_id(2)+1  << " "
                       << elem->node_id(3)+1  <<" 0\n";
          } // if
        else if (elem->type() == QUAD9)
          {
            out_stream << elem->node_id(0)+1  << " "
                       << elem->node_id(4)+1  << " "
                       << elem->node_id(8)+1  << " "
                       << elem->node_id(7)+1  <<" 0\n";
            out_stream << elem->node_id(7)+1  << " "
                       << elem->node_id(8)+1  << " "
                       << elem->node_id(6)+1  << " "
                       << elem->node_id(3)+1  <<" 0\n";
            out_stream << elem->node_id(4)+1  << " "
                       << elem->node_id(1)+1  << " "
                       << elem->node_id(5)+1  << " "
                       << elem->node_id(8)+1  <<" 0\n";
            out_stream << elem->node_id(8)+1  << " "
                       << elem->node_id(5)+1  << " "
                       << elem->node_id(2)+1  << " "
                       << elem->node_id(6)+1  <<" 0\n";
          }
      }

    // Third: write out TET4 elements:
    out_stream << "Tetrahedra\n";
    out_stream << n_tet4 << "\n";

    for (const auto & elem : the_mesh.active_element_ptr_range())
      if (elem->type() == TET4)
        {
          out_stream << elem->node_id(0)+1  << " "
                     << elem->node_id(1)+1  << " "
                     << elem->node_id(2)+1  << " "
                     << elem->node_id(3)+1  <<" 0\n";
        }
  }
  // end of the out file
  out_stream << '\n' << "# end of file\n";

  // optionally write the data
  if ((solution_names != libmesh_nullptr) &&
      (vec != libmesh_nullptr))
    {
      // Open the ".bb" file stream
      std::size_t idx = fname.find_last_of(".");
      std::string bbname = fname.substr(0,idx) + ".bb";

      std::ofstream bbout (bbname.c_str());

      // Make sure it opened correctly
      if (!bbout.good())
        libmesh_file_error(bbname.c_str());

      // Header: 3: 3D mesh, 1: scalar output, 2: node-indexed
      const std::size_t n_vars = solution_names->size();
      bbout << "3 1 " << the_mesh.n_nodes() << " 2\n";
      for (dof_id_type n=0; n<the_mesh.n_nodes(); n++)
        bbout << std::setprecision(10) << (*vec)[n*n_vars + scalar_idx] << " ";
      bbout << "\n";
    } // endif
}
Exemplo n.º 19
0
void ParmetisPartitioner::initialize (const MeshBase& mesh,
                                      const unsigned int n_sbdmns)
{
  const dof_id_type n_active_local_elem = mesh.n_active_local_elem();

  // Set parameters.
  _pmetis->wgtflag = 2;                                      // weights on vertices only
  _pmetis->ncon    = 1;                                      // one weight per vertex
  _pmetis->numflag = 0;                                      // C-style 0-based numbering
  _pmetis->nparts  = static_cast<Parmetis::idx_t>(n_sbdmns); // number of subdomains to create
  _pmetis->edgecut = 0;                                      // the numbers of edges cut by the
                                                             // partition

  // Initialize data structures for ParMETIS
  _pmetis->vtxdist.resize (mesh.n_processors()+1); std::fill (_pmetis->vtxdist.begin(), _pmetis->vtxdist.end(), 0);
  _pmetis->tpwgts.resize  (_pmetis->nparts);       std::fill (_pmetis->tpwgts.begin(),  _pmetis->tpwgts.end(),  1./_pmetis->nparts);
  _pmetis->ubvec.resize   (_pmetis->ncon);         std::fill (_pmetis->ubvec.begin(),   _pmetis->ubvec.end(),   1.05);
  _pmetis->part.resize    (n_active_local_elem);   std::fill (_pmetis->part.begin(),    _pmetis->part.end(), 0);
  _pmetis->options.resize (5);
  _pmetis->vwgt.resize    (n_active_local_elem);

  // Set the options
  _pmetis->options[0] = 1;  // don't use default options
  _pmetis->options[1] = 0;  // default (level of timing)
  _pmetis->options[2] = 15; // random seed (default)
  _pmetis->options[3] = 2;  // processor distribution and subdomain distribution are decoupled

  // Find the number of active elements on each processor.  We cannot use
  // mesh.n_active_elem_on_proc(pid) since that only returns the number of
  // elements assigned to pid which are currently stored on the calling
  // processor. This will not in general be correct for parallel meshes
  // when (pid!=mesh.processor_id()).
  _n_active_elem_on_proc.resize(mesh.n_processors());
  mesh.comm().allgather(n_active_local_elem, _n_active_elem_on_proc);

  // count the total number of active elements in the mesh.  Note we cannot
  // use mesh.n_active_elem() in general since this only returns the number
  // of active elements which are stored on the calling processor.
  // We should not use n_active_elem for any allocation because that will
  // be inheritly unscalable, but it can be useful for libmesh_assertions.
  dof_id_type n_active_elem=0;

  // Set up the vtxdist array.  This will be the same on each processor.
  // ***** Consult the Parmetis documentation. *****
  libmesh_assert_equal_to (_pmetis->vtxdist.size(),
                           cast_int<std::size_t>(mesh.n_processors()+1));
  libmesh_assert_equal_to (_pmetis->vtxdist[0], 0);

  for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
    {
      _pmetis->vtxdist[pid+1] = _pmetis->vtxdist[pid] + _n_active_elem_on_proc[pid];
      n_active_elem += _n_active_elem_on_proc[pid];
    }
  libmesh_assert_equal_to (_pmetis->vtxdist.back(), static_cast<Parmetis::idx_t>(n_active_elem));

  // ParMetis expects the elements to be numbered in contiguous blocks
  // by processor, i.e. [0, ne0), [ne0, ne0+ne1), ...
  // Since we only partition active elements we should have no expectation
  // that we currently have such a distribution.  So we need to create it.
  // Also, at the same time we are going to map all the active elements into a globally
  // unique range [0,n_active_elem) which is *independent* of the current partitioning.
  // This can be fed to ParMetis as the initial partitioning of the subdomains (decoupled
  // from the partitioning of the objects themselves).  This allows us to get the same
  // resultant partitioning independed of the input partitioning.
  MeshTools::BoundingBox bbox =
    MeshTools::bounding_box(mesh);

  _global_index_by_pid_map.clear();

  // Maps active element ids into a contiguous range independent of partitioning.
  // (only needs local scope)
  vectormap<dof_id_type, dof_id_type> global_index_map;

  {
    std::vector<dof_id_type> global_index;

    // create the mapping which is contiguous by processor
    dof_id_type pid_offset=0;
    for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
      {
        MeshBase::const_element_iterator       it  = mesh.active_pid_elements_begin(pid);
        const MeshBase::const_element_iterator end = mesh.active_pid_elements_end(pid);

        // note that we may not have all (or any!) the active elements which belong on this processor,
        // but by calling this on all processors a unique range in [0,_n_active_elem_on_proc[pid])
        // is constructed.  Only the indices for the elements we pass in are returned in the array.
        MeshCommunication().find_global_indices (mesh.comm(),
                                                 bbox, it, end,
                                                 global_index);

        for (dof_id_type cnt=0; it != end; ++it)
          {
            const Elem *elem = *it;
            libmesh_assert (!_global_index_by_pid_map.count(elem->id()));
            libmesh_assert_less (cnt, global_index.size());
            libmesh_assert_less (global_index[cnt], _n_active_elem_on_proc[pid]);

            _global_index_by_pid_map.insert(std::make_pair(elem->id(), global_index[cnt++] + pid_offset));
          }

        pid_offset += _n_active_elem_on_proc[pid];
      }

    // create the unique mapping for all active elements independent of partitioning
    {
      MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
      const MeshBase::const_element_iterator end = mesh.active_elements_end();

      // Calling this on all processors a unique range in [0,n_active_elem) is constructed.
      // Only the indices for the elements we pass in are returned in the array.
      MeshCommunication().find_global_indices (mesh.comm(),
                                               bbox, it, end,
                                               global_index);

      for (dof_id_type cnt=0; it != end; ++it)
        {
          const Elem *elem = *it;
          libmesh_assert (!global_index_map.count(elem->id()));
          libmesh_assert_less (cnt, global_index.size());
          libmesh_assert_less (global_index[cnt], n_active_elem);

          global_index_map.insert(std::make_pair(elem->id(), global_index[cnt++]));
        }
    }
    // really, shouldn't be close!
    libmesh_assert_less_equal (global_index_map.size(), n_active_elem);
    libmesh_assert_less_equal (_global_index_by_pid_map.size(), n_active_elem);

    // At this point the two maps should be the same size.  If they are not
    // then the number of active elements is not the same as the sum over all
    // processors of the number of active elements per processor, which means
    // there must be some unpartitioned objects out there.
    if (global_index_map.size() != _global_index_by_pid_map.size())
      libmesh_error_msg("ERROR:  ParmetisPartitioner cannot handle unpartitioned objects!");
  }

  // Finally, we need to initialize the vertex (partition) weights and the initial subdomain
  // mapping.  The subdomain mapping will be independent of the processor mapping, and is
  // defined by a simple mapping of the global indices we just found.
  {
    std::vector<dof_id_type> subdomain_bounds(mesh.n_processors());

    const dof_id_type first_local_elem = _pmetis->vtxdist[mesh.processor_id()];

    for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
      {
        dof_id_type tgt_subdomain_size = 0;

        // watch out for the case that n_subdomains < n_processors
        if (pid < static_cast<unsigned int>(_pmetis->nparts))
          {
            tgt_subdomain_size = n_active_elem/std::min
              (cast_int<Parmetis::idx_t>(mesh.n_processors()), _pmetis->nparts);

            if (pid < n_active_elem%_pmetis->nparts)
              tgt_subdomain_size++;
          }
        if (pid == 0)
          subdomain_bounds[0] = tgt_subdomain_size;
        else
          subdomain_bounds[pid] = subdomain_bounds[pid-1] + tgt_subdomain_size;
      }

    libmesh_assert_equal_to (subdomain_bounds.back(), n_active_elem);

    MeshBase::const_element_iterator       elem_it  = mesh.active_local_elements_begin();
    const MeshBase::const_element_iterator elem_end = mesh.active_local_elements_end();

    for (; elem_it != elem_end; ++elem_it)
      {
        const Elem *elem = *elem_it;

        libmesh_assert (_global_index_by_pid_map.count(elem->id()));
        const dof_id_type global_index_by_pid =
          _global_index_by_pid_map[elem->id()];
        libmesh_assert_less (global_index_by_pid, n_active_elem);

        const dof_id_type local_index =
          global_index_by_pid - first_local_elem;

        libmesh_assert_less (local_index, n_active_local_elem);
        libmesh_assert_less (local_index, _pmetis->vwgt.size());

        // TODO:[BSK] maybe there is a better weight?
        _pmetis->vwgt[local_index] = elem->n_nodes();

        // find the subdomain this element belongs in
        libmesh_assert (global_index_map.count(elem->id()));
        const dof_id_type global_index =
          global_index_map[elem->id()];

        libmesh_assert_less (global_index, subdomain_bounds.back());

        const unsigned int subdomain_id =
          std::distance(subdomain_bounds.begin(),
                        std::lower_bound(subdomain_bounds.begin(),
                                         subdomain_bounds.end(),
                                         global_index));
        libmesh_assert_less (subdomain_id, static_cast<unsigned int>(_pmetis->nparts));
        libmesh_assert_less (local_index, _pmetis->part.size());

        _pmetis->part[local_index] = subdomain_id;
      }
  }
}
Exemplo n.º 20
0
PetscVector<T>&
PetscVector<T>::operator = (const PetscVector<T>& v)
{
  this->_restore_array();
  v._restore_array();

  libmesh_assert_equal_to (this->size(), v.size());
  libmesh_assert_equal_to (this->local_size(), v.local_size());
  libmesh_assert (v.closed());

  PetscErrorCode ierr = 0;

  if (((this->type()==PARALLEL) && (v.type()==GHOSTED)) ||
      ((this->type()==GHOSTED) && (v.type()==PARALLEL)) ||
      ((this->type()==GHOSTED) && (v.type()==SERIAL))   ||
      ((this->type()==SERIAL) && (v.type()==GHOSTED)))
  {
    /* Allow assignment of a ghosted to a parallel vector since this
       causes no difficulty.  See discussion in libmesh-devel of
       June 24, 2010.  */
    ierr = VecCopy (v._vec, this->_vec);
    CHKERRABORT(libMesh::COMM_WORLD,ierr);
  }
  else
  {
    /* In all other cases, we assert that both vectors are of equal
       type.  */
    libmesh_assert_equal_to (this->_type, v._type);
    libmesh_assert (this->_global_to_local_map == v._global_to_local_map);

    if (v.size() != 0)
    {
      if(this->type() != GHOSTED)
      {
        ierr = VecCopy (v._vec, this->_vec);
        CHKERRABORT(libMesh::COMM_WORLD,ierr);
      }
      else
      {
        Vec loc_vec;
        Vec v_loc_vec;
        ierr = VecGhostGetLocalForm (_vec,&loc_vec);
        CHKERRABORT(libMesh::COMM_WORLD,ierr);
        ierr = VecGhostGetLocalForm (v._vec,&v_loc_vec);
        CHKERRABORT(libMesh::COMM_WORLD,ierr);

        ierr = VecCopy (v_loc_vec, loc_vec);
        CHKERRABORT(libMesh::COMM_WORLD,ierr);

        ierr = VecGhostRestoreLocalForm (v._vec,&v_loc_vec);
        CHKERRABORT(libMesh::COMM_WORLD,ierr);
        ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
        CHKERRABORT(libMesh::COMM_WORLD,ierr);
      }
    }
  }

  close();

  return *this;
}
Exemplo n.º 21
0
int main(int argc, char** argv){

	//initialize libMesh
	LibMeshInit init(argc, argv);
	
	//parameters
	GetPot infile("fem_system_params.in");
  const Real global_tolerance          = infile("global_tolerance", 0.);
  const unsigned int nelem_target      = infile("n_elements", 400);
  const bool transient                 = infile("transient", true);
  const Real deltat                    = infile("deltat", 0.005);
  unsigned int n_timesteps             = infile("n_timesteps", 1);
  //const unsigned int coarsegridsize    = infile("coarsegridsize", 1);
  const unsigned int coarserefinements = infile("coarserefinements", 0);
  const unsigned int max_adaptivesteps = infile("max_adaptivesteps", 10);
  //const unsigned int dim               = 2;
  
#ifdef LIBMESH_HAVE_EXODUS_API
  const unsigned int write_interval    = infile("write_interval", 5);
#endif

  // Create a mesh, with dimension to be overridden later, distributed
  // across the default MPI communicator.
  Mesh mesh(init.comm());
  GetPot infileForMesh("diff_convdiff_mprime.in");
  std::string find_mesh_here = infileForMesh("divided_mesh","meep.exo");
	mesh.read(find_mesh_here);
	//mesh.read("psiHF_mesh_1Dfused.xda");

  // And an object to refine it
  MeshRefinement mesh_refinement(mesh);
  mesh_refinement.coarsen_by_parents() = true;
  mesh_refinement.absolute_global_tolerance() = global_tolerance;
  mesh_refinement.nelem_target() = nelem_target;
  mesh_refinement.refine_fraction() = 0.3;
  mesh_refinement.coarsen_fraction() = 0.3;
  mesh_refinement.coarsen_threshold() = 0.1;

  mesh_refinement.uniformly_refine(coarserefinements);
  
  // Print information about the mesh to the screen.
  mesh.print_info();

  // Create an equation systems object.
  EquationSystems equation_systems (mesh);
  
  //name system
  Diff_ConvDiff_MprimeSys & system = 
  	equation_systems.add_system<Diff_ConvDiff_MprimeSys>("Diff_ConvDiff_MprimeSys");
  
  //steady-state problem	
 	system.time_solver =
    AutoPtr<TimeSolver>(new SteadySolver(system));
  libmesh_assert_equal_to (n_timesteps, 1);
  
 	//DEBUG
 	//std::string find_psiLF_here = "psiLF.xda";
  //equation_systems.read(find_psiLF_here, READ,
  //  EquationSystems::READ_HEADER |
  //  EquationSystems::READ_DATA |
  //  EquationSystems::READ_ADDITIONAL_DATA);
  //std::cout << "\n\n" << "DEBUG reading in " << find_psiLF_here << "\n\n";
  //Real readin_L2 = system.calculate_norm(*system.solution, 0, L2);  
  //std::cout << "Read in solution norm: "<< readin_L2 << std::endl << std::endl;
  //GMVIO(equation_systems.get_mesh()).write_equation_systems(std::string("right_back_out.gmv"), equation_systems);
 	//DEBUG
  
  // Initialize the system
  equation_systems.init ();

  // Set the time stepping options
  system.deltat = deltat; //this is ignored for SteadySolver...right?

  // And the nonlinear solver options
  NewtonSolver *solver = new NewtonSolver(system); 
  system.time_solver->diff_solver() = AutoPtr<DiffSolver>(solver); 
  solver->quiet = infile("solver_quiet", true);
  solver->verbose = !solver->quiet;
  solver->max_nonlinear_iterations =
    infile("max_nonlinear_iterations", 15);
  solver->relative_step_tolerance =
    infile("relative_step_tolerance", 1.e-3);
  solver->relative_residual_tolerance =
    infile("relative_residual_tolerance", 0.0);
  solver->absolute_residual_tolerance =
    infile("absolute_residual_tolerance", 0.0);

  // And the linear solver options
  solver->max_linear_iterations =
    infile("max_linear_iterations", 50000);
  solver->initial_linear_tolerance =
    infile("initial_linear_tolerance", 1.e-3);
  
  //FOR 1D DEBUG
  //read_initial_parameters();
  //system.project_solution(initial_value, initial_grad, equation_systems.parameters);
  //finish_initialization();
#ifdef LIBMESH_HAVE_GMV
  //GMVIO(equation_systems.get_mesh()).write_equation_systems(std::string("psiHF_readin_1d.gmv"), equation_systems);
#endif
	//equation_systems.write("psiLF_1D_fused.xda", WRITE, EquationSystems::WRITE_DATA | 
  //             EquationSystems::WRITE_ADDITIONAL_DATA);
  //mesh.write("psiLF_mesh_1Dfused.xda");
                          

  // Print information about the system to the screen.
  equation_systems.print_info();
  
  //std::cout << "\n~~~~~~~~~~~~~~~~\n"; //DEBUG
  //system.assemble(); //DEBUG
  //std::cout << "\n~~~~~~~~~~~~~~~~\n"; //DEBUG
  //equation_systems.write("rhs.xda", WRITE, EquationSystems::WRITE_DATA | //DEBUG
  //             EquationSystems::WRITE_ADDITIONAL_DATA);

  // Now we begin the timestep loop to compute the time-accurate
  // solution of the equations...not that this is transient, but eh, why not...
	for (unsigned int t_step=0; t_step != n_timesteps; ++t_step){
    // A pretty update message
    std::cout << "\n\nSolving time step " << t_step << ", time = "
              << system.time << std::endl;

    // Adaptively solve the timestep
    unsigned int a_step = 0;
    for (; a_step != max_adaptivesteps; ++a_step)
      {
        system.solve();
        system.postprocess();
        ErrorVector error;
        AutoPtr<ErrorEstimator> error_estimator;

        // To solve to a tolerance in this problem we
        // need a better estimator than Kelly
        if (global_tolerance != 0.)
          {
            // We can't adapt to both a tolerance and a mesh
            // size at once
            libmesh_assert_equal_to (nelem_target, 0);

            UniformRefinementEstimator *u =
              new UniformRefinementEstimator;

            // The lid-driven cavity problem isn't in H1, so
            // lets estimate L2 error
            u->error_norm = L2;

            error_estimator.reset(u);
          }
        else
          {
            // If we aren't adapting to a tolerance we need a
            // target mesh size
            libmesh_assert_greater (nelem_target, 0);

            // Kelly is a lousy estimator to use for a problem
            // not in H1 - if we were doing more than a few
            // timesteps we'd need to turn off or limit the
            // maximum level of our adaptivity eventually
            error_estimator.reset(new KellyErrorEstimator);
          }

        // Calculate error
        std::vector<Real> weights(9,1.0);  // based on u, v, p, c, their adjoints, and source parameter

        // Keep the same default norm type.
        std::vector<FEMNormType>
          norms(1, error_estimator->error_norm.type(0));
        error_estimator->error_norm = SystemNorm(norms, weights);

        error_estimator->estimate_error(system, error);

        // Print out status at each adaptive step.
        Real global_error = error.l2_norm();
        std::cout << "Adaptive step " << a_step << ": " << std::endl;
        if (global_tolerance != 0.)
          std::cout << "Global_error = " << global_error
                    << std::endl;
        if (global_tolerance != 0.)
          std::cout << "Worst element error = " << error.maximum()
                    << ", mean = " << error.mean() << std::endl;

        if (global_tolerance != 0.)
          {
            // If we've reached our desired tolerance, we
            // don't need any more adaptive steps
            if (global_error < global_tolerance)
              break;
            mesh_refinement.flag_elements_by_error_tolerance(error);
          }
        else
          {
            // If flag_elements_by_nelem_target returns true, this
            // should be our last adaptive step.
            if (mesh_refinement.flag_elements_by_nelem_target(error))
              {
                mesh_refinement.refine_and_coarsen_elements();
                equation_systems.reinit();
                a_step = max_adaptivesteps;
                break;
              }
          }

        // Carry out the adaptive mesh refinement/coarsening
        mesh_refinement.refine_and_coarsen_elements();
        equation_systems.reinit();

        std::cout << "Refined mesh to "
                  << mesh.n_active_elem()
                  << " active elements and "
                  << equation_systems.n_active_dofs()
                  << " active dofs." << std::endl;
      }
    // Do one last solve if necessary
    if (a_step == max_adaptivesteps)
      {
        system.solve();
				std::cout << "\n\n Residual L2 norm: " << system.calculate_norm(*system.rhs, L2) << "\n";
        system.postprocess();
        
        //DEBUG
        std::cout << " M_HF(psiLF): " << std::setprecision(17) << system.get_MHF_psiLF() << "\n";
  			std::cout << " I(psiLF): " << std::setprecision(17) << system.get_MLF_psiLF() << "\n";
      }

    // Advance to the next timestep in a transient problem
    system.time_solver->advance_timestep();

#ifdef LIBMESH_HAVE_EXODUS_API
    // Write out this timestep if we're requested to
    if ((t_step+1)%write_interval == 0)
      {
        //std::ostringstream file_name;

        // We write the file in the ExodusII format.
        //file_name << "out_"
        //          << std::setw(3)
        //          << std::setfill('0')
        //          << std::right
        //          << t_step+1
        //          << ".e";

        //ExodusII_IO(mesh).write_timestep(file_name.str(),
        ExodusII_IO(mesh).write_timestep("psiLF.exo",
                                         equation_systems,
                                         1, /* This number indicates how many time steps
                                               are being written to the file */
                                         system.time);
     		mesh.write("psiLF_mesh.xda");
     		equation_systems.write("psiLF.xda", WRITE, EquationSystems::WRITE_DATA | 
               EquationSystems::WRITE_ADDITIONAL_DATA);
      }
#endif // #ifdef LIBMESH_HAVE_EXODUS_API
  }
  
  // All done.
  return 0;
  
} //end main
Exemplo n.º 22
0
void PetscVector<T>::localize (NumericVector<T>& v_local_in,
			       const std::vector<numeric_index_type>& send_list) const
{
  // FIXME: Workaround for a strange bug at large-scale.
  // If we have ghosting, PETSc lets us just copy the solution, and
  // doing so avoids a segfault?
  if (v_local_in.type() == GHOSTED &&
      this->type() == PARALLEL)
    {
      v_local_in = *this;
      return;
    }

  // Normal code path begins here

  this->_restore_array();

  // Make sure the NumericVector passed in is really a PetscVector
  PetscVector<T>* v_local = libmesh_cast_ptr<PetscVector<T>*>(&v_local_in);

  libmesh_assert(v_local);
  libmesh_assert_equal_to (v_local->size(), this->size());
  libmesh_assert_less_equal (send_list.size(), v_local->size());

  PetscErrorCode ierr=0;
  const numeric_index_type n_sl = send_list.size();

  IS is;
  VecScatter scatter;

  std::vector<PetscInt> idx(n_sl + this->local_size());

  for (numeric_index_type i=0; i<n_sl; i++)
    idx[i] = static_cast<PetscInt>(send_list[i]);
  for (numeric_index_type i = 0; i != this->local_size(); ++i)
    idx[n_sl+i] = i + this->first_local_index();

  // Create the index set & scatter object
  if (idx.empty())
    ierr = ISCreateLibMesh(libMesh::COMM_WORLD,
                           n_sl+this->local_size(), PETSC_NULL, PETSC_USE_POINTER, &is);
  else
    ierr = ISCreateLibMesh(libMesh::COMM_WORLD,
			   n_sl+this->local_size(), &idx[0], PETSC_USE_POINTER, &is);
           CHKERRABORT(libMesh::COMM_WORLD,ierr);

  ierr = VecScatterCreate(_vec,          is,
			  v_local->_vec, is,
			  &scatter);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);


  // Perform the scatter
#if PETSC_VERSION_LESS_THAN(2,3,3)

  ierr = VecScatterBegin(_vec, v_local->_vec, INSERT_VALUES,
			 SCATTER_FORWARD, scatter);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  ierr = VecScatterEnd  (_vec, v_local->_vec, INSERT_VALUES,
			 SCATTER_FORWARD, scatter);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

#else

  // API argument order change in PETSc 2.3.3
  ierr = VecScatterBegin(scatter, _vec, v_local->_vec,
                         INSERT_VALUES, SCATTER_FORWARD);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  ierr = VecScatterEnd  (scatter, _vec, v_local->_vec,
                         INSERT_VALUES, SCATTER_FORWARD);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

#endif


  // Clean up
  ierr = LibMeshISDestroy (&is);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  ierr = LibMeshVecScatterDestroy(&scatter);
         CHKERRABORT(libMesh::COMM_WORLD,ierr);

  // Make sure ghost dofs are up to date
  if (v_local->type() == GHOSTED)
    v_local->close();
}
Exemplo n.º 23
0
Real FE<1,LAGRANGE>::shape_deriv(const ElemType,
                                 const Order order,
                                 const unsigned int i,
                                 const unsigned int libmesh_dbg_var(j),
                                 const Point & p)
{
  // only d()/dxi in 1D!

  libmesh_assert_equal_to (j, 0);

  const Real xi = p(0);


  switch (order)
    {
      // Lagrange linear shape function derivatives
    case FIRST:
      {
        libmesh_assert_less (i, 2);

        switch (i)
          {
          case 0:
            return -.5;

          case 1:
            return .5;

          default:
            libmesh_error_msg("Invalid shape function index i = " << i);
          }
      }


      // Lagrange quadratic shape function derivatives
    case SECOND:
      {
        libmesh_assert_less (i, 3);

        switch (i)
          {
          case 0:
            return xi-.5;

          case 1:
            return xi+.5;

          case 2:
            return -2.*xi;

          default:
            libmesh_error_msg("Invalid shape function index i = " << i);
          }
      }


      // Lagrange cubic shape function derivatives
    case THIRD:
      {
        libmesh_assert_less (i, 4);

        switch (i)
          {
          case 0:
            return -9./16.*(3.*xi*xi-2.*xi-1./9.);

          case 1:
            return -9./16.*(-3.*xi*xi-2.*xi+1./9.);

          case 2:
            return 27./16.*(3.*xi*xi-2./3.*xi-1.);

          case 3:
            return 27./16.*(-3.*xi*xi-2./3.*xi+1.);

          default:
            libmesh_error_msg("Invalid shape function index i = " << i);
          }
      }


    default:
      libmesh_error_msg("ERROR: Unsupported polynomial order = " << order);
    }

  libmesh_error_msg("We'll never get here!");
  return 0.;
}
Exemplo n.º 24
0
//---------------------------------------------------------
// CentroidPartitioner methods
void CentroidPartitioner::_do_partition (MeshBase& mesh,
					 const unsigned int n)
{
  // Check for an easy return
  if (n == 1)
    {
      this->single_partition (mesh);
      return;
    }


  // Possibly reconstruct centroids
  if (mesh.n_elem() != _elem_centroids.size())
    this->compute_centroids (mesh);



  switch (this->sort_method())
    {
    case X:
      {
	std::sort(_elem_centroids.begin(),
		  _elem_centroids.end(),
		  CentroidPartitioner::sort_x);

	break;
      }


    case Y:
      {
	std::sort(_elem_centroids.begin(),
		  _elem_centroids.end(),
		  CentroidPartitioner::sort_y);

	break;

      }


    case Z:
      {
	std::sort(_elem_centroids.begin(),
		  _elem_centroids.end(),
		  CentroidPartitioner::sort_z);

	break;
      }


     case RADIAL:
      {
	std::sort(_elem_centroids.begin(),
		  _elem_centroids.end(),
		  CentroidPartitioner::sort_radial);

	break;
      }
    default:
      libmesh_error();
    }


  // Make sure the user has not handed us an
  // invalid number of partitions.
  libmesh_assert_greater (n, 0);

  // the number of elements, e.g. 1000
  const dof_id_type n_elem      = mesh.n_elem();
  // the number of elements per processor, e.g 400
  const dof_id_type target_size = n_elem / n;

  // Make sure the mesh hasn't changed since the
  // last time we computed the centroids.
  libmesh_assert_equal_to (mesh.n_elem(), _elem_centroids.size());

  for (dof_id_type i=0; i<n_elem; i++)
    {
      Elem* elem = _elem_centroids[i].second;

      elem->processor_id() =
        std::min (libmesh_cast_int<processor_id_type>(i / target_size),
		  libmesh_cast_int<processor_id_type>(n-1));
    }
}
Exemplo n.º 25
0
void UNVIO::read_implementation (std::istream& in_stream)
{
  // clear everything, so that
  // we can start from scratch
  this->clear ();

  // Keep track of what kinds of elements this file contains
  elems_of_dimension.clear();
  elems_of_dimension.resize(4, false);

  // Note that we read this file
  // @e twice.  First time to
  // detect the number of nodes
  // and elements (and possible
  // conversion tasks like D_to_e)
  // and the order of datasets
  // (nodes first, then elements,
  // or the other way around),
  // and second to do the actual
  // read.
  std::vector<std::string> order_of_datasets;
  order_of_datasets.reserve(2);

  {
    // the first time we read the file,
    // merely to obtain overall info
    if ( !in_stream.good() )
      {
        libMesh::err << "ERROR: Input file not good."
                     << std::endl;
        libmesh_error();
      }


    // Count nodes and elements, then let
    // other methods read the element and
    // node data.  Also remember which
    // dataset comes first: nodes or elements
    if (this->verbose())
      libMesh::out << "  Counting nodes and elements" << std::endl;


    //    bool reached_eof = false;
    bool found_node  = false;
    bool found_elem  = false;


    std::string olds, news;

    while (in_stream.good())
      {
        in_stream >> olds >> news;

        // a "-1" followed by a number means the beginning of a dataset
        // stop combing at the end of the file
        while ( ((olds != "-1") || (news == "-1") ) && !in_stream.eof() )
          {
            olds = news;
            in_stream >> news;
          }

        //  if (in_stream.eof())
        //    {
        //      reached_eof = true;
        //      break;
        //    }


        // if beginning of dataset, buffer it in
        // temp_buffer, if desired
        if (news == _label_dataset_nodes)
          {
            found_node = true;
            order_of_datasets.push_back (_label_dataset_nodes);
            this->count_nodes (in_stream);

            // we can save some time scanning the file
            // when we know we already have everything
            // we want
            if (found_elem)
              break;
          }

        else if (news == _label_dataset_elements)
          {
            found_elem = true;
            order_of_datasets.push_back (_label_dataset_elements);
            this->count_elements (in_stream);

            // we can save some time scanning the file
            // when we know we already have everything
            // we want
            if (found_node)
              break;
          }
      }


    // Here we should better have found
    // the datasets for nodes and elements,
    // otherwise the unv files is bad!
    if (!found_elem)
      {
        libMesh::err << "ERROR: Could not find elements!" << std::endl;
        libmesh_error();
      }

    if (!found_node)
      {
        libMesh::err << "ERROR: Could not find nodes!" << std::endl;
        libmesh_error();
      }


    // Don't close, just seek to the beginning
    in_stream.seekg(0, std::ios::beg);

    if (!in_stream.good() )
      {
        libMesh::err << "ERROR: Cannot re-read input file."
                     << std::endl;
        libmesh_error();
      }
  }





  // We finished scanning the file,
  // and our member data
  // \p this->_n_nodes,
  // \p this->_n_elements,
  // \p this->_need_D_to_e
  // should be properly initialized.
  {
    // Read the datasets in the order that
    // we already know
    libmesh_assert_equal_to (order_of_datasets.size(), 2);

    for (unsigned int ds=0; ds < order_of_datasets.size(); ds++)
      {
        if (order_of_datasets[ds] == _label_dataset_nodes)
          this->node_in    (in_stream);

        else if (order_of_datasets[ds] == _label_dataset_elements)
          this->element_in (in_stream);

        else
          libmesh_error();
      }

    // Set the mesh dimension to the largest encountered for an element
    for (unsigned int i=0; i!=4; ++i)
      if (elems_of_dimension[i])
        MeshInput<MeshBase>::mesh().set_mesh_dimension(i);

#if LIBMESH_DIM < 3
    if (MeshInput<MeshBase>::mesh().mesh_dimension() > LIBMESH_DIM)
      {
        libMesh::err << "Cannot open dimension " <<
          MeshInput<MeshBase>::mesh().mesh_dimension() <<
          " mesh file when configured without " <<
          MeshInput<MeshBase>::mesh().mesh_dimension() << "D support." <<
          std::endl;
        libmesh_error();
      }
#endif

    // tell the MeshData object that we are finished
    // reading data
    this->_mesh_data.close_foreign_id_maps ();

    if (this->verbose())
      libMesh::out << "  Finished." << std::endl << std::endl;
  }

  // save memory
  this->_assign_nodes.clear();
  this->_ds_position.clear();
}
Exemplo n.º 26
0
Real FE<3,XYZ>::shape_second_deriv(const Elem* elem,
			           const Order libmesh_dbg_var(order),
			           const unsigned int i,
			           const unsigned int j,
			           const Point& point_in)
{
#if LIBMESH_DIM == 3

  libmesh_assert(elem);
  libmesh_assert_less (j, 6);

  // Only recompute the centroid if the element
  // has changed from the last one we computed.
  // This avoids repeated centroid calculations
  // when called in succession with the same element.
  if (elem->id() != old_elem_id)
    {
      centroid = elem->centroid();
      old_elem_id = elem->id();
      max_distance = Point(0.,0.,0.);
      for (unsigned int p = 0; p < elem->n_nodes(); p++)
        for (unsigned int d = 0; d < 3; d++)
        {
           const Real distance = std::abs(centroid(d) - elem->point(p)(d));
           max_distance(d) = std::max(distance, max_distance(d));
        }
    }

  // Using static globals for old_elem_id, etc. will fail
  // horribly with more than one thread.
  libmesh_assert_equal_to (libMesh::n_threads(), 1);

  const Real x  = point_in(0);
  const Real y  = point_in(1);
  const Real z  = point_in(2);
  const Real xc = centroid(0);
  const Real yc = centroid(1);
  const Real zc = centroid(2);
  const Real distx = max_distance(0);
  const Real disty = max_distance(1);
  const Real distz = max_distance(2);
  const Real dx = (x - xc)/distx;
  const Real dy = (y - yc)/disty;
  const Real dz = (z - zc)/distz;
  const Real dist2x = pow(distx,2.);
  const Real dist2y = pow(disty,2.);
  const Real dist2z = pow(distz,2.);
  const Real distxy = distx * disty;
  const Real distxz = distx * distz;
  const Real distyz = disty * distz;

#ifndef NDEBUG
  // totalorder is only used in the assertion below, so
  // we avoid declaring it when asserts are not active.
  const unsigned int totalorder = static_cast<Order>(order + elem->p_level());
#endif
  libmesh_assert_less (i, (static_cast<unsigned int>(totalorder)+1)*
              (static_cast<unsigned int>(totalorder)+2)*
              (static_cast<unsigned int>(totalorder)+3)/6);

    // monomials. since they are hierarchic we only need one case block.
  switch (j)
    {
      // d^2()/dx^2
    case 0:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	  return 2./dist2x;

  	case 5:
  	case 6:
  	case 7:
  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	  return 6.*dx/dist2x;

  	case 11:
  	  return 2.*dy/dist2x;

  	case 12:
  	case 13:
  	  return 0.;

  	case 14:
  	  return 2.*dz/dist2x;

  	case 15:
  	case 16:
  	case 17:
  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	  return 12.*dx*dx/dist2x;

  	case 21:
  	  return 6.*dx*dy/dist2x;

  	case 22:
  	  return 2.*dy*dy/dist2x;

  	case 23:
  	case 24:
  	  return 0.;

  	case 25:
  	  return 6.*dx*dz/dist2x;

  	case 26:
  	  return 2.*dy*dz/dist2x;

  	case 27:
  	case 28:
  	  return 0.;

  	case 29:
  	  return 2.*dz*dz/dist2x;

  	case 30:
  	case 31:
  	case 32:
  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nx * (nx - 1);
          for (unsigned int index=2; index < nx; index++)
            val *= dx;
          for (unsigned int index=0; index != ny; index++)
            val *= dy;
          for (unsigned int index=0; index != nz; index++)
            val *= dz;
          return val/dist2x;
  	}
      }


      // d^2()/dxdy
    case 1:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	  return 0.;

  	case 5:
  	  return 1./distxy;

  	case 6:
  	case 7:
  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	  return 0.;

  	case 11:
  	  return 2.*dx/distxy;

  	case 12:
  	  return 2.*dy/distxy;

  	case 13:
  	case 14:
  	  return 0.;

  	case 15:
  	  return dz/distxy;

  	case 16:
  	case 17:
  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	  return 0.;

  	case 21:
  	  return 3.*dx*dx/distxy;

  	case 22:
  	  return 4.*dx*dy/distxy;

  	case 23:
  	  return 3.*dy*dy/distxy;

  	case 24:
  	case 25:
  	  return 0.;

  	case 26:
  	  return 2.*dx*dz/distxy;

  	case 27:
  	  return 2.*dy*dz/distxy;

  	case 28:
  	case 29:
  	  return 0.;

  	case 30:
  	  return dz*dz/distxy;

  	case 31:
  	case 32:
  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nx * ny;
          for (unsigned int index=1; index < nx; index++)
            val *= dx;
          for (unsigned int index=1; index < ny; index++)
            val *= dy;
          for (unsigned int index=0; index != nz; index++)
            val *= dz;
          return val/distxy;
  	}
      }


      // d^2()/dy^2
    case 2:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	  return 0.;

  	case 6:
  	  return 2./dist2y;

  	case 7:
  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	case 11:
  	  return 0.;

  	case 12:
  	  return 2.*dx/dist2y;
  	case 13:
  	  return 6.*dy/dist2y;

  	case 14:
  	case 15:
  	  return 0.;

  	case 16:
  	  return 2.*dz/dist2y;

  	case 17:
  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	case 21:
  	  return 0.;

  	case 22:
  	  return 2.*dx*dx/dist2y;

  	case 23:
  	  return 6.*dx*dy/dist2y;

  	case 24:
  	  return 12.*dy*dy/dist2y;

  	case 25:
  	case 26:
  	  return 0.;

  	case 27:
  	  return 2.*dx*dz/dist2y;

  	case 28:
  	  return 6.*dy*dz/dist2y;

  	case 29:
  	case 30:
  	  return 0.;

  	case 31:
  	  return 2.*dz*dz/dist2y;

  	case 32:
  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = ny * (ny - 1);
          for (unsigned int index=0; index != nx; index++)
            val *= dx;
          for (unsigned int index=2; index < ny; index++)
            val *= dy;
          for (unsigned int index=0; index != nz; index++)
            val *= dz;
          return val/dist2y;
  	}
      }


      // d^2()/dxdz
    case 3:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	case 6:
  	  return 0.;

  	case 7:
  	  return 1./distxz;

  	case 8:
  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	case 11:
  	case 12:
  	case 13:
  	  return 0.;

  	case 14:
  	  return 2.*dx/distxz;

  	case 15:
  	  return dy/distxz;

  	case 16:
  	  return 0.;

  	case 17:
  	  return 2.*dz/distxz;

  	case 18:
  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	case 21:
  	case 22:
  	case 23:
  	case 24:
  	  return 0.;

  	case 25:
  	  return 3.*dx*dx/distxz;

  	case 26:
  	  return 2.*dx*dy/distxz;

  	case 27:
  	  return dy*dy/distxz;

  	case 28:
  	  return 0.;

  	case 29:
  	  return 4.*dx*dz/distxz;

  	case 30:
  	  return 2.*dy*dz/distxz;

  	case 31:
  	  return 0.;

  	case 32:
  	  return 3.*dz*dz/distxz;

  	case 33:
  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nx * nz;
          for (unsigned int index=1; index < nx; index++)
            val *= dx;
          for (unsigned int index=0; index != ny; index++)
            val *= dy;
          for (unsigned int index=1; index < nz; index++)
            val *= dz;
          return val/distxz;
  	}
      }

      // d^2()/dydz
    case 4:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	case 6:
  	case 7:
  	  return 0.;

  	case 8:
  	  return 1./distyz;

  	case 9:
  	  return 0.;

  	  // cubic
  	case 10:
  	case 11:
  	case 12:
  	case 13:
  	case 14:
  	  return 0.;

  	case 15:
  	  return dx/distyz;

  	case 16:
  	  return 2.*dy/distyz;

  	case 17:
  	  return 0.;

  	case 18:
  	  return 2.*dz/distyz;

  	case 19:
  	  return 0.;

  	  // quartics
  	case 20:
  	case 21:
  	case 22:
  	case 23:
  	case 24:
  	case 25:
  	  return 0.;

  	case 26:
  	  return dx*dx/distyz;

  	case 27:
  	  return 2.*dx*dy/distyz;

  	case 28:
  	  return 3.*dy*dy/distyz;

  	case 29:
  	  return 0.;

  	case 30:
  	  return 2.*dx*dz/distyz;

  	case 31:
  	  return 4.*dy*dz/distyz;

  	case 32:
  	  return 0.;

  	case 33:
  	  return 3.*dz*dz/distyz;

  	case 34:
  	  return 0.;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = ny * nz;
          for (unsigned int index=0; index != nx; index++)
            val *= dx;
          for (unsigned int index=1; index < ny; index++)
            val *= dy;
          for (unsigned int index=1; index < nz; index++)
            val *= dz;
          return val/distyz;
  	}
      }


      // d^2()/dz^2
    case 5:
      {
        switch (i)
  	{
  	  // constant
  	case 0:

  	  // linear
  	case 1:
  	case 2:
  	case 3:
  	  return 0.;

  	  // quadratic
  	case 4:
  	case 5:
  	case 6:
  	case 7:
  	case 8:
  	  return 0.;

  	case 9:
  	  return 2./dist2z;

  	  // cubic
  	case 10:
  	case 11:
  	case 12:
  	case 13:
  	case 14:
  	case 15:
  	case 16:
  	  return 0.;

  	case 17:
  	  return 2.*dx/dist2z;

  	case 18:
  	  return 2.*dy/dist2z;

  	case 19:
  	  return 6.*dz/dist2z;

  	  // quartics
  	case 20:
  	case 21:
  	case 22:
  	case 23:
  	case 24:
  	case 25:
  	case 26:
  	case 27:
  	case 28:
  	  return 0.;

  	case 29:
  	  return 2.*dx*dx/dist2z;

  	case 30:
  	  return 2.*dx*dy/dist2z;

  	case 31:
  	  return 2.*dy*dy/dist2z;

  	case 32:
  	  return 6.*dx*dz/dist2z;

  	case 33:
  	  return 6.*dy*dz/dist2z;

  	case 34:
  	  return 12.*dz*dz/dist2z;

  	default:
          unsigned int o = 0;
          for (; i >= (o+1)*(o+2)*(o+3)/6; o++) { }
          unsigned int i2 = i - (o*(o+1)*(o+2)/6);
          unsigned int block=o, nz = 0;
          for (; block < i2; block += (o-nz+1)) { nz++; }
          const unsigned int nx = block - i2;
          const unsigned int ny = o - nx - nz;
          Real val = nz * (nz - 1);
          for (unsigned int index=0; index != nx; index++)
            val *= dx;
          for (unsigned int index=0; index != ny; index++)
            val *= dy;
          for (unsigned int index=2; index < nz; index++)
            val *= dz;
          return val/dist2z;
  	}
      }


    default:
      libmesh_error();
    }

#endif

  libmesh_error();
  return 0.;
}
Exemplo n.º 27
0
void InfFE<Dim,T_radial,T_base>::init_face_shape_functions(const std::vector<Point>&,
                                                           const Elem* inf_side)
{
  libmesh_assert(inf_side);

  // Currently, this makes only sense in 3-D!
  libmesh_assert_equal_to (Dim, 3);

  // Initialiize the radial shape functions
  this->init_radial_shape_functions(inf_side);

  // Initialize the base shape functions
  this->update_base_elem(inf_side);

  // Initialize the base quadratur rule
  base_qrule->init(base_elem->type(), inf_side->p_level());

  // base_fe still corresponds to the (dim-1)-dimensional base of the InfFE object,
  // so update the fe_base.
  {
    libmesh_assert_equal_to (Dim, 3);

    AutoPtr<FEBase> ap_fb(FEBase::build(Dim-2, this->fe_type));

    delete base_fe;
    base_fe = ap_fb.release();
    base_fe->attach_quadrature_rule(base_qrule);
  }

  // initialize the shape functions on the base
  base_fe->init_base_shape_functions(base_fe->qrule->get_points(),
                                     base_elem);

  // the number of quadrature points
  const unsigned int n_radial_qp =
    libmesh_cast_int<unsigned int>(som.size());
  const unsigned int n_base_qp   = base_qrule->n_points();
  const unsigned int n_total_qp  = n_radial_qp * n_base_qp;

  // the quadratur weigths
  _total_qrule_weights.resize(n_total_qp);

  // now inite the shapes for boundary work
  {

    // The element type and order to use in the base map
    const Order    base_mapping_order     ( base_elem->default_order() );
    const ElemType base_mapping_elem_type ( base_elem->type()          );

    // the number of mapping shape functions
    // (Lagrange shape functions are used for mapping in the base)
    const unsigned int n_radial_mapping_sf =
      libmesh_cast_int<unsigned int>(radial_map.size());
    const unsigned int n_base_mapping_shape_functions = Base::n_base_mapping_sf(base_mapping_elem_type,
                                                                                base_mapping_order);

    const unsigned int n_total_mapping_shape_functions =
      n_radial_mapping_sf * n_base_mapping_shape_functions;


    // initialize the node and shape numbering maps
    {
      _radial_node_index.resize    (n_total_mapping_shape_functions);
      _base_node_index.resize      (n_total_mapping_shape_functions);

      const ElemType inf_face_elem_type (inf_side->type());

      // fill the node index map
      for (unsigned int n=0; n<n_total_mapping_shape_functions; n++)
        {
          compute_node_indices (inf_face_elem_type,
                                n,
                                _base_node_index[n],
                                _radial_node_index[n]);

          libmesh_assert_less (_base_node_index[n], n_base_mapping_shape_functions);
          libmesh_assert_less (_radial_node_index[n], n_radial_mapping_sf);
        }

    }

    // rezise map data fields
    {
      std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi();
      std::vector<std::vector<Real> >& dpsidxi_map = this->_fe_map->get_dpsidxi();
      std::vector<std::vector<Real> >& d2psidxi2_map = this->_fe_map->get_d2psidxi2();
      psi_map.resize          (n_total_mapping_shape_functions);
      dpsidxi_map.resize      (n_total_mapping_shape_functions);
      d2psidxi2_map.resize    (n_total_mapping_shape_functions);

      //  if (Dim == 3)
      {
        std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta();
        std::vector<std::vector<Real> >& d2psidxideta_map = this->_fe_map->get_d2psidxideta();
        std::vector<std::vector<Real> >& d2psideta2_map = this->_fe_map->get_d2psideta2();
        dpsideta_map.resize     (n_total_mapping_shape_functions);
        d2psidxideta_map.resize (n_total_mapping_shape_functions);
        d2psideta2_map.resize   (n_total_mapping_shape_functions);
      }

      for (unsigned int i=0; i<n_total_mapping_shape_functions; i++)
        {
          psi_map[i].resize         (n_total_qp);
          dpsidxi_map[i].resize     (n_total_qp);
          d2psidxi2_map[i].resize   (n_total_qp);

          // if (Dim == 3)
          {
            std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta();
            std::vector<std::vector<Real> >& d2psidxideta_map = this->_fe_map->get_d2psidxideta();
            std::vector<std::vector<Real> >& d2psideta2_map = this->_fe_map->get_d2psideta2();
            dpsideta_map[i].resize     (n_total_qp);
            d2psidxideta_map[i].resize (n_total_qp);
            d2psideta2_map[i].resize   (n_total_qp);
          }
        }
    }


    // compute shape maps
    {
      const std::vector<std::vector<Real> >& S_map  = (base_fe->get_fe_map()).get_phi_map();
      const std::vector<std::vector<Real> >& Ss_map = (base_fe->get_fe_map()).get_dphidxi_map();

      std::vector<std::vector<Real> >& psi_map = this->_fe_map->get_psi();
      std::vector<std::vector<Real> >& dpsidxi_map = this->_fe_map->get_dpsidxi();
      std::vector<std::vector<Real> >& dpsideta_map = this->_fe_map->get_dpsideta();

      for (unsigned int rp=0; rp<n_radial_qp; rp++)  // over radial qp's
        for (unsigned int bp=0; bp<n_base_qp; bp++)  // over base qp's
          for (unsigned int ti=0; ti<n_total_mapping_shape_functions; ti++)  // over all mapping shapes
            {
              // let the index vectors take care of selecting the appropriate base/radial mapping shape
              const unsigned int bi = _base_node_index  [ti];
              const unsigned int ri = _radial_node_index[ti];
              psi_map          [ti][bp+rp*n_base_qp] = S_map [bi][bp] * radial_map   [ri][rp];
              dpsidxi_map      [ti][bp+rp*n_base_qp] = Ss_map[bi][bp] * radial_map   [ri][rp];
              dpsideta_map     [ti][bp+rp*n_base_qp] = S_map [bi][bp] * dradialdv_map[ri][rp];

              // second derivatives are not implemented for infinite elements
              // d2psidxi2_map    [ti][bp+rp*n_base_qp] = 0.;
              // d2psidxideta_map [ti][bp+rp*n_base_qp] = 0.;
              // d2psideta2_map   [ti][bp+rp*n_base_qp] = 0.;
            }

    }

  }

  // quadrature rule weights
  {
    const std::vector<Real>&   radial_qw = radial_qrule->get_weights();
    const std::vector<Real>&   base_qw   = base_qrule->get_weights();

    libmesh_assert_equal_to (radial_qw.size(), n_radial_qp);
    libmesh_assert_equal_to (base_qw.size(), n_base_qp);

    for (unsigned int rp=0; rp<n_radial_qp; rp++)
      for (unsigned int bp=0; bp<n_base_qp; bp++)
        {
          _total_qrule_weights[  bp+rp*n_base_qp ] = radial_qw[rp] * base_qw[bp];
        }
  }

}
Exemplo n.º 28
0
void EnsightIO::write_scalar_ascii(const std::string &sys, const std::string &var_name)
{
  std::ostringstream scl_file;
  scl_file << _ensight_file_name << "_" << var_name << ".scl";

  scl_file << std::setw(3)
           << std::setprecision(0)
           << std::setfill('0')
           << std::right
           << _time_steps.size()-1;

  FILE * fout = fopen(scl_file.str().c_str(),"w");

  fprintf(fout,"Per node scalar value\n");
  fprintf(fout,"part\n");
  fprintf(fout,"%10d\n",1);
  fprintf(fout,"coordinates\n");

  const MeshBase& the_mesh = MeshOutput<MeshBase>::mesh();

  const unsigned int dim = the_mesh.mesh_dimension();

  const System &system = _equation_systems.get_system(sys);

  const DofMap& dof_map = system.get_dof_map();


  int var = system.variable_number(var_name);


  std::vector<dof_id_type> dof_indices;
  std::vector<dof_id_type> dof_indices_scl;

  // Now we will loop over all the elements in the mesh.

  MeshBase::const_element_iterator       el     = the_mesh.active_local_elements_begin();
  const MeshBase::const_element_iterator end_el = the_mesh.active_local_elements_end();

  typedef std::map<int,Real> map_local_soln;
  typedef map_local_soln::iterator local_soln_iterator;

  map_local_soln local_soln;

  std::vector<Number>       elem_soln;
  std::vector<Number>       nodal_soln;

  for ( ; el != end_el ; ++el){

    const Elem* elem = *el;

    const FEType& fe_type    = system.variable_type(var);

    dof_map.dof_indices (elem, dof_indices);
    dof_map.dof_indices (elem, dof_indices_scl, var);

    elem_soln.resize(dof_indices_scl.size());

    for (unsigned int i = 0; i < dof_indices_scl.size(); i++)
      elem_soln[i] = system.current_solution(dof_indices_scl[i]);

    FEInterface::nodal_soln (dim,fe_type, elem, elem_soln, nodal_soln);

    libmesh_assert_equal_to (nodal_soln.size(), elem->n_nodes());

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
    libMesh::err << "Complex-valued Ensight output not yet supported" << std::endl;
    libmesh_not_implemented();
#endif

    for (unsigned int n=0; n<elem->n_nodes(); n++)
      local_soln[elem->node(n)] = libmesh_real(nodal_soln[n]);

  }

  local_soln_iterator sol = local_soln.begin();
  const local_soln_iterator sol_end = local_soln.end();
  for(; sol != sol_end; ++sol)
    fprintf(fout,"%12.5e\n",static_cast<double>((*sol).second));

  fclose(fout);

}
Exemplo n.º 29
0
void Partitioner::set_node_processor_ids(MeshBase & mesh)
{
  START_LOG("set_node_processor_ids()","Partitioner");

  // This function must be run on all processors at once
  libmesh_parallel_only(mesh.comm());

  // If we have any unpartitioned elements at this
  // stage there is a problem
  libmesh_assert (MeshTools::n_elem(mesh.unpartitioned_elements_begin(),
                                    mesh.unpartitioned_elements_end()) == 0);


  //   const dof_id_type orig_n_local_nodes = mesh.n_local_nodes();

  //   libMesh::err << "[" << mesh.processor_id() << "]: orig_n_local_nodes="
  //     << orig_n_local_nodes << std::endl;

  // Build up request sets.  Each node is currently owned by a processor because
  // it is connected to an element owned by that processor.  However, during the
  // repartitioning phase that element may have been assigned a new processor id, but
  // it is still resident on the original processor.  We need to know where to look
  // for new ids before assigning new ids, otherwise we may be asking the wrong processors
  // for the wrong information.
  //
  // The only remaining issue is what to do with unpartitioned nodes.  Since they are required
  // to live on all processors we can simply rely on ourselves to number them properly.
  std::vector<std::vector<dof_id_type> >
    requested_node_ids(mesh.n_processors());

  // Loop over all the nodes, count the ones on each processor.  We can skip ourself
  std::vector<dof_id_type> ghost_nodes_from_proc(mesh.n_processors(), 0);

  MeshBase::node_iterator       node_it  = mesh.nodes_begin();
  const MeshBase::node_iterator node_end = mesh.nodes_end();

  for (; node_it != node_end; ++node_it)
    {
      Node * node = *node_it;
      libmesh_assert(node);
      const processor_id_type current_pid = node->processor_id();
      if (current_pid != mesh.processor_id() &&
          current_pid != DofObject::invalid_processor_id)
        {
          libmesh_assert_less (current_pid, ghost_nodes_from_proc.size());
          ghost_nodes_from_proc[current_pid]++;
        }
    }

  // We know how many objects live on each processor, so reserve()
  // space for each.
  for (processor_id_type pid=0; pid != mesh.n_processors(); ++pid)
    requested_node_ids[pid].reserve(ghost_nodes_from_proc[pid]);

  // We need to get the new pid for each node from the processor
  // which *currently* owns the node.  We can safely skip ourself
  for (node_it = mesh.nodes_begin(); node_it != node_end; ++node_it)
    {
      Node * node = *node_it;
      libmesh_assert(node);
      const processor_id_type current_pid = node->processor_id();
      if (current_pid != mesh.processor_id() &&
          current_pid != DofObject::invalid_processor_id)
        {
          libmesh_assert_less (current_pid, requested_node_ids.size());
          libmesh_assert_less (requested_node_ids[current_pid].size(),
                               ghost_nodes_from_proc[current_pid]);
          requested_node_ids[current_pid].push_back(node->id());
        }

      // Unset any previously-set node processor ids
      node->invalidate_processor_id();
    }

  // Loop over all the active elements
  MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
  const MeshBase::element_iterator elem_end = mesh.active_elements_end();

  for ( ; elem_it != elem_end; ++elem_it)
    {
      Elem * elem = *elem_it;
      libmesh_assert(elem);

      libmesh_assert_not_equal_to (elem->processor_id(), DofObject::invalid_processor_id);

      // For each node, set the processor ID to the min of
      // its current value and this Element's processor id.
      //
      // TODO: we would probably get better parallel partitioning if
      // we did something like "min for even numbered nodes, max for
      // odd numbered".  We'd need to be careful about how that would
      // affect solution ordering for I/O, though.
      for (unsigned int n=0; n<elem->n_nodes(); ++n)
        elem->get_node(n)->processor_id() = std::min(elem->get_node(n)->processor_id(),
                                                     elem->processor_id());
    }

  // And loop over the subactive elements, but don't reassign
  // nodes that are already active on another processor.
  MeshBase::element_iterator       sub_it  = mesh.subactive_elements_begin();
  const MeshBase::element_iterator sub_end = mesh.subactive_elements_end();

  for ( ; sub_it != sub_end; ++sub_it)
    {
      Elem * elem = *sub_it;
      libmesh_assert(elem);

      libmesh_assert_not_equal_to (elem->processor_id(), DofObject::invalid_processor_id);

      for (unsigned int n=0; n<elem->n_nodes(); ++n)
        if (elem->get_node(n)->processor_id() == DofObject::invalid_processor_id)
          elem->get_node(n)->processor_id() = elem->processor_id();
    }

  // Same for the inactive elements -- we will have already gotten most of these
  // nodes, *except* for the case of a parent with a subset of children which are
  // ghost elements.  In that case some of the parent nodes will not have been
  // properly handled yet
  MeshBase::element_iterator       not_it  = mesh.not_active_elements_begin();
  const MeshBase::element_iterator not_end = mesh.not_active_elements_end();

  for ( ; not_it != not_end; ++not_it)
    {
      Elem * elem = *not_it;
      libmesh_assert(elem);

      libmesh_assert_not_equal_to (elem->processor_id(), DofObject::invalid_processor_id);

      for (unsigned int n=0; n<elem->n_nodes(); ++n)
        if (elem->get_node(n)->processor_id() == DofObject::invalid_processor_id)
          elem->get_node(n)->processor_id() = elem->processor_id();
    }

  // We can't assert that all nodes are connected to elements, because
  // a ParallelMesh with NodeConstraints might have pulled in some
  // remote nodes solely for evaluating those constraints.
  // MeshTools::libmesh_assert_connected_nodes(mesh);

  // For such nodes, we'll do a sanity check later when making sure
  // that we successfully reset their processor ids to something
  // valid.

  // Next set node ids from other processors, excluding self
  for (processor_id_type p=1; p != mesh.n_processors(); ++p)
    {
      // Trade my requests with processor procup and procdown
      processor_id_type procup = cast_int<processor_id_type>
        ((mesh.processor_id() + p) % mesh.n_processors());
      processor_id_type procdown = cast_int<processor_id_type>
        ((mesh.n_processors() + mesh.processor_id() - p) %
         mesh.n_processors());
      std::vector<dof_id_type> request_to_fill;
      mesh.comm().send_receive(procup, requested_node_ids[procup],
                               procdown, request_to_fill);

      // Fill those requests in-place
      for (std::size_t i=0; i != request_to_fill.size(); ++i)
        {
          Node * node = mesh.node_ptr(request_to_fill[i]);
          libmesh_assert(node);
          const processor_id_type new_pid = node->processor_id();

          // We may have an invalid processor_id() on nodes that have been
          // "detatched" from coarsened-away elements but that have not yet
          // themselves been removed.
          // libmesh_assert_not_equal_to (new_pid, DofObject::invalid_processor_id);
          // libmesh_assert_less (new_pid, mesh.n_partitions()); // this is the correct test --
          request_to_fill[i] = new_pid;           //  the number of partitions may
        }                                         //  not equal the number of processors

      // Trade back the results
      std::vector<dof_id_type> filled_request;
      mesh.comm().send_receive(procdown, request_to_fill,
                               procup,   filled_request);
      libmesh_assert_equal_to (filled_request.size(), requested_node_ids[procup].size());

      // And copy the id changes we've now been informed of
      for (std::size_t i=0; i != filled_request.size(); ++i)
        {
          Node * node = mesh.node_ptr(requested_node_ids[procup][i]);
          libmesh_assert(node);

          // this is the correct test -- the number of partitions may
          // not equal the number of processors

          // But: we may have an invalid processor_id() on nodes that
          // have been "detatched" from coarsened-away elements but
          // that have not yet themselves been removed.
          // libmesh_assert_less (filled_request[i], mesh.n_partitions());

          node->processor_id(cast_int<processor_id_type>(filled_request[i]));
        }
    }

#ifdef DEBUG
  MeshTools::libmesh_assert_valid_procids<Node>(mesh);
#endif

  STOP_LOG("set_node_processor_ids()","Partitioner");
}
Exemplo n.º 30
0
bool TreeNode<N>::insert (const Elem * elem)
{
  libmesh_assert(elem);

  // We first want to find the corners of the cuboid surrounding the cell.
  const BoundingBox bbox = elem->loose_bounding_box();

  // Next, find out whether this cuboid has got non-empty intersection
  // with the bounding box of the current tree node.
  //
  // If not, we should not care about this element.
  if (!this->bounding_box.intersects(bbox))
    return false;

  // Only add the element if we are active
  if (this->active())
    {
      elements.push_back (elem);

#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS

      // flag indicating this node contains
      // infinite elements
      if (elem->infinite())
        this->contains_ifems = true;

#endif

      unsigned int element_count = cast_int<unsigned int>(elements.size());
      if (!mesh.get_count_lower_dim_elems_in_point_locator())
        {
          const std::set<unsigned char> & elem_dimensions = mesh.elem_dimensions();
          if (elem_dimensions.size() > 1)
            {
              element_count = 0;
              unsigned char highest_dim_elem = *elem_dimensions.rbegin();
              for (std::size_t i=0; i<elements.size(); i++)
                {
                  if (elements[i]->dim() == highest_dim_elem)
                    {
                      element_count++;
                    }
                }
            }
        }

      // Refine ourself if we reach the target bin size for a TreeNode.
      if (element_count == tgt_bin_size)
        this->refine();

      return true;
    }

  // If we are not active simply pass the element along to
  // our children
  libmesh_assert_equal_to (children.size(), N);

  bool was_inserted = false;
  for (unsigned int c=0; c<N; c++)
    if (children[c]->insert (elem))
      was_inserted = true;
  return was_inserted;
}