void ConvectionDiffusionFE<TDomain>:: prep_err_est_elem_loop(const ReferenceObjectID roid, const int si) { // get the error estimator data object and check that it is of the right type // we check this at this point in order to be able to dispense with this check later on // (i.e. in prep_err_est_elem and compute_err_est_A_elem()) if (this->m_spErrEstData.get() == NULL) { UG_THROW("No ErrEstData object has been given to this ElemDisc!"); } err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get()); if (!err_est_data) { UG_THROW("Dynamic cast to SideAndElemErrEstData failed." << std::endl << "Make sure you handed the correct type of ErrEstData to this discretization."); } // set local positions static const int refDim = TElem::dim; // get local IPs size_t numSideIPs, numElemIPs; const MathVector<refDim>* sideIPs; const MathVector<refDim>* elemIPs; try { numSideIPs = err_est_data->num_all_side_ips(roid); numElemIPs = err_est_data->num_elem_ips(roid); sideIPs = err_est_data->template side_local_ips<refDim>(roid); elemIPs = err_est_data->template elem_local_ips<refDim>(roid); if (!sideIPs || !elemIPs) return; // are NULL if TElem is not of the same dim as TDomain } UG_CATCH_THROW("Integration points for error estimator cannot be set."); // set local IPs in imports m_imDiffusion.template set_local_ips<refDim>(sideIPs, numSideIPs, false); m_imVelocity.template set_local_ips<refDim>(sideIPs, numSideIPs, false); m_imFlux.template set_local_ips<refDim>(sideIPs, numSideIPs, false); m_imSource.template set_local_ips<refDim>(elemIPs, numElemIPs, false); m_imVectorSource.template set_local_ips<refDim>(sideIPs, numSideIPs, false); m_imReactionRate.template set_local_ips<refDim>(elemIPs, numElemIPs, false); m_imReaction.template set_local_ips<refDim>(elemIPs, numElemIPs, false); m_imMassScale.template set_local_ips<refDim>(elemIPs, numElemIPs, false); m_imMass.template set_local_ips<refDim>(elemIPs, numElemIPs, false); // store values of shape functions in local IPs LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> trialSpace = Provider<LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> >::get(); m_shapeValues.resize(numElemIPs, numSideIPs, trialSpace.num_sh()); for (size_t ip = 0; ip < numElemIPs; ip++) trialSpace.shapes(m_shapeValues.shapesAtElemIP(ip), elemIPs[ip]); for (size_t ip = 0; ip < numSideIPs; ip++) trialSpace.shapes(m_shapeValues.shapesAtSideIP(ip), sideIPs[ip]); }
void FV1InnerBoundaryElemDisc<TDomain>:: prep_err_est_elem(const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[]) { // get error estimator err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get()); // set local positions if (TFVGeom::usesHangingNodes) { static const int refDim = TElem::dim; ReferenceObjectID roid = elem->reference_object_id(); size_t numSideIPs; const MathVector<refDim>* sideIPs; try { numSideIPs = err_est_data->get(0)->num_side_ips(roid); sideIPs = err_est_data->get(0)->template side_local_ips<refDim>(roid); } UG_CATCH_THROW("Integration points for error estimator cannot be set."); // store values of shape functions in local IPs LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> trialSpace = Provider<LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> >::get(); m_shapeValues.resize(numSideIPs, trialSpace.num_sh()); for (size_t ip = 0; ip < numSideIPs; ip++) trialSpace.shapes(m_shapeValues.shapesAtSideIP(ip), sideIPs[ip]); } }
void FV1InnerBoundaryElemDisc<TDomain>:: prep_err_est_elem_loop(const ReferenceObjectID roid, const int si) { // get the error estimator data object and check that it is of the right type // we check this at this point in order to be able to dispense with this check later on // (i.e. in prep_err_est_elem and compute_err_est_A_elem()) if (this->m_spErrEstData.get() == NULL) { UG_THROW("No ErrEstData object has been given to this ElemDisc!"); } err_est_type* err_est_data = dynamic_cast<err_est_type*>(this->m_spErrEstData.get()); if (!err_est_data) { UG_THROW("Dynamic cast to MultipleSideAndElemErrEstData failed." << std::endl << "Make sure you handed the correct type of ErrEstData to this discretization."); } if (!err_est_data->equal_side_order()) { UG_THROW("The underlying error estimator data objects of this discretization's " "error estimator do not all have the same integration orders. This case " "is not supported by the implementation. If you need it, implement!"); } if (err_est_data->num() < 1) { UG_THROW("No underlying error estimator data objects present. No IPs can be determined."); } // set local positions if (!TFVGeom::usesHangingNodes) { static const int refDim = TElem::dim; // get local IPs size_t numSideIPs; const MathVector<refDim>* sideIPs; try { numSideIPs = err_est_data->get(0)->num_side_ips(roid); sideIPs = err_est_data->get(0)->template side_local_ips<refDim>(roid); } UG_CATCH_THROW("Integration points for error estimator cannot be set."); // store values of shape functions in local IPs LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> trialSpace = Provider<LagrangeP1<typename reference_element_traits<TElem>::reference_element_type> >::get(); m_shapeValues.resize(numSideIPs, trialSpace.num_sh()); for (size_t ip = 0; ip < numSideIPs; ip++) trialSpace.shapes(m_shapeValues.shapesAtSideIP(ip), sideIPs[ip]); } }
void ConvectionDiffusionFVCR<TDomain>:: ex_value(number vValue[], const MathVector<dim> vGlobIP[], number time, int si, const LocalVector& u, GridObject* elem, const MathVector<dim> vCornerCoords[], const MathVector<TFVGeom::dim> vLocIP[], const size_t nip, bool bDeriv, std::vector<std::vector<number> > vvvDeriv[]) { // get finite volume geometry static const TFVGeom& geo = GeomProvider<TFVGeom>::get(); // reference element typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type; // number of shape functions static const size_t numSH = ref_elem_type::numCorners; // CRFV SCVF ip if(vLocIP == geo.scvf_local_ips()) { // Loop Sub Control Volume Faces (SCVF) for(size_t ip = 0; ip < geo.num_scvf(); ++ip) { // Get current SCVF const typename TFVGeom::SCVF& scvf = geo.scvf(ip); // compute concentration at ip vValue[ip] = 0.0; for(size_t sh = 0; sh < scvf.num_sh(); ++sh) vValue[ip] += u(_C_, sh) * scvf.shape(sh); // compute derivative w.r.t. to unknowns iff needed if(bDeriv) for(size_t sh = 0; sh < scvf.num_sh(); ++sh) vvvDeriv[ip][_C_][sh] = scvf.shape(sh); } } // CRFV SCV ip else if(vLocIP == geo.scv_local_ips()) { // solution at ip for(size_t sh = 0; sh < numSH; ++sh) vValue[sh] = u(_C_, sh); // set derivatives if needed if(bDeriv) for(size_t sh = 0; sh < numSH; ++sh) for(size_t sh2 = 0; sh2 < numSH; ++sh2) vvvDeriv[sh][_C_][sh2] = (sh==sh2) ? 1.0 : 0.0; } // general case else { // get trial space LagrangeP1<ref_elem_type> rTrialSpace = Provider<LagrangeP1<ref_elem_type> >::get(); // storage for shape function at ip number vShape[numSH]; // loop ips for(size_t ip = 0; ip < nip; ++ip) { // evaluate at shapes at ip rTrialSpace.shapes(vShape, vLocIP[ip]); // compute concentration at ip vValue[ip] = 0.0; for(size_t sh = 0; sh < numSH; ++sh) vValue[ip] += u(_C_, sh) * vShape[sh]; // compute derivative w.r.t. to unknowns iff needed // \todo: maybe store shapes directly in vvvDeriv if(bDeriv) for(size_t sh = 0; sh < numSH; ++sh) vvvDeriv[ip][_C_][sh] = vShape[sh]; } } }