libMesh::ProjectFEMSolution Class Reference

List of all members.

Public Member Functions

 ProjectFEMSolution (const System &system_in, FEMFunctionBase< Number > *f_in, FEMFunctionBase< Gradient > *g_in, NumericVector< Number > &new_v_in)
 ProjectFEMSolution (const ProjectFEMSolution &in)
void operator() (const ConstElemRange &range) const

Private Attributes

const Systemsystem
AutoPtr< FEMFunctionBase
< Number > > 
f
AutoPtr< FEMFunctionBase
< Gradient > > 
g
NumericVector< Number > & new_vector

Detailed Description

This class implements projecting an arbitrary function to the current mesh. This may be exectued in parallel on multiple threads.

Definition at line 160 of file system_projection.C.


Constructor & Destructor Documentation

libMesh::ProjectFEMSolution::ProjectFEMSolution ( const System system_in,
FEMFunctionBase< Number > *  f_in,
FEMFunctionBase< Gradient > *  g_in,
NumericVector< Number > &  new_v_in 
) [inline]

Definition at line 170 of file system_projection.C.

References f, and libMesh::AutoPtr< Tp >::get().

00173                                                          :
00174     system(system_in),
00175     f(f_in ? f_in->clone() : AutoPtr<FEMFunctionBase<Number> >(NULL)),
00176     g(g_in ? g_in->clone() : AutoPtr<FEMFunctionBase<Gradient> >(NULL)),
00177     new_vector(new_v_in)
00178     {
00179       libmesh_assert(f.get());
00180     }

libMesh::ProjectFEMSolution::ProjectFEMSolution ( const ProjectFEMSolution in  )  [inline]

Definition at line 182 of file system_projection.C.

References f, and libMesh::AutoPtr< Tp >::get().

00182                                                       :
00183     system(in.system),
00184     f(in.f.get() ? in.f->clone() : AutoPtr<FEMFunctionBase<Number> >(NULL)),
00185     g(in.g.get() ? in.g->clone() : AutoPtr<FEMFunctionBase<Gradient> >(NULL)),
00186     new_vector(in.new_vector)
00187     {
00188       libmesh_assert(f.get());
00189     }


Member Function Documentation

void libMesh::ProjectFEMSolution::operator() ( const ConstElemRange range  )  const

This method projects an arbitrary solution to the current mesh. The input function f gives the arbitrary solution, while the new_vector (which should already be correctly sized) gives the solution (to be computed) on the current mesh.

Definition at line 1831 of file system_projection.C.

References std::abs(), libMesh::Variable::active_on_subdomain(), libMesh::StoredRange< iterator_type, object_type >::begin(), libMeshEnums::C_ONE, libMeshEnums::C_ZERO, libMesh::DenseMatrix< T >::cholesky_solve(), libMesh::FunctionBase< Output >::component(), libMeshEnums::DISCONTINUOUS, libMesh::FEInterface::dofs_on_edge(), libMesh::FEInterface::dofs_on_side(), libMesh::StoredRange< iterator_type, object_type >::end(), libMesh::FEType::family, libMesh::NumericVector< T >::first_local_index(), libMesh::FEAbstract::get_continuity(), libMesh::System::get_dof_map(), libMesh::FEGenericBase< OutputType >::get_dphi(), libMesh::FEAbstract::get_fe_type(), libMesh::FEAbstract::get_JxW(), libMesh::FEGenericBase< OutputType >::get_phi(), libMesh::FEAbstract::get_xyz(), libMeshEnums::HERMITE, libMesh::Elem::is_vertex(), libMesh::NumericVector< T >::last_local_index(), libMesh::FEInterface::n_dofs_at_node(), libMesh::Elem::n_edges(), libMesh::Elem::n_nodes(), libMesh::QBase::n_points(), libMesh::Elem::n_sides(), libMesh::Elem::point(), libMesh::DenseMatrix< T >::resize(), libMesh::DenseVector< T >::resize(), libMeshEnums::SCALAR, libMesh::NumericVector< T >::set(), libMesh::Threads::spin_mtx, libMesh::Elem::subdomain_id(), system, libMesh::System::time, libMesh::TOLERANCE, libMesh::Elem::type(), libMesh::Variable::type(), libMesh::DofMap::variable(), libMesh::System::variable_scalar_number(), libMesh::DenseMatrix< T >::zero(), and libMesh::DenseVector< T >::zero().

