libMesh::ProjectFEMSolution Class Reference
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 System & | system |
| 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
AutoPtr<FEMFunctionBase<Number> > libMesh::ProjectFEMSolution::f [private] |
Definition at line 165 of file system_projection.C.
Referenced by ProjectFEMSolution().
AutoPtr<FEMFunctionBase<Gradient> > libMesh::ProjectFEMSolution::g [private] |
Definition at line 166 of file system_projection.C.
Definition at line 167 of file system_projection.C.
const System& libMesh::ProjectFEMSolution::system [private] |
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: