void ConvectionDiffusionFE<TDomain>:: compute_err_est_M_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale) { // note: mass parts only enter volume term err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get()); if (err_est_data->surface_view().get() == NULL) {UG_THROW("Error estimator has NULL surface view.");} MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid()); typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::elem_type>::secure_container elem_list; pErrEstGrid->associated_elements_sorted(elem_list, (TElem*) elem); if (elem_list.size() != 1) UG_THROW ("Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'"); // request geometry static const TFEGeom& geo = GeomProvider<TFEGeom>::get(); // loop integration points try { for (size_t ip = 0; ip < err_est_data->num_elem_ips(elem->reference_object_id()); ip++) { number total = 0.0; // mass scale // if (m_imMassScale.data_given()) { number val = 0.0; for (size_t sh = 0; sh < geo.num_sh(); sh++) val += u(_C_,sh) * m_shapeValues.shapeAtElemIP(sh,ip); total += m_imMassScale[ip] * val; } // mass // if (m_imMass.data_given()) { total += m_imMass[ip]; } (*err_est_data)(elem_list[0],ip) += scale * total; } } UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData."); }
void ConvectionDiffusionFE<TDomain>:: compute_err_est_rhs_elem(GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale) { typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type; err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get()); if (err_est_data->surface_view().get() == NULL) {UG_THROW("Error estimator has NULL surface view.");} MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid()); // SIDE TERMS // // get the sides of the element typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::side_type>::secure_container side_list; pErrEstGrid->associated_elements_sorted(side_list, (TElem*) elem); if (side_list.size() != (size_t) ref_elem_type::numSides) UG_THROW ("Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'"); // loop sides size_t passedIPs = 0; for (size_t side = 0; side < (size_t) ref_elem_type::numSides; side++) { // normal on side MathVector<dim> normal; SideNormal<ref_elem_type,dim>(normal, side, vCornerCoords); VecNormalize(normal, normal); try { for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++) { size_t ip = passedIPs + sip; // vector source // if (m_imVectorSource.data_given()) (*err_est_data)(side_list[side],sip) += scale * VecDot(m_imVectorSource[ip], normal); } passedIPs += err_est_data->num_side_ips(side_list[side]); } UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData."); } // VOLUME TERMS // if (!m_imSource.data_given()) return; typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::elem_type>::secure_container elem_list; pErrEstGrid->associated_elements_sorted(elem_list, (TElem*) elem); if (elem_list.size() != 1) UG_THROW ("Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'"); // source // try { for (size_t ip = 0; ip < err_est_data->num_elem_ips(elem->reference_object_id()); ip++) (*err_est_data)(elem_list[0],ip) += scale * m_imSource[ip]; } UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData."); }
void ConvectionDiffusionFE<TDomain>:: compute_err_est_A_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[], const number& scale) { typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type; err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get()); if (err_est_data->surface_view().get() == NULL) {UG_THROW("Error estimator has NULL surface view.");} MultiGrid* pErrEstGrid = (MultiGrid*) (err_est_data->surface_view()->subset_handler()->multi_grid()); // request geometry static const TFEGeom& geo = GeomProvider<TFEGeom>::get(); // SIDE TERMS // // get the sides of the element // We have to cast elem to a pointer of type SideAndElemErrEstData::elem_type // for the SideAndElemErrEstData::operator() to work properly. // This cannot generally be achieved by casting to TElem*, since this method is also registered for // lower-dimensional types TElem, and must therefore be compilable, even if it is never EVER to be executed. // The way we achieve this here, is by calling associated_elements_sorted() which has an implementation for // all possible types. Whatever comes out of it is of course complete nonsense if (and only if) // SideAndElemErrEstData::elem_type != TElem. To be on the safe side, we throw an error if the number of // entries in the list is not as it should be. typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::side_type>::secure_container side_list; pErrEstGrid->associated_elements_sorted(side_list, (TElem*) elem); if (side_list.size() != (size_t) ref_elem_type::numSides) UG_THROW ("Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'"); // some help variables MathVector<dim> fluxDensity, gradC, normal; // FIXME: The computation of the gradient has to be reworked. // In the case of P1 shape functions, it is valid. For Q1 shape functions, however, // the gradient is not constant (but bilinear) on the element - and along the sides. // We cannot use the FVGeom here. Instead, we need to calculate the gradient in each IP! // calculate grad u as average (over scvf) VecSet(gradC, 0.0); for(size_t ii = 0; ii < geo.num_ip(); ++ii) { for (size_t j=0; j<m_shapeValues.num_sh(); j++) VecScaleAppend(gradC, u(_C_,j), geo.global_grad(ii, j)); } VecScale(gradC, gradC, (1.0/geo.num_ip())); // calculate flux through the sides size_t passedIPs = 0; for (size_t side=0; side < (size_t) ref_elem_type::numSides; side++) { // normal on side SideNormal<ref_elem_type,dim>(normal, side, vCornerCoords); VecNormalize(normal, normal); try { for (size_t sip = 0; sip < err_est_data->num_side_ips(side_list[side]); sip++) { size_t ip = passedIPs + sip; VecSet(fluxDensity, 0.0); // diffusion // if (m_imDiffusion.data_given()) MatVecScaleMultAppend(fluxDensity, -1.0, m_imDiffusion[ip], gradC); // convection // if (m_imVelocity.data_given()) { number val = 0.0; for (size_t sh = 0; sh < m_shapeValues.num_sh(); sh++) val += u(_C_,sh) * m_shapeValues.shapeAtSideIP(sh,sip); VecScaleAppend(fluxDensity, val, m_imVelocity[ip]); } // general flux // if (m_imFlux.data_given()) VecAppend(fluxDensity, m_imFlux[ip]); (*err_est_data)(side_list[side],sip) += scale * VecDot(fluxDensity, normal); } passedIPs += err_est_data->num_side_ips(side_list[side]); } UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData."); } // VOLUME TERMS // typename MultiGrid::traits<typename SideAndElemErrEstData<TDomain>::elem_type>::secure_container elem_list; pErrEstGrid->associated_elements_sorted(elem_list, (TElem*) elem); if (elem_list.size() != 1) UG_THROW ("Mismatch of numbers of sides in 'ConvectionDiffusionFE::compute_err_est_elem'"); try { for (size_t ip = 0; ip < err_est_data->num_elem_ips(elem->reference_object_id()); ip++) { number total = 0.0; // diffusion // TODO ONLY FOR (PIECEWISE) CONSTANT DIFFUSION TENSOR SO FAR! // div(D*grad(c)) // nothing to do, as c is piecewise linear and div(D*grad(c)) disappears // if D is diagonal and c bilinear, this should also vanish (confirm this!) // convection // TODO ONLY FOR (PIECEWISE) CONSTANT OR DIVERGENCE-FREE // VELOCITY FIELDS SO FAR! // div(v*c) = div(v)*c + v*grad(c) -- gradC has been calculated above if (m_imVelocity.data_given()) total += VecDot(m_imVelocity[ip], gradC); // general flux // TODO ONLY FOR DIVERGENCE-FREE FLUX FIELD SO FAR! // nothing to do // reaction // if (m_imReactionRate.data_given()) { number val = 0.0; for (size_t sh = 0; sh < geo.num_sh(); sh++) val += u(_C_,sh) * m_shapeValues.shapeAtElemIP(sh,ip); total += m_imReactionRate[ip] * val; } if (m_imReaction.data_given()) { total += m_imReaction[ip]; } (*err_est_data)(elem_list[0],ip) += scale * total; } } UG_CATCH_THROW("Values for the error estimator could not be assembled at every IP." << std::endl << "Maybe wrong type of ErrEstData object? This implementation needs: SideAndElemErrEstData."); }