01832 {
01833   // We need data to project
01834   libmesh_assert(f.get());
01835 
01843   FEMContext context( system );
01844 
01845   // The number of variables in this system
01846   const unsigned int n_variables = context.n_vars();
01847 
01848   // The dimensionality of the current mesh
01849   const unsigned int dim = context.get_dim();
01850 
01851   // The DofMap for this system
01852   const DofMap& dof_map = system.get_dof_map();
01853 
01854   // The element matrix and RHS for projections.
01855   // Note that Ke is always real-valued, whereas
01856   // Fe may be complex valued if complex number
01857   // support is enabled
01858   DenseMatrix<Real> Ke;
01859   DenseVector<Number> Fe;
01860   // The new element coefficients
01861   DenseVector<Number> Ue;
01862   
01863   // FIXME: Need to generalize this to vector-valued elements. [PB]
01864   FEBase* fe = NULL;
01865   FEBase* side_fe = NULL;
01866   FEBase* edge_fe = NULL;
01867 
01868   // First, loop over all variables and make sure the shape functions phi will
01869   // get built as well as the shape function gradients if the gradient functor
01870   // is supplied.
01871   for (unsigned int var=0; var<n_variables; var++)
01872     {
01873       context.get_element_fe( var, fe );
01874       if (fe->get_fe_type().family == SCALAR)
01875         continue;
01876       if( dim > 1 )
01877         context.get_side_fe( var, side_fe );
01878       if( dim > 2 )
01879         context.get_edge_fe( var, edge_fe );
01880 
01881       fe->get_phi();
01882       if( dim > 1 )
01883         side_fe->get_phi();
01884       if( dim > 2 )
01885         edge_fe->get_phi();
01886 
01887       const FEContinuity cont = fe->get_continuity();
01888       if(cont == C_ONE)
01889         {
01890           libmesh_assert(g.get());
01891           fe->get_dphi();
01892           side_fe->get_dphi();
01893           if( dim > 2 )
01894             edge_fe->get_dphi();
01895         }
01896     }
01897 
01898   // Now initialize any user requested shape functions
01899   f->init_context(context);
01900   if(g.get())
01901     g->init_context(context);
01902 
01903   std::vector<unsigned int> side_dofs;
01904 
01905   // Iterate over all the elements in the range
01906   for (ConstElemRange::const_iterator elem_it=range.begin(); elem_it != range.end(); ++elem_it)
01907     {
01908       const Elem* elem = *elem_it;
01909 
01910       context.pre_fe_reinit(system, elem);
01911 
01912       // Loop over all the variables in the system
01913       for (unsigned int var=0; var<n_variables; var++)
01914         {
01915           const Variable& variable = dof_map.variable(var);
01916 
01917           const FEType& fe_type = variable.type();
01918 
01919           if (fe_type.family == SCALAR)
01920             continue;
01921 
01922           // Per-subdomain variables don't need to be projected on
01923           // elements where they're not active
01924           if (!variable.active_on_subdomain(elem->subdomain_id()))
01925             continue;
01926 
01927           const FEContinuity cont = fe->get_continuity();
01928 
01929           const unsigned int var_component =
01930             system.variable_scalar_number(var, 0);
01931 
01932           const std::vector<dof_id_type>& dof_indices = 
01933             context.get_dof_indices(var);
01934 
01935           // The number of DOFs on the element
01936           const unsigned int n_dofs =
01937             libmesh_cast_int<unsigned int>(dof_indices.size());
01938 
01939           // Fixed vs. free DoFs on edge/face projections
01940           std::vector<char> dof_is_fixed(n_dofs, false); // bools
01941           std::vector<int> free_dof(n_dofs, 0);
01942 
01943           // The element type
01944           const ElemType elem_type = elem->type();
01945 
01946           // The number of nodes on the new element
01947           const unsigned int n_nodes = elem->n_nodes();
01948 
01949           // Zero the interpolated values
01950           Ue.resize (n_dofs); Ue.zero();
01951 
01952           // In general, we need a series of
01953           // projections to ensure a unique and continuous
01954           // solution.  We start by interpolating nodes, then
01955           // hold those fixed and project edges, then
01956           // hold those fixed and project faces, then
01957           // hold those fixed and project interiors
01958 
01959           // Interpolate node values first
01960           unsigned int current_dof = 0;
01961           for (unsigned int n=0; n!= n_nodes; ++n)
01962             {
01963               // FIXME: this should go through the DofMap,
01964               // not duplicate dof_indices code badly!
01965               const unsigned int nc =
01966                 FEInterface::n_dofs_at_node (dim, fe_type, elem_type,
01967                                              n);
01968               if (!elem->is_vertex(n))
01969                 {
01970                   current_dof += nc;
01971                   continue;
01972                 }
01973               if (cont == DISCONTINUOUS)
01974                 {
01975                   libmesh_assert_equal_to (nc, 0);
01976                 }
01977               // Assume that C_ZERO elements have a single nodal
01978               // value shape function
01979               else if (cont == C_ZERO)
01980                 {
01981                   libmesh_assert_equal_to (nc, 1);
01982                   Ue(current_dof) = f->component(context,
01983                                                  var_component,
01984                                                  elem->point(n),
01985                                                  system.time);
01986                   dof_is_fixed[current_dof] = true;
01987                   current_dof++;
01988                 }
01989               // The hermite element vertex shape functions are weird
01990               else if (fe_type.family == HERMITE)
01991                 {
01992                   Ue(current_dof) = f->component(context,
01993                                                  var_component,
01994                                                  elem->point(n),
01995                                                  system.time);
01996                   dof_is_fixed[current_dof] = true;
01997                   current_dof++;
01998                   Gradient grad = g->component(context,
01999                                                var_component,
02000                                                elem->point(n),
02001                                                system.time);
02002                   // x derivative
02003                   Ue(current_dof) = grad(0);
02004                   dof_is_fixed[current_dof] = true;
02005                   current_dof++;
02006                   if (dim > 1)
02007                     {
02008                       // We'll finite difference mixed derivatives
02009                       Point nxminus = elem->point(n),
02010                             nxplus = elem->point(n);
02011                       nxminus(0) -= TOLERANCE;
02012                       nxplus(0) += TOLERANCE;
02013                       Gradient gxminus = g->component(context,
02014                                                       var_component,
02015                                                       nxminus,
02016                                                       system.time);
02017                       Gradient gxplus = g->component(context,
02018                                                      var_component,
02019                                                      nxplus,
02020                                                      system.time);
02021                       // y derivative
02022                       Ue(current_dof) = grad(1);
02023                       dof_is_fixed[current_dof] = true;
02024                       current_dof++;
02025                       // xy derivative
02026                       Ue(current_dof) = (gxplus(1) - gxminus(1))
02027                                         / 2. / TOLERANCE;
02028                       dof_is_fixed[current_dof] = true;
02029                       current_dof++;
02030 
02031                       if (dim > 2)
02032                         {
02033                           // z derivative
02034                           Ue(current_dof) = grad(2);
02035                           dof_is_fixed[current_dof] = true;
02036                           current_dof++;
02037                           // xz derivative
02038                           Ue(current_dof) = (gxplus(2) - gxminus(2))
02039                                             / 2. / TOLERANCE;
02040                           dof_is_fixed[current_dof] = true;
02041                           current_dof++;
02042                           // We need new points for yz
02043                           Point nyminus = elem->point(n),
02044                                 nyplus = elem->point(n);
02045                           nyminus(1) -= TOLERANCE;
02046                           nyplus(1) += TOLERANCE;
02047                           Gradient gyminus = g->component(context,
02048                                                           var_component,
02049                                                           nyminus,
02050                                                           system.time);
02051                           Gradient gyplus = g->component(context,
02052                                                          var_component,
02053                                                          nyplus,
02054                                                          system.time);
02055                           // xz derivative
02056                           Ue(current_dof) = (gyplus(2) - gyminus(2))
02057                                             / 2. / TOLERANCE;
02058                           dof_is_fixed[current_dof] = true;
02059                           current_dof++;
02060                           // Getting a 2nd order xyz is more tedious
02061                           Point nxmym = elem->point(n),
02062                                 nxmyp = elem->point(n),
02063                                 nxpym = elem->point(n),
02064                                 nxpyp = elem->point(n);
02065                           nxmym(0) -= TOLERANCE;
02066                           nxmym(1) -= TOLERANCE;
02067                           nxmyp(0) -= TOLERANCE;
02068                           nxmyp(1) += TOLERANCE;
02069                           nxpym(0) += TOLERANCE;
02070                           nxpym(1) -= TOLERANCE;
02071                           nxpyp(0) += TOLERANCE;
02072                           nxpyp(1) += TOLERANCE;
02073                           Gradient gxmym = g->component(context,
02074                                                         var_component,
02075                                                         nxmym,
02076                                                         system.time);
02077                           Gradient gxmyp = g->component(context,
02078                                                         var_component,
02079                                                         nxmyp,
02080                                                         system.time);
02081                           Gradient gxpym = g->component(context,
02082                                                         var_component,
02083                                                         nxpym,
02084                                                         system.time);
02085                           Gradient gxpyp = g->component(context,
02086                                                         var_component,
02087                                                         nxpyp,
02088                                                         system.time);
02089                           Number gxzplus = (gxpyp(2) - gxmyp(2))
02090                                          / 2. / TOLERANCE;
02091                           Number gxzminus = (gxpym(2) - gxmym(2))
02092                                           / 2. / TOLERANCE;
02093                           // xyz derivative
02094                           Ue(current_dof) = (gxzplus - gxzminus)
02095                                             / 2. / TOLERANCE;
02096                           dof_is_fixed[current_dof] = true;
02097                           current_dof++;
02098                         }
02099                     }
02100                 }
02101               // Assume that other C_ONE elements have a single nodal
02102               // value shape function and nodal gradient component
02103               // shape functions
02104               else if (cont == C_ONE)
02105                 {
02106                   libmesh_assert_equal_to (nc, 1 + dim);
02107                   Ue(current_dof) = f->component(context,
02108                                                  var_component,
02109                                                  elem->point(n),
02110                                                  system.time);
02111                   dof_is_fixed[current_dof] = true;
02112                   current_dof++;
02113                   Gradient grad = g->component(context,
02114                                                var_component,
02115                                                elem->point(n),
02116                                                system.time);
02117                   for (unsigned int i=0; i!= dim; ++i)
02118                     {
02119                       Ue(current_dof) = grad(i);
02120                       dof_is_fixed[current_dof] = true;
02121                       current_dof++;
02122                     }
02123                 }
02124               else
02125                 libmesh_error();
02126             }
02127 
02128           // In 3D, project any edge values next
02129           if (dim > 2 && cont != DISCONTINUOUS)
02130             {
02131               const QBase* qedgerule = context.get_edge_qrule();
02132               const unsigned int n_qp = qedgerule->n_points();
02133               const std::vector<Point>& xyz_values = edge_fe->get_xyz();
02134               const std::vector<Real>& JxW = edge_fe->get_JxW();
02135 
02136               const std::vector<std::vector<Real> >& phi = edge_fe->get_phi();
02137               const std::vector<std::vector<RealGradient> >* dphi = NULL;
02138               if (cont == C_ONE)
02139                 dphi = &(edge_fe->get_dphi());
02140               
02141               for (unsigned int e=0; e != elem->n_edges(); ++e)
02142                 {
02143                   context.edge = e;
02144                   context.edge_fe_reinit();
02145 
02146                   FEInterface::dofs_on_edge(elem, dim, fe_type, e,
02147                                             side_dofs);
02148 
02149                   // Some edge dofs are on nodes and already
02150                   // fixed, others are free to calculate
02151                   unsigned int free_dofs = 0;
02152                   for (unsigned int i=0; i != side_dofs.size(); ++i)
02153                     if (!dof_is_fixed[side_dofs[i]])
02154                       free_dof[free_dofs++] = i;
02155 
02156                   // There may be nothing to project
02157                   if (!free_dofs)
02158                     continue;
02159 
02160                   Ke.resize (free_dofs, free_dofs); Ke.zero();
02161                   Fe.resize (free_dofs); Fe.zero();
02162                   // The new edge coefficients
02163                   DenseVector<Number> Uedge(free_dofs);
02164 
02165                   // Loop over the quadrature points
02166                   for (unsigned int qp=0; qp<n_qp; qp++)
02167                     {
02168                       // solution at the quadrature point
02169                       Number fineval = f->component(context,
02170                                                     var_component,
02171                                                     xyz_values[qp],
02172                                                     system.time);
02173                       // solution grad at the quadrature point
02174                       Gradient finegrad;
02175                       if (cont == C_ONE)
02176                         finegrad = g->component(context,
02177                                                 var_component,
02178                                                 xyz_values[qp],
02179                                                 system.time);
02180 
02181                       // Form edge projection matrix
02182                       for (unsigned int sidei=0, freei=0;
02183                            sidei != side_dofs.size(); ++sidei)
02184                         {
02185                           unsigned int i = side_dofs[sidei];
02186                           // fixed DoFs aren't test functions
02187                           if (dof_is_fixed[i])
02188                             continue;
02189                           for (unsigned int sidej=0, freej=0;
02190                                sidej != side_dofs.size(); ++sidej)
02191                             {
02192                               unsigned int j = side_dofs[sidej];
02193                               if (dof_is_fixed[j])
02194                                 Fe(freei) -= phi[i][qp] * phi[j][qp] *
02195                                   JxW[qp] * Ue(j);
02196                               else
02197                                 Ke(freei,freej) += phi[i][qp] *
02198                                   phi[j][qp] * JxW[qp];
02199                               if (cont == C_ONE)
02200                                 {
02201                                   if (dof_is_fixed[j])
02202                                     Fe(freei) -= ( (*dphi)[i][qp] *
02203                                                    (*dphi)[j][qp] ) *
02204                                       JxW[qp] * Ue(j);
02205                                   else
02206                                     Ke(freei,freej) += ( (*dphi)[i][qp] *
02207                                                          (*dphi)[j][qp] )
02208                                       * JxW[qp];
02209                                 }
02210                               if (!dof_is_fixed[j])
02211                                 freej++;
02212                             }
02213                           Fe(freei) += phi[i][qp] * fineval * JxW[qp];
02214                           if (cont == C_ONE)
02215                             Fe(freei) += (finegrad * (*dphi)[i][qp] ) *
02216                               JxW[qp];
02217                           freei++;
02218                         }
02219                     }
02220 
02221                   Ke.cholesky_solve(Fe, Uedge);
02222 
02223                   // Transfer new edge solutions to element
02224                   for (unsigned int i=0; i != free_dofs; ++i)
02225                     {
02226                       Number &ui = Ue(side_dofs[free_dof[i]]);
02227                       libmesh_assert(std::abs(ui) < TOLERANCE ||
02228                                      std::abs(ui - Uedge(i)) < TOLERANCE);
02229                       ui = Uedge(i);
02230                       dof_is_fixed[side_dofs[free_dof[i]]] = true;
02231                     }
02232                 }
02233             } // end if (dim > 2 && cont != DISCONTINUOUS)
02234 
02235           // Project any side values (edges in 2D, faces in 3D)
02236           if (dim > 1 && cont != DISCONTINUOUS)
02237             {
02238               const QBase* qsiderule = context.get_side_qrule();
02239               const unsigned int n_qp = qsiderule->n_points();
02240               const std::vector<Point>& xyz_values = side_fe->get_xyz();
02241               const std::vector<Real>& JxW = side_fe->get_JxW();
02242 
02243               const std::vector<std::vector<Real> >& phi = side_fe->get_phi();
02244               const std::vector<std::vector<RealGradient> >* dphi = NULL;
02245               if (cont == C_ONE)
02246                 dphi = &(side_fe->get_dphi());
02247 
02248               for (unsigned int s=0; s != elem->n_sides(); ++s)
02249                 {
02250                   FEInterface::dofs_on_side(elem, dim, fe_type, s,
02251                                             side_dofs);
02252 
02253                   // Some side dofs are on nodes/edges and already
02254                   // fixed, others are free to calculate
02255                   unsigned int free_dofs = 0;
02256                   for (unsigned int i=0; i != side_dofs.size(); ++i)
02257                     if (!dof_is_fixed[side_dofs[i]])
02258                       free_dof[free_dofs++] = i;
02259 
02260                   // There may be nothing to project
02261                   if (!free_dofs)
02262                     continue;
02263 
02264                   Ke.resize (free_dofs, free_dofs); Ke.zero();
02265                   Fe.resize (free_dofs); Fe.zero();
02266                   // The new side coefficients
02267                   DenseVector<Number> Uside(free_dofs);
02268 
02269                   context.side = s;
02270                   context.side_fe_reinit();
02271 
02272                   // Loop over the quadrature points
02273                   for (unsigned int qp=0; qp<n_qp; qp++)
02274                     {
02275                       // solution at the quadrature point
02276                       Number fineval = f->component(context,
02277                                                     var_component,
02278                                                     xyz_values[qp],
02279                                                     system.time);
02280                       // solution grad at the quadrature point
02281                       Gradient finegrad;
02282                       if (cont == C_ONE)
02283                         finegrad = g->component(context,
02284                                                 var_component,
02285                                                 xyz_values[qp],
02286                                                 system.time);
02287 
02288                       // Form side projection matrix
02289                       for (unsigned int sidei=0, freei=0;
02290                            sidei != side_dofs.size(); ++sidei)
02291                         {
02292                           unsigned int i = side_dofs[sidei];
02293                           // fixed DoFs aren't test functions
02294                           if (dof_is_fixed[i])
02295                             continue;
02296                           for (unsigned int sidej=0, freej=0;
02297                                sidej != side_dofs.size(); ++sidej)
02298                             {
02299                               unsigned int j = side_dofs[sidej];
02300                               if (dof_is_fixed[j])
02301                                 Fe(freei) -= phi[i][qp] * phi[j][qp] *
02302                                   JxW[qp] * Ue(j);
02303                               else
02304                                 Ke(freei,freej) += phi[i][qp] *
02305                                   phi[j][qp] * JxW[qp];
02306                               if (cont == C_ONE)
02307                                 {
02308                                   if (dof_is_fixed[j])
02309                                     Fe(freei) -= ( (*dphi)[i][qp] *
02310                                                    (*dphi)[j][qp] ) *
02311                                       JxW[qp] * Ue(j);
02312                                   else
02313                                     Ke(freei,freej) += ( (*dphi)[i][qp] *
02314                                                          (*dphi)[j][qp] )
02315                                       * JxW[qp];
02316                                 }
02317                               if (!dof_is_fixed[j])
02318                                 freej++;
02319                             }
02320                           Fe(freei) += (fineval * phi[i][qp]) * JxW[qp];
02321                           if (cont == C_ONE)
02322                             Fe(freei) += (finegrad * (*dphi)[i][qp] ) *
02323                               JxW[qp];
02324                           freei++;
02325                         }
02326                     }
02327 
02328                   Ke.cholesky_solve(Fe, Uside);
02329 
02330                   // Transfer new side solutions to element
02331                   for (unsigned int i=0; i != free_dofs; ++i)
02332                     {
02333                       Number &ui = Ue(side_dofs[free_dof[i]]);
02334                       libmesh_assert(std::abs(ui) < TOLERANCE ||
02335                                      std::abs(ui - Uside(i)) < TOLERANCE);
02336                       ui = Uside(i);
02337                       dof_is_fixed[side_dofs[free_dof[i]]] = true;
02338                     }
02339                 }
02340             }// end if (dim > 1 && cont != DISCONTINUOUS)
02341 
02342           // Project the interior values, finally
02343 
02344           // Some interior dofs are on nodes/edges/sides and
02345           // already fixed, others are free to calculate
02346           unsigned int free_dofs = 0;
02347           for (unsigned int i=0; i != n_dofs; ++i)
02348             if (!dof_is_fixed[i])
02349               free_dof[free_dofs++] = i;
02350 
02351           // There may be nothing to project
02352           if (free_dofs)
02353             {
02354               context.elem_fe_reinit();
02355 
02356               const QBase* qrule = context.get_element_qrule();
02357               const unsigned int n_qp = qrule->n_points();
02358               const std::vector<Point>& xyz_values = fe->get_xyz();
02359               const std::vector<Real>& JxW = fe->get_JxW();
02360 
02361               const std::vector<std::vector<Real> >& phi = fe->get_phi();
02362               const std::vector<std::vector<RealGradient> >* dphi = NULL;
02363               if (cont == C_ONE)
02364                 dphi = &(side_fe->get_dphi());
02365 
02366               Ke.resize (free_dofs, free_dofs); Ke.zero();
02367               Fe.resize (free_dofs); Fe.zero();
02368               // The new interior coefficients
02369               DenseVector<Number> Uint(free_dofs);
02370 
02371               // Loop over the quadrature points
02372               for (unsigned int qp=0; qp<n_qp; qp++)
02373                 {
02374                   // solution at the quadrature point
02375                   Number fineval = f->component(context,
02376                                                 var_component,
02377                                                 xyz_values[qp],
02378                                                 system.time);
02379                   // solution grad at the quadrature point
02380                   Gradient finegrad;
02381                   if (cont == C_ONE)
02382                     finegrad = g->component(context,
02383                                             var_component,
02384                                             xyz_values[qp],
02385                                             system.time);
02386 
02387                   // Form interior projection matrix
02388                   for (unsigned int i=0, freei=0; i != n_dofs; ++i)
02389                     {
02390                       // fixed DoFs aren't test functions
02391                       if (dof_is_fixed[i])
02392                         continue;
02393                       for (unsigned int j=0, freej=0; j != n_dofs; ++j)
02394                         {
02395                           if (dof_is_fixed[j])
02396                             Fe(freei) -= phi[i][qp] * phi[j][qp] * JxW[qp]
02397                               * Ue(j);
02398                           else
02399                             Ke(freei,freej) += phi[i][qp] * phi[j][qp] *
02400                               JxW[qp];
02401                           if (cont == C_ONE)
02402                             {
02403                               if (dof_is_fixed[j])
02404                                 Fe(freei) -= ( (*dphi)[i][qp] *
02405                                                (*dphi)[j][qp] ) * JxW[qp] *
02406                                   Ue(j);
02407                               else
02408                                 Ke(freei,freej) += ( (*dphi)[i][qp] *
02409                                                      (*dphi)[j][qp] ) *
02410                                   JxW[qp];
02411                             }
02412                           if (!dof_is_fixed[j])
02413                             freej++;
02414                         }
02415                       Fe(freei) += phi[i][qp] * fineval * JxW[qp];
02416                       if (cont == C_ONE)
02417                         Fe(freei) += (finegrad * (*dphi)[i][qp] ) * JxW[qp];
02418                       freei++;
02419                     }
02420                 }
02421               Ke.cholesky_solve(Fe, Uint);
02422 
02423               // Transfer new interior solutions to element
02424               for (unsigned int i=0; i != free_dofs; ++i)
02425                 {
02426                   Number &ui = Ue(free_dof[i]);
02427                   libmesh_assert(std::abs(ui) < TOLERANCE ||
02428                                  std::abs(ui - Uint(i)) < TOLERANCE);
02429                   ui = Uint(i);
02430                   dof_is_fixed[free_dof[i]] = true;
02431                 }
02432 
02433             } // if there are free interior dofs
02434 
02435           // Make sure every DoF got reached!
02436           for (unsigned int i=0; i != n_dofs; ++i)
02437             libmesh_assert(dof_is_fixed[i]);
02438 
02439           const numeric_index_type
02440             first = new_vector.first_local_index(),
02441             last  = new_vector.last_local_index();
02442 
02443           // Lock the new_vector since it is shared among threads.
02444           {
02445             Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
02446 
02447             for (unsigned int i = 0; i < n_dofs; i++)
02448               // We may be projecting a new zero value onto
02449               // an old nonzero approximation - RHS
02450               // if (Ue(i) != 0.)
02451               if ((dof_indices[i] >= first) &&
02452                   (dof_indices[i] <  last))
02453                 {
02454                   new_vector.set(dof_indices[i], Ue(i));
02455                 }
02456           }
02457         }  // end variables loop
02458     } // end elem loop
02459 }


Member Data Documentation

Definition at line 163 of file system_projection.C.

Referenced by operator()().


The documentation for this class was generated from the following file:

Site Created By: libMesh Developers
Last modified: February 05 2013 19:55:06 UTC

Hosted By:
SourceForge.net Logo